'use client';

import { useEffect, useRef, useState, type ReactNode } from 'react';
import type { TimePoint, DistributionBucket, HeatmapCell, SkillStat } from './mockData';

// ─── Shared Styles ──────────────────────────────────────────────────────────

const FONT = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';

// ─── Mini Sparkline (for KPI cards) ─────────────────────────────────────────

export function Sparkline({ data, color = '#5c5fbc', width = 80, height = 28 }: {
  data: number[];
  color?: string;
  width?: number;
  height?: number;
}) {
  if (data.length < 2) return null;
  const max = Math.max(...data);
  const min = Math.min(...data);
  const range = max - min || 1;
  const points = data.map((v, i) => {
    const x = (i / (data.length - 1)) * width;
    const y = height - ((v - min) / range) * (height - 4) - 2;
    return `${x},${y}`;
  }).join(' ');

  return (
    <svg width={width} height={height} style={{ display: 'block' }}>
      <polyline
        points={points}
        fill="none"
        stroke={color}
        strokeWidth={1.5}
        strokeLinecap="round"
        strokeLinejoin="round"
      />
    </svg>
  );
}

// ─── Area Chart ─────────────────────────────────────────────────────────────

export function AreaChart({ data, color = '#5c5fbc', height = 200, label }: {
  data: TimePoint[];
  color?: string;
  height?: number;
  label?: string;
}) {
  if (data.length < 2) return null;
  const values = data.map(d => d.value);
  const max = Math.max(...values) * 1.1;
  const min = Math.min(0, Math.min(...values));
  const range = max - min || 1;
  const W = 400;
  const H = height;
  const padTop = 20;
  const padBottom = 30;
  const padLeft = 40;
  const padRight = 10;
  const chartW = W;
  const chartH = H - padTop - padBottom;

  const points = data.map((d, i) => {
    const x = padLeft + (i / (data.length - 1)) * (chartW - padLeft - padRight);
    const y = padTop + chartH - ((d.value - min) / range) * chartH;
    return { x, y, ...d };
  });

  const linePath = points.map((p, i) => `${i === 0 ? 'M' : 'L'}${p.x},${p.y}`).join(' ');
  const areaPath = `${linePath} L${points[points.length - 1].x},${padTop + chartH} L${points[0].x},${padTop + chartH} Z`;

  // Y-axis ticks
  const tickCount = 4;
  const ticks = Array.from({ length: tickCount + 1 }, (_, i) => {
    const val = min + (range * i) / tickCount;
    const y = padTop + chartH - (i / tickCount) * chartH;
    return { val: Math.round(val), y };
  });

  // X-axis labels (show ~5)
  const step = Math.max(1, Math.floor(data.length / 5));
  const xLabels = data.filter((_, i) => i % step === 0 || i === data.length - 1).map((d, idx, arr) => {
    const origIdx = data.indexOf(d);
    const x = padLeft + (origIdx / (data.length - 1)) * (chartW - padLeft - padRight);
    return { label: d.date.slice(5), x }; // MM-DD
  });

  return (
    <svg viewBox={`0 0 ${chartW} ${H}`} width="100%" height={H} preserveAspectRatio="none" style={{ fontFamily: FONT }}>
      {/* Grid lines */}
      {ticks.map((t, i) => (
        <g key={i}>
          <line x1={padLeft} y1={t.y} x2={chartW - padRight} y2={t.y} stroke="#f0f0f0" strokeWidth={0.5} />
          <text x={padLeft - 4} y={t.y + 3} textAnchor="end" fill="#9ca3af" fontSize={9}>{t.val}</text>
        </g>
      ))}
      {/* Area */}
      <path d={areaPath} fill={color} opacity={0.1} />
      {/* Line */}
      <path d={linePath} fill="none" stroke={color} strokeWidth={1.8} strokeLinecap="round" strokeLinejoin="round" />
      {/* Dots on last few */}
      {points.slice(-1).map((p, i) => (
        <circle key={i} cx={p.x} cy={p.y} r={3} fill={color} />
      ))}
      {/* X labels */}
      {xLabels.map((l, i) => (
        <text key={i} x={l.x} y={H - 8} textAnchor="middle" fill="#9ca3af" fontSize={9}>{l.label}</text>
      ))}
    </svg>
  );
}

// ─── Bar Chart (Vertical) ───────────────────────────────────────────────────

