'use client';

/**
 * Sales Performance — Win rate over time (Report 01 Chart 3).
 *
 * Line: win rate per bucket. Faint area underlay: total deals closed
 * per bucket so a 100% win rate on 1 deal doesn't read the same as
 * 80% on 50 deals. Auto-bucket granularity (weekly / monthly /
 * quarterly) is decided server-side and labelled in the chart caption.
 *
 * Recharts (matches the dashboard convention).
 */

import {
  Area,
  CartesianGrid,
  ComposedChart,
  Line,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from 'recharts';

type Granularity = 'week' | 'month' | 'quarter';

interface WinRatePoint {
  bucket: string;
  won: number;
  lost: number;
  winRate: number | null;
}

interface Props {
  granularity: Granularity;
  points: WinRatePoint[];
}

export function SalesWinRateOverTime({ granularity, points }: Props) {
  const allEmpty = points.every((p) => p.winRate === null);
  if (allEmpty) {
    return (
      <div className="py-12 flex flex-col items-center justify-center text-center space-y-2">
        <p className="text-sm text-muted-foreground max-w-xs">
          No deals closed yet in the selected period. Win-rate trend appears here as wins and losses
          accumulate.
        </p>
      </div>
    );
  }

  // Build the chart series. Render win rate as a percentage so the
  // tooltip + axis read naturally; preserve the null gaps by passing
  // `null` for winRatePct on empty buckets (recharts skips them).
  const data = points.map((p) => ({
    bucket: formatBucket(p.bucket, granularity),
    winRatePct: p.winRate === null ? null : Math.round(p.winRate * 100 * 10) / 10,
    closed: p.won + p.lost,
  }));

  // p90 for the volume underlay scale - we want the area to feel like
  // ambient context, not dominate. Capping at p90 trims spike weeks.
  const closedSorted = data.map((d) => d.closed).sort((a, b) => a - b);
  const p90Closed = closedSorted[Math.floor(closedSorted.length * 0.9)] ?? 1;
  const maxClosed = Math.max(p90Closed, 1);

  return (
    <ResponsiveContainer width="100%" height={280}>
      <ComposedChart data={data} margin={{ top: 8, right: 8, left: -16, bottom: 24 }}>
        <CartesianGrid strokeDasharray="3 3" className="stroke-border" />
        <XAxis
          dataKey="bucket"
          tick={{ fontSize: 11, fill: 'hsl(var(--muted-foreground))' }}
          interval="preserveStartEnd"
        />
        {/* Left axis: win rate %, fixed 0-100 scale so deltas read true */}
        <YAxis
          yAxisId="rate"
          domain={[0, 100]}
          tickFormatter={(v) => `${v}%`}
          tick={{ fontSize: 11, fill: 'hsl(var(--muted-foreground))' }}
        />
        {/* Right axis: deals closed (volume underlay). Hidden but used
            so the area can scale independently of the line. */}
        <YAxis yAxisId="volume" orientation="right" domain={[0, maxClosed * 1.2]} hide />
        <Tooltip
          contentStyle={{
            background: 'hsl(var(--popover))',
            border: '1px solid hsl(var(--border))',
            borderRadius: '6px',
            fontSize: 12,
          }}
          formatter={(value, name) => {
            if (name === 'winRatePct') {
              return [value === null ? '—' : `${value}%`, 'Win rate'];
            }
            if (name === 'closed') {
              return [value, 'Deals closed'];
            }
            return [value, String(name)];
          }}
        />
        <Area
          yAxisId="volume"
          type="monotone"
          dataKey="closed"
          stroke="none"
          fill="hsl(var(--muted))"
          fillOpacity={0.55}
          isAnimationActive={false}
        />
        <Line
          yAxisId="rate"
          type="monotone"
          dataKey="winRatePct"
          stroke="hsl(var(--primary))"
          strokeWidth={2}
          dot={{ r: 3, fill: 'hsl(var(--primary))' }}
          activeDot={{ r: 5 }}
          // Recharts renders gaps where the value is null.
          connectNulls={false}
        />
      </ComposedChart>
    </ResponsiveContainer>
  );
}

function formatBucket(bucket: string, granularity: Granularity): string {
  if (granularity === 'week') {
    // "2026-W18" → "W18"
    const m = bucket.match(/-W(\d+)/);
    return m ? `W${m[1]}` : bucket;
  }
  if (granularity === 'month') {
    // "2026-04" → "Apr"
    const [year, month] = bucket.split('-');
    if (!year || !month) return bucket;
    const date = new Date(parseInt(year), parseInt(month) - 1, 1);
    return date.toLocaleDateString(undefined, { month: 'short' });
  }
  // "2026-Q2" → "Q2 '26"
  const m = bucket.match(/(\d{4})-Q(\d)/);
  if (!m) return bucket;
  return `Q${m[2]} '${m[1]!.slice(-2)}`;
}
