'use client';

import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';

export interface ParlayLeg {
  id: string;
  sport: 'NBA' | 'MLB' | 'WNBA';
  player: string;
  stat: string;
  line: number;
  direction: 'over' | 'under';
  grade: string;
  confidence: number;
  // Session 50 — needed for the correlation model.
  team?: string;
  game?: string;
  archetype?: string;
}

// Session 50 — the combined analysis from /api/parlay/grade.
export interface ParlayCombined { grade: string; score: number; penalty: number }
export interface ParlayCorrelation { max: number; avg: number; warning: string | null }
export interface ParlayPayout { amount: number; multiplier: number; fairMultiplier?: number; discount?: number }

interface ParlayContextValue {
  legs: ParlayLeg[];
  legCount: number;
  isOpen: boolean;
  open: () => void;
  close: () => void;
  toggle: () => void;
  addLeg: (leg: Omit<ParlayLeg, 'id'>) => void;
  removeLeg: (id: string) => void;
  clear: () => void;
  // Session 50 — live combined metrics (auto-graded when legs ≥ 2).
  combined: ParlayCombined | null;
  correlation: ParlayCorrelation | null;
  payout: ParlayPayout | null;
  grading: boolean;
  hasLeg: (key: string) => boolean;
  // Session 50 — tier-aware leg cap (set by the panel from useAuth).
  maxLegs: number;
  setMaxLegs: (n: number) => void;
  atCap: boolean;
}

const STORAGE_KEY = 'bbk:parlay';
const MAX_LEGS = 6; // Session 50 — Desk cap; lower tiers gated in the UI.

/** Stable de-dupe key for a leg (player|stat|line|direction). */
export function legKey(l: { player: string; stat: string; line: number; direction: string }) {
  return `${l.player}|${l.stat}|${l.line}|${l.direction}`;
}

const ParlayContext = createContext<ParlayContextValue | null>(null);

export default function ParlayProvider({ children }: { children: React.ReactNode }) {
  const [legs, setLegs] = useState<ParlayLeg[]>([]);
  const [isOpen, setOpen] = useState(false);
  // Session 50 — tier cap (default Desk 6; the panel lowers it for free/analyst).
  const [maxLegs, setMaxLegs] = useState(MAX_LEGS);
  const maxLegsRef = useRef(MAX_LEGS);
  useEffect(() => { maxLegsRef.current = maxLegs; }, [maxLegs]);

  // Restore from localStorage so a refresh doesn't drop the tray
  useEffect(() => {
    if (typeof window === 'undefined') return;
    try {
      const raw = window.localStorage.getItem(STORAGE_KEY);
      if (raw) {
        const parsed = JSON.parse(raw);
        if (Array.isArray(parsed)) setLegs(parsed);
      }
    } catch {
      /* ignore */
    }
  }, []);

  useEffect(() => {
    if (typeof window === 'undefined') return;
    try {
      window.localStorage.setItem(STORAGE_KEY, JSON.stringify(legs));
    } catch {
      /* ignore quota */
    }
  }, [legs]);

  const addLeg = useCallback((leg: Omit<ParlayLeg, 'id'>) => {
    setLegs((prev) => {
      if (prev.length >= maxLegsRef.current) return prev;
      // De-dupe by player+stat+line+direction
      const key = `${leg.player}|${leg.stat}|${leg.line}|${leg.direction}`;
      if (prev.some((p) => `${p.player}|${p.stat}|${p.line}|${p.direction}` === key)) return prev;
      const id = typeof crypto !== 'undefined' && 'randomUUID' in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random()}`;
      const next = [...prev, { ...leg, id }];
      // Fire-and-forget: tell the backend so most-parlayed counts get bumped
      void fetch('/api/parlay/add-leg', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          sport: leg.sport,
          player: leg.player,
          stat: leg.stat,
          line: leg.line,
          direction: leg.direction,
        }),
      }).catch(() => {});
      return next;
    });
  }, []);

  const removeLeg = useCallback((id: string) => {
    setLegs((prev) => prev.filter((l) => l.id !== id));
  }, []);

  const clear = useCallback(() => setLegs([]), []);

  const hasLeg = useCallback((key: string) => legs.some((l) => legKey(l) === key), [legs]);

  // Session 50 — auto-grade the slip whenever the legs change (≥ 2 legs).
  // Debounced so rapid adds make one request; clears when below 2.
  const [combined, setCombined] = useState<ParlayCombined | null>(null);
  const [correlation, setCorrelation] = useState<ParlayCorrelation | null>(null);
  const [payout, setPayout] = useState<ParlayPayout | null>(null);
  const [grading, setGrading] = useState(false);

  useEffect(() => {
    if (legs.length < 2) { setCombined(null); setCorrelation(null); setPayout(null); return; }
    let active = true;
    setGrading(true);
    const t = setTimeout(() => {
      fetch('/api/parlay/grade', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          legs: legs.map((l) => ({
            player: l.player, team: l.team || '', game: l.game || '',
            stat: l.stat, line: l.line, grade: l.grade,
          })),
          betAmount: 10,
        }),
      })
        .then((r) => (r.ok ? r.json() : null))
        .then((d) => {
          if (!active || !d || d.error) return;
          setCombined(d.combined ?? null);
          setCorrelation(d.correlation ?? null);
          setPayout(d.payout ?? null);
        })
        .catch(() => { /* keep last-known on failure */ })
        .finally(() => { if (active) setGrading(false); });
    }, 250);
    return () => { active = false; clearTimeout(t); setGrading(false); };
  }, [legs]);

  const value = useMemo<ParlayContextValue>(() => ({
    legs,
    legCount: legs.length,
    isOpen,
    open: () => setOpen(true),
    close: () => setOpen(false),
    toggle: () => setOpen((o) => !o),
    addLeg,
    removeLeg,
    clear,
    combined,
    correlation,
    payout,
    grading,
    hasLeg,
    maxLegs,
    setMaxLegs,
    atCap: legs.length >= maxLegs,
  }), [legs, isOpen, addLeg, removeLeg, clear, combined, correlation, payout, grading, hasLeg, maxLegs]);

  return <ParlayContext.Provider value={value}>{children}</ParlayContext.Provider>;
}

export function useParlay(): ParlayContextValue {
  const ctx = useContext(ParlayContext);
  if (!ctx) {
    // Provide a noop fallback so components can render outside the provider
    // (e.g. during prerender of marketing pages).
    return {
      legs: [],
      legCount: 0,
      isOpen: false,
      open: () => {},
      close: () => {},
      toggle: () => {},
      addLeg: () => {},
      removeLeg: () => {},
      clear: () => {},
      combined: null,
      correlation: null,
      payout: null,
      grading: false,
      hasLeg: () => false,
      maxLegs: 6,
      setMaxLegs: () => {},
      atCap: false,
    };
  }
  return ctx;
}
