import { useEffect, useMemo, useState } from 'react';
import { resolveColorToken } from '../utils/token-resolver.js';

const FALLBACK_TRACK = '#F2F4F7';
const FALLBACK_PROGRESS = '#3D71FF';
const FALLBACK_TEXT = '#1D1D2E';
const FALLBACK_SUBTEXT = '#646475';
const FALLBACK_TICK = '#9797A1';

function clamp01(v) {
  if (!Number.isFinite(v)) return 0;
  return Math.min(1, Math.max(0, v));
}

function angleForValue(value, min, max) {
  if (!Number.isFinite(value) || !Number.isFinite(min) || !Number.isFinite(max) || max <= min) {
    return Math.PI;
  }
  const t = clamp01((value - min) / (max - min));
  return Math.PI - t * Math.PI;
}

function pointAt(cx, cy, radius, rad) {
  return {
    x: cx + radius * Math.cos(rad),
    y: cy - radius * Math.sin(rad),
  };
}

function formatTick(v) {
  const n = Number(v);
  if (!Number.isFinite(n)) return '';
  return Number.isInteger(n) ? String(n) : n.toFixed(1);
}

function formatValue(v) {
  const n = Number(v);
  if (!Number.isFinite(n)) return '--';
  return Number.isInteger(n) ? String(n) : n.toFixed(1);
}

/**
 * SmartGaugeChart：半圆仪表盘，默认主色 data-0（青绿，与默认色板首位一致）。
 *
 * spec:
 *  - value: 当前值
 *  - min: 最小值（默认 3）
 *  - max: 最大值（默认 5）
 *  - tickValues: 刻度数组（默认 [3, 3.5, 4, 4.5, 5]）
 *  - config:
 *      showProgress: 是否显示进度弧
 *      animate: 是否播放入场动画
 *      durationMs: 动画时长
 *      title: 中心标题
 *      progressColorToken: 默认 data-0
 *      trackColorToken: 默认 bg-elevated
 *      textColorToken: 默认 text-primary
 *      subTextColorToken: 默认 text-secondary
 *      tickColorToken: 默认 text-tertiary
 *      resolveRoot: token 解析挂载点
 */
