import type { ReactElement } from "react";
import { useEffect, useMemo, useState } from "react";

import type { WebPerformanceSummaryResponse, WebPerformanceSummaryRow } from "../../types/domain";
import { api } from "../../services/api/client";
import { asArray, formatBeijingTime, toneClass } from "../../utils";
import { StateTag } from "../shared/StateTag";

type PerformanceState = {
  loading: boolean;
  payload: WebPerformanceSummaryResponse | null;
  error: string | null;
  observedAt: string | null;
};

const SLOW_ROW_LIMIT = 8;

export function PerformanceView(): ReactElement {
  const [state, setState] = useState<PerformanceState>({ loading: true, payload: null, error: null, observedAt: null });

  async function refresh(): Promise<void> {
    setState((current) => ({ ...current, loading: true, error: null }));
    const response = await api.webPerformanceSummary();
    setState({
      loading: false,
      payload: response.ok ? response.data : null,
      error: response.ok ? null : response.error ?? "性能摘要不可用",
      observedAt: response.ok ? response.data?.observedAt ?? new Date().toISOString() : null
    });
  }

  useEffect(() => {
    void refresh();
    const timer = window.setInterval(() => void refresh(), 15000);
    return () => window.clearInterval(timer);
  }, []);

  const payload = state.payload;
  const summary = payload?.summary ?? {};
  const sampleCount = numeric(summary.sampleCount);
  const problemCount = numeric(summary.problemCount);
  const status = state.error ? "blocked" : sampleCount === 0 ? "pending" : problemCount > 0 ? "warn" : "ok";
  const apiRows = useMemo(() => sortRows(payload?.apiRoutes).slice(0, SLOW_ROW_LIMIT), [payload]);
  const vitalRows = useMemo(() => sortRows(payload?.webVitals).slice(0, SLOW_ROW_LIMIT), [payload]);
  const longTaskRows = useMemo(() => sortRows(payload?.longTasks).slice(0, SLOW_ROW_LIMIT), [payload]);
  const problemRows = useMemo(() => sortRows(payload?.problems).slice(0, SLOW_ROW_LIMIT), [payload]);

  return (
    <section className="view performance-view" id="performance" data-view="performance" aria-labelledby="performance-title">
      <header className="performance-header">
        <div>
          <p className="eyebrow">User-perceived WebUI</p>
          <h2 id="performance-title">性能监控</h2>
        </div>
        <div className="performance-actions">
          <StateTag tone={toneClass(status)} id="performance-status" title={state.error ?? `observedAt=${state.observedAt ?? "unknown"}`}>{performanceStatusLabel(state, sampleCount, problemCount)}</StateTag>
          <button className="command-button secondary" id="performance-refresh" type="button" onClick={() => void refresh()} disabled={state.loading}>{state.loading ? "刷新中" : "刷新"}</button>
        </div>
      </header>

      {state.error ? <p className="performance-error" id="performance-error">{state.error}</p> : null}

      <div className="performance-kpi-grid" aria-label="性能摘要">
        <MetricTile label="RUM 样本" value={String(sampleCount)} detail={sampleCount < 10 ? "低样本，仅作链路基线" : `${numeric(summary.routeCount)} routes`} tone={sampleCount === 0 ? "pending" : sampleCount < 10 ? "warn" : "ok"} />
        <MetricTile label="问题队列" value={String(problemCount)} detail={problemCount > 0 ? "需要关注的慢路径/错误" : "暂无明显问题"} tone={problemCount > 0 ? "warn" : "ok"} />
        <MetricTile label="API 最慢 p95" value={formatMetric(maxP95(apiRows), "seconds")} detail={apiRows[0]?.route ?? "等待 API 样本"} tone={apiRows[0]?.tone ?? "source"} />
        <MetricTile label="Long task p95" value={formatMetric(maxP95(longTaskRows), "seconds")} detail={longTaskRows[0]?.route ?? "等待长任务样本"} tone={longTaskRows[0]?.tone ?? "source"} />
      </div>

      <div className="performance-source-line" aria-label="性能数据来源">
        <span>source <strong>{payload?.source ?? "cloud-api-rum-store"}</strong></span>
        <span>namespace <strong>{payload?.namespace ?? "hwlab-v02"}</strong></span>
        <span>target <strong>{payload?.gitopsTarget ?? "v02"}</strong></span>
        <span>observed <strong>{formatBeijingTime(state.observedAt, { withSeconds: true })}</strong></span>
      </div>

      <div className="performance-grid">
        <PerformanceTable title="慢 API 路径" eyebrow="Route p95" empty="等待浏览器同源 API 请求样本。" rows={apiRows} />
        <PerformanceTable title="Web Vitals / 首屏" eyebrow="Vitals" empty="等待 LCP / INP / navigation 样本。" rows={vitalRows} />
        <PerformanceTable title="主线程长任务" eyebrow="Long task" empty="当前没有 long task 样本。" rows={longTaskRows} />
        <PerformanceTable title="需要关注" eyebrow="Problems" empty="暂无错误、超时或慢路径。" rows={problemRows} showProblem />
      </div>
    </section>
  );
}