export function BarChart({ data, height = 200, showValues = true }: {
  data: DistributionBucket[];
  height?: number;
  showValues?: boolean;
}) {
  const containerRef = useRef<HTMLDivElement>(null);
  const [W, setW] = useState(400);

  useEffect(() => {
    const el = containerRef.current;
    if (!el) return;
    const obs = new ResizeObserver(([entry]) => setW(entry.contentRect.width));
    obs.observe(el);
    return () => obs.disconnect();
  }, []);

  const padTop = 20;
  const padBottom = 36;
  const padLeft = 34;
  const padRight = 10;
  const chartW = W - padLeft - padRight;
  const chartH = height - padTop - padBottom;
  const rawMax = Math.max(...data.map(d => d.value));
  const max = rawMax * 1.15;

  const tickCount = 4;
  const ticks = Array.from({ length: tickCount + 1 }, (_, i) => {
    const val = Math.round((rawMax * i) / tickCount);
    const y = padTop + chartH - (i / tickCount) * ((rawMax / max) * chartH);
    return { val, y };
  });

  const slotW = chartW / data.length;
  const barWidth = Math.min(56, slotW * 0.6);
  const barOffset = (slotW - barWidth) / 2;

  return (
    <div ref={containerRef} style={{ width: '100%' }}>
      <svg viewBox={`0 0 ${W} ${height}`} width={W} height={height} style={{ display: 'block', fontFamily: FONT }}>
        {/* Y-axis gridlines + labels */}
        {ticks.map((t, i) => (
          <g key={i}>
            <line x1={padLeft} y1={t.y} x2={W - padRight} y2={t.y} stroke="#f0f0f0" strokeWidth={0.8} />
            <text x={padLeft - 5} y={t.y + 3} textAnchor="end" fill="#9ca3af" fontSize={9}>{t.val}</text>
          </g>
        ))}
        {/* Baseline */}
        <line x1={padLeft} y1={padTop + chartH} x2={W - padRight} y2={padTop + chartH} stroke="#e5e7eb" strokeWidth={1} />
        {/* Bars */}
        {data.map((d, i) => {
          const barH = (d.value / max) * chartH;
          const x = padLeft + i * slotW + barOffset;
          const y = padTop + chartH - barH;
          return (
            <g key={i}>
              <rect x={x} y={y} width={barWidth} height={barH} rx={3} fill={d.color || '#5c5fbc'} opacity={0.85} />
              {showValues && (
                <text x={x + barWidth / 2} y={y - 4} textAnchor="middle" fill="#4b5563" fontSize={9} fontWeight={600}>
                  {d.value}
                </text>
              )}
              <text x={x + barWidth / 2} y={padTop + chartH + 13} textAnchor="middle" fill="#6b7280" fontSize={9}>
                {d.label}
              </text>
            </g>
          );
        })}
      </svg>
    </div>
  );
}

// ─── Horizontal Bar Chart ───────────────────────────────────────────────────

export function HorizontalBarChart({ data, height: explicitHeight, maxBarWidth = 240 }: {
  data: DistributionBucket[];
  height?: number;
  maxBarWidth?: number;
}) {
  const max = Math.max(...data.map(d => d.value));
  const barH = 22;
  const gap = 6;
  const height = explicitHeight || data.length * (barH + gap) + 10;
  const labelW = 90;

  return (
    <svg viewBox={`0 0 ${labelW + maxBarWidth + 60} ${height}`} width="100%" height={height} preserveAspectRatio="none" style={{ fontFamily: FONT }}>
      {data.map((d, i) => {
        const y = i * (barH + gap) + 5;
        const w = (d.value / max) * maxBarWidth;
        return (
          <g key={i}>
            <text x={labelW - 6} y={y + barH / 2 + 4} textAnchor="end" fill="#4b5563" fontSize={11}>
              {d.label}
            </text>
            <rect x={labelW} y={y} width={w} height={barH} rx={4} fill={d.color || '#5c5fbc'} opacity={0.85} />
            <text x={labelW + w + 6} y={y + barH / 2 + 4} fill="#6b7280" fontSize={10}>
              {d.value}
            </text>
          </g>
        );
      })}
    </svg>
  );
}

// ─── Donut Chart ────────────────────────────────────────────────────────────

