import { useCallback, useMemo, useState } from 'react';
import { resolveColorToken } from '../utils/token-resolver.js';
import { useChartChrome } from './chart-chrome';
import { FloatingTooltip } from './native';
import ChartTooltip from './ChartTooltip';

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

const FALLBACK_MAIN = '#3D71FF';
const FALLBACK_DANGER = '#FC7E90';
const FALLBACK_TEXT = '#475467';
const FALLBACK_GRID = '#E4E7EC';
const FALLBACK_AXIS = '#98A2B3';

/** 范围条/进度条/目标线，子段 height 占 band 比例 */
const RANGE_BAR_RATIO = 0.55;
const MEASURE_BAR_RATIO = 0.28;
const TARGET_LINE_RATIO = 0.65;

function clampPositiveArray(values, fallback) {
  const list = Array.isArray(values) ? values : [fallback];
  const parsed = list.map((v) => Number(v)).filter((v) => Number.isFinite(v) && v >= 0);
  return parsed.length ? parsed : [fallback];
}

function hexToRgba(hex, alpha) {
  const raw = String(hex || '').replace('#', '').trim();
  if (!/^[0-9a-fA-F]{3,8}$/.test(raw)) return `rgba(61, 113, 255, ${alpha})`;
  let h = raw;
  if (h.length === 3 || h.length === 4) {
    h = h.split('').map((c) => c + c).join('');
  }
  const rgb = h.slice(0, 6);
  const r = Number.parseInt(rgb.slice(0, 2), 16);
  const g = Number.parseInt(rgb.slice(2, 4), 16);
  const b = Number.parseInt(rgb.slice(4, 6), 16);
  if (![r, g, b].every(Number.isFinite)) return `rgba(61, 113, 255, ${alpha})`;
  return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}

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

/**
 * SmartBulletChart（native 实现）
 *
 * 三变体：
 *  - grouped（默认）：横向 bullet，每行一个 title，可按 group 分组着色
 *  - basic：横向 bullet，无 group
 *  - transposed：纵向 bullet（band 横排，刻度纵向）
 *
 * 配色硬约束（来自 dashboard.rules）：
 *  - ranges = mainColor @ 10%
 *  - measures = mainColor @ 100%
 *  - targets = 红色目标线 100%
 */
