import { useCallback, useMemo, useRef, useState } from 'react';
import FloatingTooltip from './FloatingTooltip';

/**
 * Sparkline — 微缩面积图（业务侧 Indicator/Progress 卡片专用）
 *
 * 不依赖任何图表库，纯 SVG 自渲染：
 *  - 单值序列（number[] 或 { value, at }[]）
 *  - linear 折线 + 渐变填充
 *  - 可选均值参考线（虚线）
 *  - hover 显示 tooltip 跟手（FloatingTooltip）
 *  - ResizeObserver 自适应容器尺寸
 *
 * Props
 *  - data: number[] | { value:number, at?:string }[]
 *  - color: 描边/填充主色（CSS 颜色）
 *  - strokeWidth: 默认 1.2
 *  - showMeanLine: 是否画均值参考线，默认 true
 *  - margin: { top,right,bottom,left }，默认 { top:12,right:4,bottom:0,left:4 }
 *  - tooltipEnabled: 默认 true
 *  - formatTooltipValue: (n:number) => string
 *  - height: 当不设外层 height 时给 SVG 一个回退高度
 */
export default function Sparkline({
  data,
  color = 'var(--semi-color-success)',
  strokeWidth = 1.2,
  showMeanLine = true,
  margin = { top: 12, right: 4, bottom: 0, left: 4 },
  tooltipEnabled = true,
  formatTooltipValue,
  fillStops,
  className,
  style,
  ariaLabel,
}) {
  const rows = useMemo(() => {
    const list = Array.isArray(data) ? data : [];
    return list.map((d, i) => {
      if (typeof d === 'number') {
        return { i, v: d, label: '' };
      }
      return { i, v: Number(d?.value || 0), label: d?.at || '' };
    });
  }, [data]);

  const [size, setSize] = useState({ w: 0, h: 0 });
  const containerRef = useCallback((node) => {
    if (!node) return;
    const ro = new ResizeObserver((entries) => {
      for (const e of entries) {
        const r = e.contentRect;
        setSize({ w: Math.floor(r.width), h: Math.floor(r.height) });
      }
    });
    ro.observe(node);
    const r = node.getBoundingClientRect();
    setSize({ w: Math.floor(r.width), h: Math.floor(r.height) });
  }, []);

  const gradIdRef = useRef(`sparkline-fill-${Math.random().toString(36).slice(2, 9)}`);
  const gradId = gradIdRef.current;

  const [hover, setHover] = useState(null); // { idx, clientX, clientY }

  const stops = fillStops || [
    { offset: '0%', opacity: 0.34 },
    { offset: '62%', opacity: 0.2 },
    { offset: '88%', opacity: 0.1 },
    { offset: '100%', opacity: 0.02 },
  ];

  const innerW = Math.max(0, size.w - margin.left - margin.right);
  const innerH = Math.max(0, size.h - margin.top - margin.bottom);

  // domain
  const values = rows.map((r) => r.v);
  const vMin = values.length ? Math.min(...values) : 0;
  const vMax = values.length ? Math.max(...values) : 1;
  const span = Math.max(1e-6, Math.abs(vMax - vMin) || 1);
  const yPad = span * 0.14;
  const yMin = vMin - yPad;
  const yMax = vMax + yPad;
  const yRange = yMax - yMin || 1;

  const mean = values.length ? values.reduce((a, b) => a + b, 0) / values.length : 0;

  const xAt = (i) => {
    if (rows.length <= 1) return margin.left + innerW / 2;
    return margin.left + (i / (rows.length - 1)) * innerW;
  };
  const yAt = (v) => margin.top + (1 - (v - yMin) / yRange) * innerH;

  const linePath = useMemo(() => {
    if (rows.length === 0) return '';
    return rows.map((r, i) => `${i === 0 ? 'M' : 'L'}${xAt(r.i)},${yAt(r.v)}`).join(' ');
  }, [rows, size.w, size.h]); // eslint-disable-line react-hooks/exhaustive-deps

  const areaPath = useMemo(() => {
    if (rows.length === 0) return '';
    const top = rows.map((r, i) => `${i === 0 ? 'M' : 'L'}${xAt(r.i)},${yAt(r.v)}`).join(' ');
    const last = rows[rows.length - 1];
    const baseY = margin.top + innerH;
    return `${top} L${xAt(last.i)},${baseY} L${xAt(rows[0].i)},${baseY} Z`;
  }, [rows, size.w, size.h]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleMove = useCallback(
    (e) => {
      if (!tooltipEnabled || rows.length === 0 || size.w === 0) return;
      const rect = e.currentTarget.getBoundingClientRect();
      const localX = e.clientX - rect.left;
      // 找最近 i
      const t = Math.max(0, Math.min(1, (localX - margin.left) / Math.max(1, innerW)));
      const idx = Math.round(t * (rows.length - 1));
      setHover({ idx, clientX: e.clientX, clientY: e.clientY });
    },
    [tooltipEnabled, rows.length, size.w, innerW, margin.left],
  );

  const handleLeave = useCallback(() => setHover(null), []);

  const fmt = formatTooltipValue || ((n) => String(n));

  const activeRow = hover ? rows[hover.idx] : null;
  const activeX = activeRow ? xAt(activeRow.i) : 0;

  return (
    <div
      ref={containerRef}
      className={className}
      style={{ width: '100%', height: '100%', position: 'relative', ...style }}
      aria-label={ariaLabel}
    >
      {size.w > 0 && size.h > 0 && (
        <svg
          width={size.w}
          height={size.h}
          style={{ display: 'block', overflow: 'visible' }}
          onMouseMove={handleMove}
          onMouseLeave={handleLeave}
          role="img"
        >
          <defs>
            <linearGradient id={gradId} x1="0" y1="0" x2="0" y2="1">
              {stops.map((s, i) => (
                <stop key={i} offset={s.offset} stopColor={color} stopOpacity={s.opacity} />
              ))}
            </linearGradient>
          </defs>

          {areaPath && (
            <path
              d={areaPath}
              fill={`url(#${gradId})`}
              stroke="none"
              pointerEvents="none"
            />
          )}

          {showMeanLine && rows.length > 0 && (
            <line
              x1={margin.left}
              x2={margin.left + innerW}
              y1={yAt(mean)}
              y2={yAt(mean)}
              stroke="var(--semi-color-border)"
              strokeWidth={1}
              strokeDasharray="3 3"
              pointerEvents="none"
            />
          )}

          {linePath && (
            <path
              d={linePath}
              fill="none"
              stroke={color}
              strokeWidth={strokeWidth}
              strokeLinecap="round"
              strokeLinejoin="round"
              pointerEvents="none"
            />
          )}

          {/* hover cursor + dot */}
          {hover && activeRow && (
            <g pointerEvents="none">
              <line
                x1={activeX}
                x2={activeX}
                y1={margin.top}
                y2={margin.top + innerH}
                stroke="var(--semi-color-border)"
                strokeWidth={1}
                strokeDasharray="3 3"
              />
              <circle
                cx={activeX}
                cy={yAt(activeRow.v)}
                r={3}
                fill={color}
                stroke="var(--color-surface, #FFFFFF)"
                strokeWidth={1.5}
              />
            </g>
          )}

          {/* hit area */}
          <rect
            x={margin.left}
            y={margin.top}
            width={Math.max(0, innerW)}
            height={Math.max(0, innerH)}
            fill="transparent"
          />
        </svg>
      )}

      {tooltipEnabled && hover && activeRow && (
        <FloatingTooltip mouse={{ clientX: hover.clientX, clientY: hover.clientY }}>
          <div
            className="chart-tooltip chart-tooltip--caption"
            style={{
              background: 'var(--color-surface, #FFFFFF)',
              border: '1px solid var(--color-border-divider, #E5E6EB)',
              borderRadius: 8,
              padding: '4px 8px',
              fontSize: 12,
              lineHeight: '16px',
              color: 'var(--color-foreground-secondary, #475467)',
              whiteSpace: 'nowrap',
              boxShadow: '0 2px 8px rgba(0,0,0,0.06)',
            }}
          >
            {activeRow.label ? (
              <span style={{ marginRight: 8 }}>{activeRow.label}</span>
            ) : null}
            <span style={{ fontWeight: 600, color: 'var(--color-foreground, #222727)' }}>
              {fmt(activeRow.v)}
            </span>
          </div>
        </FloatingTooltip>
      )}
    </div>
  );
}
