"use client";

import { useEffect, useState } from "react";
import { createClient, waitForRealtimeAuth } from "@/lib/supabase/client";
import { DayCard, type DayRow } from "./day-card";
import { PANTHEON_PRESETS, getGodPreset } from "@/lib/pantheon";
import { IconPlus } from "@/components/icons";
import { formatCountdown } from "@/lib/tribunal-date";

export function CalendrierView({
  isJudge,
  initialDays,
  initialTribunalDate,
}: {
  isJudge: boolean;
  initialDays: DayRow[];
  initialTribunalDate: string | null;
}) {
  const [days, setDays] = useState<DayRow[]>(initialDays);
  const [tribunalDate, setTribunalDate] = useState<string | null>(initialTribunalDate);
  const [editingTribunalDate, setEditingTribunalDate] = useState(false);
  const [tribunalInput, setTribunalInput] = useState(
    initialTribunalDate ? initialTribunalDate.slice(0, 16) : "",
  );
  const [addingDay, setAddingDay] = useState(false);
  const [newDate, setNewDate] = useState("");
  const [newGod, setNewGod] = useState(PANTHEON_PRESETS[0].name);
  const [newGodDomain, setNewGodDomain] = useState(PANTHEON_PRESETS[0].domain);
  const [customGod, setCustomGod] = useState(false);
  const [error, setError] = useState<string | null>(null);

  async function refetch() {
    const supabase = createClient();
    const { data } = await supabase
      .from("days")
      .select("id, date, god_name, god_domain, description, events(*)")
      .order("date", { ascending: true });
    if (data) {
      setDays(
        data.map((day) => ({
          ...day,
          events: [...day.events].sort((a, b) =>
            (a.start_time ?? "99:99").localeCompare(b.start_time ?? "99:99"),
          ),
        })),
      );
    }

    const { data: settingsRow } = await supabase
      .from("settings")
      .select("tribunal_date")
      .eq("id", true)
      .single();
    setTribunalDate(settingsRow?.tribunal_date ?? null);
  }

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

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

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

  async function handleSaveTribunalDate() {
    const supabase = createClient();
    const isoValue = tribunalInput ? new Date(tribunalInput).toISOString() : null;
    const { error: updateError } = await supabase
      .from("settings")
      .update({ tribunal_date: isoValue })
      .eq("id", true);

    if (!updateError) {
      setTribunalDate(isoValue);
      setEditingTribunalDate(false);
    }
  }

  async function handleAddDay(event: React.FormEvent) {
    event.preventDefault();
    setError(null);
    if (!newDate) {
      setError("Choisis une date.");
      return;
    }

    const supabase = createClient();
    const { error: insertError } = await supabase.from("days").insert({
      date: newDate,
      god_name: newGod,
      god_domain: newGodDomain,
    });

    if (insertError) {
      setError(
        insertError.message.includes("duplicate key")
          ? "Une journée existe déjà à cette date."
          : "Une erreur est survenue.",
      );
      return;
    }

    setAddingDay(false);
    setNewDate("");
    setNewGod(PANTHEON_PRESETS[0].name);
    setNewGodDomain(PANTHEON_PRESETS[0].domain);
    setCustomGod(false);
    refetch();
  }

  return (
    <div className="flex flex-col gap-6">
      <div className="marble-surface rounded-2xl border border-gold/40 px-6 py-5 text-center shadow-xl">
        <p className="font-heading text-lg tracking-wide text-text-marble uppercase sm:text-xl">
          {formatCountdown(tribunalDate)}
        </p>
        {tribunalDate && (
          <p className="mt-1 font-serif text-sm text-text-mut italic">
            {new Date(tribunalDate).toLocaleString("fr-FR", {
              dateStyle: "full",
              timeStyle: "short",
              timeZone: "Europe/Paris",
            })}
          </p>
        )}

        {isJudge && (
          <div className="mt-3">
            {editingTribunalDate ? (
              <div className="flex flex-wrap items-center justify-center gap-2">
                <input
                  type="datetime-local"
                  value={tribunalInput}
                  onChange={(e) => setTribunalInput(e.target.value)}
                  className="rounded-md border border-gold/30 bg-white/50 px-2 py-1 text-sm text-text-marble"
                />
                <button
                  type="button"
                  onClick={handleSaveTribunalDate}
                  className="rounded-md bg-ink-2 px-3 py-1.5 text-xs font-medium text-gold-bright hover:bg-ink"
                >
                  Enregistrer
                </button>
                <button
                  type="button"
                  onClick={() => setEditingTribunalDate(false)}
                  className="rounded-md border border-gold/30 px-3 py-1.5 text-xs text-text-marble hover:bg-gold/10"
                >
                  Annuler
                </button>
              </div>
            ) : (
              <button
                type="button"
                onClick={() => setEditingTribunalDate(true)}
                className="rounded-md border border-gold/40 px-3 py-1.5 text-xs font-medium text-text-marble hover:bg-gold/10"
              >
                Définir la date du Tribunal
              </button>
            )}
          </div>
        )}
      </div>

      {days.length === 0 && !addingDay && (
        <p className="text-center text-sm text-marble/60">
          Aucune journée n&apos;a encore été inscrite au calendrier.
        </p>
      )}

      <div className="flex flex-col gap-4">
        {days.map((day) => (
          <DayCard key={day.id} day={day} isJudge={isJudge} onChanged={refetch} />
        ))}
      </div>

      {isJudge && (
        <div className="marble-surface rounded-2xl border border-gold/40 p-4 shadow-sm">
          {addingDay ? (
            <form onSubmit={handleAddDay} className="flex flex-col gap-3">
              <div className="flex flex-col gap-1">
                <label className="text-sm font-medium text-text-marble">Date</label>
                <input
                  type="date"
                  value={newDate}
                  onChange={(e) => setNewDate(e.target.value)}
                  required
                  className="rounded-md border border-gold/30 bg-white/50 px-2 py-1.5 text-sm text-text-marble"
                />
              </div>

              <div className="flex flex-col gap-1">
                <label className="text-sm font-medium text-text-marble">Divinité</label>
                <select
                  value={customGod ? "custom" : newGod}
                  onChange={(e) => {
                    if (e.target.value === "custom") {
                      setCustomGod(true);
                      setNewGod("");
                      setNewGodDomain("");
                    } else {
                      setCustomGod(false);
                      setNewGod(e.target.value);
                      setNewGodDomain(getGodPreset(e.target.value)?.domain ?? "");
                    }
                  }}
                  className="rounded-md border border-gold/30 bg-white/50 px-2 py-1.5 text-sm text-text-marble"
                >
                  {PANTHEON_PRESETS.map((g) => (
                    <option key={g.name} value={g.name}>
                      {g.name}
                    </option>
                  ))}
                  <option value="custom">Autre…</option>
                </select>
              </div>

              {customGod && (
                <div className="flex flex-col gap-1">
                  <label className="text-sm font-medium text-text-marble">Nom de la divinité</label>
                  <input
                    type="text"
                    value={newGod}
                    onChange={(e) => setNewGod(e.target.value)}
                    required
                    className="rounded-md border border-gold/30 bg-white/50 px-2 py-1.5 text-sm text-text-marble"
                  />
                </div>
              )}

              <div className="flex flex-col gap-1">
                <label className="text-sm font-medium text-text-marble">Domaine</label>
                <input
                  type="text"
                  value={newGodDomain}
                  onChange={(e) => setNewGodDomain(e.target.value)}
                  required
                  className="rounded-md border border-gold/30 bg-white/50 px-2 py-1.5 text-sm text-text-marble"
                />
              </div>

              {error && <p className="text-sm text-oxblood">{error}</p>}

              <div className="flex gap-2">
                <button
                  type="submit"
                  className="rounded-md bg-ink-2 px-4 py-2 font-heading text-sm tracking-wide text-gold-bright uppercase hover:bg-ink"
                >
                  Ajouter
                </button>
                <button
                  type="button"
                  onClick={() => setAddingDay(false)}
                  className="rounded-md border border-gold/30 px-4 py-2 text-sm text-text-marble hover:bg-gold/10"
                >
                  Annuler
                </button>
              </div>
            </form>
          ) : (
            <button
              type="button"
              onClick={() => setAddingDay(true)}
              className="flex w-full items-center justify-center gap-2 rounded-md border border-gold/40 px-4 py-2 text-sm font-medium text-text-marble hover:bg-gold/10"
            >
              <IconPlus className="h-4 w-4" />
              Ajouter une journée
            </button>
          )}
        </div>
      )}
    </div>
  );
}
