"use client";

import { useMemo, useState } from "react";
import { ChevronUp, Layers3, Lock, X } from "lucide-react";
import { EventMarketSelection } from "@/components/event-market-selection";
import { useBetSlip, type SlipSelection } from "@/components/bet-slip";
import { SportGlyph } from "@/components/sport-glyph";
import { cn, formatOdds } from "@/lib/utils";

type MatchMarket = {
  id: string;
  key: string;
  name: string;
  selections: Array<{
    id: string;
    key: string;
    name: string;
    odds: string;
    oddsVersion: number;
  }>;
};

type MatchEvent = {
  id: string;
  eventName: string;
  homeName: string;
  awayName: string;
  sport: { slug: string; name: string };
  markets: MatchMarket[];
};

type TeamSide = "home" | "away";

type SameGameLeg = {
  selectionId: string;
  eventId: string;
  marketId: string;
  marketKey: string;
  marketName: string;
  selectionKey: string;
  selectionName: string;
  odds: string;
  oddsVersion: number;
  marker: TeamSide | null;
};

type Mode = "main" | "same-game";

export function MatchMarkets({ event, lockedMarketNames }: { event: MatchEvent; lockedMarketNames: string[] }) {
  const { addSelection } = useBetSlip();
  const [mode, setMode] = useState<Mode>("main");
  const [legs, setLegs] = useState<SameGameLeg[]>([]);
  const [message, setMessage] = useState("");
  const totalOdds = useMemo(() => legs.reduce((total, leg) => total * Number(leg.odds), 1), [legs]);
  const canAddSameGame = mode === "same-game" && legs.length >= 2;

  function toggleLeg(leg: SameGameLeg) {
    setMessage("");
    setLegs((current) => {
      if (current.some((item) => item.selectionId === leg.selectionId)) {
        return current.filter((item) => item.selectionId !== leg.selectionId);
      }

      const validation = validateNextSameGameLegs([...current, leg]);
      if (!validation.ok) {
        setMessage(validation.message);
        return current;
      }

      return [...current, leg];
    });
  }

  function addSameGameToCoupon() {
    if (!canAddSameGame) {
      setMessage("Sélectionnez au moins deux options compatibles.");
      return;
    }

    const selectionId = `same-game:${event.id}:${legs.map((leg) => leg.selectionId).sort().join(":")}`;
    const selectionLabel = legs.length === 2 ? "2 sélections" : `${legs.length} sélections`;
    const slipSelection: SlipSelection = {
      selectionId,
      eventId: event.id,
      marketId: `same-game:${event.id}`,
      eventName: event.eventName,
      marketName: "Combiné sur le même match",
      selectionName: selectionLabel,
      odds: totalOdds.toFixed(2),
      oddsVersion: Math.max(...legs.map((leg) => leg.oddsVersion)),
      allowCombinations: false,
      sameGame: {
        legs: legs.map((leg) => ({
          selectionId: leg.selectionId,
          marketId: leg.marketId,
          marketName: leg.marketName,
          selectionName: leg.selectionName,
          odds: leg.odds,
          oddsVersion: leg.oddsVersion
        }))
      }
    };

    addSelection(slipSelection);
    setLegs([]);
    setMessage("Combiné ajouté au coupon en pari simple.");
  }

  function clearSameGame() {
    setLegs([]);
    setMessage("");
  }

  return (
    <section className="space-y-3 px-5 sm:px-0">
      <div className="grid grid-cols-[1fr_1.45fr] gap-0 rounded-lg bg-[#202631] p-1">
        <button
          type="button"
          onClick={() => setMode("main")}
          className={cn(
            "h-10 rounded-md px-2 text-[13px] font-extrabold transition",
            mode === "main" ? "bg-[#343946] text-white" : "text-slate-400 hover:text-white"
          )}
        >
          Principaux marchés
        </button>
        <button
          type="button"
          onClick={() => setMode("same-game")}
          className={cn(
            "flex h-10 min-w-0 items-center justify-center gap-2 rounded-md px-2 text-[13px] font-semibold transition",
            mode === "same-game" ? "bg-felt/15 text-felt" : "text-slate-400 hover:text-white"
          )}
        >
          <Layers3 className="h-4 w-4 shrink-0 text-felt" />
          <span className="truncate">Combiné sur le même match</span>
        </button>
      </div>

      {message ? <div className="rounded-lg border border-felt/20 bg-felt/10 px-3 py-2 text-[12px] font-semibold text-felt">{message}</div> : null}

      <div className="overflow-hidden rounded-lg border border-white/10 bg-[#11161d] shadow-panel">
        {event.markets.map((market) => (
          <details key={market.id} open className="group border-b border-white/10 last:border-b-0">
            <summary className="flex min-h-12 cursor-pointer list-none items-center justify-between gap-3 bg-[#11161d] px-3 py-3 [&::-webkit-details-marker]:hidden">
              <h2 className="truncate text-[13px] font-extrabold text-white">{displayMarketName(market.name)}</h2>
              <ChevronUp className="h-4 w-4 shrink-0 text-white" />
            </summary>
            <div className="space-y-2 bg-[#202631] px-3 py-3">
              {sortSelections(market.selections).map((selection) => {
                const selectionName = displaySelectionName(selection, market, event);
                const marker = selectionMarker(selection, market);
                const leg: SameGameLeg = {
                  selectionId: selection.id,
                  eventId: event.id,
                  marketId: market.id,
                  marketKey: market.key,
                  marketName: market.name,
                  selectionKey: selection.key,
                  selectionName,
                  odds: selection.odds,
                  oddsVersion: selection.oddsVersion,
                  marker
                };

                if (mode === "same-game") {
                  return (
                    <SameGameOption
                      key={selection.id}
                      leg={leg}
                      sport={event.sport}
                      active={legs.some((item) => item.selectionId === selection.id)}
                      onClick={() => toggleLeg(leg)}
                    />
                  );
                }

                return (
                  <EventMarketSelection
                    key={selection.id}
                    marker={marker ? <SelectionSportMarker sport={event.sport} /> : null}
                    selection={{
                      selectionId: selection.id,
                      eventId: event.id,
                      marketId: market.id,
                      eventName: event.eventName,
                      marketName: market.name,
                      selectionName,
                      odds: selection.odds,
                      oddsVersion: selection.oddsVersion
                    }}
                  />
                );
              })}
            </div>
          </details>
        ))}

        {lockedMarketNames.map((name) => (
          <section key={name} className="flex min-h-12 items-center justify-between gap-3 border-b border-white/10 bg-[#11161d] px-3 py-3 last:border-b-0">
            <h2 className="truncate text-[13px] font-extrabold text-white">{name}</h2>
            <span className="inline-flex shrink-0 items-center gap-1 text-[11px] font-semibold text-slate-500">
              <Lock className="h-3.5 w-3.5" />
              Non coté
            </span>
          </section>
        ))}
      </div>

      {mode === "same-game" && legs.length > 0 ? (
        <div className="fixed inset-x-0 bottom-[calc(4.65rem+env(safe-area-inset-bottom))] z-40 border-t border-white/10 bg-[#11151c] p-3 shadow-panel sm:sticky sm:bottom-3 sm:rounded-lg sm:border">
          <div className="mb-3 flex items-center justify-between gap-3">
            <div className="min-w-0 text-[13px] font-extrabold text-white">
              Total des cotes: <span className="text-felt">{formatOdds(totalOdds)}</span>
              <span className="ml-2 inline-grid h-6 min-w-6 place-items-center rounded-md bg-felt px-1.5 text-xs font-black text-ink-950">{legs.length}</span>
            </div>
            <ChevronUp className="h-4 w-4 shrink-0 text-white" />
          </div>
          <div className="grid grid-cols-2 gap-2">
            <button type="button" onClick={clearSameGame} className="h-10 rounded-lg border border-white/70 text-[13px] font-extrabold text-white">
              Effacer tout
            </button>
            <button
              type="button"
              onClick={addSameGameToCoupon}
              disabled={!canAddSameGame}
              className="h-10 rounded-lg bg-felt text-[13px] font-extrabold text-ink-950 disabled:bg-slate-600 disabled:text-slate-300"
            >
              Ajouter un pari
            </button>
          </div>
          <div className="mt-3 space-y-2 border-t border-white/10 pt-3">
            {legs.map((leg) => (
              <div key={leg.selectionId} className="flex items-start justify-between gap-3">
                <div className="min-w-0">
                  <div className="truncate text-[13px] font-extrabold text-felt">
                    {leg.marker ? <SelectionSportMarker sport={event.sport} className="mr-1.5" /> : null}
                    {leg.selectionName}
                    <span className="ml-1.5 font-semibold text-slate-500">{displayMarketName(leg.marketName)}</span>
                  </div>
                </div>
                <button type="button" onClick={() => toggleLeg(leg)} className="grid h-7 w-7 shrink-0 place-items-center text-slate-400 hover:text-white" aria-label="Retirer la sélection">
                  <X className="h-4 w-4" />
                </button>
              </div>
            ))}
          </div>
        </div>
      ) : null}
    </section>
  );
}

