"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { Avatar } from "@/components/avatar";
import { Podium } from "@/components/podium";
import { IconClose, IconTrophy } from "@/components/icons";
import { computeRanksBy } from "@/lib/ranking";
import { createClient, waitForRealtimeAuth } from "@/lib/supabase/client";
import { IcarusGame, type IcarusRunTelemetry } from "./icarus-game";
import type { IcarusScoreEntry } from "./page";

export function IcareView({
  initialLeaderboard,
  initialOwnBestScore,
  isFrozen,
}: {
  initialLeaderboard: IcarusScoreEntry[];
  initialOwnBestScore: number | null;
  isFrozen: boolean;
}) {
  const [leaderboard, setLeaderboard] = useState(initialLeaderboard);
  const [ownBestScore, setOwnBestScore] = useState(initialOwnBestScore);
  const [showRanking, setShowRanking] = useState(false);
  const refetch = useCallback(async () => {
    const supabase = createClient();
    const { data: scores } = await supabase
      .from("icarus_scores")
      .select("user_id, best_score")
      .order("best_score", { ascending: false });

    const userIds = (scores ?? []).map((row) => row.user_id);
    const { data: profiles } =
      userIds.length > 0
        ? await supabase.from("profiles").select("id, pseudo, avatar_url").in("id", userIds)
        : { data: [] as { id: string; pseudo: string; avatar_url: string | null }[] };
    const profileById = new Map((profiles ?? []).map((profile) => [profile.id, profile]));

    setLeaderboard(
      (scores ?? []).map((row) => ({
        id: row.user_id,
        pseudo: profileById.get(row.user_id)?.pseudo ?? "Un Citoyen",
        avatar_url: profileById.get(row.user_id)?.avatar_url ?? null,
        best_score: row.best_score,
      })),
    );
  }, []);

  useEffect(() => {
    const supabase = createClient();
    let channel: ReturnType<typeof supabase.channel> | null = null;
    let cancelled = false;

    waitForRealtimeAuth(supabase).then(() => {
      if (cancelled) return;
      channel = supabase
        .channel("icarus-scores")
        .on("postgres_changes", { event: "*", schema: "public", table: "icarus_scores" }, () => {
          refetch();
        })
        .subscribe();
    });

    return () => {
      cancelled = true;
      if (channel) supabase.removeChannel(channel);
    };
  }, [refetch]);

  async function handleFinish(score: number, run: IcarusRunTelemetry) {
    const supabase = createClient();
    const { data, error } = await supabase.rpc("submit_icarus_score", { p_score: score, p_run: run });
    if (!error && data) {
      setOwnBestScore(data.best_score);
      refetch();
    }
  }

  // Le classement vit dans une modale, complètement hors du flux de mise en
  // page du jeu : sans ça, une mise à jour Realtime pendant une partie (le
  // score d'un autre joueur qui change) redimensionnait le canvas et cassait
  // la partie en cours.
  const ranked = useMemo(() => computeRanksBy(leaderboard, (a, b) => b.best_score - a.best_score), [leaderboard]);
  const podiumProfiles = ranked.filter((p) => p.rank <= 3);
  const rest = ranked.filter((p) => p.rank > 3);

  return (
    <div className="relative flex flex-1 flex-col bg-ink">
      <div className="flex items-center justify-between px-4 py-2">
        <h1 className="font-heading text-sm tracking-[0.15em] text-gold-bright uppercase">Le Vol d&apos;Icare</h1>
        <button
          type="button"
          onClick={() => setShowRanking(true)}
          className="flex items-center gap-1.5 rounded-md border border-gold/30 px-3 py-1.5 text-xs font-medium text-marble/80 uppercase tracking-wide transition hover:bg-gold/10"
        >
          <IconTrophy className="h-4 w-4" />
          Classement
        </button>
      </div>

      <IcarusGame onFinish={handleFinish} />

      {showRanking && (
        <div className="fixed inset-0 z-30 flex items-center justify-center bg-ink/80 p-4 backdrop-blur-sm">
          <div className="marble-surface flex max-h-[85vh] w-full max-w-md flex-col overflow-hidden rounded-2xl border border-gold/40 shadow-xl">
            <div className="flex items-center justify-between border-b border-gold/20 px-4 py-3">
              <h2 className="font-heading text-sm tracking-[0.1em] text-text-marble uppercase">Classement</h2>
              <button
                type="button"
                onClick={() => setShowRanking(false)}
                className="rounded-md p-1 text-text-mut transition hover:bg-gold/10 hover:text-text-marble"
                aria-label="Fermer"
              >
                <IconClose className="h-5 w-5" />
              </button>
            </div>

            <div className="overflow-y-auto px-4 py-4">
              {isFrozen && (
                <p className="mb-4 rounded-lg border border-gold/40 px-4 py-2 text-center text-sm text-text-marble">
                  Les scores sont figés depuis le début du Tribunal.
                </p>
              )}

              {podiumProfiles.length > 0 && (
                <Podium profiles={podiumProfiles} renderValue={(member) => member.best_score} />
              )}

              {rest.length > 0 && (
                <ol className="flex flex-col gap-1.5">
                  {rest.map((entry) => (
                    <li
                      key={entry.id}
                      className="flex items-center gap-3 rounded-lg border border-gold/25 px-3 py-2"
                    >
                      <span className="w-5 shrink-0 text-center font-heading text-sm text-text-mut">
                        {entry.rank}
                      </span>
                      <Avatar pseudo={entry.pseudo} avatarUrl={entry.avatar_url} size="xs" />
                      <span className="flex-1 truncate text-sm font-medium text-text-marble">{entry.pseudo}</span>
                      <span className="font-heading text-sm font-semibold text-sea">{entry.best_score}</span>
                    </li>
                  ))}
                </ol>
              )}

              {ownBestScore !== null && (
                <p className="mt-4 text-center font-heading text-sm tracking-wide text-text-marble">
                  Ton record : <span className="text-sea">{ownBestScore}</span>
                </p>
              )}

              <p className="mt-4 text-center text-xs text-text-mut">
                {isFrozen
                  ? "Les gloires du podium ont été attribuées automatiquement au début du Tribunal."
                  : "Au début du Tribunal, les scores seront figés et le podium recevra des gloires automatiquement — aucun Archonte n'a besoin d'intervenir."}
              </p>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
