import { useEffect, useMemo, useState } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useActivation } from '../../hooks/useActivation';
import { useTrades } from '../../hooks/useTrades';
import { qualifiesSetup, activationSummary, primaryTargetProbability } from '../../lib/qualification';
import { TradeTable, type SortColumn, type SortDirection, computeTradeAnalysis } from '../scanner/TradeTable';
import { SkeletonTable } from '../ui/Skeleton';
import { useToast } from '../ui/Toast';
import { Button } from '../ui/Button';
import { Callout } from '../ui/Callout';
import { Disclosure } from '../ui/Disclosure';
import { Field, Input } from '../ui/Field';
import { Dropdown } from '../ui/Dropdown';
import { triggerJob } from '../../api/admin';
import type { TradeSetup } from '../../lib/types';
import { RECOMMENDATION_ACTION_GLOSSARY, RECOMMENDATION_ACTION_LABELS } from '../../lib/recommendation';

type DirectionFilter = 'both' | 'long' | 'short';
type ActionFilter = 'all' | 'LONG_HIGH' | 'LONG_MODERATE' | 'SHORT_HIGH' | 'SHORT_MODERATE' | 'NEUTRAL';

function filterTrades(
  trades: TradeSetup[],
  minRR: number,
  direction: DirectionFilter,
  minConfidence: number,
  action: ActionFilter,
): TradeSetup[] {
  return trades.filter((t) => {
    if (t.rr_ratio < minRR) return false;
    if (direction !== 'both' && t.direction !== direction) return false;
    if (minConfidence > 0 && (t.confidence_score ?? 0) < minConfidence) return false;
    if (action !== 'all' && t.recommended_action !== action) return false;
    return true;
  });
}

function getComputedValue(trade: TradeSetup, column: SortColumn): number {
  const analysis = computeTradeAnalysis(trade);
  switch (column) {
    case 'risk_amount': return analysis.risk_amount;
    case 'reward_amount': return analysis.reward_amount;
    case 'stop_pct': return analysis.stop_pct;
    case 'target_pct': return analysis.target_pct;
    case 'confidence_score': return trade.confidence_score ?? -1;
    case 'primary_target_probability':
      return primaryTargetProbability(trade) ?? -1;
    case 'strategy_rank':
      return trade.strategy_rank ?? trade.momentum_percentile ?? -1;
    case 'momentum_percentile':
      return trade.momentum_percentile ?? -1;
    case 'risk_level':
      if (trade.risk_level === 'Low') return 1;
      if (trade.risk_level === 'Medium') return 2;
      if (trade.risk_level === 'High') return 3;
      return 0;
    default: return 0;
  }
}

function sortTrades(
  trades: TradeSetup[],
  column: SortColumn,
  direction: SortDirection,
): TradeSetup[] {
  const sorted = [...trades].sort((a, b) => {
    let cmp = 0;
    switch (column) {
      case 'symbol':
        cmp = a.symbol.localeCompare(b.symbol);
        break;
      case 'direction':
        cmp = a.direction.localeCompare(b.direction);
        break;
      case 'recommended_action':
        cmp = (a.recommended_action ?? '').localeCompare(b.recommended_action ?? '');
        break;
      case 'detected_at':
        cmp = new Date(a.detected_at).getTime() - new Date(b.detected_at).getTime();
        break;
      case 'risk_amount':
      case 'reward_amount':
      case 'stop_pct':
      case 'target_pct':
      case 'confidence_score':
      case 'primary_target_probability':
      case 'strategy_rank':
      case 'momentum_percentile':
      case 'risk_level':
        cmp = getComputedValue(a, column) - getComputedValue(b, column);
        break;
      case 'entry_price':
      case 'stop_loss':
      case 'target':
      case 'rr_ratio':
      case 'composite_score':
        cmp = a[column] - b[column];
        break;
    }
    return direction === 'asc' ? cmp : -cmp;
  });
  return sorted;
}

