import { useMemo, useState } from "react";
import { useI18n } from "@/lib/i18n";
import {
    Calculator,
    ShieldAlert,
    CheckCircle2,
    CircleDashed,
    XCircle,
    Target,
    TrendingDown,
    TrendingUp,
    RefreshCw,
} from "lucide-react";
import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import {
    Accordion,
    AccordionContent,
    AccordionItem,
    AccordionTrigger,
} from "@/components/ui/accordion";
import type { MarketType } from "@/lib/market";
import type { SignalMode, SignalSetup } from "@/types/insight";
import {
    isExecutableSignal,
    isSignalSnapshotCurrent,
    type SignalSnapshot,
} from "@/lib/SignalSnapshot";

function positivePrice(value: unknown): number | null {
    return typeof value === "number" && Number.isFinite(value) && value > 0
        ? value
        : null;
}

/** Preserve small-quote precision; fixed locale defaults can round 0.0016 to 0.002. */
function formatPlanPrice(value: number): string {
    return new Intl.NumberFormat(undefined, {
        useGrouping: false,
        maximumFractionDigits: 8,
    }).format(value);
}

function explainBlocker(
    reason: string,
    t: (key: string, fallback?: string) => string,
): string {
    const normalized = reason.replace(/^BLOCK:\s*/i, "").trim();
    if (/^strategy trigger confirmed$/i.test(normalized)) {
        return t(
            "trade_plan.blocker.strategy_trigger",
            "Strategy trigger has not been confirmed on a closed candle.",
        );
    }
    if (/^structure-aware trade plan valid$/i.test(normalized)) {
        return t(
            "trade_plan.blocker.structure",
            "Trade plan has not passed structure, price-level, or risk/reward validation.",
        );
    }
    if (/^hard stop-distance \/ risk-reward guard$/i.test(normalized)) {
        return t(
            "trade_plan.blocker.risk_guard",
            "Stop-loss distance or risk/reward requirements have not been met.",
        );
    }
    if (/^mtf alignment$/i.test(normalized)) {
        return t(
            "trade_plan.blocker.mtf",
            "Multi-timeframe alignment has not met the selected mode threshold.",
        );
    }
    if (/^Volume aligned$/i.test(normalized)) {
        return t(
            "trade_plan.blocker.volume_aligned",
            "Requirement not met: Volume alignment",
        );
    }
    if (/^Strategy engine confirmation$/i.test(normalized)) {
        return t(
            "trade_plan.blocker.strategy_engine",
            "Requirement not met: Strategy engine confirmation",
        );
    }
    return normalized.startsWith("Belum ") || normalized.startsWith("Tidak ")
        ? normalized
        : `${t("trade_plan.blocker.requirement_prefix", "Requirement not met")}: ${normalized}`;
}

interface Props {
    symbol: string;
    market: MarketType;
    interval: string;
    provider?: string;
    signal: SignalSetup | null;
    enabled: boolean;
    loading?: boolean;
    signalStatus?: "idle" | "loading" | "success" | "empty" | "error";
    signalUpdatedAt?: number | null;
    signalMode: SignalMode;
    signalSnapshot?: SignalSnapshot | null;
    signalDataIntegrity?: boolean;
}

