"use client";

import Link from "next/link";
import { useEffect, useMemo, useRef, useState } from "react";

import { StatusBadge } from "@/components/status-badge";
import { apiFetch, todayString } from "@/lib/api";
import { Reservation, ReservationListResponse, ReservationStatus } from "@/lib/types";

const statuses: ReservationStatus[] = ["pending", "confirmed", "seated", "completed", "cancelled", "no_show"];
const AUTO_REFRESH_INTERVAL_MS = 10000;
const sourceLabels: Record<string, string> = {
  manual: "Manuale",
  whatsapp: "WhatsApp",
  web: "Web"
};

function EditIcon() {
  return (
    <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M12 20h9" />
      <path d="m16.5 3.5 4 4L7 21l-4 1 1-4L16.5 3.5Z" />
    </svg>
  );
}

function TrashIcon() {
  return (
    <svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
      <path d="M3 6h18" />
      <path d="M8 6V4h8v2" />
      <path d="m19 6-1 14H6L5 6" />
      <path d="M10 11v6" />
      <path d="M14 11v6" />
    </svg>
  );
}

export default function ReservationsPage() {
  const [reservationDate, setReservationDate] = useState(todayString());
  const [status, setStatus] = useState("");
  const [reservations, setReservations] = useState<Reservation[]>([]);
  const [loading, setLoading] = useState(true);
  const [message, setMessage] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [lastUpdatedAt, setLastUpdatedAt] = useState<string | null>(null);
  const [autoRefreshError, setAutoRefreshError] = useState<string | null>(null);
  const requestControllerRef = useRef<AbortController | null>(null);

  async function loadReservations({ silent = false }: { silent?: boolean } = {}) {
    if (silent && requestControllerRef.current) {
      return;
    }
    if (!silent) {
      requestControllerRef.current?.abort();
    }
    const controller = new AbortController();
    requestControllerRef.current = controller;

    if (!silent) {
      setLoading(true);
      setError(null);
    }

    const params = new URLSearchParams();
    if (reservationDate) {
      params.set("reservation_date", reservationDate);
    }
    if (status) {
      params.set("status", status);
    }

    try {
      const response = await apiFetch<ReservationListResponse>(`/reservations?${params.toString()}`, {
        signal: controller.signal
      });
      setReservations(response.items);
      setLastUpdatedAt(
        new Date().toLocaleTimeString("it-IT", {
          hour: "2-digit",
          minute: "2-digit",
          second: "2-digit"
        })
      );
      setAutoRefreshError(null);
      if (silent) {
        setError(null);
      }
    } catch (err) {
      if (err instanceof Error && err.name === "AbortError") {
        return;
      }
      if (silent) {
        setAutoRefreshError("Aggiornamento automatico momentaneamente non riuscito. Riprovo tra pochi secondi.");
      } else {
        setError(err instanceof Error ? err.message : "Impossibile caricare le prenotazioni");
      }
    } finally {
      if (!silent) {
        setLoading(false);
      }
      if (requestControllerRef.current === controller) {
        requestControllerRef.current = null;
      }
    }
  }

  useEffect(() => {
    void loadReservations();
  }, [reservationDate, status]);

  useEffect(() => {
    function refreshVisibleReservations() {
      if (document.visibilityState === "visible") {
        void loadReservations({ silent: true });
      }
    }

    const intervalId = window.setInterval(() => {
      if (document.visibilityState === "visible") {
        void loadReservations({ silent: true });
      }
    }, AUTO_REFRESH_INTERVAL_MS);

    window.addEventListener("focus", refreshVisibleReservations);
    document.addEventListener("visibilitychange", refreshVisibleReservations);

    return () => {
      window.clearInterval(intervalId);
      window.removeEventListener("focus", refreshVisibleReservations);
      document.removeEventListener("visibilitychange", refreshVisibleReservations);
      requestControllerRef.current?.abort();
    };
  }, [reservationDate, status]);

  const summary = useMemo(
    () => ({
      total: reservations.length,
      withoutTable: reservations.filter(
        (reservation) => reservation.assigned_table_id === null && reservation.assigned_combination_id === null
      ).length
    }),
    [reservations]
  );

  async function handleRecalculate() {
    setMessage(null);
    try {
      const response = await apiFetch<{ processed: number; unassigned_reservation_ids: number[] }>(
        "/reservations/recalculate-day",
        {
          method: "POST",
          body: JSON.stringify({ reservation_date: reservationDate })
        }
      );
      setMessage(
        `Aggiornate ${response.processed} prenotazioni. Ancora senza tavolo: ${response.unassigned_reservation_ids.length}.`
      );
      await loadReservations();
    } catch (err) {
      setMessage(err instanceof Error ? err.message : "Aggiornamento assegnazioni non riuscito");
    }
  }

  async function handleSingleReassign(id: number) {
    setMessage(null);
    try {
      const response = await apiFetch<{
        assignment_label: string | null;
        requires_table_join: boolean;
        service_summary: string | null;
      }>(`/reservations/${id}/reassign`, {
        method: "POST"
      });
      setMessage(
        response.assignment_label
          ? response.requires_table_join && response.service_summary
            ? `Prenotazione ${id} assegnata a ${response.assignment_label}. ${response.service_summary}`
            : `Prenotazione ${id} assegnata a ${response.assignment_label}.`
          : `Prenotazione ${id} rimasta senza assegnazione.`
      );
      await loadReservations();
    } catch (err) {
      setMessage(err instanceof Error ? err.message : "Riassegnazione non riuscita");
    }
  }

  async function handleDeleteReservation(reservation: Reservation) {
    const confirmed = window.confirm(
      `Eliminare la prenotazione di ${reservation.customer.name} del ${reservation.reservation_date} alle ${reservation.start_time.slice(0, 5)}?`
    );
    if (!confirmed) {
      return;
    }

    setMessage(null);
    setError(null);
    try {
      const response = await apiFetch<{ deleted_id: number; detail: string }>(`/reservations/${reservation.id}`, {
        method: "DELETE"
      });
      setMessage(response.detail);
      await loadReservations();
    } catch (err) {
      setError(err instanceof Error ? err.message : "Eliminazione prenotazione non riuscita");
    }
  }

  return (
    <main className="space-y-6">
      <section className="grid gap-4 xl:grid-cols-[1.45fr,0.95fr]">
        <div className="panel">
          <p className="section-kicker">Controllo prenotazioni</p>
          <h2 className="mt-3 section-title">Agenda servizio</h2>
          <p className="mt-3 section-intro">
            Filtra le prenotazioni per data e stato, poi aggiorna le assegnazioni quando serve. La vista lavora come
            regia del turno, non come semplice tabella.
          </p>

          <div className="mt-6 grid gap-4 md:grid-cols-[220px,220px,1fr]">
            <label className="block">
              <span className="mb-2 block text-sm text-stone-600">Data</span>
              <input className="field" type="date" value={reservationDate} onChange={(e) => setReservationDate(e.target.value)} />
            </label>
            <label className="block">
              <span className="mb-2 block text-sm text-stone-600">Stato</span>
              <select className="field" value={status} onChange={(e) => setStatus(e.target.value)}>
                <option value="">Tutti gli stati</option>
                {statuses.map((item) => (
                  <option key={item} value={item}>
                    {item}
                  </option>
                ))}
              </select>
            </label>
          </div>

          <p className="mt-4 text-xs uppercase tracking-[0.14em] text-stone-500">
            Aggiornamento automatico attivo ogni 10 secondi
            {lastUpdatedAt ? ` · Ultimo aggiornamento alle ${lastUpdatedAt}` : ""}
          </p>
          {autoRefreshError ? <p className="mt-2 text-sm text-amber-700">{autoRefreshError}</p> : null}

          {message ? <p className="notice mt-4">{message}</p> : null}
          {error ? <p className="notice is-error mt-4">{error}</p> : null}
        </div>

        <div className="panel">
          <p className="section-kicker">Azioni rapide</p>
          <h3 className="mt-3 font-display text-3xl text-ink">Regia del turno</h3>
          <div className="mt-6 grid gap-4 sm:grid-cols-2 xl:grid-cols-1">
            <div className="soft-card">
              <p className="text-[11px] uppercase tracking-[0.18em] text-stone-500">Prenotazioni filtrate</p>
              <p className="mt-3 font-display text-4xl text-ink">{summary.total}</p>
            </div>
            <div className="soft-card">
              <p className="text-[11px] uppercase tracking-[0.18em] text-stone-500">Senza tavolo</p>
              <p className="mt-3 font-display text-4xl text-ink">{summary.withoutTable}</p>
            </div>
          </div>

          <div className="mt-6 grid gap-3">
            <Link href="/reservations/new" className="button-primary">
              Nuova prenotazione
            </Link>
            <button className="button-secondary" onClick={() => void handleRecalculate()}>
              Aggiorna assegnazioni
            </button>
          </div>
        </div>
      </section>

      <section className="panel">
        {loading ? <p className="text-sm text-stone-500">Caricamento prenotazioni...</p> : null}

        {!loading ? (
          <div className="table-shell">
            <table className="data-table">
              <thead>
                <tr>
                  <th>Ora</th>
                  <th>Cliente</th>
                  <th>Coperti</th>
                  <th>Canale</th>
                  <th>Stato</th>
                  <th>Assegnazione</th>
                  <th>Azioni</th>
                </tr>
              </thead>
              <tbody>
                {reservations.map((reservation) => (
                  <tr key={reservation.id}>
                    <td data-label="Ora">
                      <div className="inline-flex rounded-2xl bg-stone-100 px-3 py-2 font-semibold text-slate">
                        {reservation.start_time.slice(0, 5)}
                      </div>
                    </td>
                    <td data-label="Cliente">
                      <div className="font-semibold">{reservation.customer.name}</div>
                      <div className="mt-1 text-xs uppercase tracking-[0.12em] text-stone-500">{reservation.customer.phone}</div>
                    </td>
                    <td data-label="Coperti" className="font-semibold text-stone-700">{reservation.guests}</td>
                    <td data-label="Canale">
                      <span className="subtle-pill bg-stone-100 text-stone-700">
                        {sourceLabels[reservation.source] || reservation.source}
                      </span>
                    </td>
                    <td data-label="Stato">
                      <StatusBadge status={reservation.status} />
                    </td>
                    <td data-label="Assegnazione">
                      {reservation.assigned_table?.name || reservation.assigned_combination?.name ? (
                        <span className="subtle-pill bg-emerald-50 text-emerald-900">
                          {reservation.assigned_table?.name || reservation.assigned_combination?.name}
                        </span>
                      ) : (
                        <span className="subtle-pill bg-rose-50 text-rose-700">Non assegnata</span>
                      )}

                      {reservation.requires_table_join && reservation.service_summary ? (
                        <div className="mt-3 max-w-sm rounded-[22px] border border-amber-200 bg-amber-50 p-3 text-xs leading-5 text-stone-700">
                          <div className="font-semibold uppercase tracking-[0.16em] text-amber-800">Unione richiesta</div>
                          <div className="mt-1">{reservation.service_summary}</div>
                          <div className="mt-2 space-y-1.5">
                            {reservation.service_steps.map((step) => (
                              <div key={step} className="rounded-2xl bg-white/90 px-3 py-2">
                                {step}
                              </div>
                            ))}
                          </div>
                        </div>
                      ) : null}
                    </td>
                    <td data-label="Azioni">
                      <div className="icon-action-row">
                        <button className="button-secondary px-3 py-2 text-xs" onClick={() => void handleSingleReassign(reservation.id)}>
                          Riassegna
                        </button>
                        <Link
                          href={`/reservations/${reservation.id}`}
                          className="icon-action-button"
                          aria-label={`Modifica prenotazione ${reservation.id}`}
                          title="Modifica prenotazione"
                        >
                          <EditIcon />
                        </Link>
                        <button
                          type="button"
                          className="icon-action-button is-danger"
                          onClick={() => void handleDeleteReservation(reservation)}
                          aria-label={`Elimina prenotazione ${reservation.id}`}
                          title="Elimina prenotazione"
                        >
                          <TrashIcon />
                        </button>
                      </div>
                    </td>
                  </tr>
                ))}
                {reservations.length === 0 ? (
                  <tr>
                    <td className="empty-state-cell py-6 text-stone-500" colSpan={7}>
                      Nessuna prenotazione trovata con i filtri selezionati.
                    </td>
                  </tr>
                ) : null}
              </tbody>
            </table>
          </div>
        ) : null}
      </section>
    </main>
  );
}
