import { useCallback, useMemo, useState } from 'react';
import {
  ChartRoot,
  XAxis as NativeXAxis,
  YAxis as NativeYAxis,
  Grid,
  TooltipHost,
  Legend,
  FloatingTooltip,
  bandScale,
  linearScale,
  buildRoundedRectPath,
} from './native';
import {
  CHART_DEFAULT_CATEGORY_COUNT,
  CHART_DEFAULT_Y_AXIS_TICK_COUNT,
  buildNumericYDomainZeroOrDataMin,
  buildStackedPositiveYDomain,
  chartMockCategoryDateLabel,
  normalizeDataColorToken,
  getDefaultDataColorToken,
  snapNumericAxisToIntegerUniformTicks,
} from './chart-common';
import ChartTooltip from './ChartTooltip';
import { resolveColorToken, resolveLengthVar } from '../utils/token-resolver.js';
import {
  mergeSmartBarChartConfig,
  STACK_SEGMENT_GAP_PX,
} from './chart-bar-primitives';

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

const FALLBACK_BAR = '#98A2B3';

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

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

const BAR_CATEGORY_GAP = 0.22; // recharts barCategoryGap="22%"
const MAX_BAR_SIZE = 40;

function truncateCategoryLabel(value, maxLen = 8) {
  const limit = Math.max(1, Number(maxLen) || 8);
  const str = String(value ?? '');
  if (str.length <= limit) return str;
  return `${str.slice(0, limit - 1)}…`;
}

/**
 * 计算堆叠段在 stack 内的圆角分布：仅最外端（顶/右）保留 fullRadius，其余为 0
 * - 纵向柱：fullRadius=[r,r,0,0]，仅最高段（segmentIndex 最大且值>0）顶部圆角
 * - 横向柱：fullRadius=[0,r,r,0]，仅最右段（segmentIndex 最大且值>0）右侧圆角
 *
 * 参数 outerIndex 由调用方传入：当前 row 中实际"最外端段"的 segmentIndex
 */
function getStackSegmentRadius({ stack, segmentIndex, outerIndex, fullRadius }) {
  if (!stack) return fullRadius;
  if (segmentIndex !== outerIndex) return [0, 0, 0, 0];
  return fullRadius;
}

/**
 * 柱状图（native 实现，外塔 API 与原 SmartBarChart 一致）
 *
 * P3.1 全特性覆盖：
 * - layout: vertical (默认竖柱) / horizontal (横柱)
 * - stack: 多段堆叠 + 自绘 stack gap (2px) + 仅最外端段圆角
 * - cornerMode: square / rounded（rounded → 取 --radius-sm）
 * - showLegend / showXAxis / showYAxis / showLabel
 * - legendPosition: top / bottom / left / right
 * - yAxisWidth / yAxisCategoryPadding / categoryLabelMaxLength / plotAreaMinWidth
 * - hover: 类目背景高亮 + Tooltip 跟随鼠标
 */