export default function TradePlan({
    symbol,
    market,
    interval,
    provider = "binance",
    signal,
    enabled,
    loading = false,
    signalStatus = "idle",
    signalUpdatedAt = null,
    signalMode,
    signalSnapshot = null,
    signalDataIntegrity = false,
}: Props) {
    const { t } = useI18n();
    const [capital, setCapital] = useState(1000);
    const [riskPct, setRiskPct] = useState(1);
    const [leverage, setLeverage] = useState(1);
    const [sizingOpen, setSizingOpen] = useState(false);

    const isSpot = market === "spot";
    // Only a current, snapshot-validated signal can activate sizing/execution.
    // A matching last-known snapshot may still be shown as explicitly stale
    // reference levels after a same-context refresh failure.
    const snapshotMatchesSignal = isSignalSnapshotCurrent(
        signalSnapshot,
        signal,
        { symbol, market, interval, provider, mode: signalMode },
    );
    const activeSignal = signalDataIntegrity ? signal : null;
    // On a same-context refresh failure, preserve only a snapshot-matched
    // last-known plan as stale preview. Never show stale levels for another
    // symbol, market, timeframe, or mode.
    const staleSignal =
        signalStatus === "error" && snapshotMatchesSignal ? signal : null;
    const displaySignal = activeSignal ?? staleSignal;
    // `direction` is executable state. Candidate fields describe an idea that
    // may be previewed, but must not be represented as an active plan.
    const candidateDirection: "long" | "short" | null =
        displaySignal?.candidate_direction === "long" ||
        displaySignal?.candidate_direction === "short"
            ? displaySignal.candidate_direction
            : displaySignal?.candidate_action === "long" ||
                displaySignal?.candidate_action === "short"
              ? displaySignal.candidate_action
              : displaySignal?.action === "long" ||
                  displaySignal?.action === "short"
                ? displaySignal.action
                : displaySignal?.direction === "long" ||
                    displaySignal?.direction === "short"
                  ? displaySignal.direction
                  : null;
    const nestedTradePlan =
        displaySignal?.trade_plan &&
        typeof displaySignal.trade_plan === "object" &&
        !Array.isArray(displaySignal.trade_plan)
            ? displaySignal.trade_plan
            : null;
    const hasPlan = enabled && isExecutableSignal(activeSignal);
    const previewEntry =
        positivePrice(nestedTradePlan?.entry) ??
        positivePrice(displaySignal?.entry);
    const previewSl =
        positivePrice(nestedTradePlan?.sl) ?? positivePrice(displaySignal?.sl);
    const previewTp =
        positivePrice(nestedTradePlan?.tp) ?? positivePrice(displaySignal?.tp);
    const previewEntryZone =
        nestedTradePlan?.entry_zone &&
        typeof nestedTradePlan.entry_zone === "object" &&
        !Array.isArray(nestedTradePlan.entry_zone)
            ? (nestedTradePlan.entry_zone as Record<string, unknown>)
            : null;
    const previewEntryLow = positivePrice(previewEntryZone?.low);
    const previewEntryHigh = positivePrice(previewEntryZone?.high);
    const previewLevelsOrdered =
        candidateDirection === "long"
            ? previewSl !== null &&
              previewEntry !== null &&
              previewTp !== null &&
              previewSl < previewEntry &&
              previewEntry < previewTp
            : candidateDirection === "short"
              ? previewSl !== null &&
                previewEntry !== null &&
                previewTp !== null &&
                previewTp < previewEntry &&
                previewEntry < previewSl
              : false;
    const previewPlan =
        enabled &&
        !hasPlan &&
        displaySignal !== null &&
        candidateDirection !== null &&
        previewLevelsOrdered
            ? {
                  direction: candidateDirection,
                  entry: previewEntry!,
                  sl: previewSl!,
                  tp: previewTp!,
                  entryZone:
                      previewEntryLow !== null &&
                      previewEntryHigh !== null &&
                      previewEntryLow <= previewEntryHigh
                          ? { low: previewEntryLow, high: previewEntryHigh }
                          : null,
              }
            : null;
    const previewReasons = [
        ...(displaySignal?.policy?.execution_blockers ?? []),
        ...(displaySignal?.policy?.hard_failures ?? []),
        ...(Array.isArray(nestedTradePlan?.warnings)
            ? nestedTradePlan.warnings.filter(
                  (reason): reason is string => typeof reason === "string",
              )
            : []),
        ...(displaySignal?.reason?.filter((reason) =>
            reason.toLowerCase().startsWith("block:"),
        ) ?? []),
    ]
        .map((reason) => explainBlocker(reason, t))
        .filter((reason, index, all) => all.indexOf(reason) === index)
        .slice(0, 3);
    const isLong = hasPlan && activeSignal?.direction === "long";
    const isShort = hasPlan && activeSignal?.direction === "short";
    const snapshotIsCurrent = signalDataIntegrity;

    const plan = useMemo(() => {
        if (
            !hasPlan ||
            !activeSignal?.entry ||
            activeSignal.sl == null ||
            activeSignal.tp == null
        )
            return null;
        const entry = activeSignal.entry;
        const riskPerUnit = Math.abs(entry - activeSignal.sl);
        if (riskPerUnit <= 0) return null;

        const riskBudget = (Math.max(0, capital) * Math.max(0, riskPct)) / 100;
        const quantity = riskBudget / riskPerUnit;
        const notional = quantity * entry;
        const margin = isSpot ? notional : notional / Math.max(1, leverage);
        const rewardPerUnit = Math.abs(activeSignal.tp - entry);
        const potentialProfit = quantity * rewardPerUnit;

        return {
            entry,
            riskBudget,
            quantity,
            notional,
            margin,
            potentialProfit,
        };
    }, [capital, riskPct, leverage, isSpot, hasPlan, activeSignal]);

    if (!enabled) return null;

    const DirectionIcon = isLong ? TrendingUp : isShort ? TrendingDown : Target;
    const isSpotCandidate =
        isSpot &&
        activeSignal?.direction === "neutral" &&
        (activeSignal?.action === "buy" || activeSignal?.action === "sell");

    const directionLabel =
        !signalDataIntegrity && signal
            ? staleSignal
                ? candidateDirection
                    ? `STALE ${candidateDirection.toUpperCase()}`
                    : "STALE"
                : "SYNCING"
            : hasPlan
              ? isSpot
                  ? activeSignal?.action === "buy"
                      ? "BUY"
                      : activeSignal?.action === "sell"
                        ? "SELL"
                        : "NEUTRAL"
                  : isLong
                    ? "LONG"
                    : isShort
                      ? "SHORT"
                      : "NEUTRAL"
              : isSpotCandidate
                ? activeSignal?.action === "buy"
                    ? "BUY CANDIDATE"
                    : "SELL CANDIDATE"
                : candidateDirection
                  ? `${candidateDirection.toUpperCase()} CANDIDATE`
                  : "WAITING";

    return (
        <Card className="mt-0 flex h-auto flex-col overflow-hidden border-border/80 bg-background/70 py-0 shadow-sm shadow-primary/5">
            <CardHeader className="border-b border-border/70 bg-muted/[0.12] px-3.5 py-4 sm:px-5 sm:py-4">
                <div className="flex flex-wrap items-center justify-between gap-3">
                    <div className="flex min-w-0 items-center gap-3">
                        <div className="flex size-9 shrink-0 items-center justify-center rounded-xl border border-primary/20 bg-primary/5">
                            <Calculator className="size-4 text-primary" />
                        </div>
                        <div className="min-w-0">
                            <div className="flex items-center gap-2">
                                <div className="text-sm font-semibold tracking-tight">
                                    {t("trade_plan.title", "Trade Plan")}
                                </div>
                                <span className="rounded-md bg-muted px-1.5 py-0.5 text-[9px] font-bold uppercase tracking-[0.12em] text-muted-foreground">
                                    {signalMode}
                                </span>
                            </div>
                            <div className="mt-0.5 truncate text-[11px] text-muted-foreground">
                                {symbol} ·{" "}
                                {market === "futures"
                                    ? t("trade_plan.futures", "Futures")
                                    : t("trade_plan.spot", "Spot")}{" "}
                                · {interval}
                                {signalUpdatedAt && !loading && (
                                    <span className="ml-1.5">
                                        · {t("trade_plan.updated", "Updated")}{" "}
                                        {formatFreshness(signalUpdatedAt)}
                                    </span>
                                )}
                                {signalSnapshot &&
                                    !loading &&
                                    !snapshotIsCurrent && (
                                        <span className="ml-1.5 text-warning">
                                            · {t("trade_plan.stale", "Stale")}
                                        </span>
                                    )}
                            </div>
                        </div>
                    </div>

                    {loading ? (
                        <div
                            className="h-7 w-[88px] animate-pulse rounded-full bg-muted"
                            aria-label={t(
                                "trade_plan.loading_direction",
                                "Loading signal direction",
                            )}
                            role="status"
                        />
                    ) : (
                        <div className="flex items-center gap-2">
                            <span className="hidden text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground sm:inline">
                                {hasPlan
                                    ? t("trade_plan.ready", "Execution ready")
                                    : t("trade_plan.waiting", "Waiting")}
                            </span>
                            <Badge
                                variant={
                                    !signalDataIntegrity && signal
                                        ? "secondary"
                                        : !hasPlan && isSpotCandidate
                                          ? "secondary"
                                          : isLong ||
                                              activeSignal?.action === "buy"
                                            ? "default"
                                            : isShort ||
                                                activeSignal?.action === "sell"
                                              ? "destructive"
                                              : "secondary"
                                }
                                className="px-2.5"
                            >
                                <DirectionIcon className="mr-1 size-3" />
                                {directionLabel}
                            </Badge>
                        </div>
                    )}
                </div>
            </CardHeader>

            <CardContent className="relative flex-1 space-y-4 px-3.5 pt-4 pb-6 sm:space-y-5 sm:px-5 sm:pt-5 sm:pb-7">
                {loading && (hasPlan || previewPlan) && (
                    <div
                        className="pointer-events-auto absolute inset-0 z-10 flex items-start justify-center rounded-2xl bg-background/55 px-4 pt-4 backdrop-blur-[1px]"
                        role="status"
                        aria-live="polite"
                        aria-label={t(
                            "trade_plan.refreshing",
                            "Refreshing trade plan",
                        )}
                    >
                        <div className="inline-flex items-center gap-2 rounded-full border border-border/70 bg-card/95 px-3 py-1.5 text-[10px] font-semibold text-muted-foreground shadow-sm">
                            <RefreshCw
                                className="size-3 animate-spin"
                                aria-hidden="true"
                            />
                            {t(
                                "trade_plan.refreshing",
                                "Refreshing trade plan…",
                            )}
                        </div>
                    </div>
                )}

                {loading && !hasPlan && !previewPlan ? (
                    <TradePlanSkeleton />
                ) : previewPlan ? (
                    <div className="space-y-4">
                        <div className="flex flex-wrap items-start justify-between gap-3 rounded-xl border border-warning/30 bg-warning/5 px-3.5 py-3 sm:px-4 sm:py-3.5">
                            <div className="min-w-0">
                                <div className="flex items-center gap-2">
                                    <span className="size-1.5 rounded-full bg-warning" />
                                    <div className="text-xs font-semibold text-foreground">
                                        {staleSignal
                                            ? `${t("trade_plan.last_known", "Last known")} ${previewPlan.direction.toUpperCase()} · ${t("trade_plan.stale_preview", "stale preview")}`
                                            : `${previewPlan.direction.toUpperCase()} ${t("trade_plan.candidate_plan_preview", "candidate · plan preview")}`}
                                    </div>
                                </div>
                                <p className="mt-1 text-[11px] leading-5 text-muted-foreground">
                                    {staleSignal
                                        ? t(
                                              "trade_plan.stale_description",
                                              "The latest refresh failed. These levels match the current context and are shown for reference only.",
                                          )
                                        : t(
                                              "trade_plan.preview_description",
                                              "Structural levels are available, but execution is still blocked until every required gate passes.",
                                          )}
                                </p>
                            </div>
                            <Badge
                                variant="outline"
                                className="border-warning/40 bg-warning/5 text-warning"
                            >
                                {staleSignal
                                    ? t("trade_plan.stale", "STALE")
                                    : t("trade_plan.blocked", "BLOCKED")}
                            </Badge>
                        </div>

                        <div className="grid gap-2 sm:grid-cols-3">
                            <ExecutionLevel
                                label={
                                    staleSignal
                                        ? "Last Entry"
                                        : "Entry · Preview"
                                }
                                value={previewPlan.entry}
                                tone="neutral"
                            />
                            <ExecutionLevel
                                label={
                                    staleSignal
                                        ? "Last Invalidation / SL"
                                        : "Invalidation / SL · Preview"
                                }
                                value={previewPlan.sl}
                                tone="risk"
                            />
                            <ExecutionLevel
                                label={
                                    staleSignal
                                        ? "Last Target / TP"
                                        : "Target / TP · Preview"
                                }
                                value={previewPlan.tp}
                                tone="reward"
                            />
                        </div>

                        {previewPlan.entryZone && (
                            <div className="flex items-center justify-between gap-3 rounded-xl border border-border/70 bg-muted/20 px-3.5 py-3">
                                <div>
                                    <div className="text-[9px] font-bold uppercase tracking-[0.14em] text-muted-foreground">
                                        {staleSignal
                                            ? t(
                                                  "trade_plan.last_entry_zone",
                                                  "Last Entry Zone",
                                              )
                                            : t(
                                                  "trade_plan.entry_zone_preview",
                                                  "Entry Zone · Preview",
                                              )}
                                    </div>
                                    <div className="mt-1 font-mono text-sm font-bold tracking-tight">
                                        {formatPlanPrice(
                                            previewPlan.entryZone.low,
                                        )}{" "}
                                        —{" "}
                                        {formatPlanPrice(
                                            previewPlan.entryZone.high,
                                        )}
                                    </div>
                                </div>
                                <Target className="size-4 shrink-0 text-muted-foreground" />
                            </div>
                        )}

                        {previewReasons.length > 0 && (
                            <div className="rounded-xl border border-border/70 bg-muted/10 px-3.5 py-3">
                                <div className="text-[9px] font-bold uppercase tracking-[0.14em] text-muted-foreground">
                                    Why execution is blocked
                                </div>
                                <ul className="mt-2 space-y-1.5 text-[10px] leading-4 text-muted-foreground">
                                    {previewReasons.map((reason) => (
                                        <li key={reason} className="flex gap-2">
                                            <XCircle className="mt-0.5 size-3 shrink-0 text-warning" />
                                            <span>{reason}</span>
                                        </li>
                                    ))}
                                </ul>
                            </div>
                        )}
                    </div>
                ) : !hasPlan ? (
                    <div className="flex items-start gap-3 rounded-xl border border-border/70 bg-muted/15 px-4 py-4">
                        <div className="flex size-8 shrink-0 items-center justify-center rounded-lg bg-warning/10 text-warning">
                            <CircleDashed className="size-4" />
                        </div>
                        <div className="min-w-0">
                            <div className="text-xs font-semibold text-foreground">
                                {signal && !signalDataIntegrity
                                    ? t(
                                          "trade_plan.waiting_sync",
                                          "Waiting for signal synchronization",
                                      )
                                    : isSpotCandidate
                                      ? `${activeSignal?.action === "buy" ? "BUY" : "SELL"} ${t("trade_plan.candidate_not_plan", "candidate is not yet a trade plan")}`
                                      : candidateDirection
                                        ? `${candidateDirection.toUpperCase()} ${t("trade_plan.candidate_not_plan", "candidate is not yet a trade plan")}`
                                        : t(
                                              "trade_plan.not_active",
                                              "Trade plan is not active",
                                          )}
                            </div>
                            <div className="mt-1 text-[11px] leading-5 text-muted-foreground">
                                {signal && !signalDataIntegrity
                                    ? t(
                                          "trade_plan.waiting_consistency",
                                          "Levels are held until the signal snapshot, mode, timeframe, and Entry/SL/TP context are consistent again.",
                                      )
                                    : isSpotCandidate || candidateDirection
                                      ? t(
                                            "trade_plan.candidate_description",
                                            "A candidate direction was detected, but executable levels are not available yet. Review MTF, policy gates, and blockers in Signal Engine.",
                                        )
                                      : t(
                                            "trade_plan.incomplete_description",
                                            "Entry, invalidation, and target are incomplete because the signal is still waiting for required conditions.",
                                        )}
                            </div>
                        </div>
                    </div>
                ) : (
                    <>
                        <section aria-labelledby="execution-levels-title">
                            <div className="mb-2 flex items-end justify-between gap-3">
                                <div>
                                    <div
                                        id="execution-levels-title"
                                        className="text-[10px] font-bold uppercase tracking-[0.16em] text-muted-foreground"
                                    >
                                        Execution levels
                                    </div>
                                    <div className="mt-0.5 text-[11px] text-muted-foreground">
                                        The active setup in one glance.
                                    </div>
                                </div>
                                {activeSignal!.risk_reward?.ratio != null && (
                                    <div className="rounded-lg border border-primary/20 bg-primary/5 px-2.5 py-1.5 text-right">
                                        <div className="text-[8px] font-bold uppercase tracking-[0.14em] text-muted-foreground">
                                            R:R
                                        </div>
                                        <div className="font-mono text-sm font-bold text-primary">
                                            {activeSignal!.risk_reward.ratio.toLocaleString(
                                                undefined,
                                                { maximumFractionDigits: 2 },
                                            )}
                                            R
                                        </div>
                                    </div>
                                )}
                            </div>

                            <div className="grid gap-2 sm:grid-cols-3">
                                <ExecutionLevel
                                    label="Entry"
                                    value={activeSignal!.entry!}
                                    tone="neutral"
                                    emphasis
                                />
                                <ExecutionLevel
                                    label="Invalidation / SL"
                                    value={activeSignal!.sl!}
                                    tone="risk"
                                    emphasis
                                />
                                <ExecutionLevel
                                    label="Target / TP"
                                    value={activeSignal!.tp!}
                                    tone="reward"
                                    emphasis
                                />
                            </div>
                        </section>

                        <ExecutionContext
                            signal={activeSignal}
                            isLong={isLong}
                            isShort={isShort}
                        />

                        <section
                            className="overflow-hidden rounded-2xl border border-border/70 bg-muted/10"
                            aria-labelledby="position-sizing-title"
                        >
                            <button
                                type="button"
                                onClick={() => setSizingOpen((open) => !open)}
                                className="flex w-full items-center justify-between gap-3 px-4 py-3 text-left transition-colors hover:bg-muted/20"
                                aria-expanded={sizingOpen}
                                aria-controls="position-sizing-content"
                            >
                                <span className="flex min-w-0 items-center gap-2.5">
                                    <span className="flex size-7 shrink-0 items-center justify-center rounded-lg border border-border bg-background">
                                        <Calculator className="size-3.5 text-primary" />
                                    </span>
                                    <span className="min-w-0">
                                        <span
                                            id="position-sizing-title"
                                            className="block text-xs font-semibold"
                                        >
                                            Position sizing
                                        </span>
                                        <span className="mt-0.5 block truncate text-[10px] text-muted-foreground">
                                            Capital, risk per trade, and
                                            leverage assumptions
                                        </span>
                                    </span>
                                </span>
                                <span className="shrink-0 text-[10px] font-semibold text-muted-foreground">
                                    {sizingOpen ? "Hide" : "Adjust"}
                                </span>
                            </button>

                            {sizingOpen && (
                                <div
                                    id="position-sizing-content"
                                    className="space-y-3 border-t border-border/70 px-4 py-4"
                                >
                                    <div className="grid gap-3 sm:grid-cols-4">
                                        <NumberInput
                                            label="Capital"
                                            hint={t(
                                                "trade_plan.reference_capital",
                                                "Reference capital",
                                            )}
                                            value={capital}
                                            onChange={setCapital}
                                            step={100}
                                        />
                                        <NumberInput
                                            label="Risk / Trade %"
                                            hint={t(
                                                "trade_plan.risk_percent_hint",
                                                "Percentage of capital at risk",
                                            )}
                                            value={riskPct}
                                            onChange={setRiskPct}
                                            step={0.1}
                                        />
                                        {!isSpot ? (
                                            <NumberInput
                                                label="Leverage"
                                                hint={t(
                                                    "trade_plan.leverage_hint",
                                                    "Notional multiplier; not a risk-budget multiplier",
                                                )}
                                                value={leverage}
                                                onChange={setLeverage}
                                                step={1}
                                            />
                                        ) : (
                                            <div
                                                className="hidden sm:block"
                                                aria-hidden="true"
                                            />
                                        )}
                                        <PlanMetric
                                            label="Risk / Reward"
                                            value={
                                                activeSignal!.risk_reward
                                                    ?.ratio ?? 0
                                            }
                                            suffix="R"
                                            hint="Reward ÷ risk distance"
                                        />
                                    </div>

                                    {plan && (
                                        <>
                                            <div className="grid gap-2 sm:grid-cols-4">
                                                <PlanMetric
                                                    label="Risk Budget"
                                                    value={plan.riskBudget}
                                                    hint={t(
                                                        "trade_plan.risk_budget_hint",
                                                        "Nominal limit from risk %",
                                                    )}
                                                />
                                                <PlanMetric
                                                    label="Position Size"
                                                    value={plan.quantity}
                                                    hint={t(
                                                        "trade_plan.position_size_hint",
                                                        "Quantity based on SL distance",
                                                    )}
                                                />
                                                <PlanMetric
                                                    label="Notional"
                                                    value={plan.notional}
                                                    hint={t(
                                                        "trade_plan.notional_hint",
                                                        "Quantity × entry",
                                                    )}
                                                />
                                                <PlanMetric
                                                    label={
                                                        isSpot
                                                            ? "Potential Profit"
                                                            : "Est. Margin"
                                                    }
                                                    value={
                                                        isSpot
                                                            ? plan.potentialProfit
                                                            : plan.margin
                                                    }
                                                    hint={
                                                        isSpot
                                                            ? "Reward distance × quantity"
                                                            : "Notional ÷ leverage"
                                                    }
                                                />
                                            </div>
                                            <div className="grid gap-2 sm:grid-cols-3">
                                                <SizingStep
                                                    number="1"
                                                    title="Risk budget"
                                                    detail={`${formatNumber(plan.riskBudget)} ${t("trade_plan.from_capital_risk", "from capital × risk %")}`}
                                                />
                                                <SizingStep
                                                    number="2"
                                                    title="Position size"
                                                    detail={`${formatNumber(plan.quantity)} ${t("trade_plan.based_on_entry_sl", "based on entry → SL distance")}`}
                                                />
                                                <SizingStep
                                                    number="3"
                                                    title={
                                                        isSpot
                                                            ? "Notional"
                                                            : "Margin"
                                                    }
                                                    detail={
                                                        isSpot
                                                            ? `${formatNumber(plan.notional)} ${t("trade_plan.total_position_value", "total position value")}`
                                                            : `${formatNumber(plan.margin)} ${t("trade_plan.estimated_margin_at", "estimated margin at leverage")} ${formatNumber(leverage)}`
                                                    }
                                                />
                                            </div>
                                            <div className="flex items-start gap-2 rounded-xl border border-primary/20 bg-primary/5 px-3 py-2.5 text-[10px] leading-4 text-muted-foreground">
                                                <Calculator className="mt-0.5 size-3.5 shrink-0 text-primary" />
                                                <span>
                                                    {t(
                                                        "trade_plan.risk_budget_explainer",
                                                        "Risk budget is based on capital × risk per trade. For futures, leverage changes required margin/notional, while position size remains determined by risk budget and Entry → SL distance.",
                                                    )}
                                                </span>
                                            </div>
                                        </>
                                    )}
                                </div>
                            )}
                        </section>

                        <div className="flex items-start gap-2 border-t border-border/60 pt-3 text-[10px] leading-4 text-muted-foreground">
                            <ShieldAlert className="mt-0.5 size-3.5 shrink-0" />
                            <span>
                                {t(
                                    "trade_plan.invalidation_sizing_explainer",
                                    "Invalidation is the setup cancellation level, not a guarantee that price will stop exactly there. Position size is calculated from the risk you set.",
                                )}
                            </span>
                        </div>
                    </>
                )}

                {activeSignal?.requirements && (
                    <TradeRequirements
                        signal={activeSignal}
                        isSpot={isSpot}
                        isLong={isLong}
                        isShort={isShort}
                    />
                )}
            </CardContent>
        </Card>
    );
}