function SameGameOption({
  leg,
  sport,
  active,
  onClick
}: {
  leg: SameGameLeg;
  sport: { slug: string; name: string };
  active: boolean;
  onClick: () => void;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      className={cn(
        "flex min-h-[50px] w-full items-center justify-between gap-3 rounded-md border px-3 py-2.5 text-left transition",
        active ? "border-felt bg-felt text-ink-950" : "border-white/[0.04] bg-black/70 text-white hover:border-felt/35 hover:bg-black/80"
      )}
    >
      <span className="flex min-w-0 items-center gap-2">
        {leg.marker ? <SelectionSportMarker sport={sport} /> : null}
        <span className={cn("truncate text-[13px] font-semibold leading-4", active ? "text-ink-950" : "text-white")}>{leg.selectionName}</span>
      </span>
      <span className={cn("shrink-0 text-[14px] font-extrabold leading-4", active ? "text-ink-950" : "text-felt")}>{formatOdds(leg.odds)}</span>
    </button>
  );
}

function SelectionSportMarker({ sport, className }: { sport: { slug: string; name: string }; className?: string }) {
  return (
    <span className={cn("inline-grid h-5 w-7 shrink-0 place-items-center overflow-hidden align-middle text-felt leading-none", className)} aria-hidden="true">
      <SportGlyph slug={sport.slug} label={sport.name} className="h-[18px] w-[18px]" />
    </span>
  );
}