export default function SmartBarChart({ spec }) {
  const { data, series, config: rawConfig } = spec || {};
  const config = mergeSmartBarChartConfig(rawConfig);
  const resolveRoot = config.resolveRoot;
  const resolveOpts = useMemo(
    () => (resolveRoot ? { root: resolveRoot } : {}),
    [resolveRoot],
  );

  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) => resolveColorToken(s.colorToken, resolveOpts) || FALLBACK_BAR),
    [seriesNormalized, resolveOpts],
  );

  const radiusPx = useMemo(() => {
    if (config.cornerMode === 'square') return 0;
    return resolveLengthVar('--radius-sm', resolveOpts) ?? 4;
  }, [config.cornerMode, resolveOpts]);

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

  const {
    layout,
    stack,
    showLegend,
    showXAxis,
    showYAxis,
    showLabel,
    legendPosition,
    height,
    margin: marginCfg,
    yAxisWidth,
    yAxisCategoryPadding,
    categoryLabelMaxLength,
    plotAreaMinWidth,
    yAxisTickCount = CHART_DEFAULT_Y_AXIS_TICK_COUNT,
  } = config;

  const isHorizontalBars = layout === 'horizontal';
  const yAxisTickCountResolved = Math.max(
    2,
    Number.isFinite(Number(yAxisTickCount)) ? Number(yAxisTickCount) : CHART_DEFAULT_Y_AXIS_TICK_COUNT,
  );

  // 数值轴 domain
  const valueDomain = useMemo(() => {
    const keys = seriesNormalized.map((s) => s.dataKey);
    if (stack) return buildStackedPositiveYDomain(chartData, keys) || [0, 1];
    return buildNumericYDomainZeroOrDataMin(chartData, keys) || [0, 1];
  }, [stack, chartData, seriesNormalized]);

  const valueAxisUi = useMemo(
    () => snapNumericAxisToIntegerUniformTicks(valueDomain, yAxisTickCountResolved),
    [valueDomain, yAxisTickCountResolved],
  );

  // margin（含 axis / legend 占位 + 横向最小宽度兜底）
  const yAxisGutter = useMemo(() => {
    if (!showYAxis) return 0;
    if (isHorizontalBars) return Number(yAxisWidth ?? 90);
    return Number(yAxisWidth ?? 44);
  }, [showYAxis, isHorizontalBars, yAxisWidth]);

  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 += yAxisGutter;
    if (showLegend) {
      // 图例自身约 20px 高 + 净距 12px + Y/X 轴顶部刻度文字高度 ~12px = 44~52px
      if (legendPosition === 'top') m.top += 52;
      else if (legendPosition === 'bottom') m.bottom += 52;
      else if (legendPosition === 'left') m.left += 96;
      else if (legendPosition === 'right') m.right += 96;
    }
    return m;
  }, [marginCfg, showXAxis, showYAxis, showLegend, legendPosition, yAxisGutter]);

  // 横向柱图 plot 区最小宽度兜底
  const containerMinWidth = useMemo(() => {
    if (!isHorizontalBars || !plotAreaMinWidth) return undefined;
    return margin.left + plotAreaMinWidth + margin.right;
  }, [isHorizontalBars, plotAreaMinWidth, margin.left, margin.right]);

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

  // fillContainer 模式：跟随父容器高度自适应（嵌入到 flex-1 卡片时用）
  const fillContainer = Boolean(config.fillContainer);
  const [measuredH, setMeasuredH] = useState(0);
  const wrapRef = useCallback((node) => {
    if (!node) return;
    const ro = new ResizeObserver((entries) => {
      for (const e of entries) setMeasuredH(Math.floor(e.contentRect.height));
    });
    ro.observe(node);
    const rect = node.getBoundingClientRect();
    setMeasuredH(Math.floor(rect.height));
  }, []);
  const effectiveHeight = fillContainer && measuredH > 0 ? measuredH : height;

  // 类目轴 padding（横向柱：纵轴；纵向柱：横轴）
  const categoryPaddingFraction = useMemo(() => {
    const inset = (() => {
      if (isHorizontalBars) {
        const top = Number(yAxisCategoryPadding?.top);
        const bottom = Number(yAxisCategoryPadding?.bottom);
        return [Number.isFinite(top) ? top : 12, Number.isFinite(bottom) ? bottom : 12];
      }
      // 纵向柱：使用全局 X_AXIS_CATEGORY_PADDING（在 native bandScale 里通过 paddingOuter 实现）
      return [12, 12];
    })();
    return inset;
  }, [isHorizontalBars, yAxisCategoryPadding]);

  return (
    <div
      ref={fillContainer ? wrapRef : undefined}
      className="smart-bar-chart"
      style={{
        width: '100%',
        minWidth: containerMinWidth,
        height: fillContainer ? '100%' : height,
        minHeight: fillContainer ? 160 : undefined,
        outline: 'none',
        background: 'var(--color-surface, #FFFFFF)',
        position: 'relative',
      }}
      tabIndex={-1}
    >
      <ChartRoot height={effectiveHeight} margin={margin}>
        {({ width, height: geomH, plot }) => {
          // ── 类目轴（categoryAxis）位于 X 或 Y
          const categories = chartData.map((row) => row.name);
          const valueRange = isHorizontalBars
            ? [plot.x, plot.x + plot.w]                 // 横向：值轴 = X 轴（左 → 右）
            : [plot.y + plot.h, plot.y];                // 纵向：值轴 = Y 轴（下 → 上）
          const valueScale = linearScale(
            [valueAxisUi?.domain?.[0] ?? valueDomain[0], valueAxisUi?.domain?.[1] ?? valueDomain[1]],
            valueRange,
          );
          const valueZero = valueScale(0);

          // 类目轴 band scale
          const categoryRange = isHorizontalBars
            ? [plot.y + categoryPaddingFraction[0], plot.y + plot.h - categoryPaddingFraction[1]]
            : [plot.x, plot.x + plot.w];
          const catScale = bandScale(categories, categoryRange, {
            paddingOuter: 0.5,
            paddingInner: BAR_CATEGORY_GAP,
          });
          const bandWidth = Math.min(catScale.bandwidth(), MAX_BAR_SIZE);

          // ── 网格 / 坐标轴 ticks
          const valueTicksRaw = valueAxisUi?.ticks || [valueDomain[0], valueDomain[1]];

          const xTicksObj = isHorizontalBars
            ? valueTicksRaw.map((v) => ({ value: v, x: valueScale(v), label: String(v) }))
            : categories.map((k) => ({ value: k, x: catScale.center(k) ?? 0, label: String(k) }));
          const yTicksObj = isHorizontalBars
            ? categories.map((k) => ({
                value: k,
                y: catScale.center(k) ?? 0,
                label: truncateCategoryLabel(k, categoryLabelMaxLength),
              }))
            : valueTicksRaw.map((v) => ({ value: v, y: valueScale(v), label: String(v) }));

          const gridYTicks = isHorizontalBars ? [] : yTicksObj;
          const gridXTicks = isHorizontalBars ? xTicksObj : [];

          // ── active 类目
          const activeKey = active?.key;
          const activeRow = activeKey != null ? chartData.find((r) => r.name === activeKey) : null;

          // ── 计算每行各段几何
          // 堆叠态：自下/自左累加；非堆叠态：在类目带宽内分组并列
          const rectsByRow = chartData.map((row) => {
            const center = catScale.center(row.name);
            if (center == null) return [];

            if (stack) {
              // 找到当前 row 的 outerIndex：value > 0 的最大 segmentIndex
              let outerIndex = -1;
              seriesNormalized.forEach((s, i) => {
                if (Number(row[s.dataKey]) > 0) outerIndex = i;
              });
              let lo = 0;
              return seriesNormalized.map((s, i) => {
                const v = Math.max(0, Number(row[s.dataKey]) || 0);
                const hi = lo + v;
                const fullRadiusBase = isHorizontalBars
                  ? [0, radiusPx, radiusPx, 0]
                  : [radiusPx, radiusPx, 0, 0];
                const radius = getStackSegmentRadius({
                  stack: true,
                  segmentIndex: i,
                  outerIndex,
                  fullRadius: fullRadiusBase,
                });
                let rect;
                if (isHorizontalBars) {
                  // 横向：x = scale(lo)，width = scale(hi) - scale(lo)
                  const x0 = valueScale(lo);
                  const x1 = valueScale(hi);
                  const left = Math.min(x0, x1);
                  const right = Math.max(x0, x1);
                  // stack gap：两侧各让出 half
                  const half = STACK_SEGMENT_GAP_PX / 2;
                  const cutLeft = i > 0 ? half : 0;
                  const cutRight = i < seriesNormalized.length - 1 && v > 0 ? half : 0;
                  rect = {
                    x: left + cutLeft,
                    y: center - bandWidth / 2,
                    w: Math.max(0, right - left - cutLeft - cutRight),
                    h: bandWidth,
                    radius,
                  };
                } else {
                  const y0 = valueScale(lo);
                  const y1 = valueScale(hi);
                  const top = Math.min(y0, y1);
                  const bot = Math.max(y0, y1);
                  const half = STACK_SEGMENT_GAP_PX / 2;
                  const cutBottom = i > 0 ? half : 0;
                  const cutTop = i < seriesNormalized.length - 1 && v > 0 ? half : 0;
                  rect = {
                    x: center - bandWidth / 2,
                    y: top + cutTop,
                    w: bandWidth,
                    h: Math.max(0, bot - top - cutTop - cutBottom),
                    radius,
                  };
                }
                lo = hi;
                return { ...rect, color: seriesColors[i], series: s, raw: Number(row[s.dataKey]) };
              });
            }

            // 非堆叠：组内并列
            const groupCount = seriesNormalized.length;
            const innerGap = 2;
            const groupBand = bandWidth;
            const eachW = (groupBand - innerGap * (groupCount - 1)) / groupCount;
            return seriesNormalized.map((s, i) => {
              const v = Number(row[s.dataKey]) || 0;
              const fullRadius = isHorizontalBars
                ? [0, radiusPx, radiusPx, 0]
                : [radiusPx, radiusPx, 0, 0];
              if (isHorizontalBars) {
                const x0 = valueZero;
                const x1 = valueScale(v);
                const left = Math.min(x0, x1);
                const right = Math.max(x0, x1);
                const yTop = center - groupBand / 2 + i * (eachW + innerGap);
                return {
                  x: left,
                  y: yTop,
                  w: right - left,
                  h: eachW,
                  radius: fullRadius,
                  color: seriesColors[i],
                  series: s,
                  raw: v,
                };
              }
              const xLeft = center - groupBand / 2 + i * (eachW + innerGap);
              const y0 = valueZero;
              const y1 = valueScale(v);
              const top = Math.min(y0, y1);
              const bot = Math.max(y0, y1);
              return {
                x: xLeft,
                y: top,
                w: eachW,
                h: bot - top,
                radius: fullRadius,
                color: seriesColors[i],
                series: s,
                raw: v,
              };
            });
          });

          return (
            <>
              <svg
                width={width}
                height={geomH}
                style={{ display: 'block', overflow: 'visible' }}
              >
                {/* 网格：仅在数值轴方向画 */}
                <Grid
                  plot={plot}
                  yTicks={gridYTicks}
                  xTicks={gridXTicks}
                  showHorizontal={!isHorizontalBars}
                  showVertical={isHorizontalBars}
                />

                {/* 类目背景高亮（hover） */}
                {activeKey != null && (() => {
                  const center = catScale.center(activeKey);
                  if (center == null) return null;
                  if (isHorizontalBars) {
                    return (
                      <rect
                        x={plot.x}
                        y={center - catScale.bandwidth() / 2}
                        width={plot.w}
                        height={catScale.bandwidth()}
                        fill="var(--color-fill-base, rgba(45, 66, 107, 0.06))"
                        pointerEvents="none"
                      />
                    );
                  }
                  return (
                    <rect
                      x={center - catScale.bandwidth() / 2}
                      y={plot.y}
                      width={catScale.bandwidth()}
                      height={plot.h}
                      fill="var(--color-fill-base, rgba(45, 66, 107, 0.06))"
                      pointerEvents="none"
                    />
                  );
                })()}

                {/* 坐标轴 */}
                {showXAxis && <NativeXAxis plot={plot} ticks={xTicksObj} />}
                {showYAxis && <NativeYAxis plot={plot} ticks={yTicksObj} />}

                {/* 柱体 */}
                {rectsByRow.map((rects, ri) => (
                  <g key={chartData[ri].name}>
                    {rects.map((rect, si) => {
                      if (rect.w <= 0 || rect.h <= 0) return null;
                      const d = buildRoundedRectPath(rect.x, rect.y, rect.w, rect.h, rect.radius);
                      return (
                        <path
                          key={`${ri}-${si}`}
                          d={d}
                          fill={rect.color}
                          stroke="none"
                        />
                      );
                    })}
                    {/* 数值标签 */}
                    {showLabel && rects.map((rect, si) => {
                      if (rect.w <= 0 || rect.h <= 0) return null;
                      const text = String(rect.raw);
                      if (isHorizontalBars) {
                        return (
                          <text
                            key={`lbl-${ri}-${si}`}
                            x={rect.x + rect.w + 6}
                            y={rect.y + rect.h / 2}
                            dominantBaseline="middle"
                            fontSize={11}
                            fill="var(--color-foreground-secondary, #475467)"
                          >{text}</text>
                        );
                      }
                      return (
                        <text
                          key={`lbl-${ri}-${si}`}
                          x={rect.x + rect.w / 2}
                          y={rect.y - 6}
                          textAnchor="middle"
                          fontSize={11}
                          fill="var(--color-foreground-secondary, #475467)"
                        >{text}</text>
                      );
                    })}
                  </g>
                ))}

                {/* hover 探测 */}
                <TooltipHost
                  plot={plot}
                  getCategoryAtX={(px, py) => {
                    if (isHorizontalBars) return catScale.invert(py);
                    return catScale.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="dot"
                    position={legendPosition}
                  />
                </div>
              )}

              {/* Tooltip 浮层（HTML 层），跟随鼠标，向右上展开；过 70% 翻到左侧 */}
              {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>
  );
}