function ExecutionContext({
    signal,
    isLong,
    isShort,
}: {
    signal: SignalSetup | null;
    isLong: boolean;
    isShort: boolean;
}) {
    const { t } = useI18n();
    if (!signal) return null;

    const entry = signal.entry;
    const sl = signal.sl;
    const tp = signal.tp;
    if (entry == null || sl == null || tp == null) return null;

    const riskDistance = Math.abs(entry - sl);
    const rewardDistance = Math.abs(tp - entry);
    const ratio =
        signal.risk_reward?.ratio ??
        (riskDistance > 0 ? rewardDistance / riskDistance : null);
    const tradePlan =
        signal.trade_plan &&
        typeof signal.trade_plan === "object" &&
        !Array.isArray(signal.trade_plan)
            ? signal.trade_plan
            : null;
    const atr = positivePrice(tradePlan?.atr);
    const stopDistanceAtr = atr !== null && atr > 0 ? riskDistance / atr : null;
    const targetDistanceAtr =
        positivePrice(tradePlan?.target_distance_atr) ??
        (atr !== null && atr > 0 ? rewardDistance / atr : null);
    const targetBasis =
        typeof tradePlan?.target_basis === "string"
            ? tradePlan.target_basis.replaceAll("_", " ")
            : null;
    const direction = isLong ? "LONG" : isShort ? "SHORT" : "SETUP";

    return (
        <div className="grid gap-2 sm:grid-cols-4">
            <ContextMetric
                label="Risk distance"
                value={riskDistance.toLocaleString(undefined, {
                    maximumFractionDigits: 8,
                })}
                hint={`Entry → ${t("trade_plan.invalidation", "invalidation")}`}
            />
            <ContextMetric
                label="Reward distance"
                value={rewardDistance.toLocaleString(undefined, {
                    maximumFractionDigits: 8,
                })}
                hint={`Entry → ${t("trade_plan.target", "target")}`}
            />
            <ContextMetric
                label="Target basis"
                value={targetBasis ? targetBasis : "—"}
                hint={`${direction} setup`}
            />
            <ContextMetric
                label="Structure"
                value={
                    stopDistanceAtr !== null && targetDistanceAtr !== null
                        ? `${stopDistanceAtr.toFixed(1)} / ${targetDistanceAtr.toFixed(1)} ATR`
                        : "—"
                }
                hint={
                    ratio != null
                        ? `${ratio.toFixed(2)}R risk/reward`
                        : "Risk/reward unavailable"
                }
            />
        </div>
    );
}