export default function SmartBulletChart({ spec }) {
  const rawConfig = spec?.config || {};
  const variant = ['grouped', 'basic', 'transposed'].includes(rawConfig.variant)
    ? rawConfig.variant
    : 'grouped';
  const resolveOpts = useMemo(
    () => (rawConfig.resolveRoot ? { root: rawConfig.resolveRoot } : {}),
    [rawConfig.resolveRoot],
  );
  const chrome = useChartChrome(resolveOpts);

  const mainColor = rawConfig.mainColor
    || resolveColorToken(rawConfig.mainColorToken || 'data-0', resolveOpts)
    || FALLBACK_MAIN;
  const targetColor = rawConfig.targetColor
    || resolveColorToken(rawConfig.targetColorToken || 'data-4', resolveOpts)
    || FALLBACK_DANGER;
  const textColor = chrome.textSecondary || FALLBACK_TEXT;
  const gridColor = chrome.gridStroke || FALLBACK_GRID;
  const axisColor = chrome.baselineStroke || FALLBACK_AXIS;
  const rangeColor = rawConfig.rangeColor || hexToRgba(mainColor, 0.1);

  const data = useMemo(() => {
    const list = Array.isArray(spec?.data) ? spec.data : [];
    return list.map((row, idx) => ({
      title: row?.title || row?.name || `数据${idx + 1}`,
      ranges: clampPositiveArray(row?.ranges, 100),
      measures: clampPositiveArray(row?.measures, 0),
      targets: clampPositiveArray(row?.targets, 0),
      group: row?.group || row?.series || undefined,
    }));
  }, [spec?.data]);

  const chartHeight = Number(rawConfig.height) > 0 ? Number(rawConfig.height) : 340;
  const legendPosition = ['top', 'bottom'].includes(rawConfig.legendPosition)
    ? rawConfig.legendPosition
    : 'top';
  const showLegend = rawConfig.showLegend !== false && rawConfig.legend !== false;
  const showAxis = rawConfig.xAxis !== false && rawConfig.yAxis !== false;
  const showGrid = rawConfig.grid !== false;
  const showTooltip = rawConfig.tooltip !== false;
  const sparkline = rawConfig.sparkline === true;

  // 计算全局最大值（用于刻度轴范围）
  const globalMax = useMemo(() => {
    let m = 0;
    for (const row of data) {
      for (const v of row.ranges) m = Math.max(m, v);
      for (const v of row.measures) m = Math.max(m, v);
      for (const v of row.targets) m = Math.max(m, v);
    }
    return m > 0 ? m : 100;
  }, [data]);

  const isTransposed = variant === 'transposed';

  const legendItems = [
    { key: 'ranges', label: '范围条', color: rangeColor },
    { key: 'measures', label: '进度条', color: mainColor },
    { key: 'targets', label: '目标线', color: targetColor },
  ];

  const isVerticalLegend = legendPosition === 'left' || legendPosition === 'right';
  const hostStyle = !showLegend
    ? { width: '100%', maxWidth: '100%', height: chartHeight }
    : isVerticalLegend
      ? {
          width: '100%',
          maxWidth: '100%',
          height: chartHeight,
          display: 'grid',
          gridTemplateColumns: legendPosition === 'left' ? 'auto 1fr' : '1fr auto',
          columnGap: 20,
        }
      : {
          width: '100%',
          maxWidth: '100%',
          height: chartHeight,
          display: 'grid',
          gridTemplateRows: legendPosition === 'top' ? 'auto 1fr' : '1fr auto',
          rowGap: 12,
        };
  const legendWrapStyle = {
    display: 'flex',
    flexDirection: isVerticalLegend ? 'column' : 'row',
    alignItems: isVerticalLegend ? 'flex-start' : 'center',
    justifyContent: isVerticalLegend ? 'flex-start' : 'center',
    gap: isVerticalLegend ? 8 : 20,
    minWidth: isVerticalLegend ? 88 : undefined,
  };
  const chartWrapStyle = { minWidth: 0, minHeight: 0, width: '100%', height: '100%', overflow: 'hidden' };

  return (
    <div
      className="smart-bullet-chart"
      style={{
        ...hostStyle,
        outline: 'none',
        background: 'var(--color-surface, #FFFFFF)',
        overflow: 'hidden',
      }}
    >
      {showLegend && (legendPosition === 'top' || legendPosition === 'left') ? (
        <div style={legendWrapStyle}>
          {legendItems.map((item) => (
            <div key={item.key} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <span aria-hidden style={{ width: 8, height: 8, borderRadius: 999, backgroundColor: item.color, flexShrink: 0 }} />
              <span style={{ color: textColor, fontSize: 12, lineHeight: '16px' }}>{item.label}</span>
            </div>
          ))}
        </div>
      ) : null}

      <div style={chartWrapStyle}>
        <BulletSvg
          data={data}
          globalMax={globalMax}
          isTransposed={isTransposed}
          mainColor={mainColor}
          rangeColor={rangeColor}
          targetColor={targetColor}
          textColor={textColor}
          gridColor={gridColor}
          axisColor={axisColor}
          showAxis={showAxis}
          showGrid={showGrid}
          showTooltip={showTooltip}
          sparkline={sparkline}
        />
      </div>

      {showLegend && (legendPosition === 'bottom' || legendPosition === 'right') ? (
        <div style={legendWrapStyle}>
          {legendItems.map((item) => (
            <div key={item.key} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
              <span aria-hidden style={{ width: 8, height: 8, borderRadius: 999, backgroundColor: item.color, flexShrink: 0 }} />
              <span style={{ color: textColor, fontSize: 12, lineHeight: '16px' }}>{item.label}</span>
            </div>
          ))}
        </div>
      ) : null}
    </div>
  );
}

/**
 * Bullet 主体 SVG：测量容器尺寸自适应渲染
 */
