import React, { useMemo, useRef, useState, useEffect } from "react";

function formatValue(v) {
  if (typeof v === "number") {
    return v.toLocaleString(undefined, { maximumFractionDigits: 2 });
  }
  return String(v);
}

const COLORS = [
  "var(--cyan)", "var(--purple)", "var(--green)", "var(--yellow)",
  "var(--red)", "#ff9f43", "#a29bfe", "#fd79a8", "#00cec9", "#e17055",
];

// ─── Horizontal bars (original) ──────────────────────────────────
function HBarChart({ data, maxValue }) {
  return (
    <div style={{ flex: 1, overflow: "auto", padding: "4px 0" }}>
      {data.length === 0 ? (
        <div style={{ padding: 40, textAlign: "center", color: "var(--text-dim)" }}>No data</div>
      ) : (
        data.map((r, i) => (
          <div
            key={r.group}
            style={{
              display: "flex", alignItems: "center", gap: 8,
              padding: "4px 16px", fontSize: 12,
              background: i % 2 === 1 ? "var(--row-alt)" : "transparent",
            }}
            onMouseEnter={(e) => { e.currentTarget.style.background = "var(--row-hover)"; }}
            onMouseLeave={(e) => { e.currentTarget.style.background = i % 2 === 1 ? "var(--row-alt)" : "transparent"; }}
          >
            <span style={{ width: 120, flexShrink: 0, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: "var(--text)", fontSize: 11 }} title={r.group}>
              {r.group}
            </span>
            <div style={{ flex: 1, height: 18, background: "rgba(34, 211, 238, 0.06)", borderRadius: 3, overflow: "hidden" }}>
              <div style={{ width: `${(Math.abs(r.value) / maxValue) * 100}%`, height: "100%", background: "var(--cyan)", opacity: 0.4, borderRadius: 3, transition: "width 0.3s ease", minWidth: 2 }} />
            </div>
            <span style={{ width: 80, flexShrink: 0, textAlign: "right", color: "var(--cyan)", fontWeight: 600, fontSize: 11 }}>
              {formatValue(r.value)}
            </span>
          </div>
        ))
      )}
    </div>
  );
}

// ─── Vertical bars ───────────────────────────────────────────────
function VBarChart({ data, maxValue }) {
  const containerRef = useRef(null);
  const [size, setSize] = useState({ w: 400, h: 300 });

  useEffect(() => {
    if (!containerRef.current) return;
    const ro = new ResizeObserver((entries) => {
      const { width, height } = entries[0].contentRect;
      setSize({ w: width, h: height });
    });
    ro.observe(containerRef.current);
    return () => ro.disconnect();
  }, []);

  const padding = { top: 20, right: 20, bottom: 60, left: 60 };
  const chartW = size.w - padding.left - padding.right;
  const chartH = size.h - padding.top - padding.bottom;
  const barW = data.length > 0 ? Math.min(40, (chartW / data.length) * 0.7) : 20;
  const gap = data.length > 0 ? chartW / data.length : 0;

  return (
    <div ref={containerRef} style={{ flex: 1, overflow: "hidden" }}>
      <svg width={size.w} height={size.h}>
        {/* Y axis */}
        <line x1={padding.left} y1={padding.top} x2={padding.left} y2={padding.top + chartH} stroke="var(--border)" strokeWidth={1} />
        {/* X axis */}
        <line x1={padding.left} y1={padding.top + chartH} x2={padding.left + chartW} y2={padding.top + chartH} stroke="var(--border)" strokeWidth={1} />
        {/* Y labels */}
        {[0, 0.25, 0.5, 0.75, 1].map((frac) => {
          const y = padding.top + chartH * (1 - frac);
          return (
            <g key={frac}>
              <line x1={padding.left - 4} y1={y} x2={padding.left + chartW} y2={y} stroke="var(--border)" strokeWidth={0.5} strokeDasharray={frac > 0 ? "2,4" : "0"} />
              <text x={padding.left - 8} y={y + 3} textAnchor="end" fill="var(--text-dim)" fontSize={9}>{formatValue(Math.round(maxValue * frac))}</text>
            </g>
          );
        })}
        {/* Bars */}
        {data.map((r, i) => {
          const x = padding.left + gap * i + (gap - barW) / 2;
          const barH = maxValue > 0 ? (Math.abs(r.value) / maxValue) * chartH : 0;
          const y = padding.top + chartH - barH;
          return (
            <g key={r.group}>
              <rect x={x} y={y} width={barW} height={barH} fill={COLORS[i % COLORS.length]} opacity={0.6} rx={2} />
              <text x={x + barW / 2} y={padding.top + chartH + 12} textAnchor="middle" fill="var(--text-dim)" fontSize={9} transform={`rotate(-35, ${x + barW / 2}, ${padding.top + chartH + 12})`}>
                {r.group.length > 10 ? r.group.slice(0, 9) + "…" : r.group}
              </text>
            </g>
          );
        })}
      </svg>
    </div>
  );
}