function ContextMetric({
    label,
    value,
    hint,
}: {
    label: string;
    value: string;
    hint: string;
}) {
    return (
        <div className="rounded-xl border border-border/70 bg-muted/5 px-3 py-2.5">
            <div className="text-[9px] font-bold uppercase tracking-[0.12em] text-muted-foreground">
                {label}
            </div>
            <div className="mt-1 truncate font-mono text-xs font-semibold tracking-tight">
                {value}
            </div>
            <div className="mt-0.5 truncate text-[9px] leading-4 text-muted-foreground">
                {hint}
            </div>
        </div>
    );
}

function ExecutionLevel({
    label,
    value,
    tone,
    emphasis = false,
}: {
    label: string;
    value: number;
    tone: "neutral" | "risk" | "reward";
    emphasis?: boolean;
}) {
    const accent =
        tone === "risk"
            ? "text-destructive"
            : tone === "reward"
              ? "text-success"
              : "text-primary";
    const border =
        tone === "risk"
            ? "border-destructive/20"
            : tone === "reward"
              ? "border-success/20"
              : "border-primary/20";
    return (
        <div
            className={`rounded-xl border ${border} bg-background px-3.5 py-3`}
        >
            <div className="flex items-center justify-between gap-2">
                <div className="text-[9px] font-bold uppercase tracking-[0.12em] text-muted-foreground">
                    {label}
                </div>
                <div
                    className={`size-1.5 rounded-full ${tone === "risk" ? "bg-destructive" : tone === "reward" ? "bg-success" : "bg-primary"}`}
                />
            </div>
            <div
                className={`mt-1.5 font-mono tracking-tight ${emphasis ? "text-base font-bold" : "text-sm font-semibold"} ${accent}`}
            >
                {formatPlanPrice(value)}
            </div>
        </div>
    );
}