export default function SmartGaugeChart({ spec }) {
  const rawValue = Number(spec?.value ?? 4.2);
  const min = Number(spec?.min ?? 3);
  const max = Number(spec?.max ?? 5);
  const tickValues = Array.isArray(spec?.tickValues) && spec.tickValues.length > 0
    ? spec.tickValues
    : [3, 3.5, 4, 4.5, 5];
  const config = spec?.config || {};

  const resolveRoot = config.resolveRoot;
  const resolveOpts = useMemo(() => (resolveRoot ? { root: resolveRoot } : {}), [resolveRoot]);

  const showProgress = config.showProgress !== false;
  const animate = config.animate !== false;
  const durationMs = Number(config.durationMs) > 0 ? Number(config.durationMs) : 900;
  const centerTitle = String(config.title || '标题');

  const progressToken = config.progressColorToken || 'data-0';
  const trackToken = config.trackColorToken || 'bg-elevated';
  const textToken = config.textColorToken || 'text-primary';
  const subTextToken = config.subTextColorToken || 'text-secondary';
  const tickToken = config.tickColorToken || 'text-tertiary';

  const progressColor = useMemo(
    () => resolveColorToken(progressToken, resolveOpts) || FALLBACK_PROGRESS,
    [progressToken, resolveOpts],
  );
  const trackColor = useMemo(
    () => resolveColorToken(trackToken, resolveOpts) || FALLBACK_TRACK,
    [trackToken, resolveOpts],
  );
  const textColor = useMemo(
    () => resolveColorToken(textToken, resolveOpts) || FALLBACK_TEXT,
    [textToken, resolveOpts],
  );
  const subTextColor = useMemo(
    () => resolveColorToken(subTextToken, resolveOpts) || FALLBACK_SUBTEXT,
    [subTextToken, resolveOpts],
  );
  const tickColor = useMemo(
    () => resolveColorToken(tickToken, resolveOpts) || FALLBACK_TICK,
    [tickToken, resolveOpts],
  );

  const ratio = useMemo(() => {
    if (!showProgress) return 0;
    return clamp01((rawValue - min) / Math.max(max - min, 1e-9));
  }, [rawValue, min, max, showProgress]);

  const [displayRatio, setDisplayRatio] = useState(animate ? 0 : ratio);

  useEffect(() => {
    if (!animate) {
      setDisplayRatio(ratio);
      return;
    }
    setDisplayRatio(0);
    const raf = window.requestAnimationFrame(() => {
      setDisplayRatio(ratio);
    });
    return () => window.cancelAnimationFrame(raf);
  }, [ratio, animate]);

  const cx = 120;
  const cy = 132;
  const radius = 92;
  const stroke = 20;
  const semicircle = Math.PI * radius;
  const start = pointAt(cx, cy, radius, Math.PI);
  const end = pointAt(cx, cy, radius, 0);
  const trackPath = `M ${start.x} ${start.y} A ${radius} ${radius} 0 0 1 ${end.x} ${end.y}`;
  /** SVG viewBox：左右各预留 16 给端点刻度文字（如 "3"/"5"），底部预留 18 给基线文字 */
  const VIEWBOX_PAD_X = 16;
  const VIEWBOX_W = 240 + VIEWBOX_PAD_X * 2;
  const VIEWBOX_H = 188;

  return (
    <div
      className="relative w-full"
      style={{ aspectRatio: `${VIEWBOX_W} / ${VIEWBOX_H + 24}` }}
    >
      <svg
        viewBox={`${-VIEWBOX_PAD_X} 0 ${VIEWBOX_W} ${VIEWBOX_H}`}
        preserveAspectRatio="xMidYMin meet"
        className="absolute left-0 right-0 top-0 mx-auto block h-auto w-full max-w-[272px]"
        aria-hidden="true"
      >
        {Array.from({ length: 25 }).map((_, i) => {
          const t = i / 24;
          const rad = Math.PI - t * Math.PI;
          const p1 = pointAt(cx, cy, radius + 7, rad);
          const p2 = pointAt(cx, cy, radius + 10, rad);
          return (
            <line
              key={`minor-${i}`}
              x1={p1.x}
              y1={p1.y}
              x2={p2.x}
              y2={p2.y}
              stroke={tickColor}
              strokeWidth={0.8}
              strokeLinecap="round"
              opacity={0.65}
            />
          );
        })}

        <path
          d={trackPath}
          fill="none"
          stroke={trackColor}
          strokeWidth={stroke}
          strokeLinecap="round"
        />
        <path
          d={trackPath}
          fill="none"
          stroke={progressColor}
          strokeWidth={stroke}
          strokeLinecap="round"
          strokeDasharray={semicircle}
          strokeDashoffset={semicircle * (1 - displayRatio)}
          style={{
            transition: animate ? `stroke-dashoffset ${durationMs}ms cubic-bezier(0.2, 0.8, 0.2, 1)` : 'none',
          }}
        />

        {/* 刻度文字：放入 SVG 让其随容器自适应缩放，避免在小卡片中跑出可视区域 */}
        {tickValues.map((tick) => {
          const rad = angleForValue(Number(tick), min, max);
          const p = pointAt(cx, cy, radius + 26, rad);
          const cosA = Math.cos(rad);
          const anchor = cosA < -0.25 ? 'end' : cosA > 0.25 ? 'start' : 'middle';
          return (
            <text
              key={`tick-${tick}`}
              x={p.x}
              y={p.y + 12}
              textAnchor={anchor}
              fill={tickColor}
              fontSize={12}
              fontFamily='var(--font-number-medium, "DouyinNumberABC-Medium", Inter, system-ui, sans-serif)'
            >
              {formatTick(tick)}
            </text>
          );
        })}

        {/* 中心数值 / 副标题：放入 SVG 跟随缩放 */}
        <text
          x={cx}
          y={cy - 18}
          textAnchor="middle"
          fontSize={38}
          fontWeight={600}
          fill={textColor}
          fontFamily='var(--font-number, "DouyinNumberABC-Bold", Inter, system-ui, sans-serif)'
        >
          {formatValue(rawValue)}
        </text>
        <text
          x={cx}
          y={cy + 4}
          textAnchor="middle"
          fontSize={14}
          fill={subTextColor}
        >
          {centerTitle}
        </text>
      </svg>
    </div>
  );
}