// ─── Pie chart ───────────────────────────────────────────────────
function PieChart({ data }) {
  const containerRef = useRef(null);
  const [size, setSize] = useState({ w: 400, h: 300 });

  useEffect(() => {
    if (!containerRef.current) return;
    const ro = new ResizeObserver((entries) => {
      const { width, height } = entries[0].contentRect;
      setSize({ w: width, h: height });
    });
    ro.observe(containerRef.current);
    return () => ro.disconnect();
  }, []);

  const total = data.reduce((s, r) => s + Math.abs(r.value), 0);
  const radius = Math.min(size.w * 0.35, (size.h - 20) * 0.45);
  const cx = size.w * 0.4;
  const cy = size.h / 2;

  let cumAngle = -Math.PI / 2;
  const slices = data.map((r, i) => {
    const frac = total > 0 ? Math.abs(r.value) / total : 0;
    const angle = frac * Math.PI * 2;
    const startAngle = cumAngle;
    cumAngle += angle;
    const endAngle = cumAngle;
    const largeArc = angle > Math.PI ? 1 : 0;
    const x1 = cx + radius * Math.cos(startAngle);
    const y1 = cy + radius * Math.sin(startAngle);
    const x2 = cx + radius * Math.cos(endAngle);
    const y2 = cy + radius * Math.sin(endAngle);
    const d = frac >= 1
      ? `M ${cx - radius} ${cy} A ${radius} ${radius} 0 1 1 ${cx + radius} ${cy} A ${radius} ${radius} 0 1 1 ${cx - radius} ${cy}`
      : `M ${cx} ${cy} L ${x1} ${y1} A ${radius} ${radius} 0 ${largeArc} 1 ${x2} ${y2} Z`;
    return { ...r, d, color: COLORS[i % COLORS.length], frac };
  });

  const legendX = size.w * 0.72;

  return (
    <div ref={containerRef} style={{ flex: 1, overflow: "hidden" }}>
      <svg width={size.w} height={size.h}>
        {slices.map((s) => (
          <path key={s.group} d={s.d} fill={s.color} opacity={0.7} stroke="var(--bg)" strokeWidth={1.5} />
        ))}
        {/* Legend */}
        {slices.slice(0, 12).map((s, i) => (
          <g key={s.group} transform={`translate(${legendX}, ${20 + i * 18})`}>
            <rect width={10} height={10} fill={s.color} opacity={0.7} rx={2} />
            <text x={14} y={9} fill="var(--text)" fontSize={10}>{s.group.length > 14 ? s.group.slice(0, 13) + "…" : s.group}</text>
            <text x={14 + 110} y={9} fill="var(--text-dim)" fontSize={9} textAnchor="end">{(s.frac * 100).toFixed(1)}%</text>
          </g>
        ))}
        {data.length > 12 && (
          <text x={legendX} y={20 + 12 * 18 + 10} fill="var(--text-dim)" fontSize={9}>+{data.length - 12} more...</text>
        )}
      </svg>
    </div>
  );
}

