import { useEffect, useMemo, useState } from "react";
import { readCssToken } from "@/shared/utils/cssTokens.js";
import { EChart } from "./EChart.jsx";

const DEFAULT_COLOR_TOKENS = ["--chart-blue", "--chart-green", "--chart-orange", "--chart-red", "--info", "--stopped"];
const countFormatter = new Intl.NumberFormat("zh-CN");

export function DistributionPieChart({ ariaLabel, data = [], emptyText = "当前无数据" }) {
  const reducedMotion = usePrefersReducedMotion();
  const items = useMemo(() => normalizeDistributionItems(data), [data]);
  const option = useMemo(() => createDistributionPieOption(items, reducedMotion), [items, reducedMotion]);

  if (!items.length) {
    return (
      <div aria-label={ariaLabel} className="distribution-pie-empty" role="status">
        {emptyText}
      </div>
    );
  }

  return (
    <div aria-label={ariaLabel} className="distribution-pie" role="group">
      <EChart className="distribution-pie__chart" option={option} />
      <div className="distribution-pie__legend" role="list">
        {items.map((item) => (
          <div className="distribution-pie__legend-row" key={item.key} role="listitem" title={item.label}>
            <span className="distribution-pie__legend-dot" style={{ backgroundColor: item.color }} />
            <span className="distribution-pie__legend-label">{item.label}</span>
            <strong>{countFormatter.format(item.count)}</strong>
          </div>
        ))}
      </div>
    </div>
  );
}

export function normalizeDistributionItems(data) {
  // 过滤非法值和零值，避免 ECharts 生成不可见扇区却仍在 tooltip/图例中展示伪数据。
  return (Array.isArray(data) ? data : [])
    .map((item, index) => {
      const count = Number(item?.count);
      const colorToken = item?.colorToken || DEFAULT_COLOR_TOKENS[index % DEFAULT_COLOR_TOKENS.length];
      return {
        color: readCssToken(colorToken, "#64748b"),
        count,
        key: String(item?.key || `distribution-${index}`),
        label: String(item?.label || item?.key || "未知")
      };
    })
    .filter((item) => Number.isFinite(item.count) && item.count > 0);
}

export function createDistributionPieOption(items, reducedMotion = false) {
  return {
    animation: !reducedMotion,
    animationDuration: reducedMotion ? 0 : 450,
    animationDurationUpdate: reducedMotion ? 0 : 300,
    color: items.map((item) => item.color),
    tooltip: {
      trigger: "item",
      backgroundColor: readCssToken("--chart-tooltip-bg", "#ffffff"),
      borderColor: readCssToken("--chart-tooltip-border", "#d8e0ec"),
      textStyle: { color: readCssToken("--chart-tooltip-text", "#0f172a") },
      valueFormatter: (value) => `${countFormatter.format(Number(value) || 0)} 人`
    },
    series: [
      {
        type: "pie",
        radius: ["44%", "72%"],
        center: ["50%", "50%"],
        avoidLabelOverlap: true,
        label: { show: false },
        labelLine: { show: false },
        itemStyle: {
          borderColor: readCssToken("--bg-card", "#ffffff"),
          borderWidth: 2
        },
        emphasis: { scaleSize: 6 },
        data: items.map((item) => ({ name: item.label, value: item.count }))
      }
    ]
  };
}

function usePrefersReducedMotion() {
  const [reducedMotion, setReducedMotion] = useState(() => readReducedMotionPreference());

  useEffect(() => {
    if (typeof window.matchMedia !== "function") {
      return undefined;
    }
    const media = window.matchMedia("(prefers-reduced-motion: reduce)");
    const update = (event) => setReducedMotion(event.matches);
    setReducedMotion(media.matches);
    media.addEventListener?.("change", update);
    return () => media.removeEventListener?.("change", update);
  }, []);

  return reducedMotion;
}

function readReducedMotionPreference() {
  return typeof window !== "undefined" && typeof window.matchMedia === "function"
    ? window.matchMedia("(prefers-reduced-motion: reduce)").matches
    : false;
}
