import { AppIcon } from "./PixelIcons";
import { Card, Loading, RefreshButton } from "./ui";
import {
  type AnalystConsensus,
  type CongressTradeRow,
  type HolderMeta,
  type HolderRow,
  type HoldersPayload,
  type InstitutionalFlowPayload,
  type InstitutionalDay,
  type EtfHolderRow,
  type NotableFundManagerRow,
  type NotableHoldersPayload,
} from "../lib/api";
import { fmtMoneyShort, fmtNum } from "../lib/stockTechnical";

function fmtShares(n: number | null | undefined) {
  if (n == null || !Number.isFinite(n)) return "—";
  const abs = Math.abs(n);
  const sign = n < 0 ? "-" : "";
  if (abs >= 1e8) return `${sign}${(abs / 1e8).toFixed(2)}億`;
  if (abs >= 1e4) return `${sign}${(abs / 1e4).toFixed(1)}萬`;
  return `${sign}${abs.toLocaleString()}`;
}

function fmtDate(iso?: string | null) {
  if (!iso) return "—";
  const d = iso.slice(0, 10);
  return d.length === 10 ? d : iso;
}

function FlowBar({ day }: { day: InstitutionalDay }) {
  const rows = [
    { key: "foreign", label: "外資", data: day.foreign },
    { key: "trust", label: "投信", data: day.trust },
    { key: "dealer", label: "自營", data: day.dealer },
  ] as const;
  const maxAbs = Math.max(
    ...rows.map((r) => Math.abs(r.data.net || 0)),
    Math.abs(day.total?.net || 0),
    1,
  );
  return (
    <div className="flow-day">
      <div className="flow-date">{day.date}</div>
      {rows.map((r) => {
        const net = r.data.net || 0;
        const pct = Math.min(100, (Math.abs(net) / maxAbs) * 100);
        return (
          <div className="flow-bar-row" key={r.key}>
            <span className="flow-bar-label">{r.label}</span>
            <div className="flow-bar-track">
              <div className={`flow-bar-fill ${net >= 0 ? "up" : "down"}`} style={{ width: `${pct}%` }} />
            </div>
            <span className={`flow-bar-val ${net >= 0 ? "up" : "down"}`}>{fmtShares(net)}</span>
          </div>
        );
      })}
      <div className="flow-total">
        合計淨買賣：<strong className={day.total.net >= 0 ? "up" : "down"}>{fmtShares(day.total.net)}</strong>
      </div>
    </div>
  );
}

function FreshnessStrip({ meta, holders, flow }: { meta?: HolderMeta | null; holders?: HoldersPayload | null; flow?: InstitutionalFlowPayload | null }) {
  const m = meta || holders?.meta || flow?.meta;
  if (!m && !holders?.cached && !flow?.cached) return null;
  return (
    <div className="flow-freshness">
      <div className="flow-freshness-row">
        <span className="flow-freshness-label">資料狀態</span>
        <span className={`flow-freshness-badge ${m?.isPartial ? "partial" : ""}`}>
          {m?.freshnessLabel || (holders?.cached || flow?.cached ? "快取" : "即時")}
        </span>
        {m?.fetchedAt ? <span>抓取 {fmtDate(m.fetchedAt)}</span> : null}
        {m?.dataAsOf ? <span>申報截至 <strong>{fmtDate(m.dataAsOf)}</strong></span> : null}
        {m?.sources?.length ? <span>來源 {m.sources.join("、")}</span> : null}
      </div>
      {m?.lagNote ? <p className="small muted flow-lag-note">{m.lagNote}</p> : null}
      {m?.etfScanNote ? <p className="small muted">{m.etfScanNote}</p> : null}
    </div>
  );
}

