import { memo, useMemo } from "react";
import { CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";

import type { TrendPoint } from "../../shared/api";

interface TrendChartProps {
  data: TrendPoint[];
}

export const TrendChart = memo(function TrendChart({ data }: TrendChartProps) {
  const windowMs = useMemo(() => {
    if (data.length < 2) return 0;
    const first = new Date(data[0]!.bucketStart).getTime();
    const last = new Date(data[data.length - 1]!.bucketEnd).getTime();
    return last - first;
  }, [data]);

  const chartData = useMemo(
    () =>
      data.map((point) => ({
        ...point,
        label: formatBucketLabel(point.bucketStart, windowMs),
        statusLevel: getStatusLevel(point),
      })),
    [data, windowMs],
  );

  if (data.length === 0) {
    return <div className="trend-empty">暂无趋势数据</div>;
  }

  return (
    <div className="trend-chart">
      <ResponsiveContainer height={280} width="100%">
        <LineChart data={chartData}>
          <CartesianGrid stroke="var(--td-border-level-2-color)" strokeDasharray="3 3" />
          <XAxis dataKey="label" stroke="var(--td-text-color-secondary)" tick={{ fontSize: 12 }} />
          <YAxis
            label={{ fontSize: 11, position: "insideTopRight", value: "ms" }}
            stroke="var(--td-text-color-secondary)"
            tick={{ fontSize: 12 }}
            yAxisId="duration"
          />
          <Tooltip content={<TrendTooltip />} />
          <Line
            connectNulls={false}
            dataKey="avgDurationMs"
            dot={false}
            name="avgDurationMs"
            stroke="var(--td-brand-color)"
            strokeWidth={2}
            type="monotone"
            yAxisId="duration"
          />
          <Line
            connectNulls={false}
            dataKey="p95DurationMs"
            dot={false}
            name="p95DurationMs"
            stroke="var(--td-warning-color)"
            strokeDasharray="4 2"
            strokeWidth={1}
            type="monotone"
            yAxisId="duration"
          />
        </LineChart>
      </ResponsiveContainer>
      <div className="trend-status-bar">
        {chartData.map((point) => (
          <div
            className={`trend-status-block trend-status-block--${point.statusLevel}`}
            key={point.bucketStart}
            title={`${point.label}: ${getStatusText(point)}`}
          />
        ))}
      </div>
    </div>
  );
});

function formatBucketLabel(bucketStart: string, windowMs: number): string {
  const date = new Date(bucketStart);
  if (windowMs > 24 * 60 * 60 * 1000) {
    return date.toLocaleString("zh-CN", {
      day: "2-digit",
      hour: "2-digit",
      hour12: false,
      minute: "2-digit",
      month: "2-digit",
    });
  }
  return date.toLocaleTimeString("zh-CN", { hour: "2-digit", hour12: false, minute: "2-digit" });
}

function formatTime(iso: string): string {
  return new Date(iso).toLocaleTimeString("zh-CN", { hour: "2-digit", hour12: false, minute: "2-digit" });
}

function getStatusLevel(point: TrendPoint): "down" | "empty" | "ok" | "partial" {
  if (point.totalChecks === 0) return "empty";
  if (point.availability >= 100) return "ok";
  if (point.availability > 0) return "partial";
  return "down";
}

function getStatusText(point: TrendPoint): string {
  const level = getStatusLevel(point);
  if (level === "empty") return "无检查数据";
  if (level === "ok") return "正常";
  if (level === "partial") return "部分异常";
  return "全异常";
}

function TrendTooltip({ active, payload }: { active?: boolean; payload?: Array<{ payload: TrendPoint }> }) {
  if (!active || !payload?.length) return null;
  const point = payload[0]!.payload;
  const level = getStatusLevel(point);
  const timeRange = `${formatTime(point.bucketStart)} - ${formatTime(point.bucketEnd)}`;

  return (
    <div className="trend-tooltip">
      <div className="trend-tooltip-time">{timeRange}</div>
      {level === "empty" ? (
        <div className="trend-tooltip-empty">无检查数据</div>
      ) : (
        <>
          <div>可用率：{point.availability.toFixed(1)}%</div>
          <div>
            成功/总数：{point.upChecks}/{point.totalChecks}
          </div>
          <div>失败数：{point.downChecks}</div>
          {point.avgDurationMs !== null && <div>平均耗时：{Math.round(point.avgDurationMs)}ms</div>}
          {point.p95DurationMs !== null && <div>P95：{Math.round(point.p95DurationMs)}ms</div>}
        </>
      )}
    </div>
  );
}