function TradeRequirements({
    signal,
    isSpot,
    isLong,
    isShort,
}: {
    signal: SignalSetup;
    isSpot: boolean;
    isLong: boolean;
    isShort: boolean;
}) {
    const { t } = useI18n();
    const requirements = signal.requirements;
    if (!requirements) return null;

    const titleFor = (side: "long" | "short") =>
        isSpot
            ? side === "long"
                ? "BUY"
                : "SELL"
            : side === "long"
              ? "LONG"
              : "SHORT";

    const totals = (["long", "short"] as const).map((side) => {
        const items = requirements[side];
        return {
            side,
            passed: items.filter((item) => item.met).length,
            total: items.length,
        };
    });

    const activeSide = isLong ? "long" : isShort ? "short" : null;

    return (
        <Accordion
            type="single"
            collapsible
            className="rounded-2xl border border-border bg-muted/10 px-3"
        >
            <AccordionItem value="signal-requirements" className="border-0">
                <AccordionTrigger className="py-3 hover:no-underline">
                    <div className="min-w-0 flex-1">
                        <div className="flex flex-wrap items-center gap-2">
                            <div className="text-xs font-semibold">
                                {t(
                                    "trade_plan.requirements",
                                    "Signal requirements",
                                )}
                            </div>
                            <Badge variant="outline" className="text-[9px]">
                                {signal.signal_mode === "balanced"
                                    ? "Balanced"
                                    : signal.signal_mode === "flexible"
                                      ? "Flexible"
                                      : "Strict"}
                            </Badge>
                        </div>
                        <div className="mt-0.5 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-[10px] font-normal text-muted-foreground">
                            <span>
                                LONG {totals[0].passed}/{totals[0].total}
                            </span>
                            <span>·</span>
                            <span>
                                SHORT {totals[1].passed}/{totals[1].total}
                            </span>
                            <span>·</span>
                            <span>
                                {t(
                                    "trade_plan.requirement_legend",
                                    "Green = met · red = not met",
                                )}
                            </span>
                        </div>
                    </div>
                    <Badge variant="outline" className="shrink-0 text-[10px]">
                        {activeSide
                            ? `${t("trade_plan.active", "Active")}: ${titleFor(activeSide)}`
                            : t("trade_plan.not_active", "Not active")}
                    </Badge>
                </AccordionTrigger>

                <AccordionContent className="pt-1">
                    <div className="grid gap-3 md:grid-cols-2">
                        {(["long", "short"] as const).map((side) => {
                            const items = requirements[side];
                            const passed = items.filter(
                                (item) => item.met,
                            ).length;
                            const hardFailed = items.filter(
                                (item) => item.hard && !item.met,
                            ).length;
                            const active = side === activeSide;

                            return (
                                <div
                                    key={side}
                                    className={`rounded-xl border p-3 ${
                                        active
                                            ? "border-primary/50 bg-primary/5"
                                            : "border-border bg-background/60"
                                    }`}
                                >
                                    <div className="mb-2 flex items-center justify-between gap-2">
                                        <div className="text-xs font-semibold">
                                            {titleFor(side)}
                                        </div>
                                        <span
                                            className={`text-[10px] font-semibold ${
                                                hardFailed > 0
                                                    ? "text-destructive"
                                                    : passed === items.length
                                                      ? "text-success"
                                                      : "text-warning"
                                            }`}
                                        >
                                            {passed}/{items.length}{" "}
                                            {t("trade_plan.met", "met")}
                                        </span>
                                    </div>

                                    <div className="space-y-1.5">
                                        {items.map((item) => (
                                            <RequirementRow
                                                key={item.key}
                                                item={item}
                                            />
                                        ))}
                                    </div>
                                </div>
                            );
                        })}
                    </div>
                </AccordionContent>
            </AccordionItem>
        </Accordion>
    );
}