export function DonutChart({ data, size = 180 }: {
  data: DistributionBucket[];
  size?: number;
}) {
  const total = data.reduce((s, d) => s + d.value, 0);
  const cx = size / 2;
  const cy = size / 2;
  const r = size * 0.36;
  const strokeW = size * 0.14;
  let cumAngle = -90;

  const arcs = data.map((d) => {
    const angle = (d.value / total) * 360;
    const startAngle = cumAngle;
    cumAngle += angle;
    const endAngle = cumAngle;
    const startRad = (startAngle * Math.PI) / 180;
    const endRad = (endAngle * Math.PI) / 180;
    const largeArc = angle > 180 ? 1 : 0;
    const x1 = cx + r * Math.cos(startRad);
    const y1 = cy + r * Math.sin(startRad);
    const x2 = cx + r * Math.cos(endRad);
    const y2 = cy + r * Math.sin(endRad);
    return {
      d: `M ${x1} ${y1} A ${r} ${r} 0 ${largeArc} 1 ${x2} ${y2}`,
      color: d.color || '#5c5fbc',
      label: d.label,
      value: d.value,
      pct: ((d.value / total) * 100).toFixed(1),
    };
  });

  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 16 }}>
      <svg width={size} height={size} style={{ fontFamily: FONT }}>
        {arcs.map((a, i) => (
          <path key={i} d={a.d} fill="none" stroke={a.color} strokeWidth={strokeW} strokeLinecap="butt" />
        ))}
        <text x={cx} y={cy - 4} textAnchor="middle" fill="#1f2937" fontSize={18} fontWeight={700}>{total}</text>
        <text x={cx} y={cy + 12} textAnchor="middle" fill="#9ca3af" fontSize={10}>total</text>
      </svg>
      <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
        {arcs.map((a, i) => (
          <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12 }}>
            <div style={{ width: 10, height: 10, borderRadius: 2, background: a.color, flexShrink: 0 }} />
            <span style={{ color: '#4b5563' }}>{a.label}</span>
            <span style={{ color: '#9ca3af', marginLeft: 'auto' }}>{a.pct}%</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// ─── Heatmap ────────────────────────────────────────────────────────────────

export function Heatmap({ data }: { data: HeatmapCell[] }) {
  const days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
  const hours = Array.from({ length: 24 }, (_, i) => i);
  const maxVal = Math.max(...data.map(d => d.value));
  const cellSize = 18;
  const gap = 2;
  const labelW = 32;
  const labelH = 20;

  function getColor(val: number) {
    const intensity = val / maxVal;
    if (intensity < 0.1) return '#f3f4f6';
    if (intensity < 0.25) return '#e0e7ff';
    if (intensity < 0.4) return '#c7d2fe';
    if (intensity < 0.55) return '#a5b4fc';
    if (intensity < 0.7) return '#818cf8';
    if (intensity < 0.85) return '#6366f1';
    return '#4f46e5';
  }

  const W = labelW + hours.length * (cellSize + gap);
  const H = labelH + days.length * (cellSize + gap) + 10;

  return (
    <svg viewBox={`0 0 ${W} ${H}`} width="100%" height={H} preserveAspectRatio="none" style={{ fontFamily: FONT }}>
      {/* Hour labels */}
      {hours.filter(h => h % 3 === 0).map(h => (
        <text
          key={`h-${h}`}
          x={labelW + h * (cellSize + gap) + cellSize / 2}
          y={12}
          textAnchor="middle"
          fill="#9ca3af"
          fontSize={8}
        >
          {h.toString().padStart(2, '0')}
        </text>
      ))}
      {/* Day labels + cells */}
      {days.map((day, di) => (
        <g key={day}>
          <text x={0} y={labelH + di * (cellSize + gap) + cellSize / 2 + 3} fill="#6b7280" fontSize={9}>{day}</text>
          {hours.map(hour => {
            const cell = data.find(c => c.day === day && c.hour === hour);
            const val = cell?.value ?? 0;
            return (
              <rect
                key={`${day}-${hour}`}
                x={labelW + hour * (cellSize + gap)}
                y={labelH + di * (cellSize + gap)}
                width={cellSize}
                height={cellSize}
                rx={3}
                fill={getColor(val)}
              />
            );
          })}
        </g>
      ))}
    </svg>
  );
}

// ─── Skill Bar with Success Rate ────────────────────────────────────────────

export function SkillBars({ skills }: { skills: SkillStat[] }) {
  const max = Math.max(...skills.map(s => s.invocations));
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
      {skills.map((s, i) => (
        <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <span style={{ width: 160, fontSize: 12, color: '#4b5563', textAlign: 'right', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flexShrink: 0 }}>
            {s.name}
          </span>
          <div style={{ flex: 1, height: 18, background: '#f3f4f6', borderRadius: 4, overflow: 'hidden', position: 'relative' }}>
            <div
              style={{
                width: `${(s.invocations / max) * 100}%`,
                height: '100%',
                background: s.successRate >= 95 ? '#5c5fbc' : s.successRate >= 90 ? '#f59e0b' : '#ef4444',
                borderRadius: 4,
                transition: 'width 0.3s',
              }}
            />
          </div>
          <span style={{ width: 50, fontSize: 11, color: '#6b7280', textAlign: 'right', flexShrink: 0 }}>
            {s.invocations}
          </span>
          <span style={{
            width: 50,
            fontSize: 11,
            fontWeight: 600,
            textAlign: 'right',
            flexShrink: 0,
            color: s.successRate >= 95 ? '#10b981' : s.successRate >= 90 ? '#f59e0b' : '#ef4444',
          }}>
            {s.successRate}%
          </span>
        </div>
      ))}
    </div>
  );
}

// ─── Section Card Wrapper ───────────────────────────────────────────────────

export function SectionCard({ title, subtitle, children, style }: {
  title: string;
  subtitle?: string;
  children: ReactNode;
  style?: Record<string, unknown>;
}) {
  return (
    <div style={{
      background: '#fff',
      borderRadius: 14,
      boxShadow: '0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)',
      border: '1px solid #f0f0f5',
      padding: '20px 24px',
      ...style,
    }}>
      <div style={{ marginBottom: 16 }}>
        <h3 style={{ margin: 0, fontSize: 15, fontWeight: 650, color: '#1f2937' }}>{title}</h3>
        {subtitle && <p style={{ margin: '4px 0 0', fontSize: 12, color: '#9ca3af' }}>{subtitle}</p>}
      </div>
      {children}
    </div>
  );
}
