"use client";

import { useEffect, useState, useCallback, useRef } from "react";
import { fetchAPI, postAPI } from "@/lib/api";
import type { LatestResult, SectorData, IndexOverview, OpsStatusResponse, StrategyBoard } from "@/lib/api";
import MarketTemp from "@/components/market-temp";
import SectorHeatmap from "@/components/sector-heatmap";
import { useWebSocket } from "@/hooks/use-websocket";
import { useAuth } from "@/hooks/use-auth";
import { ThemeToggle } from "@/components/theme-toggle";

interface ScanStatus {
  is_trading: boolean;
  scan_mode: string;
  description: string;
}

const SCAN_TIMEOUT_MS = 120_000; // 扫描超时：120秒后自动刷新数据

export default function DashboardPage() {
  const { user } = useAuth();
  const [data, setData] = useState<LatestResult | null>(null);
  const [sectors, setSectors] = useState<SectorData[]>([]);
  const [scanStatus, setScanStatus] = useState<ScanStatus | null>(null);
  const [loading, setLoading] = useState(true);
  const [refreshing, setRefreshing] = useState(false);
  const [refreshResult, setRefreshResult] = useState<string | null>(null);
  const [indices, setIndices] = useState<IndexOverview[]>([]);
  const [strategyBoard, setStrategyBoard] = useState<StrategyBoard | null>(null);
  const [opsStatus, setOpsStatus] = useState<OpsStatusResponse | null>(null);
  const [opsRunning, setOpsRunning] = useState<string | null>(null);
  const scanTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);

  const loadData = useCallback(async () => {
    try {
      const [latest, sectorData, status, overview, board, ops] = await Promise.all([
        fetchAPI<LatestResult>("/api/recommendations/latest"),
        fetchAPI<SectorData[]>("/api/sectors/hot?limit=8"),
        fetchAPI<ScanStatus>("/api/recommendations/status"),
        fetchAPI<IndexOverview[]>("/api/market/overview").catch(() => []),
        fetchAPI<StrategyBoard>("/api/market/strategy-board").catch(() => null),
        fetchAPI<OpsStatusResponse>("/api/market/ops-status").catch(() => null),
      ]);
      setData(latest);
      setSectors(sectorData);
      setScanStatus(status);
      setIndices(overview);
      setStrategyBoard(board);
      setOpsStatus(ops);
    } catch (e) {
      console.error("加载数据失败:", e);
    } finally {
      setLoading(false);
    }
  }, []);

  // 清除扫描超时计时器
  const clearScanTimeout = useCallback(() => {
    if (scanTimeoutRef.current) {
      clearTimeout(scanTimeoutRef.current);
      scanTimeoutRef.current = null;
    }
  }, []);

  useEffect(() => {
    loadData();
  }, [loadData]);

  useWebSocket(
    useCallback((msg: { type: string; count?: number; scan_mode?: string; message?: string }) => {
      clearScanTimeout();
      if (msg.type === "scan_update") {
        const modeLabel = msg.scan_mode === "intraday" ? "盘中实时" : "盘后";
        setRefreshResult(`${modeLabel}扫描完成，发现 ${msg.count ?? 0} 只股票`);
        setRefreshing(false);
        loadData();
        setTimeout(() => setRefreshResult(null), 5000);
      } else if (msg.type === "scan_error") {
        setRefreshResult("扫描失败，请重试");
        setRefreshing(false);
        setTimeout(() => setRefreshResult(null), 5000);
      } else {
        // 其他消息类型（如 llm_analysis_ready），刷新数据
        loadData();
      }
    }, [loadData, clearScanTimeout]),
    ["scan_update", "scan_error", "llm_analysis_ready", "sector_scan_ready", "scan_complete"]
  );

  const handleRefresh = async () => {
    setRefreshing(true);
    setRefreshResult(null);
    try {
      const res = await postAPI<{
        status: string;
        message?: string;
        is_trading: boolean;
      }>("/api/recommendations/refresh?scan_session=manual");

      if (res.status === "already_running") {
        setRefreshResult(res.message || "扫描正在执行中，请稍候");
        // 保持 refreshing，等待 WS 推送完成
      } else if (res.status === "scanning") {
        setRefreshResult("扫描已启动，完成后自动刷新...");
        // 保持 refreshing，等待 WS 推送
      }

      // 设置超时：如果 120 秒内没收到 WebSocket 消息，自动停止加载状态并刷新数据
      scanTimeoutRef.current = setTimeout(() => {
        setRefreshResult("扫描超时，已自动刷新数据");
        setRefreshing(false);
        loadData();
        setTimeout(() => setRefreshResult(null), 5000);
      }, SCAN_TIMEOUT_MS);
    } catch (e) {
      console.error("触发扫描失败:", e);
      setRefreshResult("触发扫描失败，请重试");
      setRefreshing(false);
      setTimeout(() => setRefreshResult(null), 5000);
    }
  };

  const handleAdminAction = async (action: "update_tracking" | "generate_strategy_board" | "generate_strategy_iteration") => {
    setOpsRunning(action);
    setRefreshResult(null);
    try {
      if (action === "update_tracking") {
        const result = await postAPI<{ tracked?: number; win_rate?: number; avg_return?: number }>("/api/recommendations/update-tracking");
        setRefreshResult(`跟踪已更新，样本 ${result.tracked ?? 0}，胜率 ${(result.win_rate ?? 0).toFixed(1)}%`);
      } else if (action === "generate_strategy_board") {
        await postAPI("/api/market/generate-strategy-board");
        setRefreshResult("策略板已生成");
      } else {
        await postAPI("/api/market/generate-strategy-iteration");
        setRefreshResult("策略复盘已生成");
      }
      await loadData();
      setTimeout(() => setRefreshResult(null), 5000);
    } catch (error) {
      console.error("管理员操作失败:", error);
      setRefreshResult("管理员操作失败，请重试");
      setTimeout(() => setRefreshResult(null), 5000);
    } finally {
      setOpsRunning(null);
    }
  };

  // 清理超时计时器
  useEffect(() => {
    return () => clearScanTimeout();
  }, [clearScanTimeout]);

  if (loading) {
    return (
      <div className="max-w-7xl mx-auto px-4 md:px-8 pt-6 space-y-5">
        <div className="h-32 glass-card-static animate-shimmer" />
        <div className="h-48 glass-card-static animate-shimmer" />
        <div className="h-48 glass-card-static animate-shimmer" />
      </div>
    );
  }

  return (
    <div className="max-w-7xl mx-auto px-4 md:px-8 pt-6 pb-20 md:pb-10 space-y-6">
      {/* Header bar */}
      <div className="flex items-center justify-between animate-fade-in-up">
        <div>
          <h1 className="text-lg font-bold tracking-tight">今日作战</h1>
          {scanStatus && (
            <p className="text-xs text-text-muted mt-1">
              {scanStatus.is_trading ? (
                <span className="inline-flex items-center gap-1.5">
                  <span className="w-1.5 h-1.5 bg-emerald-400 rounded-full animate-pulse" />
                  <span className="text-emerald-400/80">交易中</span>
                  <span className="text-text-muted/40">·</span>
                  实时行情
                </span>
              ) : (
                <span className="inline-flex items-center gap-1.5">
                  <span className="w-1.5 h-1.5 bg-text-muted/40 rounded-full" />
                  已收盘
                  <span className="text-text-muted/40">·</span>
                  Tushare 日级数据
                </span>
              )}
            </p>
          )}
        </div>
        <div className="flex items-center gap-2">
          <ThemeToggle />
          {user?.role === "admin" && (
        <button
          onClick={handleRefresh}
          disabled={refreshing}
          className="text-xs px-4 py-2 bg-gradient-to-r from-amber-500/20 to-amber-600/15 text-amber-400 rounded-xl hover:from-amber-500/30 hover:to-amber-600/25 disabled:opacity-40 transition-all duration-200 border border-amber-500/10 font-medium"
        >
          {refreshing ? (
            <span className="inline-flex items-center gap-1.5">
              <span className="w-3 h-3 border border-amber-400/40 border-t-amber-400 rounded-full animate-spin" />
              分析中...
            </span>
          ) : scanStatus?.is_trading ? (
            "盘中扫描"
          ) : (
            "立即扫描"
          )}
        </button>
        )}
        </div>
      </div>

      {/* Scan result toast */}
      {refreshResult && (
        <div className="glass-card-static border-amber-500/15 px-4 py-2.5 text-xs text-amber-400 animate-fade-in-up flex items-center gap-2">
          <span className="w-1 h-1 rounded-full bg-amber-400" />
          {refreshResult}
        </div>
      )}

      <MissionControl
        board={strategyBoard}
        recommendations={data?.recommendations ?? []}
        sectors={sectors}
        strategyProfile={data?.strategy_profile ?? null}
      />

      {opsStatus && (
        user?.role === "admin" ? (
          <OpsPanel
            opsStatus={opsStatus}
            isAdmin={true}
            refreshing={refreshing}
            onRefresh={handleRefresh}
            opsRunning={opsRunning}
            onAction={handleAdminAction}
          />
        ) : null
      )}

      <div className="animate-fade-in-up delay-100">
        <EvidenceHeader title="决策证据" />
        <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mt-3">
          <MarketTemp data={data?.market_temperature ?? null} indices={indices} />
          <SectorHeatmap sectors={sectors} />
        </div>
      </div>

    </div>
  );
}