function RequirementRow({
    item,
}: {
    item: NonNullable<SignalSetup["requirements"]>["long"][number];
}) {
    const { t } = useI18n();
    const Icon = item.met ? CheckCircle2 : item.hard ? XCircle : CircleDashed;
    const iconClass = item.met
        ? "text-success"
        : item.hard
          ? "text-destructive"
          : "text-warning";

    const displayValue =
        item.value === null || item.value === undefined
            ? "—"
            : typeof item.value === "number"
              ? item.value.toLocaleString(undefined, {
                    maximumFractionDigits: 2,
                })
              : item.value;

    return (
        <div className="flex items-start gap-2 rounded-lg border border-border/60 bg-background p-2">
            <Icon className={`mt-0.5 size-3.5 shrink-0 ${iconClass}`} />
            <div className="min-w-0 flex-1">
                <div className="flex items-start justify-between gap-2">
                    <span className="text-[11px] font-medium leading-4">
                        {item.label}
                    </span>
                    {item.hard && (
                        <span className="shrink-0 text-[9px] font-bold uppercase tracking-wider text-muted-foreground">
                            {t("trade_plan.required", "Required")}
                        </span>
                    )}
                </div>
                <div className="mt-0.5 text-[9px] text-muted-foreground">
                    {item.detail} · {t("trade_plan.actual", "actual")}:{" "}
                    <span className="font-mono">{displayValue}</span> · target:{" "}
                    <span className="font-mono">{item.target}</span>
                </div>
            </div>
        </div>
    );
}

