import { useCallback, useMemo, useState } from 'react';
import {
  ChartRoot,
  XAxis,
  YAxis,
  Grid,
  TooltipHost,
  Legend,
  FloatingTooltip,
  bandScale,
  linearScale,
  buildLinePath,
} from './native';
import {
  CHART_DEFAULT_CATEGORY_COUNT,
  CHART_DEFAULT_Y_AXIS_TICK_COUNT,
  buildNumericYDomainZeroOrDataMin,
  chartMockCategoryDateLabel,
  normalizeDataColorToken,
  getDefaultDataColorToken,
  snapNumericAxisToIntegerUniformTicks,
} from './chart-common';
import ChartTooltip from './ChartTooltip';
import { tokenNameToCssVar } from '../utils/token-resolver.js';
import {
  CHART_DATA_LABEL_POINT_RADIUS,
  CHART_SERIES_LINE_STROKE_WIDTH,
  mergeSmartLineChartConfig,
} from './chart-line-primitives';

export { CHART_DATA_COLOR_SLOTS } from './chart-common';

const FALLBACK_LINE = '#98A2B3';

const DEFAULT_DATA = Array.from({ length: CHART_DEFAULT_CATEGORY_COUNT }, (_, idx) => ({
  name: chartMockCategoryDateLabel(idx),
  v1: 18 + idx * 2 + (idx % 3),
  v2: 14 + idx * 2 + ((idx + 1) % 4),
}));

const DEFAULT_SERIES = [
  { dataKey: 'v1', colorToken: 'data-0', name: '序列 A' },
  { dataKey: 'v2', colorToken: 'data-4', name: '序列 B' },
];

/** 取色：优先 token CSS 变量，外部 fallback hex */
function resolveSeriesColor(colorToken) {
  const v = tokenNameToCssVar(colorToken);
  if (v && v.startsWith('--')) return `var(${v}, ${FALLBACK_LINE})`;
  return FALLBACK_LINE;
}

/**
 * 折线图（native 实现，外塔 API 与原 SmartLineChart 一致）
 *
 * P1.1 覆盖：单轴 / 网格 / 多系列 / linear curve / 圆点 / hover 游标 + Tooltip / Legend
 * 后续 P1.2 补：双轴、percent 格式、step/monotone、strokeDasharray、各种 tickAlign 等
 */