function validateNextSameGameLegs(legs: SameGameLeg[]) {
  if (legs.length > 8) return { ok: false as const, message: "Maximum 8 sélections sur un combiné du même match." };

  const marketIds = new Set<string>();
  const families = new Set<string>();

  for (const leg of legs) {
    if (marketIds.has(leg.marketId)) {
      return { ok: false as const, message: "Vous ne pouvez pas choisir deux options du même marché." };
    }

    const family = marketFamily(leg.marketKey, leg.marketName);
    if (family === "result" && families.has("result")) {
      return { ok: false as const, message: "Une seule sélection de résultat est autorisée dans ce combiné." };
    }

    marketIds.add(leg.marketId);
    families.add(family);
  }

  return { ok: true as const };
}

function marketFamily(key: string, name: string) {
  const value = `${key} ${name}`.toLowerCase().replaceAll(" ", "");
  if (value.includes("1x2") || value.includes("matchwinner") || value.includes("doublechance") || value.includes("remboursesinul") || value.includes("drawnobet")) {
    return "result";
  }
  return key;
}

function displayMarketName(name: string) {
  return marketNameKey(name) === "1x2" ? "1x2" : name;
}

function displaySelectionName<T extends { key: string; name: string }>(selection: T, market: { key: string; name: string }, event: { homeName: string; awayName: string }) {
  if (!isWinnerMarket(market)) return selection.name;
  const rank = selectionRank(selection);
  if (rank === 1) return event.homeName;
  if (rank === 2) return "Match nul";
  if (rank === 3) return event.awayName;
  return selection.name;
}

function selectionMarker<T extends { key: string; name: string }>(
  selection: T,
  market: { key: string; name: string }
) {
  if (!isWinnerMarket(market) && !marketNameKey(market.name).includes("remboursesinul")) return null;
  const rank = selectionRank(selection);
  if (rank === 1) return "home";
  if (rank === 3) return "away";
  return null;
}

function isWinnerMarket(market: { key: string; name: string }) {
  const value = `${market.key} ${market.name}`.toLowerCase().replaceAll(" ", "");
  return value.includes("1x2") || value.includes("matchwinner") || value.includes("vainqueur");
}

function marketNameKey(value: string) {
  return value
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toLowerCase()
    .replace(/[^a-z0-9]/g, "");
}

function sortSelections<T extends { key: string; name: string }>(selections: T[]) {
  return [...selections].sort((left, right) => selectionRank(left) - selectionRank(right) || left.name.localeCompare(right.name));
}

function selectionRank(selection: { key: string; name: string }) {
  const key = selection.key.toLowerCase();
  const name = selection.name.toLowerCase();
  if (key === "home" || name === "1") return 1;
  if (key === "draw" || name === "x") return 2;
  if (key === "away" || name === "2") return 3;
  if (key === "over") return 4;
  if (key === "under") return 5;
  if (key === "yes" || name === "oui") return 6;
  if (key === "no" || name === "non") return 7;
  return 10;
}