function MetricTile({ label, value, detail, tone }: { label: string; value: string; detail: string; tone?: string }): ReactElement {
  return (
    <article className={`performance-tile tone-border-${toneClass(tone)}`}>
      <span>{label}</span>
      <strong>{value}</strong>
      <p>{detail}</p>
    </article>
  );
}

function PerformanceTable({ title, eyebrow, empty, rows, showProblem = false }: { title: string; eyebrow: string; empty: string; rows: WebPerformanceSummaryRow[]; showProblem?: boolean }): ReactElement {
  return (
    <section className="workspace-panel performance-panel" aria-label={title}>
      <div className="performance-panel-head">
        <div><p className="eyebrow">{eyebrow}</p><h3>{title}</h3></div>
        <StateTag tone={rows.length > 0 ? toneClass(rows[0]?.tone) : "source"}>{rows.length > 0 ? `${rows.length} rows` : "waiting"}</StateTag>
      </div>
      {rows.length === 0 ? <p className="performance-empty">{empty}</p> : (
        <div className="performance-table-wrap">
          <table className="performance-table">
            <thead>
              <tr>
                <th>对象</th>
                <th>指标</th>
                <th>p95</th>
                <th>样本</th>
                <th>结果</th>
                {showProblem ? <th>问题</th> : null}
              </tr>
            </thead>
            <tbody>
              {rows.map((row, index) => <PerformanceRow key={`${row.metric}-${row.route}-${row.method}-${index}`} row={row} showProblem={showProblem} />)}
            </tbody>
          </table>
        </div>
      )}
    </section>
  );
}

function PerformanceRow({ row, showProblem }: { row: WebPerformanceSummaryRow; showProblem: boolean }): ReactElement {
  return (
    <tr data-performance-tone={toneClass(row.tone)}>
      <td className="mono wrap">{row.route ?? "--"}</td>
      <td><span className="performance-metric-name">{row.metric ?? row.kind ?? "metric"}</span>{row.method && row.method !== "NONE" ? <span className="performance-method">{row.method}</span> : null}</td>
      <td className="mono">{formatMetric(row.p95, row.unit)}</td>
      <td>{numeric(row.count)}</td>
      <td><StateTag tone={toneClass(row.tone)}>{row.outcome ?? row.statusClass ?? "ok"}</StateTag></td>
      {showProblem ? <td className="wrap">{row.problem ?? "ok"}</td> : null}
    </tr>
  );
}

function sortRows(rows: unknown): WebPerformanceSummaryRow[] {
  return asArray<WebPerformanceSummaryRow>(rows).sort((left, right) => toneWeight(right.tone) - toneWeight(left.tone) || numeric(right.p95) - numeric(left.p95) || numeric(right.count) - numeric(left.count));
}

function performanceStatusLabel(state: PerformanceState, sampleCount: number, problemCount: number): string {
  if (state.loading && !state.payload) return "读取中";
  if (state.error) return "性能摘要阻塞";
  if (sampleCount === 0) return "等待样本";
  if (sampleCount < 10) return `低样本 ${sampleCount}`;
  if (problemCount > 0) return `${problemCount} 个问题`;
  return "观测正常";
}

function maxP95(rows: WebPerformanceSummaryRow[]): number {
  return rows.reduce((max, row) => Math.max(max, numeric(row.p95)), 0);
}

function formatMetric(value: unknown, unit: unknown): string {
  const number = numeric(value);
  if (number <= 0) return "--";
  if (unit === "score") return number.toFixed(number < 0.1 ? 3 : 2);
  if (number < 1) return `${Math.round(number * 1000)}ms`;
  return `${number.toFixed(number < 10 ? 2 : 1)}s`;
}

function numeric(value: unknown): number {
  const number = Number(value);
  return Number.isFinite(number) && number >= 0 ? number : 0;
}

function toneWeight(value: unknown): number {
  const tone = toneClass(value);
  if (tone === "blocked" || tone === "error") return 4;
  if (tone === "warn" || tone === "pending") return 3;
  if (tone === "ok") return 2;
  return 1;
}
