import { useState, type FormEvent, type ChangeEvent } from 'react';
import { usePositions } from '../../api/hooks';
import {
  useSubmitOverrideOrder,
  type OverrideOrderRequest,
  type OverrideOrderResponse,
} from '../../api/tradingHooks';
import { ApiError } from '../../api/client';
import { Card, LoadingSpinner } from '../../components/ui';

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

type OrderType = OverrideOrderRequest['order_type'];
type Side = OverrideOrderRequest['side'];

interface FormState {
  ticker: string;
  side: Side;
  quantity: string;
  order_type: OrderType;
  limit_price: string;
  stop_price: string;
}

interface ValidationErrors {
  ticker?: string;
  quantity?: string;
  limit_price?: string;
  stop_price?: string;
}

const INITIAL_FORM: FormState = {
  ticker: '',
  side: 'buy',
  quantity: '',
  order_type: 'market',
  limit_price: '',
  stop_price: '',
};

const ORDER_TYPES: { value: OrderType; label: string }[] = [
  { value: 'market', label: 'Market' },
  { value: 'limit', label: 'Limit' },
  { value: 'stop', label: 'Stop' },
  { value: 'stop_limit', label: 'Stop Limit' },
];

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

const TICKER_RE = /^[A-Z]{1,10}$/;

function needsLimitPrice(orderType: OrderType): boolean {
  return orderType === 'limit' || orderType === 'stop_limit';
}

function needsStopPrice(orderType: OrderType): boolean {
  return orderType === 'stop' || orderType === 'stop_limit';
}

function validate(form: FormState): ValidationErrors {
  const errors: ValidationErrors = {};
  const ticker = form.ticker.toUpperCase();
  if (!TICKER_RE.test(ticker)) {
    errors.ticker = 'Ticker must be 1–10 alphabetic characters';
  }
  const qty = Number(form.quantity);
  if (!form.quantity || isNaN(qty) || qty <= 0) {
    errors.quantity = 'Quantity must be a positive number';
  }
  if (needsLimitPrice(form.order_type)) {
    const lp = Number(form.limit_price);
    if (!form.limit_price || isNaN(lp) || lp <= 0) {
      errors.limit_price = 'Limit price is required and must be positive';
    }
  }
  if (needsStopPrice(form.order_type)) {
    const sp = Number(form.stop_price);
    if (!form.stop_price || isNaN(sp) || sp <= 0) {
      errors.stop_price = 'Stop price is required and must be positive';
    }
  }
  return errors;
}

function fmtUsd(v: number | null | undefined) {
  if (v == null) return '—';
  return v.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}

function pnlColor(v: number | null | undefined) {
  if (v == null || v === 0) return 'text-gray-400';
  return v > 0 ? 'text-green-400' : 'text-red-400';
}

// ---------------------------------------------------------------------------
// Component
// ---------------------------------------------------------------------------