// ─── Line / Area chart ───────────────────────────────────────────
function LineAreaChart({ data, maxValue, filled }) {
  const containerRef = useRef(null);
  const [size, setSize] = useState({ w: 400, h: 300 });

  useEffect(() => {
    if (!containerRef.current) return;
    const ro = new ResizeObserver((entries) => {
      const { width, height } = entries[0].contentRect;
      setSize({ w: width, h: height });
    });
    ro.observe(containerRef.current);
    return () => ro.disconnect();
  }, []);

  const padding = { top: 20, right: 20, bottom: 60, left: 60 };
  const chartW = size.w - padding.left - padding.right;
  const chartH = size.h - padding.top - padding.bottom;

  const points = data.map((r, i) => {
    const x = padding.left + (data.length > 1 ? (i / (data.length - 1)) * chartW : chartW / 2);
    const y = padding.top + chartH - (maxValue > 0 ? (Math.abs(r.value) / maxValue) * chartH : 0);
    return { x, y, ...r };
  });

  const polyline = points.map((p) => `${p.x},${p.y}`).join(" ");
  const areaPath = points.length > 0
    ? `M ${padding.left} ${padding.top + chartH} ` + points.map((p) => `L ${p.x} ${p.y}`).join(" ") + ` L ${padding.left + chartW} ${padding.top + chartH} Z`
    : "";

  return (
    <div ref={containerRef} style={{ flex: 1, overflow: "hidden" }}>
      <svg width={size.w} height={size.h}>
        {/* Y axis */}
        <line x1={padding.left} y1={padding.top} x2={padding.left} y2={padding.top + chartH} stroke="var(--border)" strokeWidth={1} />
        <line x1={padding.left} y1={padding.top + chartH} x2={padding.left + chartW} y2={padding.top + chartH} stroke="var(--border)" strokeWidth={1} />
        {/* Y labels */}
        {[0, 0.25, 0.5, 0.75, 1].map((frac) => {
          const y = padding.top + chartH * (1 - frac);
          return (
            <g key={frac}>
              <line x1={padding.left - 4} y1={y} x2={padding.left + chartW} y2={y} stroke="var(--border)" strokeWidth={0.5} strokeDasharray={frac > 0 ? "2,4" : "0"} />
              <text x={padding.left - 8} y={y + 3} textAnchor="end" fill="var(--text-dim)" fontSize={9}>{formatValue(Math.round(maxValue * frac))}</text>
            </g>
          );
        })}
        {/* Area fill */}
        {filled && areaPath && <path d={areaPath} fill="var(--cyan)" opacity={0.15} />}
        {/* Line */}
        {points.length > 1 && <polyline points={polyline} fill="none" stroke="var(--cyan)" strokeWidth={2} opacity={0.8} />}
        {/* Dots */}
        {points.map((p) => (
          <circle key={p.group} cx={p.x} cy={p.y} r={3.5} fill="var(--cyan)" opacity={0.9} />
        ))}
        {/* X labels */}
        {points.map((p, i) => (
          <text key={p.group} x={p.x} y={padding.top + chartH + 12} textAnchor="middle" fill="var(--text-dim)" fontSize={9} transform={`rotate(-35, ${p.x}, ${padding.top + chartH + 12})`}>
            {p.group.length > 10 ? p.group.slice(0, 9) + "…" : p.group}
          </text>
        ))}
      </svg>
    </div>
  );
}

// ─── Main component ──────────────────────────────────────────────
export default function GroupByView({ results, config, tableName, chartType = "hbar" }) {
  const data = results?.results ?? [];

  const maxValue = useMemo(
    () => Math.max(...data.map((r) => Math.abs(r.value)), 1),
    [data]
  );

  const aggLabel =
    config?.aggregation === "count"
      ? "COUNT"
      : `${(config?.aggregation || "count").toUpperCase()} of ${config?.valueColumn || "?"}`;

  return (
    <div style={{ flex: 1, display: "flex", flexDirection: "column", overflow: "hidden" }}>
      {/* Header */}
      <div
        style={{
          padding: "6px 16px", fontSize: 11, color: "var(--text-dim)",
          borderBottom: "1px solid var(--border)", background: "var(--panel)",
          flexShrink: 0,
        }}
      >
        GROUP BY <span style={{ color: "var(--text)" }}>{config?.groupByColumn}</span>
        {" — "}{aggLabel}
        <span style={{ marginLeft: 8, opacity: 0.6 }}>{data.length} groups</span>
      </div>

      {/* Chart */}
      {data.length === 0 ? (
        <div style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", color: "var(--text-dim)" }}>No data</div>
      ) : chartType === "hbar" ? (
        <HBarChart data={data} maxValue={maxValue} />
      ) : chartType === "vbar" ? (
        <VBarChart data={data} maxValue={maxValue} />
      ) : chartType === "pie" ? (
        <PieChart data={data} />
      ) : chartType === "line" ? (
        <LineAreaChart data={data} maxValue={maxValue} filled={false} />
      ) : chartType === "area" ? (
        <LineAreaChart data={data} maxValue={maxValue} filled={true} />
      ) : (
        <HBarChart data={data} maxValue={maxValue} />
      )}
    </div>
  );
}
