import { useState } from 'react';
import type { TradeSetup } from '../../lib/types';
import { formatPrice, formatPercent } from '../../lib/format';
import { useCreatePaperTrade } from '../../hooks/usePaperTrades';
import { recommendationActionDirection, recommendationActionLabel } from '../../lib/recommendation';
import { useRiskSettings, type RiskSettings } from '../../hooks/useRiskSettings';
import { positionSize } from '../../lib/position';
import { useMarketRegime } from '../../hooks/useMarketRegime';
import { isCounterTrend } from '../../lib/regime';
import type { MarketRegime } from '../../lib/types';

interface RecommendationPanelProps {
  symbol: string;
  longSetup?: TradeSetup;
  shortSetup?: TradeSetup;
  currentPrice?: number;
  nextEarningsDate?: string | null;
}

/** Whole days from today until an ISO date (negative if past). */
function daysUntil(iso: string): number | null {
  const t = new Date(iso).getTime();
  if (Number.isNaN(t)) return null;
  return Math.ceil((t - Date.now()) / 86_400_000);
}

/** Earnings within the ~30-day target horizon can gap price through stop/target. */
const EARNINGS_HORIZON_DAYS = 30;

/**
 * How far current price has drifted from the setup's entry. A setup whose
 * entry is far from the live price (price already ran toward target, or fell
 * through the stop) is stale — entering now changes the risk/reward.
 */
function entryDrift(setup: TradeSetup, currentPrice?: number) {
  if (currentPrice == null || !setup.entry_price) return null;
  const pct = ((currentPrice - setup.entry_price) / setup.entry_price) * 100;
  const towardTarget = setup.direction === 'long' ? currentPrice >= setup.entry_price : currentPrice <= setup.entry_price;
  // Judge staleness by how much of the entry→target distance is already gone,
  // not the raw % move — an 8%-wide setup is "used up" far faster than a 40% one.
  const span = Math.abs(setup.target - setup.entry_price);
  const moved = Math.abs(currentPrice - setup.entry_price);
  const progressPct = span > 0 ? (moved / span) * 100 : 0;
  const beyondStop = setup.direction === 'long' ? currentPrice <= setup.stop_loss : currentPrice >= setup.stop_loss;
  let status: 'fresh' | 'stale' | 'invalidated' = 'fresh';
  if (beyondStop) status = 'invalidated';
  else if (towardTarget && progressPct > 33) status = 'stale';
  else if (!towardTarget && progressPct > 33) status = 'stale';
  return { pct, progressPct, towardTarget, status };
}

function riskClass(risk: TradeSetup['risk_level']) {
  if (risk === 'Low') return 'text-emerald-400';
  if (risk === 'Medium') return 'text-amber-400';
  if (risk === 'High') return 'text-red-400';
  return 'text-gray-400';
}

function isRecommended(setup: TradeSetup | undefined, action: TradeSetup['recommended_action'] | undefined) {
  if (!setup || !action) return false;
  if (setup.direction === 'long') return action.startsWith('LONG');
  return action.startsWith('SHORT');
}