export default function OverrideTradePanel() {
  const [form, setForm] = useState<FormState>(INITIAL_FORM);
  const [errors, setErrors] = useState<ValidationErrors>({});
  const [serverErrors, setServerErrors] = useState<string[]>([]);
  const [banner, setBanner] = useState<{ type: 'success' | 'error'; message: string } | null>(null);
  const [successData, setSuccessData] = useState<OverrideOrderResponse | null>(null);

  const submitOrder = useSubmitOverrideOrder();
  const { data: positions, isLoading: positionsLoading } = usePositions();

  // --- Form field handlers ---

  function updateField(field: keyof FormState, value: string) {
    setForm((prev) => ({ ...prev, [field]: value }));
    // Clear field-level error on change
    if (field in errors) {
      setErrors((prev) => {
        const next = { ...prev };
        delete next[field as keyof ValidationErrors];
        return next;
      });
    }
    // Clear server errors and banner on any change
    if (serverErrors.length) setServerErrors([]);
    if (banner) setBanner(null);
    if (successData) setSuccessData(null);
  }

  function handleTickerChange(e: ChangeEvent<HTMLInputElement>) {
    updateField('ticker', e.target.value.toUpperCase());
  }

  function handleQuantityChange(e: ChangeEvent<HTMLInputElement>) {
    updateField('quantity', e.target.value);
  }

  function handleOrderTypeChange(e: ChangeEvent<HTMLSelectElement>) {
    const newType = e.target.value as OrderType;
    setForm((prev) => ({
      ...prev,
      order_type: newType,
      limit_price: needsLimitPrice(newType) ? prev.limit_price : '',
      stop_price: needsStopPrice(newType) ? prev.stop_price : '',
    }));
    // Clear price errors when switching order type
    setErrors((prev) => {
      const next = { ...prev };
      if (!needsLimitPrice(newType)) delete next.limit_price;
      if (!needsStopPrice(newType)) delete next.stop_price;
      return next;
    });
    if (serverErrors.length) setServerErrors([]);
    if (banner) setBanner(null);
  }

  function handleSideToggle(side: Side) {
    updateField('side', side);
  }

  // --- Submit ---

  function handleSubmit(e: FormEvent) {
    e.preventDefault();
    const validationErrors = validate(form);
    setErrors(validationErrors);
    if (Object.keys(validationErrors).length > 0) return;

    setServerErrors([]);
    setBanner(null);
    setSuccessData(null);

    const body: OverrideOrderRequest = {
      ticker: form.ticker.toUpperCase(),
      side: form.side,
      quantity: Number(form.quantity),
      order_type: form.order_type,
    };
    if (needsLimitPrice(form.order_type)) {
      body.limit_price = Number(form.limit_price);
    }
    if (needsStopPrice(form.order_type)) {
      body.stop_price = Number(form.stop_price);
    }

    submitOrder.mutate(body, {
      onSuccess: (data) => {
        setSuccessData(data);
        setBanner({ type: 'success', message: `Order queued — Job ID: ${data.job_id}` });
        setForm(INITIAL_FORM);
        setErrors({});
        setServerErrors([]);
      },
      onError: (err) => {
        if (err instanceof ApiError) {
          if (err.status === 422) {
            // Extract validation errors from response body
            const body = err.body as { detail?: Array<{ msg: string; loc?: string[] }> | string } | null;
            if (body?.detail && Array.isArray(body.detail)) {
              const msgs = body.detail.map((d) => d.msg ?? String(d));
              setServerErrors(msgs);
            } else if (typeof body?.detail === 'string') {
              setServerErrors([body.detail]);
            } else {
              setServerErrors(['Validation failed']);
            }
            return;
          }
          if (err.status === 503) {
            setBanner({ type: 'error', message: 'Broker service is unavailable. Please try again later.' });
            return;
          }
          setBanner({ type: 'error', message: `Server error (${err.status})` });
          return;
        }
        // Network / fetch error
        setBanner({ type: 'error', message: 'Unable to connect. Check your network and try again.' });
      },
    });
  }

  // --- Render ---

  const showLimitPrice = needsLimitPrice(form.order_type);
  const showStopPrice = needsStopPrice(form.order_type);

  return (
    <div className="space-y-6">
      {/* Order Form */}
      <Card>
        <h2 className="mb-4 text-sm font-medium text-gray-400">Submit Override Order</h2>

        {/* Success banner */}
        {banner?.type === 'success' && (
          <div
            className="mb-4 rounded-md border border-green-700/50 bg-green-900/20 px-4 py-3 text-sm text-green-400"
            role="alert"
            data-testid="success-banner"
          >
            {banner.message}
            {successData && (
              <span className="ml-2 text-xs text-green-500">
                Status: {successData.status}
              </span>
            )}
          </div>
        )}

        {/* Error banner (503 / network) */}
        {banner?.type === 'error' && (
          <div
            className="mb-4 rounded-md border border-red-700/50 bg-red-900/20 px-4 py-3 text-sm text-red-400"
            role="alert"
            data-testid="error-banner"
          >
            {banner.message}
          </div>
        )}

        {/* Server validation errors (422) */}
        {serverErrors.length > 0 && (
          <div
            className="mb-4 rounded-md border border-red-700/50 bg-red-900/20 px-4 py-3 text-sm text-red-400"
            role="alert"
            data-testid="validation-errors"
          >
            <ul className="list-inside list-disc space-y-1">
              {serverErrors.map((msg, i) => (
                <li key={i}>{msg}</li>
              ))}
            </ul>
          </div>
        )}

        <form onSubmit={handleSubmit} className="space-y-4">
          {/* Ticker */}
          <div>
            <label htmlFor="override-ticker" className="mb-1 block text-xs text-gray-500">
              Ticker
            </label>
            <input
              id="override-ticker"
              type="text"
              data-testid="ticker-input"
              value={form.ticker}
              onChange={handleTickerChange}
              placeholder="AAPL"
              className={`w-40 rounded-md border bg-surface-950 px-3 py-2 font-mono text-sm text-gray-200 uppercase placeholder-gray-600 focus:outline-none focus:ring-2 focus:ring-brand-500 ${
                errors.ticker ? 'border-red-500' : 'border-surface-700'
              }`}
              aria-label="Ticker symbol"
              aria-invalid={!!errors.ticker}
            />
            {errors.ticker && (
              <p className="mt-1 text-xs text-red-400" role="alert">{errors.ticker}</p>
            )}
          </div>

          {/* Side toggle */}
          <div>
            <span className="mb-1 block text-xs text-gray-500">Side</span>
            <div className="inline-flex rounded-md border border-surface-700" role="group" aria-label="Order side">
              <button
                type="button"
                data-testid="side-buy"
                onClick={() => handleSideToggle('buy')}
                className={`px-4 py-2 text-sm font-medium transition-colors first:rounded-l-md last:rounded-r-md ${
                  form.side === 'buy'
                    ? 'bg-green-700 text-white'
                    : 'bg-surface-900 text-gray-400 hover:bg-surface-800'
                }`}
                aria-pressed={form.side === 'buy'}
              >
                Buy
              </button>
              <button
                type="button"
                data-testid="side-sell"
                onClick={() => handleSideToggle('sell')}
                className={`px-4 py-2 text-sm font-medium transition-colors first:rounded-l-md last:rounded-r-md ${
                  form.side === 'sell'
                    ? 'bg-red-700 text-white'
                    : 'bg-surface-900 text-gray-400 hover:bg-surface-800'
                }`}
                aria-pressed={form.side === 'sell'}
              >
                Sell
              </button>
            </div>
          </div>

          {/* Quantity */}
          <div>
            <label htmlFor="override-quantity" className="mb-1 block text-xs text-gray-500">
              Quantity
            </label>
            <input
              id="override-quantity"
              type="number"
              data-testid="quantity-input"
              value={form.quantity}
              onChange={handleQuantityChange}
              placeholder="10"
              min="0"
              step="any"
              className={`w-40 rounded-md border bg-surface-950 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:outline-none focus:ring-2 focus:ring-brand-500 ${
                errors.quantity ? 'border-red-500' : 'border-surface-700'
              }`}
              aria-label="Quantity"
              aria-invalid={!!errors.quantity}
            />
            {errors.quantity && (
              <p className="mt-1 text-xs text-red-400" role="alert">{errors.quantity}</p>
            )}
          </div>

          {/* Order Type */}
          <div>
            <label htmlFor="override-order-type" className="mb-1 block text-xs text-gray-500">
              Order Type
            </label>
            <select
              id="override-order-type"
              data-testid="order-type-select"
              value={form.order_type}
              onChange={handleOrderTypeChange}
              className="w-40 rounded-md border border-surface-700 bg-surface-950 px-3 py-2 text-sm text-gray-200 focus:outline-none focus:ring-2 focus:ring-brand-500"
              aria-label="Order type"
            >
              {ORDER_TYPES.map((ot) => (
                <option key={ot.value} value={ot.value}>
                  {ot.label}
                </option>
              ))}
            </select>
          </div>

          {/* Limit Price (conditional) */}
          {showLimitPrice && (
            <div>
              <label htmlFor="override-limit-price" className="mb-1 block text-xs text-gray-500">
                Limit Price
              </label>
              <input
                id="override-limit-price"
                type="number"
                data-testid="limit-price-input"
                value={form.limit_price}
                onChange={(e) => updateField('limit_price', e.target.value)}
                placeholder="0.00"
                min="0"
                step="any"
                className={`w-40 rounded-md border bg-surface-950 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:outline-none focus:ring-2 focus:ring-brand-500 ${
                  errors.limit_price ? 'border-red-500' : 'border-surface-700'
                }`}
                aria-label="Limit price"
                aria-invalid={!!errors.limit_price}
              />
              {errors.limit_price && (
                <p className="mt-1 text-xs text-red-400" role="alert">{errors.limit_price}</p>
              )}
            </div>
          )}

          {/* Stop Price (conditional) */}
          {showStopPrice && (
            <div>
              <label htmlFor="override-stop-price" className="mb-1 block text-xs text-gray-500">
                Stop Price
              </label>
              <input
                id="override-stop-price"
                type="number"
                data-testid="stop-price-input"
                value={form.stop_price}
                onChange={(e) => updateField('stop_price', e.target.value)}
                placeholder="0.00"
                min="0"
                step="any"
                className={`w-40 rounded-md border bg-surface-950 px-3 py-2 text-sm text-gray-200 placeholder-gray-600 focus:outline-none focus:ring-2 focus:ring-brand-500 ${
                  errors.stop_price ? 'border-red-500' : 'border-surface-700'
                }`}
                aria-label="Stop price"
                aria-invalid={!!errors.stop_price}
              />
              {errors.stop_price && (
                <p className="mt-1 text-xs text-red-400" role="alert">{errors.stop_price}</p>
              )}
            </div>
          )}

          {/* Submit */}
          <button
            type="submit"
            data-testid="submit-order"
            disabled={submitOrder.isPending}
            className="rounded-md bg-brand-600 px-6 py-2 text-sm font-medium text-white transition-colors hover:bg-brand-700 disabled:cursor-not-allowed disabled:opacity-50"
            aria-label="Submit order"
          >
            {submitOrder.isPending ? 'Submitting…' : 'Submit Order'}
          </button>
        </form>
      </Card>

      {/* Positions Display */}
      <Card>
        <h2 className="mb-3 text-sm font-medium text-gray-400">Current Positions</h2>

        {positionsLoading ? (
          <LoadingSpinner />
        ) : !positions?.length ? (
          <p className="text-sm text-gray-500" data-testid="no-positions">No current positions</p>
        ) : (
          <div className="overflow-x-auto">
            <table className="w-full text-sm" role="table" data-testid="positions-table">
              <thead>
                <tr className="border-b border-surface-700 text-left text-gray-500">
                  <th className="px-3 py-2">Ticker</th>
                  <th className="px-3 py-2">Quantity</th>
                  <th className="px-3 py-2">Avg Entry</th>
                  <th className="px-3 py-2">Current</th>
                  <th className="px-3 py-2">Unrealized P&amp;L</th>
                </tr>
              </thead>
              <tbody>
                {positions.map((pos) => (
                  <tr key={pos.id} className="border-b border-surface-700/50">
                    <td className="px-3 py-2 font-mono font-semibold text-brand-300">{pos.ticker}</td>
                    <td className="px-3 py-2 text-gray-300">{pos.quantity}</td>
                    <td className="px-3 py-2 text-gray-300">${fmtUsd(pos.avg_entry_price)}</td>
                    <td className="px-3 py-2 text-gray-300">
                      {pos.current_price != null ? `$${fmtUsd(pos.current_price)}` : '—'}
                    </td>
                    <td className={`px-3 py-2 font-medium ${pnlColor(pos.unrealized_pnl)}`}>
                      {pos.unrealized_pnl != null ? `$${fmtUsd(pos.unrealized_pnl)}` : '—'}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </Card>
    </div>
  );
}