function OpsPanel({
  opsStatus,
  isAdmin,
  refreshing,
  onRefresh,
  opsRunning,
  onAction,
}: {
  opsStatus: OpsStatusResponse;
  isAdmin: boolean;
  refreshing: boolean;
  onRefresh: () => void;
  opsRunning: string | null;
  onAction: (action: "update_tracking" | "generate_strategy_board" | "generate_strategy_iteration") => void;
}) {
  return (
    <div className="glass-card-static p-4 animate-fade-in-up">
      <div className="flex flex-wrap items-center justify-between gap-3">
        <div>
          <div className="text-[10px] uppercase tracking-[0.22em] text-cyan-400 font-semibold">Admin Ops</div>
          <div className="text-xs text-text-muted mt-2">
            {opsStatus.data_freshness.message}
          </div>
        </div>
        <div className="flex flex-wrap items-center gap-2 text-[11px] text-text-muted">
          <span>市场 {opsStatus.data_freshness.market_trade_date || "暂无"}</span>
          <span>板块 {opsStatus.data_freshness.sector_trade_date || "暂无"}</span>
          <span>跟踪 {opsStatus.data_freshness.tracking_trade_date || "暂无"}</span>
          <span>{opsStatus.scan_running ? "扫描中" : "空闲"}</span>
        </div>
      </div>
      {isAdmin ? (
        <div className="flex flex-wrap gap-2 mt-3">
          <button
            onClick={onRefresh}
            disabled={refreshing || !!opsRunning}
            className="text-xs px-3 py-2 bg-gradient-to-r from-amber-500/20 to-amber-600/15 text-amber-400 rounded-xl hover:from-amber-500/30 hover:to-amber-600/25 disabled:opacity-40 transition-all border border-amber-500/10"
          >
            {refreshing ? "扫描中..." : "立即扫描"}
          </button>
          <button
            onClick={() => onAction("update_tracking")}
            disabled={refreshing || !!opsRunning}
            className="text-xs px-3 py-2 rounded-xl border border-border-subtle bg-surface-1 text-text-secondary hover:text-cyan-400 transition-colors disabled:opacity-40"
          >
            {opsRunning === "update_tracking" ? "更新中..." : "更新跟踪"}
          </button>
          <button
            onClick={() => onAction("generate_strategy_board")}
            disabled={refreshing || !!opsRunning}
            className="text-xs px-3 py-2 rounded-xl border border-border-subtle bg-surface-1 text-text-secondary hover:text-cyan-400 transition-colors disabled:opacity-40"
          >
            {opsRunning === "generate_strategy_board" ? "生成中..." : "生成策略板"}
          </button>
          <button
            onClick={() => onAction("generate_strategy_iteration")}
            disabled={refreshing || !!opsRunning}
            className="text-xs px-3 py-2 rounded-xl border border-border-subtle bg-surface-1 text-text-secondary hover:text-cyan-400 transition-colors disabled:opacity-40"
          >
            {opsRunning === "generate_strategy_iteration" ? "生成中..." : "生成策略复盘"}
          </button>
          <a href="/strategy" className="text-xs px-3 py-2 rounded-xl border border-border-subtle bg-surface-1 text-text-secondary hover:text-cyan-400 transition-colors">
            查看策略复盘
          </a>
          <a href="/recommendations" className="text-xs px-3 py-2 rounded-xl border border-border-subtle bg-surface-1 text-text-secondary hover:text-amber-400 transition-colors">
            查看推荐闭环
          </a>
        </div>
      ) : null}
    </div>
  );
}