export default function SmartLineChart({ spec }) {
  const { data, series, config: rawConfig } = spec || {};
  const config = mergeSmartLineChartConfig(rawConfig);
  const {
    grid,
    showLegend,
    showXAxis,
    showYAxis,
    showDots,
    showLabel,
    curveType,
    legendPosition,
    height,
    margin: marginCfg,
    yAxisTickCount = CHART_DEFAULT_Y_AXIS_TICK_COUNT,
    strokeWidth = CHART_SERIES_LINE_STROKE_WIDTH,
    legendShape,
  } = config;

  const seriesNormalized = useMemo(() => {
    const list = Array.isArray(series) && series.length > 0 ? series : DEFAULT_SERIES;
    return list.map((s, idx) => ({
      ...s,
      dataKey: s.dataKey,
      name: s.name ?? s.dataKey,
      colorToken: normalizeDataColorToken(s.colorToken || getDefaultDataColorToken(idx)),
    }));
  }, [series]);

  const seriesColors = useMemo(
    () => seriesNormalized.map((s) => resolveSeriesColor(s.colorToken)),
    [seriesNormalized],
  );

  const chartData = Array.isArray(data) && data.length > 0 ? data : DEFAULT_DATA;
  const categories = chartData.map((row) => row.name);

  // ── Y 轴 ticks（整数等距）
  const yDomain = useMemo(() => {
    return (
      buildNumericYDomainZeroOrDataMin(
        chartData,
        seriesNormalized.map((s) => s.dataKey),
      ) || [0, 1]
    );
  }, [chartData, seriesNormalized]);
  const yAxisUi = useMemo(
    () => snapNumericAxisToIntegerUniformTicks(yDomain, yAxisTickCount),
    [yDomain, yAxisTickCount],
  );

  // ── margin（包含 legend 占位）
  const margin = useMemo(() => {
    const m = {
      top: Math.max(Number(marginCfg?.top) || 0, 16),
      right: Math.max(Number(marginCfg?.right) || 0, 24),
      bottom: Math.max(Number(marginCfg?.bottom) || 0, 8),
      left: Math.max(Number(marginCfg?.left) || 0, 8),
    };
    if (showXAxis) m.bottom += 24;
    if (showYAxis) m.left += 36;
    if (showLegend) {
      if (legendPosition === 'top') m.top += 28;
      else if (legendPosition === 'bottom') m.bottom += 28;
      else if (legendPosition === 'left') m.left += 96;
      else if (legendPosition === 'right') m.right += 96;
    }
    return m;
  }, [marginCfg, showXAxis, showYAxis, showLegend, legendPosition]);

  const [active, setActive] = useState(null);
  const handleActive = useCallback((info) => setActive(info), []);

  return (
    <div
      className="smart-line-chart"
      style={{ width: '100%', height, position: 'relative', background: 'var(--color-surface, #FFFFFF)' }}
    >
      <ChartRoot height={height} margin={margin}>
        {({ width, plot }) => {
          // ── 标度
          const xScale = bandScale(categories, [plot.x, plot.x + plot.w], { paddingOuter: 0.5, paddingInner: 1 });
          const yScale = linearScale(
            [yAxisUi?.domain?.[0] ?? yDomain[0], yAxisUi?.domain?.[1] ?? yDomain[1]],
            [plot.y + plot.h, plot.y],
          );
          const yTicksRaw = yAxisUi?.ticks || [yDomain[0], yDomain[1]];

          // ── 给 Axis / Grid 用的 tick 对象
          const xTicksObj = categories.map((k) => ({
            value: k,
            x: xScale.center(k) ?? 0,
            label: String(k),
          }));
          const yTicksObj = yTicksRaw.map((v) => ({
            value: v,
            y: yScale(v),
            label: String(v),
          }));

          // ── 系列点位
          const seriesPoints = seriesNormalized.map((s) => {
            const pts = chartData
              .map((row) => {
                const x = xScale.center(row.name);
                const y = Number(row[s.dataKey]);
                if (x == null || !Number.isFinite(y)) return null;
                return { x, y: yScale(y), raw: y };
              })
              .filter(Boolean);
            return { ...s, pts };
          });

          // ── active 类目（用于 cursor + tooltip）
          const activeKey = active?.key;
          const activeRow = activeKey != null ? chartData.find((r) => r.name === activeKey) : null;
          const activeX = activeKey != null ? xScale.center(activeKey) : null;

          return (
            <>
              <svg
                width={width}
                height={height}
                style={{ display: 'block', overflow: 'visible' }}
              >
                {grid && (
                  <Grid
                    plot={plot}
                    yTicks={yTicksObj}
                    showHorizontal
                  />
                )}
                {showXAxis && <XAxis plot={plot} ticks={xTicksObj} />}
                {showYAxis && <YAxis plot={plot} ticks={yTicksObj} />}

                {/* hover 游标（虚线） */}
                {activeX != null && (
                  <line
                    x1={activeX}
                    x2={activeX}
                    y1={plot.y}
                    y2={plot.y + plot.h}
                    stroke="var(--color-border-divider, #E5E6EB)"
                    strokeWidth={1}
                    strokeDasharray="3 3"
                    pointerEvents="none"
                  />
                )}

                {/* 数据折线 */}
                {seriesPoints.map((s, i) => {
                  if (s.pts.length === 0) return null;
                  const d = buildLinePath(s.pts, curveType);
                  const color = seriesColors[i];
                  return (
                    <g key={s.dataKey}>
                      {showLabel && !showDots && s.pts.map((p, j) => (
                        <circle
                          key={`label-point-${j}`}
                          cx={p.x}
                          cy={p.y}
                          r={CHART_DATA_LABEL_POINT_RADIUS}
                          fill={color}
                          pointerEvents="none"
                        />
                      ))}
                      <path
                        d={d}
                        fill="none"
                        stroke={color}
                        strokeWidth={strokeWidth}
                        strokeLinejoin="round"
                        strokeLinecap="round"
                        strokeDasharray={s.strokeDasharray || undefined}
                      />
                      {showDots && s.pts.map((p, j) => (
                        <circle
                          key={j}
                          cx={p.x}
                          cy={p.y}
                          r={3}
                          fill={color}
                          stroke="var(--color-border-divider, #E5E6EB)"
                          strokeWidth={1}
                        />
                      ))}
                      {/* hover 高亮点（active 时显示） */}
                      {activeKey != null && (() => {
                        const hit = chartData.find((r) => r.name === activeKey);
                        if (!hit) return null;
                        const xv = xScale.center(activeKey);
                        const yv = yScale(Number(hit[s.dataKey]));
                        if (xv == null || !Number.isFinite(yv)) return null;
                        return (
                          <circle
                            cx={xv}
                            cy={yv}
                            r={4}
                            fill="#FFFFFF"
                            stroke={color}
                            strokeWidth={2}
                          />
                        );
                      })()}
                    </g>
                  );
                })}

                {/* 数据标签：按同类目做轻量避让，默认关闭 */}
                {showLabel && (() => {
                  const minGap = 14;
                  const labels = seriesPoints.flatMap((s) =>
                    s.pts.map((p, pointIndex) => ({
                      key: `${s.dataKey}-${pointIndex}`,
                      x: p.x,
                      y: p.y - 8,
                      raw: p.raw,
                    })),
                  );
                  const byX = new Map();
                  labels.forEach((label) => {
                    const key = Math.round(label.x);
                    const group = byX.get(key) || [];
                    group.push(label);
                    byX.set(key, group);
                  });
                  const placed = [];
                  const labelTopBoundary = Math.max(8, plot.y - 8);
                  byX.forEach((group) => {
                    const sorted = [...group].sort((a, b) => a.y - b.y);
                    let prevY = -Infinity;
                    sorted.forEach((label) => {
                      const y = Math.max(label.y, prevY + minGap);
                      prevY = y;
                      placed.push({
                        ...label,
                        y: Math.min(Math.max(y, labelTopBoundary), plot.y + plot.h - 4),
                      });
                    });
                  });
                  return placed.map((label) => (
                    <text
                      key={label.key}
                      x={label.x}
                      y={label.y}
                      textAnchor="middle"
                      fontSize={11}
                      fill="var(--color-foreground-secondary, #475467)"
                      pointerEvents="none"
                    >
                      {String(label.raw)}
                    </text>
                  ));
                })()}

                {/* hover 探测层：放最上面，pointerEvents */}
                <TooltipHost
                  plot={plot}
                  getCategoryAtX={(px) => xScale.invert(px)}
                  onActiveChange={handleActive}
                />
              </svg>

              {/* Legend */}
              {showLegend && (
                <div
                  style={{
                    position: 'absolute',
                    left: 0,
                    right: 0,
                    ...(legendPosition === 'top' ? { top: 0 } : {}),
                    ...(legendPosition === 'bottom' ? { bottom: 0 } : {}),
                    ...(legendPosition === 'left' ? { left: 0, top: '50%', transform: 'translateY(-50%)', right: 'auto', width: 96 } : {}),
                    ...(legendPosition === 'right' ? { right: 0, top: '50%', transform: 'translateY(-50%)', left: 'auto', width: 96 } : {}),
                    padding: '4px 8px',
                  }}
                >
                  <Legend
                    items={seriesNormalized.map((s, i) => ({ name: s.name, color: seriesColors[i] }))}
                    shape={legendShape === 'dot' ? 'dot' : 'line'}
                    position={legendPosition}
                  />
                </div>
              )}

              {/* Tooltip 浮层：通过 FloatingTooltip Portal 到 body，
                  彻底脱离任何父级 overflow / 容器裁切。 */}
              {activeRow && active && (
                <FloatingTooltip mouse={{ clientX: active.clientX, clientY: active.clientY }}>
                  <ChartTooltip
                    variant="chart"
                    label={String(activeRow.name)}
                    rows={seriesNormalized.map((s, i) => ({
                      name: s.name,
                      value: Number(activeRow[s.dataKey]),
                      color: seriesColors[i],
                      dataKey: s.dataKey,
                    }))}
                  />
                </FloatingTooltip>
              )}
            </>
          );
        }}
      </ChartRoot>
    </div>
  );
}