function AnalystCard({ analyst }: { analyst?: AnalystConsensus | null }) {
  if (!analyst) return null;
  const r = analyst.ratings;
  const total = analyst.ratingTotal || (r ? r.strongBuy + r.buy + r.hold + r.sell + r.strongSell : 0);
  const segments = r
    ? [
        { key: "strongBuy", label: "強買", count: r.strongBuy, cls: "bull-strong" },
        { key: "buy", label: "買進", count: r.buy, cls: "bull" },
        { key: "hold", label: "持有", count: r.hold, cls: "neutral" },
        { key: "sell", label: "賣出", count: r.sell, cls: "bear" },
        { key: "strongSell", label: "強賣", count: r.strongSell, cls: "bear-strong" },
      ]
    : [];

  return (
    <Card title="分析師共識" ico={<AppIcon name="coin" size={22} framed variant="hero" />}>
      {analyst.unavailable && !r ? (
        <p className="small muted">分析師評等暫不可用（Yahoo 限流或無覆蓋）。目標價可參考財報分頁。</p>
      ) : (
        <>
          <div className="analyst-verdict-row">
            <span className={`analyst-verdict analyst-verdict--${analyst.tone || "neutral"}`}>{analyst.verdict}</span>
            {analyst.targetMean != null ? (
              <span className="analyst-target">
                目標價 <strong>{fmtMoneyShort(analyst.targetMean)}</strong>
                {analyst.analystCount != null ? `（${analyst.analystCount} 位分析師）` : ""}
                {analyst.upsidePct != null ? (
                  <span className={analyst.upsidePct >= 0 ? "up" : "down"}>
                    {" "}
                    {analyst.upsidePct >= 0 ? "+" : ""}
                    {fmtNum(analyst.upsidePct, 1)}% vs 現價
                  </span>
                ) : null}
              </span>
            ) : null}
          </div>
          {total > 0 && r ? (
            <div className="analyst-rating-bar" aria-label="分析師評等分布">
              {segments.map((s) =>
                s.count > 0 ? (
                  <div
                    key={s.key}
                    className={`analyst-rating-seg ${s.cls}`}
                    style={{ flexGrow: s.count }}
                    title={`${s.label} ${s.count}`}
                  >
                    <span>{s.label}</span>
                    <strong>{s.count}</strong>
                  </div>
                ) : null,
              )}
            </div>
          ) : null}
          {analyst.targetLow != null && analyst.targetHigh != null ? (
            <p className="small muted mt-s">
              共識目標區間 {fmtMoneyShort(analyst.targetLow)} – {fmtMoneyShort(analyst.targetHigh)}
              {analyst.source ? ` · ${analyst.source}` : ""}
            </p>
          ) : null}

          {analyst.recentActions?.length ? (
            <div className="analyst-actions-wrap mt">
              <h4 className="analyst-actions-title">近期分析師動作（機構 / 建議）</h4>
              <div className="fund-table-scroll">
                <table className="fin-table compact analyst-actions-table">
                  <thead>
                    <tr>
                      <th>日期</th>
                      <th>機構</th>
                      <th>建議</th>
                      <th>評等變化</th>
                      <th>目標價</th>
                    </tr>
                  </thead>
                  <tbody>
                    {analyst.recentActions.slice(0, 18).map((a, i) => (
                      <tr key={`${a.firm}-${a.date}-${i}`}>
                        <td className="muted small">{fmtDate(a.date)}</td>
                        <td className="analyst-firm">{a.firm}</td>
                        <td>
                          <span className={`analyst-action analyst-action--${a.tone || "neutral"}`}>
                            {a.actionLabel || "—"}
                          </span>
                        </td>
                        <td className="muted small">{a.gradeChange || a.toGrade || "—"}</td>
                        <td>{a.priceTarget != null ? fmtMoneyShort(a.priceTarget) : "—"}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <p className="small muted mt-s">
                單筆目標價僅在該次評等公告有揭露時顯示；共識目標價見上方。
              </p>
            </div>
          ) : !analyst.unavailable ? (
            <p className="small muted mt-s">暫無個別機構調升/調降紀錄（Yahoo 限流時可稍後重試）。</p>
          ) : null}

          <p className="small muted mt-s">{analyst.disclaimer}</p>
        </>
      )}
    </Card>
  );
}

function TierBadge({ tier, label }: { tier?: string; label?: string }) {
  if (!tier || tier === "other") return null;
  return <span className={`holder-tier holder-tier--${tier}`}>{label || tier}</span>;
}

function InstitutionTable({ rows, title }: { rows: HolderRow[]; title: string }) {
  if (!rows.length) return null;
  return (
    <div className="flow-inst-block">
      <h4>{title}</h4>
      <div className="fund-table-scroll">
        <table className="fin-table compact flow-inst-table">
          <thead>
            <tr>
              <th>#</th>
              <th>機構</th>
              <th>規模</th>
              <th>占比</th>
              <th>股數</th>
              <th>市值</th>
              <th>申報日</th>
              <th>變化</th>
            </tr>
          </thead>
          <tbody>
            {rows.map((h, i) => (
              <tr key={`${h.organization}-${i}`}>
                <td className="muted">{h.rank ?? i + 1}</td>
                <td className="flow-inst-name">{h.organization}</td>
                <td>
                  <TierBadge tier={h.tier} label={h.tierLabel} />
                </td>
                <td>{h.pctHeld != null ? `${fmtNum(h.pctHeld, 2)}%` : "—"}</td>
                <td>{h.shares != null ? fmtShares(h.shares) : "—"}</td>
                <td>{h.value != null ? fmtMoneyShort(h.value) : "—"}</td>
                <td className="muted small">{fmtDate(h.reportDate)}</td>
                <td className={`small ${(h.sharesChangePct ?? 0) >= 0 ? "up" : "down"}`}>
                  {h.sharesChangePct != null
                    ? `${h.sharesChangePct >= 0 ? "+" : ""}${fmtNum(h.sharesChangePct, 1)}%`
                    : h.sharesChange || "—"}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  );
}

function TagPills({ tags }: { tags?: string[] }) {
  if (!tags?.length) return null;
  return (
    <span className="notable-tags">
      {tags.map((t) => (
        <span key={t} className="notable-tag">
          {t}
        </span>
      ))}
    </span>
  );
}

function NotableFundTable({ rows }: { rows: NotableFundManagerRow[] }) {
  return (
    <div className="fund-table-scroll">
      <table className="fin-table compact flow-notable-table">
        <thead>
          <tr>
            <th>經理人</th>
            <th>機構</th>
            <th>占比</th>
            <th>股數</th>
            <th>市值</th>
            <th>申報日</th>
            <th>變化</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((h) => (
            <tr key={h.id}>
              <td className="notable-person">
                <strong>{h.nameZh}</strong>
                <span className="muted small">{h.nameEn}</span>
                <TagPills tags={h.tags} />
              </td>
              <td>
                <div>{h.fundZh}</div>
                <span className="muted small">{h.organization}</span>
              </td>
              <td>{h.pctHeld != null ? `${fmtNum(h.pctHeld, 2)}%` : "—"}</td>
              <td>{h.shares != null ? fmtShares(h.shares) : "—"}</td>
              <td>{h.value != null ? fmtMoneyShort(h.value) : "—"}</td>
              <td className="muted small">{fmtDate(h.reportDate)}</td>
              <td className={`small ${(h.sharesChangePct ?? "").toString().startsWith("-") ? "down" : "up"}`}>
                {h.sharesChangePct || h.sharesChange || "—"}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function CongressTradeTable({ rows }: { rows: CongressTradeRow[] }) {
  return (
    <div className="fund-table-scroll">
      <table className="fin-table compact flow-notable-table">
        <thead>
          <tr>
            <th>議員</th>
            <th>院別</th>
            <th>交易</th>
            <th>金額區間</th>
            <th>交易日期</th>
            <th>披露</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((t) => (
            <tr key={t.id}>
              <td className="notable-person">
                {t.link ? (
                  <a href={t.link} target="_blank" rel="noopener noreferrer">
                    <strong>{t.nameZh || t.nameEn}</strong>
                  </a>
                ) : (
                  <strong>{t.nameZh || t.nameEn}</strong>
                )}
                {t.nameEn && t.nameZh !== t.nameEn ? <span className="muted small">{t.nameEn}</span> : null}
                <TagPills tags={t.tags} />
              </td>
              <td className="muted small">{t.chamber === "senate" ? "參議院" : t.chamber === "house" ? "眾議院" : "—"}</td>
              <td>{t.transactionType || "—"}</td>
              <td>{t.amountLabel || "—"}</td>
              <td className="muted small">{fmtDate(t.transactionDate)}</td>
              <td className="muted small">{fmtDate(t.disclosureDate)}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function NotableHoldersCard({
  notable,
  loading,
  error,
  market,
}: {
  notable?: NotableHoldersPayload | null;
  loading?: boolean;
  error?: boolean;
  market?: string;
}) {
  if (market === "tw") {
    return (
      <Card className="mt" title="名人持股" ico={<AppIcon name="world" size={22} framed variant="hero" />}>
        <p className="small muted">{notable?.disclaimer || "台股暫不支援名人 13F／國會披露查詢。"}</p>
      </Card>
    );
  }

  const fundRows = notable?.fundManagers || [];
  const congressRows = notable?.congressTrades || [];
  const catalogFm = notable?.catalog?.fundManagers ?? 18;
  const catalogCm = notable?.catalog?.congressTracked ?? 8;

  return (
    <Card className="mt" title={`名人持股（${notable?.notableCount ?? 0}）`} ico={<AppIcon name="world" size={22} framed variant="hero" />}>
      <p className="small muted mb-s flow-notable-explainer">
        追蹤 <strong>{catalogFm}</strong> 位知名基金經理人／機構（SEC 13F 季報）與 <strong>{catalogCm}</strong> 位活躍國會議員披露。
        經理人含巴菲特、達里歐、凱西·伍德、阿克曼、貝瑞等；國會含裴洛西、圖伯維爾等。
      </p>

      {loading ? <Loading label="掃描名人持股…" /> : null}

      {!loading && fundRows.length ? (
        <div className="flow-notable-block">
          <h4>知名基金經理人（13F）</h4>
          <NotableFundTable rows={fundRows} />
        </div>
      ) : null}

      {!loading && congressRows.length ? (
        <div className="flow-notable-block">
          <h4>國會議員交易</h4>
          <CongressTradeTable rows={congressRows.slice(0, 20)} />
        </div>
      ) : null}

      {!loading && !fundRows.length && !congressRows.length ? (
        <p className="small muted">
          {error
            ? "名人持股暫時無法載入，請稍後重試。"
            : "此標的未在追蹤名單的 13F 前 80 大機構中出現，或尚無國會披露紀錄。"}
        </p>
      ) : null}

      {notable?.congressPremiumRequired ? (
        <p className="small muted mt-s" style={{ color: "var(--gold-soft)" }}>
          國會交易：FMP 需付費方案。可在設定頁填入 <strong>FINNHUB_API_KEY</strong> 啟用 Finnhub 備援。
        </p>
      ) : null}

      {notable?.scanNote ? <p className="small muted mt-s">{notable.scanNote}</p> : null}
      {notable?.disclaimer ? <p className="small muted mt-s">{notable.disclaimer}</p> : null}
    </Card>
  );
}

function EtfTable({ rows }: { rows: EtfHolderRow[] }) {
  return (
    <div className="fund-table-scroll">
      <table className="fin-table compact flow-etf-table">
        <thead>
          <tr>
            <th>ETF</th>
            <th>名稱</th>
            <th>類別</th>
            <th>成分權重</th>
            <th>成分截至</th>
            <th>來源</th>
          </tr>
        </thead>
        <tbody>
          {rows.map((h, i) => (
            <tr key={`${h.ticker || h.name}-${i}`}>
              <td>
                <strong>{h.ticker || "—"}</strong>
              </td>
              <td>{h.name}</td>
              <td className="muted small">{h.category || "—"}</td>
              <td>
                {h.weightPct != null
                  ? `${fmtNum(h.weightPct, 2)}%`
                  : h.weightFmt || (h.shares != null ? fmtShares(h.shares) : "—")}
              </td>
              <td className="muted small">{fmtDate(h.reportDate) || "月報/季報"}</td>
              <td className="muted small">
                {h.source === "institution_etf_hint"
                  ? "機構推斷"
                  : h.source === "fmp_asset_exposure"
                    ? "FMP 反查"
                    : h.source === "yahoo_top_holdings" || h.source === "nasdaq_etf_holdings"
                      ? "成分掃描"
                      : h.source === "yahoo_fund_ownership" || h.source === "yahoo_fund_ownership_direct"
                        ? "基金持股"
                        : h.source || "—"}
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

export interface FlowPanelProps {
  flow?: InstitutionalFlowPayload | null;
  holders?: HoldersPayload | null;
  notable?: NotableHoldersPayload | null;
  flowLoading?: boolean;
  holdersLoading?: boolean;
  notableLoading?: boolean;
  flowError?: boolean;
  holdersError?: boolean;
  notableError?: boolean;
  chipRefreshing?: boolean;
  onRefreshChip?: () => void;
  aiBase?: { symbol: string; name?: string };
}

export default function FlowPanel({
  flow,
  holders,
  notable,
  flowLoading,
  holdersLoading,
  notableLoading,
  flowError,
  holdersError,
  notableError,
  chipRefreshing,
  onRefreshChip,
}: FlowPanelProps) {
  const analyst = flow?.analyst;
  const meta = flow?.meta || holders?.meta;
  const bd = flow?.breakdown || holders?.breakdown;
  const institutions = holders?.institutions?.length ? holders.institutions : flow?.institutions || [];
  const etfRows = holders?.etfHolders?.length ? holders.etfHolders : flow?.etfHolders || [];
  const etfCount = holders?.etfCount ?? flow?.etfCount ?? etfRows.length;

  if (flowLoading && holdersLoading) return <Loading label="載入籌碼…" />;

  return (
    <div className="backpack-panel flow-panel">
      <div className="flow-panel-toolbar">
        <FreshnessStrip meta={meta} holders={holders} flow={flow} />
        {onRefreshChip ? (
          <RefreshButton
            onClick={onRefreshChip}
            loading={chipRefreshing || holdersLoading || notableLoading}
            label="重新整理籌碼"
          />
        ) : null}
      </div>

      {flow?.market === "us" ? <AnalystCard analyst={analyst} /> : null}

      {flow?.market === "tw" && flow.days?.length ? (
        <Card title="三大法人買賣超（台股）" ico={<AppIcon name="flow" size={22} framed variant="hero" />}>
          {flow.summary ? (
            <div className="flow-summary">
              <div>
                <span>外資</span>
                <strong className={(flow.summary.foreignNet as number) >= 0 ? "up" : "down"}>
                  {fmtShares(flow.summary.foreignNet as number)}
                </strong>
              </div>
              <div>
                <span>投信</span>
                <strong className={(flow.summary.trustNet as number) >= 0 ? "up" : "down"}>
                  {fmtShares(flow.summary.trustNet as number)}
                </strong>
              </div>
              <div>
                <span>自營</span>
                <strong className={(flow.summary.dealerNet as number) >= 0 ? "up" : "down"}>
                  {fmtShares(flow.summary.dealerNet as number)}
                </strong>
              </div>
              <div>
                <span>合計</span>
                <strong className={(flow.summary.totalNet as number) >= 0 ? "up" : "down"}>
                  {fmtShares(flow.summary.totalNet as number)}
                </strong>
              </div>
            </div>
          ) : null}
          <div className="flow-days">
            {flow.days.map((d) => (
              <FlowBar key={d.date} day={d} />
            ))}
          </div>
          <p className="small muted">{flow.disclaimer}</p>
        </Card>
      ) : flow?.market === "us" ? (
        <Card title="持股結構（美股）" ico={<AppIcon name="flow" size={22} framed variant="hero" />}>
          {!bd ? (
            flowError && holdersError ? (
              <p className="small muted">資料源暫時限流，請稍後重試。</p>
            ) : (
              <p className="small muted">載入持股結構中…</p>
            )
          ) : (
            <div className="holder-breakdown flow-breakdown">
              <div>
                <span>機構持股</span>
                <strong>{bd.institutionsPct != null ? `${fmtNum(bd.institutionsPct, 1)}%` : "—"}</strong>
              </div>
              <div>
                <span>內部人</span>
                <strong>{bd.insidersPct != null ? `${fmtNum(bd.insidersPct, 1)}%` : "—"}</strong>
              </div>
              <div>
                <span>機構家數</span>
                <strong>{bd.institutionsCount ?? "—"}</strong>
              </div>
              <div>
                <span>流通股</span>
                <strong>{bd.floatShares != null ? fmtShares(bd.floatShares) : "—"}</strong>
              </div>
            </div>
          )}
          {(holders?.partial || holders?.fallback || flow?.partial) ? (
            <p className="small muted mt-s" style={{ color: "var(--teal)" }}>
              {holders?.source === "Nasdaq" || holders?.fallback
                ? "機構名單以 Nasdaq 13F 為主；ETF 成分可能需 Nasdaq/Yahoo 掃描。"
                : "部分欄位來自快取或備援來源。"}
            </p>
          ) : null}
          <p className="small muted">{flow?.disclaimer || holders?.disclaimer}</p>
        </Card>
      ) : null}

      <Card
        className="mt"
        title={`ETF 間接持有（${etfCount}）`}
        ico={<AppIcon name="cards" size={22} framed variant="hero" />}
      >
        <p className="small muted mb-s flow-etf-explainer">
          ETF 成分為<strong>公開月報/季報</strong>，不是每日持股。系統優先用 FMP 反查（設定頁填 FMP_API_KEY 可取得完整清單，RKLB 約 200+ 檔），
          並掃描 UFO、NASA、ARKX 等太空/國防主題 ETF，加上 QQQ、IWM、SMH 等大盤/產業 ETF 成分。
        </p>
        {etfRows.length ? (
          <>
            <EtfTable rows={etfRows.slice(0, 20)} />
            <p className="small muted mt-s">{holders?.etfDisclaimer || flow?.etfDisclaimer}</p>
          </>
        ) : holdersLoading ? (
          <Loading label="掃描 ETF 成分…" />
        ) : holdersError ? (
          <p className="small muted">ETF 掃描暫時失敗（常見為 Yahoo 429）。機構 13F 仍可參考上方表格。</p>
        ) : (
          <p className="small muted">未在掃描的熱門 ETF 中找到此股；可稍後重試或查看機構名單中的 Vanguard/BlackRock 等指數基金。</p>
        )}
      </Card>

      <NotableHoldersCard
        notable={notable}
        loading={notableLoading}
        error={notableError}
        market={flow?.market || holders?.market}
      />

      {institutions.length || holders?.funds?.length ? (
        <Card className="mt" title="主要機構持股" ico={<AppIcon name="world" size={22} framed variant="hero" />}>
          <div className="flow-inst-layout">
            <InstitutionTable rows={institutions.slice(0, 12)} title="機構（13F 季報）" />
            {holders?.funds?.length ? (
              <div className="flow-inst-block">
                <h4>共同基金</h4>
                <div className="fund-table-scroll">
                  <table className="fin-table compact">
                    <thead>
                      <tr>
                        <th>名稱</th>
                        <th>占比</th>
                        <th>申報日</th>
                      </tr>
                    </thead>
                    <tbody>
                      {holders.funds.slice(0, 8).map((h, i) => (
                        <tr key={i}>
                          <td>{h.organization}</td>
                          <td>{h.pctHeld != null ? `${fmtNum(h.pctHeld, 2)}%` : "—"}</td>
                          <td className="muted small">{fmtDate(h.reportDate)}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                </div>
              </div>
            ) : null}
          </div>
        </Card>
      ) : null}
    </div>
  );
}