function EvidenceHeader({ title }: { title: string }) {
  return (
    <div>
      <h2 className="text-xs font-semibold text-text-muted uppercase tracking-wider">
        {title}
      </h2>
    </div>
  );
}

function MissionControl({
  board,
  recommendations,
  sectors,
  strategyProfile,
}: {
  board: StrategyBoard | null;
  recommendations: LatestResult["recommendations"];
  sectors: SectorData[];
  strategyProfile: LatestResult["strategy_profile"];
}) {
  const actionable = recommendations.filter((rec) => rec.action_plan === "可操作");
  const watch = recommendations.filter((rec) => rec.action_plan === "重点关注");
  const observe = recommendations.filter((rec) => !["可操作", "重点关注"].includes(rec.action_plan ?? ""));
  const topSectors = sectors.slice(0, 3);
  const risks = board?.avoid_rules?.length ? board.avoid_rules : ["等待市场状态和推荐结果更新后生成风险约束。"];
  const primaryQueue = (actionable.length ? actionable : watch).slice(0, 3);
  const laneTitle = actionable.length ? "优先执行" : watch.length ? "候选观察" : "等待信号";
  const strategyName = strategyProfile?.name ?? board?.recommended_mode ?? "待定";
  const strategyHint = strategyProfile?.description ?? "系统判断今天更适合采用的出手方式";
  const riskText = risks.slice(0, 2).join(" / ");

  return (
    <div className="glass-card-static px-4 py-4 md:px-5 md:py-5 overflow-hidden relative animate-fade-in-up">
      <div className="absolute right-[-100px] top-[-120px] w-72 h-72 rounded-full bg-amber-500/[0.04] blur-3xl pointer-events-none" />
      <div className="relative grid grid-cols-1 xl:grid-cols-[minmax(0,1fr)_300px] gap-4">
        <div className="min-w-0 space-y-3">
          <div className="flex flex-wrap items-center justify-between gap-2">
            <div className="flex flex-wrap items-center gap-2">
              <span className="text-[10px] uppercase tracking-[0.22em] text-amber-400 font-semibold">今日结论</span>
              {board?.generated_by === "rules+llm" && (
                <span className="text-[10px] px-2 py-0.5 rounded-full border border-cyan-500/15 bg-cyan-500/10 text-cyan-400">AI增强</span>
              )}
            </div>
            <a href="/recommendations" className="text-[11px] text-text-muted hover:text-amber-400 transition-colors">
              推荐池
            </a>
          </div>

          <div className="grid grid-cols-1 lg:grid-cols-[minmax(0,1fr)_220px] gap-3 items-start">
            <div className="min-w-0">
              <h2 className="text-lg md:text-[1.2rem] font-bold tracking-tight truncate">
                {board?.market_regime ?? "等待市场状态"}
              </h2>
              <p className="text-[12px] text-text-secondary leading-relaxed mt-1.5 max-w-3xl line-clamp-2">
                {board?.summary ?? "系统尚未生成今日作战结论。触发扫描后，将基于市场温度、板块主线、推荐生命周期和策略复盘生成操作框架。"}
              </p>
            </div>
            <div className="grid grid-cols-3 lg:grid-cols-1 gap-1.5">
              <CommandMetric label="可操作" value={actionable.length} description="盯盘" />
              <CommandMetric label="关注" value={watch.length} description="等确认" />
              <CommandMetric label="观察" value={observe.length} description="不追" />
            </div>
          </div>

          <div className="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-2">
            <CompactDecision label="今日打法" value={strategyName} extra={strategyHint} />
            <CompactDecision label="仓位建议" value={board?.position_suggestion ?? "等待判断"} extra="今天建议的进攻上限" />
            <CompactDecision label="市场倾向" value={board?.action_bias ?? "等待确认"} extra={`风险 ${board?.risk_level ?? "-"}`} />
            <CompactDecision label="主线板块" value={topSectors.length ? topSectors.map((sector) => sector.sector_name).join(" / ") : "暂无"} extra={riskText || "暂无风险约束"} />
          </div>

          <div className="flex flex-wrap items-center gap-2">
            {topSectors.length ? (
              topSectors.map((sector) => (
                <span key={sector.sector_code} className="inline-flex items-center gap-1.5 rounded-full bg-surface-1/80 border border-border-subtle px-2.5 py-1 text-[11px]">
                  <span className="font-medium text-text-primary">{sector.sector_name}</span>
                  <span className={`font-mono tabular-nums ${sector.pct_change >= 0 ? "text-red-400" : "text-emerald-400"}`}>
                    {sector.pct_change > 0 ? "+" : ""}{sector.pct_change.toFixed(2)}%
                  </span>
                </span>
              ))
            ) : (
              <span className="text-xs text-text-muted">暂无主线板块</span>
            )}
          </div>
        </div>

        <div className="rounded-2xl bg-surface-1/70 border border-border-subtle p-3">
          <div className="flex items-center justify-between gap-3">
            <SectionTitle title={laneTitle} />
            <span className="text-[10px] text-text-muted">{primaryQueue.length}只</span>
          </div>
          <div className="mt-2.5 space-y-1.5">
            {primaryQueue.length ? (
              primaryQueue.map((rec) => (
                <CompactMissionStock key={`mission-${rec.ts_code}`} rec={rec} />
              ))
            ) : (
              <div className="rounded-lg bg-surface-2/60 border border-border-subtle p-3 text-center">
                <div className="text-xs text-text-muted">暂无执行标的</div>
                <div className="text-[11px] text-text-muted/50 mt-0.5">等待扫描生成可操作或重点关注列表</div>
              </div>
            )}
          </div>
          <a
            href="/strategy"
            className="inline-flex items-center justify-center mt-3 w-full rounded-xl border border-border-subtle bg-surface-2/60 px-3 py-2 text-[11px] text-text-muted hover:text-amber-400 hover:border-amber-500/20 transition-colors"
          >
            查看策略复盘
          </a>
        </div>
      </div>
    </div>
  );
}

