"use client";

import { useCallback, useEffect, useState } from "react";
import { Avatar } from "@/components/avatar";
import { createClient, waitForRealtimeAuth } from "@/lib/supabase/client";
import type { CitizenRow, MyVoteRow } from "./page";

function CitizenVoteRow({ citizen, onVote }: { citizen: CitizenRow; onVote: () => void }) {
  const [confirming, setConfirming] = useState(false);

  return (
    <li className="flex items-center gap-2 rounded-md px-2 py-1.5 text-sm">
      <Avatar pseudo={citizen.pseudo} avatarUrl={citizen.avatar_url} size="sm" />
      <span className="min-w-0 flex-1 truncate text-text-marble">{citizen.pseudo}</span>
      {confirming ? (
        <button
          type="button"
          onClick={onVote}
          className="shrink-0 rounded-md bg-oxblood px-3 py-1.5 text-xs font-medium text-marble"
        >
          Confirmer ?
        </button>
      ) : (
        <button
          type="button"
          onClick={() => setConfirming(true)}
          onBlur={() => setConfirming(false)}
          className="shrink-0 rounded-md border border-gold/40 px-3 py-1.5 text-xs font-medium text-text-marble hover:bg-gold/10"
        >
          Déposer un jeton
        </button>
      )}
    </li>
  );
}

export function UrneView({
  isJudge,
  currentUserId,
  citizens,
  initialVoteCounts,
  initialMyVoteToday,
}: {
  isJudge: boolean;
  currentUserId: string;
  citizens: CitizenRow[];
  initialVoteCounts: Record<string, number>;
  initialMyVoteToday: MyVoteRow | null;
}) {
  const [voteCounts, setVoteCounts] = useState(initialVoteCounts);
  const [myVoteToday, setMyVoteToday] = useState(initialMyVoteToday);
  const [error, setError] = useState<string | null>(null);

  const refetch = useCallback(async () => {
    const supabase = createClient();
    const [{ data: counts }, { data: myVotes }] = await Promise.all([
      supabase.rpc("urn_vote_counts"),
      isJudge
        ? Promise.resolve({ data: null })
        : supabase
            .from("urn_votes")
            .select("target_id, created_at")
            .eq("voter_id", currentUserId)
            .order("created_at", { ascending: false }),
    ]);
    if (counts) {
      const next: Record<string, number> = {};
      for (const row of counts) next[row.target_id] = row.votes;
      setVoteCounts(next);
    }
    if (myVotes) {
      const today = new Date().toLocaleDateString("sv-SE", { timeZone: "Europe/Paris" });
      setMyVoteToday(
        myVotes.find(
          (v) => new Date(v.created_at).toLocaleDateString("sv-SE", { timeZone: "Europe/Paris" }) === today,
        ) ?? null,
      );
    }
  }, [isJudge, currentUserId]);

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

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

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

  async function handleVote(targetId: string) {
    setError(null);
    const supabase = createClient();
    const { error: rpcError } = await supabase.rpc("cast_urn_vote", { p_target_id: targetId });

    if (rpcError) {
      setError(
        rpcError.message.includes("already voted")
          ? "Tu as déjà voté aujourd'hui."
          : "Une erreur est survenue, réessaie.",
      );
      refetch();
      return;
    }

    refetch();
  }

  const sortedCitizens = [...citizens].sort((a, b) => {
    const diff = (voteCounts[b.id] ?? 0) - (voteCounts[a.id] ?? 0);
    return diff !== 0 ? diff : a.pseudo.localeCompare(b.pseudo);
  });
  const myVoteTarget = myVoteToday ? citizens.find((c) => c.id === myVoteToday.target_id) : null;
  const otherCitizens = citizens.filter((c) => c.id !== currentUserId);

  return (
    <div className="flex flex-col gap-6">
      <div className="marble-surface rounded-2xl border border-gold/40 p-4 shadow-lg">
        <p className="mb-2 text-center font-heading text-sm tracking-wide text-text-mut uppercase">Classement</p>
        <ul className="grid grid-cols-2 gap-x-4 gap-y-1.5 sm:grid-cols-3">
          {sortedCitizens.map((citizen) => {
            const count = voteCounts[citizen.id] ?? 0;
            return (
              <li key={citizen.id} className="flex min-w-0 items-center gap-1.5 text-xs">
                <Avatar pseudo={citizen.pseudo} avatarUrl={citizen.avatar_url} size="xs" />
                <span className={`truncate ${count === 0 ? "text-text-mut/60" : "text-text-marble"}`}>
                  {citizen.pseudo}
                </span>
                <span className="ml-auto shrink-0 font-heading text-gold-bright">
                  {count > 0 ? `×${count}` : "—"}
                </span>
              </li>
            );
          })}
        </ul>
      </div>

      {!isJudge && (
        <div className="marble-surface rounded-2xl border border-gold/40 p-4 shadow-sm">
          {myVoteToday ? (
            <div>
              <p className="text-sm text-olive">
                Tu as voté pour {myVoteTarget?.pseudo ?? "quelqu'un"} aujourd&apos;hui.
              </p>
              <p className="mt-2 text-xs text-text-mut">Reviens demain pour déposer un nouveau jeton.</p>
            </div>
          ) : (
            <>
              <p className="mb-2 font-heading text-sm tracking-wide text-text-mut uppercase">Déposer un jeton</p>
              {error && (
                <p role="alert" className="mb-2 text-sm text-oxblood">
                  {error}
                </p>
              )}
              <ul className="flex flex-col divide-y divide-gold/10">
                {otherCitizens.map((citizen) => (
                  <CitizenVoteRow key={citizen.id} citizen={citizen} onVote={() => handleVote(citizen.id)} />
                ))}
              </ul>
            </>
          )}
        </div>
      )}
    </div>
  );
}