export function SetupsPanel() {
  const { data: trades, isLoading, isError, error } = useTrades();
  const activation = useActivation();
  const queryClient = useQueryClient();
  const toast = useToast();

  // "Qualified only" applies the admin activation gate; the refinement filters
  // can raise the bar further.
  const [qualifiedOnly, setQualifiedOnly] = useState(true);
  const [minRR, setMinRR] = useState(0);
  const [minConfidence, setMinConfidence] = useState(0);
  const [directionFilter, setDirectionFilter] = useState<DirectionFilter>('both');
  const [actionFilter, setActionFilter] = useState<ActionFilter>('all');
  // Production book orders by 80/20 strategy_rank, not raw R:R.
  const [sortColumn, setSortColumn] = useState<SortColumn>('strategy_rank');
  const [sortDirection, setSortDirection] = useState<SortDirection>('desc');

  // Keep the Min R:R / Min Confidence inputs showing the *effective* floor: when
  // qualified-only is on they reflect the activation gate (so they're never a
  // misleading 0); off, they reset to 0 (no minimum).
  useEffect(() => {
    if (qualifiedOnly && activation.data) {
      setMinRR(activation.data.min_rr);
      setMinConfidence(activation.data.min_confidence);
    } else if (!qualifiedOnly) {
      setMinRR(0);
      setMinConfidence(0);
    }
  }, [qualifiedOnly, activation.data]);

  const scanMutation = useMutation({
    mutationFn: () => triggerJob('rr_scanner'),
    onSuccess: () => {
      toast.addToast('success', 'Scanner triggered. Results will refresh shortly.');
      setTimeout(() => queryClient.invalidateQueries({ queryKey: ['trades'] }), 3000);
    },
    onError: () => {
      toast.addToast('error', 'Failed to trigger scanner');
    },
  });

  const handleSort = (column: SortColumn) => {
    if (column === sortColumn) {
      setSortDirection((prev) => (prev === 'asc' ? 'desc' : 'asc'));
    } else {
      setSortColumn(column);
      setSortDirection('asc');
    }
  };

  const processed = useMemo(() => {
    if (!trades) return [];
    let base = trades;
    if (qualifiedOnly && activation.data) {
      base = base.filter((t) => qualifiesSetup(t, activation.data!));
    }
    const filtered = filterTrades(base, minRR, directionFilter, minConfidence, actionFilter);
    return sortTrades(filtered, sortColumn, sortDirection);
  }, [trades, qualifiedOnly, activation.data, minRR, directionFilter, minConfidence, actionFilter, sortColumn, sortDirection]);

  return (
    <div className="space-y-4">
      {/* Action row — Run Scanner is a job trigger, kept apart from the filters */}
      <div className="flex flex-wrap items-center justify-between gap-3">
        <p className="text-xs text-gray-500">
          Setups from the latest scan. Re-run to refresh against current prices.
        </p>
        <Button onClick={() => scanMutation.mutate()} loading={scanMutation.isPending}>
          {scanMutation.isPending ? 'Scanning…' : 'Run Scanner'}
        </Button>
      </div>

      {/* Filters — qualified gate on top, refinements below */}
      <div className="glass-sm space-y-4 p-4">
        <label className="flex cursor-pointer items-center gap-2.5 text-sm text-gray-300">
          <input
            type="checkbox"
            checked={qualifiedOnly}
            onChange={(e) => setQualifiedOnly(e.target.checked)}
            className="h-4 w-4 cursor-pointer accent-blue-400"
          />
          <span>
            Qualified only
            {activation.data && (
              <span className="num ml-2 text-xs text-gray-500">{activationSummary(activation.data)}</span>
            )}
          </span>
        </label>

        <div className="flex flex-wrap items-end gap-4 border-t border-white/[0.06] pt-4">
          <Field label="Direction" htmlFor="direction">
            <Dropdown
              id="direction"
              value={directionFilter}
              onChange={(v) => setDirectionFilter(v as DirectionFilter)}
              className="w-32"
              options={[
                { value: 'both', label: 'Both' },
                { value: 'long', label: 'Long' },
                { value: 'short', label: 'Short' },
              ]}
            />
          </Field>
          <Field label="Min Risk:Reward" htmlFor="min-rr">
            <div className="flex items-center gap-1">
              <span className="text-sm text-gray-400">1 :</span>
              <Input
                id="min-rr"
                type="number"
                min={0}
                step={0.1}
                value={minRR}
                onChange={(e) => setMinRR(Number(e.target.value) || 0)}
                className="w-20"
              />
            </div>
          </Field>
          <Field label="Min Confidence" htmlFor="min-confidence">
            <Input
              id="min-confidence"
              type="number"
              min={0}
              max={100}
              step={1}
              value={minConfidence}
              onChange={(e) => setMinConfidence(Number(e.target.value) || 0)}
              className="w-24"
            />
          </Field>
          <Field label="Recommended Action" htmlFor="action">
            <Dropdown
              id="action"
              value={actionFilter}
              onChange={(v) => setActionFilter(v as ActionFilter)}
              className="w-56"
              options={[
                { value: 'all', label: 'All' },
                { value: 'LONG_HIGH', label: RECOMMENDATION_ACTION_LABELS.LONG_HIGH },
                { value: 'LONG_MODERATE', label: RECOMMENDATION_ACTION_LABELS.LONG_MODERATE },
                { value: 'SHORT_HIGH', label: RECOMMENDATION_ACTION_LABELS.SHORT_HIGH },
                { value: 'SHORT_MODERATE', label: RECOMMENDATION_ACTION_LABELS.SHORT_MODERATE },
                { value: 'NEUTRAL', label: RECOMMENDATION_ACTION_LABELS.NEUTRAL },
              ]}
            />
          </Field>
        </div>
      </div>

      <Disclosure summary="How the scanner works & action glossary">
        <p className="mb-3 text-xs text-gray-400">
          The scanner builds long setups with a 1.5× ATR stop and a Gate Target Ladder proposal used
          only for R:R / reach-probability screening — not as a take-profit. Structural chart S/R is
          separate. Live exit is the ATR trail / max hold. Click{' '}
          <span className="font-medium text-gray-300">Run Scanner</span> to scan all tickers now, or
          wait for the scheduled run.
        </p>
        <div className="grid gap-1 md:grid-cols-2">
          {RECOMMENDATION_ACTION_GLOSSARY.map((item) => (
            <p key={item.action} className="text-xs text-gray-300">
              <span className="font-semibold text-blue-300">{RECOMMENDATION_ACTION_LABELS[item.action]}:</span>{' '}
              {item.description}
            </p>
          ))}
        </div>
      </Disclosure>

      {isLoading && <SkeletonTable rows={8} cols={8} />}

      {isError && (
        <Callout variant="error">
          {error instanceof Error ? error.message : 'Failed to load trade setups'}
        </Callout>
      )}

      {trades && processed.length === 0 && !isLoading && (
        <Callout variant="empty">
          No trade setups match the current filters. Try lowering the Min R:R or click Run Scanner to refresh.
        </Callout>
      )}

      {trades && processed.length > 0 && (
        <TradeTable
          trades={processed}
          sortColumn={sortColumn}
          sortDirection={sortDirection}
          onSort={handleSort}
        />
      )}
    </div>
  );
}