function CompactDecision({ label, value, extra }: { label: string; value: string; extra: string }) {
  return (
    <div className="rounded-lg bg-surface-2 px-3 py-2">
      <div className="text-[10px] text-text-muted uppercase tracking-wider font-semibold">{label}</div>
      <div className="text-sm font-semibold text-text-primary mt-1 truncate">{value}</div>
      {extra ? <div className="text-[10px] text-text-muted mt-1 truncate">{extra}</div> : null}
    </div>
  );
}

function CompactMissionStock({ rec }: { rec: LatestResult["recommendations"][number] }) {
  const actionStyle: Record<string, string> = {
    "可操作": "bg-red-500/15 text-red-400 border-red-500/20",
    "重点关注": "bg-amber-500/15 text-amber-400 border-amber-500/20",
    "观察": "bg-surface-3 text-text-muted border-border-default",
  };

  return (
    <a
      href={`/stock/${rec.ts_code}`}
      className="block rounded-lg bg-surface-2/60 border border-border-subtle px-3 py-2 hover:border-amber-500/20 transition-colors"
    >
      <div className="flex items-center justify-between gap-3">
        <div className="min-w-0">
          <div className="flex items-center gap-1.5 min-w-0">
            <span className="text-sm font-semibold truncate">{rec.name}</span>
            <span className={`shrink-0 text-[10px] px-1.5 py-0.5 rounded-md border ${actionStyle[rec.action_plan ?? "观察"] ?? actionStyle["观察"]}`}>
              {rec.action_plan ?? "观察"}
            </span>
          </div>
          <div className="text-[10px] text-text-muted font-mono tabular-nums mt-0.5 truncate">
            {rec.ts_code} · {rec.sector}
          </div>
        </div>
        <div className="shrink-0 text-right">
          <div className="text-base font-bold font-mono tabular-nums text-text-primary">{rec.score}</div>
          <div className="text-[10px] text-text-muted">参考</div>
        </div>
      </div>
      <div className="mt-1.5 text-[11px] text-text-secondary leading-relaxed line-clamp-1">
        {rec.trigger_condition ?? rec.reasons?.[0] ?? "等待触发条件确认"}
      </div>
    </a>
  );
}

function CommandMetric({ label, value, description }: { label: string; value: number; description: string }) {
  return (
    <div className="rounded-lg bg-surface-1/70 border border-border-subtle px-2.5 py-2">
      <div className="text-[10px] text-text-muted uppercase tracking-wider font-semibold">{label}</div>
      <div className="flex items-baseline justify-between gap-2 mt-0.5">
        <div className="text-lg font-bold font-mono tabular-nums text-text-primary">{value}</div>
        <div className="text-[10px] text-text-muted">{description}</div>
      </div>
    </div>
  );
}

function SectionTitle({ title }: { title: string }) {
  return (
    <div className="text-[10px] text-text-muted uppercase tracking-wider font-semibold">
      {title}
    </div>
  );
}