function TradePlanSkeleton() {
    const { t } = useI18n();

    return (
        <div
            className="min-h-[260px] space-y-4 animate-pulse sm:min-h-[320px]"
            aria-label={t("trade_plan.calculating", "Calculating trade plan")}
            aria-busy="true"
        >
            <div className="grid gap-3 sm:grid-cols-3">
                {["entry", "sl", "tp"].map((item) => (
                    <div
                        key={item}
                        className="rounded-xl border border-border/60 p-3"
                    >
                        <div className="h-2.5 w-20 rounded bg-muted" />
                        <div className="mt-2 h-5 w-28 rounded bg-muted" />
                    </div>
                ))}
            </div>

            <div className="rounded-xl border border-border/60 bg-muted/20 p-3">
                <div className="h-2.5 w-24 rounded bg-muted" />
                <div className="mt-2 h-4 w-48 rounded bg-muted" />
            </div>

            <div className="grid gap-3 sm:grid-cols-4">
                {["capital", "risk", "leverage", "rr"].map((item) => (
                    <div
                        key={item}
                        className="rounded-xl border border-border/60 p-3"
                    >
                        <div className="h-2.5 w-24 rounded bg-muted" />
                        <div className="mt-2 h-8 w-full rounded-md bg-muted" />
                    </div>
                ))}
            </div>

            <div className="grid gap-3 sm:grid-cols-4">
                {["risk-budget", "position", "margin", "profit"].map((item) => (
                    <div
                        key={item}
                        className="rounded-xl border border-border/60 p-3"
                    >
                        <div className="h-2.5 w-20 rounded bg-muted" />
                        <div className="mt-2 h-5 w-24 rounded bg-muted" />
                    </div>
                ))}
            </div>

            <div className="flex items-center gap-2 text-xs text-muted-foreground">
                <span className="size-2 rounded-full bg-muted-foreground/50" />
                {t(
                    "trade_plan.recalculating",
                    "Recalculating the trade plan for the new signal mode…",
                )}
            </div>
        </div>
    );
}