function TargetTable({ setup }: { setup: TradeSetup }) {
  if (!setup.targets || setup.targets.length === 0) {
    return <p className="text-xs text-gray-500">No target probabilities available.</p>;
  }

  return (
    <div className="overflow-x-auto">
      <table className="w-full text-xs">
        <thead>
          <tr className="text-left text-gray-500 border-b border-white/[0.06]">
            <th className="py-2 pr-3">Classification</th>
            <th className="py-2 pr-3">Price</th>
            <th className="py-2 pr-3">Distance</th>
            <th className="py-2 pr-3">R:R</th>
            <th className="py-2">Probability</th>
          </tr>
        </thead>
        <tbody>
          {setup.targets.map((target) => (
            <tr
              key={`${setup.id}-${target.sr_level_id}-${target.price}`}
              className={`border-b border-white/[0.04] ${target.is_primary ? 'bg-blue-400/10' : ''}`}
            >
              <td className="py-2 pr-3 text-gray-300">
                {target.is_primary && <span className="mr-1 text-blue-300">★</span>}
                {target.classification}
              </td>
              <td className="py-2 pr-3 font-mono text-gray-200">{formatPrice(target.price)}</td>
              <td className="py-2 pr-3 font-mono text-gray-200">{formatPercent((target.distance_from_entry / setup.entry_price) * 100)}</td>
              <td className="py-2 pr-3 font-mono text-gray-200">{target.rr_ratio.toFixed(2)}</td>
              <td className="py-2 font-mono text-gray-200">{target.probability.toFixed(1)}%</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function SetupCard({ setup, action, currentPrice, risk, regime }: { setup?: TradeSetup; action?: TradeSetup['recommended_action']; currentPrice?: number; risk: RiskSettings; regime?: MarketRegime }) {
  if (!setup) {
    return (
      <div className="glass-sm p-4 text-xs text-gray-500">
        Setup unavailable for this direction.
      </div>
    );
  }

  const recommended = isRecommended(setup, action);
  const drift = entryDrift(setup, currentPrice);
  const sizing = positionSize(risk.accountSize, risk.riskPct, setup.entry_price, setup.stop_loss);
  const counterTrend = regime ? isCounterTrend(setup.direction, regime.label) : false;

  const createTrade = useCreatePaperTrade();
  const [taking, setTaking] = useState(false);
  const [takeShares, setTakeShares] = useState<number>(sizing?.shares ?? 0);
  const [takeEntry, setTakeEntry] = useState<number>(currentPrice ?? setup.entry_price);

  const confirmTake = () => {
    createTrade.mutate(
      {
        symbol: setup.symbol,
        direction: setup.direction as 'long' | 'short',
        entry_price: takeEntry,
        shares: takeShares,
        stop_loss: setup.stop_loss,
        target: setup.target,
      },
      { onSuccess: () => setTaking(false) },
    );
  };

  return (
    <div
      data-direction={setup.direction}
      className={`glass-sm p-4 space-y-3 ${recommended ? 'border border-emerald-500/40' : 'opacity-80'}`}
    >
      <div className="flex items-center justify-between">
        <h4 className={`text-sm font-semibold ${setup.direction === 'long' ? 'text-emerald-400' : 'text-red-400'}`}>
          {setup.direction.toUpperCase()}
        </h4>
        <span className="text-xs text-gray-300">{setup.confidence_score?.toFixed(1) ?? '—'}%</span>
      </div>

      {!recommended && recommendationActionDirection(action ?? null) !== 'neutral' && (
        <p className="text-[11px] text-amber-400">Alternative setup (ticker bias currently favors the opposite direction).</p>
      )}

      {counterTrend && regime && (
        <p className="text-[11px] text-amber-400">
          ⚠ Counter-trend: {setup.direction.toUpperCase()} against a {regime.label} market
          ({regime.benchmark ?? 'SPY'}). Lower odds — size down or wait for confirmation.
        </p>
      )}

      {drift && drift.status === 'invalidated' && (
        <p className="text-[11px] text-red-400">
          ⚠ Price ({formatPrice(currentPrice!)}) is past the stop — this setup is invalidated.
        </p>
      )}
      {drift && drift.status === 'stale' && (
        <p className="text-[11px] text-amber-400">
          {drift.towardTarget
            ? `⚠ ${drift.progressPct.toFixed(0)}% of the entry→target move is already gone (${drift.pct >= 0 ? '+' : ''}${drift.pct.toFixed(1)}% from entry) — little reward left.`
            : `⚠ Price has moved ${Math.abs(drift.pct).toFixed(1)}% against the setup (toward the stop) — entry may be stale.`}
        </p>
      )}

      <div className="grid grid-cols-2 gap-2 text-xs">
        <div className="text-gray-500">Current</div><div className="font-mono text-gray-200">{currentPrice != null ? formatPrice(currentPrice) : '—'}</div>
        <div className="text-gray-500">Entry</div><div className="font-mono text-gray-200">{formatPrice(setup.entry_price)}{drift ? ` (${drift.pct >= 0 ? '+' : ''}${drift.pct.toFixed(1)}%)` : ''}</div>
        <div className="text-gray-500">Stop</div><div className="font-mono text-gray-200">{formatPrice(setup.stop_loss)}</div>
        <div className="text-gray-500">Primary Target</div><div className="font-mono text-gray-200">{formatPrice(setup.target)}</div>
        <div className="text-gray-500">R:R</div><div className="font-mono text-gray-200">{setup.rr_ratio.toFixed(2)}</div>
      </div>

      {sizing ? (
        <div className="rounded border border-white/[0.06] bg-white/[0.02] p-2.5 text-xs">
          <p className="mb-1.5 text-[10px] uppercase tracking-wider text-gray-500">
            Position size · {risk.riskPct}% of {formatPrice(risk.accountSize)}
          </p>
          <div className="grid grid-cols-3 gap-2 text-center">
            <div>
              <div className="font-mono text-sm text-gray-100">{sizing.shares}</div>
              <div className="text-[10px] text-gray-500">shares</div>
            </div>
            <div>
              <div className={`font-mono text-sm ${sizing.exceedsAccount ? 'text-amber-400' : 'text-gray-100'}`}>{formatPrice(sizing.positionValue)}</div>
              <div className="text-[10px] text-gray-500">position</div>
            </div>
            <div>
              <div className="font-mono text-sm text-gray-100">{formatPrice(sizing.dollarRisk)}</div>
              <div className="text-[10px] text-gray-500">max loss</div>
            </div>
          </div>
          {sizing.exceedsAccount && (
            <p className="mt-1.5 text-[10px] text-amber-400">Position exceeds account — needs margin.</p>
          )}
        </div>
      ) : (
        <p className="text-[11px] text-gray-600">Set account size below to size this trade.</p>
      )}

      {!taking ? (
        <button
          onClick={() => {
            setTakeShares(sizing?.shares ?? 0);
            setTakeEntry(currentPrice ?? setup.entry_price);
            setTaking(true);
          }}
          className="w-full rounded-md border border-emerald-500/30 bg-emerald-500/10 px-3 py-1.5 text-xs font-medium text-emerald-300 transition-colors hover:bg-emerald-500/20"
        >
          + Mark as taken (paper trade)
        </button>
      ) : (
        <div className="rounded-md border border-white/[0.08] bg-white/[0.02] p-2.5 space-y-2">
          <div className="grid grid-cols-2 gap-2">
            <label className="block space-y-1">
              <span className="text-[10px] uppercase tracking-wider text-gray-500">Shares</span>
              <input
                type="number"
                min={0}
                value={takeShares}
                onChange={(e) => setTakeShares(Number(e.target.value))}
                className="w-full input-glass px-2 py-1 text-sm num"
              />
            </label>
            <label className="block space-y-1">
              <span className="text-[10px] uppercase tracking-wider text-gray-500">Entry</span>
              <input
                type="number"
                min={0}
                step="0.01"
                value={takeEntry}
                onChange={(e) => setTakeEntry(Number(e.target.value))}
                className="w-full input-glass px-2 py-1 text-sm num"
              />
            </label>
          </div>
          <p className="text-[10px] text-gray-500">
            Stop {formatPrice(setup.stop_loss)} · Target {formatPrice(setup.target)} · {setup.direction.toUpperCase()}
          </p>
          <div className="flex gap-2">
            <button
              onClick={confirmTake}
              disabled={createTrade.isPending || !(takeShares > 0) || !(takeEntry > 0)}
              className="flex-1 rounded-md bg-emerald-500/20 px-3 py-1.5 text-xs font-medium text-emerald-300 hover:bg-emerald-500/30 disabled:opacity-50"
            >
              {createTrade.isPending ? 'Taking…' : 'Confirm'}
            </button>
            <button
              onClick={() => setTaking(false)}
              className="rounded-md border border-white/[0.08] px-3 py-1.5 text-xs text-gray-400 hover:text-gray-200"
            >
              Cancel
            </button>
          </div>
        </div>
      )}

      <TargetTable setup={setup} />

      {setup.conflict_flags.length > 0 && (
        <div className="rounded border border-amber-500/30 bg-amber-500/10 p-2 text-[11px] text-amber-300">
          {setup.conflict_flags.join(' • ')}
        </div>
      )}
    </div>
  );
}

const RISK_PRESETS = [0.5, 1, 2, 3];

/** Compact, set-once sizing controls: a clean account field (no spinners) and a
 *  segmented risk-% selector — risk is almost always one of a few values. */
function RiskControls({ risk, update }: { risk: RiskSettings; update: (p: Partial<RiskSettings>) => void }) {
  return (
    <div className="flex flex-wrap items-center gap-2 text-xs text-gray-500">
      <span>Sizing assumes a</span>
      <span className="inline-flex items-center rounded-md border border-white/[0.08] bg-white/[0.03] px-2 py-0.5">
        <span className="mr-0.5 text-gray-500">$</span>
        <input
          type="text"
          inputMode="numeric"
          value={risk.accountSize ? String(risk.accountSize) : ''}
          onChange={(e) => update({ accountSize: Number(e.target.value.replace(/[^0-9]/g, '')) || 0 })}
          placeholder="10000"
          aria-label="Account size"
          className="w-20 bg-transparent font-mono text-gray-100 outline-none"
        />
      </span>
      <span>account, risking</span>
      <span className="inline-flex overflow-hidden rounded-md border border-white/[0.08]">
        {RISK_PRESETS.map((p) => (
          <button
            key={p}
            type="button"
            onClick={() => update({ riskPct: p })}
            className={`px-2 py-0.5 font-mono transition-colors ${
              risk.riskPct === p
                ? 'bg-blue-400/15 text-blue-200'
                : 'text-gray-400 hover:bg-white/[0.05] hover:text-gray-200'
            }`}
          >
            {p}%
          </button>
        ))}
      </span>
      <span>per trade.</span>
    </div>
  );
}

export function RecommendationPanel({ symbol, longSetup, shortSetup, currentPrice, nextEarningsDate }: RecommendationPanelProps) {
  const { settings: risk, update: updateRisk } = useRiskSettings();
  const regime = useMarketRegime().data;
  const summary = longSetup?.recommendation_summary ?? shortSetup?.recommendation_summary;
  const earningsDays = nextEarningsDate ? daysUntil(nextEarningsDate) : null;
  const action = (summary?.action ?? 'NEUTRAL') as TradeSetup['recommended_action'];
  const preferredDirection = recommendationActionDirection(action);

  const preferredSetup =
    preferredDirection === 'long'
      ? longSetup
      : preferredDirection === 'short'
        ? shortSetup
        : undefined;

  const alternativeSetup =
    preferredDirection === 'long'
      ? shortSetup
      : preferredDirection === 'short'
        ? longSetup
        : undefined;

  if (!longSetup && !shortSetup) {
    return null;
  }

  return (
    <section>
      <h2 className="mb-3 text-xs font-medium uppercase tracking-widest text-gray-500">Recommendation</h2>
      <div className="glass p-5 space-y-4">
        <div className="flex flex-wrap items-center gap-4">
          <span className="text-sm font-semibold text-blue-300">{recommendationActionLabel(action)}</span>
          <span className={`text-sm font-semibold ${riskClass(summary?.risk_level ?? null)}`}>
            Risk: {summary?.risk_level ?? '—'}
          </span>
          <span className="text-sm text-gray-300">Composite: {summary?.composite_score?.toFixed(1) ?? '—'}</span>
          <span className="text-xs text-gray-500">{symbol.toUpperCase()}</span>
          <div className="ml-auto">
            <RiskControls risk={risk} update={updateRisk} />
          </div>
        </div>

        <p className="text-xs text-gray-500">Recommended Action is the ticker-level bias. The preferred setup is shown first; the opposite side is available under Alternative scenario.</p>

        {summary?.reasoning && (
          <p className="text-sm text-gray-300">{summary.reasoning}</p>
        )}

        {earningsDays != null && earningsDays >= 0 && (
          earningsDays <= EARNINGS_HORIZON_DAYS ? (
            <p className="rounded border border-amber-500/30 bg-amber-500/10 px-3 py-2 text-[11px] text-amber-300">
              ⚠ Earnings in {earningsDays} day{earningsDays === 1 ? '' : 's'} ({nextEarningsDate}) — inside the ~30-day
              target horizon. A report can gap price through your stop or target; consider waiting or sizing down.
            </p>
          ) : (
            <p className="text-[11px] text-gray-500">Next earnings: {nextEarningsDate} ({earningsDays} days).</p>
          )
        )}

        {preferredDirection !== 'neutral' && preferredSetup ? (
          <div className="space-y-3">
            <SetupCard setup={preferredSetup} action={action} currentPrice={currentPrice} risk={risk} regime={regime} />

            {alternativeSetup && (
              <details className="glass-sm p-3">
                <summary className="cursor-pointer text-xs font-medium text-gray-300">
                  Alternative scenario ({alternativeSetup.direction.toUpperCase()})
                </summary>
                <div className="mt-3">
                  <SetupCard setup={alternativeSetup} action={action} currentPrice={currentPrice} risk={risk} regime={regime} />
                </div>
              </details>
            )}
          </div>
        ) : (
          <div className="grid gap-4 lg:grid-cols-2">
            <SetupCard setup={longSetup} action={action} currentPrice={currentPrice} risk={risk} regime={regime} />
            <SetupCard setup={shortSetup} action={action} currentPrice={currentPrice} risk={risk} regime={regime} />
          </div>
        )}
      </div>
    </section>
  );
}