function BulletSvg({
  data,
  globalMax,
  isTransposed,
  mainColor,
  rangeColor,
  targetColor,
  textColor,
  gridColor,
  axisColor,
  showAxis,
  showGrid,
  showTooltip,
  sparkline,
}) {
  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 [hover, setHover] = useState(null); // { idx, x, y, containerW }

  const titleAxisGutter = sparkline ? 0 : (isTransposed ? 24 : 80);
  const valueAxisGutter = sparkline ? 0 : 24;

  // 边距
  const pad = { top: 8, right: 16, bottom: showAxis && !isTransposed ? valueAxisGutter : 8, left: showAxis ? titleAxisGutter : 8 };
  if (isTransposed) {
    pad.bottom = showAxis ? titleAxisGutter : 8;
    pad.left = showAxis ? valueAxisGutter : 8;
  }

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

  const N = data.length || 1;

  // band 维度：横向时是 row（垂直堆叠），转置时是 column（水平排列）
  const bandSize = isTransposed ? innerW / N : innerH / N;
  const bandPadding = bandSize * 0.18;
  const bandInner = Math.max(8, bandSize - bandPadding);

  // value 维度像素长度
  const valuePx = isTransposed ? innerH : innerW;

  /** 给定 value，返回起点像素 */
  const valueStart = isTransposed ? pad.top + innerH : pad.left;
  const valueDir = isTransposed ? -1 : 1; // 转置时数值轴向上为正
  const valueAt = (v) => {
    const t = globalMax > 0 ? Math.max(0, Math.min(1, v / globalMax)) : 0;
    return valueStart + valueDir * t * valuePx;
  };

  /** 给定 band index，返回 band 起点（左/上） */
  const bandStart = (i) => (isTransposed ? pad.left + i * bandSize : pad.top + i * bandSize);

  // 生成刻度（5 段）
  const valueTicks = useMemo(() => {
    const n = 5;
    return Array.from({ length: n + 1 }, (_, k) => Math.round((globalMax * k) / n));
  }, [globalMax]);

  const handleMove = useCallback((e, idx) => {
    if (!showTooltip) return;
    const host = e.currentTarget.ownerSVGElement?.parentElement;
    if (!host) return;
    const rect = host.getBoundingClientRect();
    setHover({
      idx,
      x: e.clientX - rect.left,
      y: e.clientY - rect.top,
      clientX: e.clientX,
      clientY: e.clientY,
      containerW: rect.width,
    });
  }, [showTooltip]);

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

  const activeRow = hover?.idx != null ? data[hover.idx] : null;

  return (
    <div ref={containerRef} style={{ position: 'relative', width: '100%', height: '100%' }}>
      {size.w > 0 && size.h > 0 && (
        <svg
          width={size.w}
          height={size.h}
          style={{ display: 'block', overflow: 'visible' }}
          onMouseLeave={handleLeave}
        >
          {/* 网格线（沿数值轴方向） */}
          {showGrid && valueTicks.map((tickV, i) => {
            const px = valueAt(tickV);
            if (isTransposed) {
              return (
                <line
                  key={`gv-${i}`}
                  x1={pad.left}
                  x2={pad.left + innerW}
                  y1={px}
                  y2={px}
                  stroke={gridColor}
                  strokeWidth={1}
                  strokeDasharray="3 3"
                />
              );
            }
            return (
              <line
                key={`gv-${i}`}
                x1={px}
                x2={px}
                y1={pad.top}
                y2={pad.top + innerH}
                stroke={gridColor}
                strokeWidth={1}
                strokeDasharray="3 3"
              />
            );
          })}

          {/* 主轴 baseline */}
          {showAxis && (() => {
            if (isTransposed) {
              return (
                <line
                  x1={pad.left}
                  x2={pad.left + innerW}
                  y1={pad.top + innerH}
                  y2={pad.top + innerH}
                  stroke={axisColor}
                  strokeWidth={1}
                />
              );
            }
            return (
              <line
                x1={pad.left}
                x2={pad.left}
                y1={pad.top}
                y2={pad.top + innerH}
                stroke={axisColor}
                strokeWidth={1}
              />
            );
          })()}

          {/* 数值轴刻度文字 */}
          {showAxis && !sparkline && valueTicks.map((tickV, i) => {
            const px = valueAt(tickV);
            if (isTransposed) {
              return (
                <text
                  key={`vt-${i}`}
                  x={pad.left - 6}
                  y={px}
                  textAnchor="end"
                  dominantBaseline="middle"
                  fill={textColor}
                  fontSize={12}
                >
                  {String(tickV)}
                </text>
              );
            }
            return (
              <text
                key={`vt-${i}`}
                x={px}
                y={pad.top + innerH + 14}
                textAnchor="middle"
                fill={textColor}
                fontSize={12}
              >
                {String(tickV)}
              </text>
            );
          })}

          {/* 每个 band：ranges → measures → targets */}
          {data.map((row, idx) => {
            const bs = bandStart(idx);
            const bandCenter = bs + bandSize / 2;
            const rangeH = bandInner * RANGE_BAR_RATIO;
            const measureH = bandInner * MEASURE_BAR_RATIO;
            const targetH = bandInner * TARGET_LINE_RATIO;

            // ranges：取最大值，画一条整长 bar
            const rangeMax = row.ranges[row.ranges.length - 1];
            // measures：取最大值
            const measureMax = row.measures[row.measures.length - 1];
            // targets：所有目标值都画
            const targets = row.targets;

            if (isTransposed) {
              // 纵向：band 在 x 方向，value 在 y 方向（向上为正）
              const xCenter = bandCenter;
              const yBase = pad.top + innerH;
              const yRange = valueAt(rangeMax);
              const yMeasure = valueAt(measureMax);
              return (
                <g key={`row-${idx}`} onMouseMove={(e) => handleMove(e, idx)}>
                  {/* hit-area 透明层 */}
                  <rect
                    x={bs}
                    y={pad.top}
                    width={bandSize}
                    height={innerH}
                    fill="transparent"
                  />
                  {/* range 条 */}
                  <rect
                    x={xCenter - rangeH / 2}
                    y={yRange}
                    width={rangeH}
                    height={Math.max(0, yBase - yRange)}
                    fill={rangeColor}
                    rx={sparkline ? 1 : 2}
                  />
                  {/* measure 条 */}
                  <rect
                    x={xCenter - measureH / 2}
                    y={yMeasure}
                    width={measureH}
                    height={Math.max(0, yBase - yMeasure)}
                    fill={mainColor}
                    rx={sparkline ? 1 : 2}
                  />
                  {/* target 线 */}
                  {targets.map((tv, ti) => {
                    const yT = valueAt(tv);
                    return (
                      <line
                        key={`t-${idx}-${ti}`}
                        x1={xCenter - targetH / 2}
                        x2={xCenter + targetH / 2}
                        y1={yT}
                        y2={yT}
                        stroke={targetColor}
                        strokeWidth={sparkline ? 1 : 2}
                        strokeLinecap="round"
                      />
                    );
                  })}
                  {/* title 标签 */}
                  {showAxis && !sparkline && (
                    <text
                      x={xCenter}
                      y={pad.top + innerH + 18}
                      textAnchor="middle"
                      fill={textColor}
                      fontSize={12}
                    >
                      {String(row.title)}
                    </text>
                  )}
                </g>
              );
            }

            // 横向（grouped/basic）
            const yCenter = bandCenter;
            const xStart = pad.left;
            const xRange = valueAt(rangeMax);
            const xMeasure = valueAt(measureMax);
            return (
              <g key={`row-${idx}`} onMouseMove={(e) => handleMove(e, idx)}>
                <rect
                  x={pad.left}
                  y={bs}
                  width={innerW}
                  height={bandSize}
                  fill="transparent"
                />
                <rect
                  x={xStart}
                  y={yCenter - rangeH / 2}
                  width={Math.max(0, xRange - xStart)}
                  height={rangeH}
                  fill={rangeColor}
                  rx={sparkline ? 1 : 2}
                />
                <rect
                  x={xStart}
                  y={yCenter - measureH / 2}
                  width={Math.max(0, xMeasure - xStart)}
                  height={measureH}
                  fill={mainColor}
                  rx={sparkline ? 1 : 2}
                />
                {targets.map((tv, ti) => {
                  const xT = valueAt(tv);
                  return (
                    <line
                      key={`t-${idx}-${ti}`}
                      x1={xT}
                      x2={xT}
                      y1={yCenter - targetH / 2}
                      y2={yCenter + targetH / 2}
                      stroke={targetColor}
                      strokeWidth={sparkline ? 1 : 2}
                      strokeLinecap="round"
                    />
                  );
                })}
                {/* title 标签 */}
                {showAxis && !sparkline && (
                  <text
                    x={pad.left - 8}
                    y={yCenter}
                    textAnchor="end"
                    dominantBaseline="middle"
                    fill={textColor}
                    fontSize={12}
                  >
                    {String(row.title)}
                  </text>
                )}
              </g>
            );
          })}

          {/* hover 高亮 band */}
          {hover?.idx != null && (() => {
            const bs = bandStart(hover.idx);
            if (isTransposed) {
              return (
                <rect
                  x={bs}
                  y={pad.top}
                  width={bandSize}
                  height={innerH}
                  fill="var(--color-fill-base, rgba(45, 66, 107, 0.06))"
                  pointerEvents="none"
                />
              );
            }
            return (
              <rect
                x={pad.left}
                y={bs}
                width={innerW}
                height={bandSize}
                fill="var(--color-fill-base, rgba(45, 66, 107, 0.06))"
                pointerEvents="none"
              />
            );
          })()}
        </svg>
      )}

      {/* tooltip 跟手 */}
      {showTooltip && hover && activeRow && (
        <FloatingTooltip mouse={{ clientX: hover.clientX, clientY: hover.clientY }}>
          <ChartTooltip
            variant="chart"
            label={String(activeRow.title)}
            rows={[
              { name: '范围条', value: formatNumber(activeRow.ranges[activeRow.ranges.length - 1]), color: rangeColor, dataKey: 'ranges' },
              { name: '进度条', value: formatNumber(activeRow.measures[activeRow.measures.length - 1]), color: mainColor, dataKey: 'measures' },
              { name: '目标线', value: formatNumber(activeRow.targets[activeRow.targets.length - 1]), color: targetColor, dataKey: 'targets' },
            ]}
          />
        </FloatingTooltip>
      )}
    </div>
  );
}