function PlanMetric({
    label,
    value,
    suffix,
    hint,
}: {
    label: string;
    value: number;
    suffix?: string;
    hint?: string;
}) {
    return (
        <div className="rounded-xl border border-border bg-background p-3">
            <div className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
                {label}
            </div>
            <div className="mt-1 font-mono text-sm font-bold">
                {value.toLocaleString(undefined, { maximumFractionDigits: 8 })}
                {suffix ? ` ${suffix}` : ""}
            </div>
            {hint && (
                <div className="mt-1 text-[9px] leading-3.5 text-muted-foreground">
                    {hint}
                </div>
            )}
        </div>
    );
}

function NumberInput({
    label,
    hint,
    value,
    onChange,
    step,
}: {
    label: string;
    hint?: string;
    value: number;
    onChange: (value: number) => void;
    step: number;
}) {
    return (
        <label className="block rounded-xl border border-border bg-background p-3">
            <span className="text-[10px] font-semibold uppercase tracking-wider text-muted-foreground">
                {label}
            </span>
            {hint && (
                <span className="mt-0.5 block text-[9px] leading-3.5 text-muted-foreground">
                    {hint}
                </span>
            )}
            <input
                type="number"
                value={value}
                min={0}
                step={step}
                onChange={(event) => onChange(Number(event.target.value))}
                className="mt-1 h-8 w-full rounded-lg border border-border bg-muted/20 px-2.5 text-xs font-semibold outline-none focus:border-primary"
            />
        </label>
    );
}

function SizingStep({
    number,
    title,
    detail,
}: {
    number: string;
    title: string;
    detail: string;
}) {
    return (
        <div className="rounded-xl border border-border/70 bg-background/70 p-2.5">
            <div className="flex items-center gap-2">
                <span className="flex size-5 items-center justify-center rounded-full bg-muted text-[9px] font-bold">
                    {number}
                </span>
                <span className="text-[10px] font-semibold">{title}</span>
            </div>
            <div className="mt-1 pl-7 text-[9px] leading-3.5 text-muted-foreground">
                {detail}
            </div>
        </div>
    );
}

function formatNumber(value: number): string {
    return value.toLocaleString(undefined, { maximumFractionDigits: 8 });
}

function formatFreshness(timestamp: number): string {
    const seconds = Math.max(0, Math.floor((Date.now() - timestamp) / 1000));
    if (seconds < 10) return "just now";
    if (seconds < 60) return `${seconds}s ago`;
    const minutes = Math.floor(seconds / 60);
    if (minutes < 60) return `${minutes}m ago`;
    return `${Math.floor(minutes / 60)}h ago`;
}
