import { Link } from "react-router-dom";
import { useEffect, useMemo, useState } from "react";

import { usePortalSession } from "../context/PortalSessionContext";
import {
  fetchTenantUsers,
  fetchTimeclockOverview,
  fetchTimeclockStatus,
  startTimeclockShift,
  stopTimeclockShift,
  type TenantStaffUser,
  type TimeclockEntry,
  type TimeclockOverviewResponse,
  type TimeclockStatusResponse,
} from "../lib/api";
import { portalRuntimeConfig } from "../config/runtime";

function formatHours(hours: number): string {
  return `${hours.toFixed(2)} h`;
}

function formatDuration(seconds: number): string {
  const safeSeconds = Math.max(0, Math.floor(seconds));
  const hours = Math.floor(safeSeconds / 3600);
  const minutes = Math.floor((safeSeconds % 3600) / 60);
  const restSeconds = safeSeconds % 60;
  return `${hours}h ${String(minutes).padStart(2, "0")}m ${String(restSeconds).padStart(2, "0")}s`;
}

function formatDateTime(value?: string | null): string {
  if (!value) {
    return "Non disponibile";
  }
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) {
    return value;
  }
  return new Intl.DateTimeFormat("it-IT", {
    day: "2-digit",
    month: "2-digit",
    year: "numeric",
    hour: "2-digit",
    minute: "2-digit",
  }).format(date);
}

function formatTime(value?: string | null): string {
  if (!value) {
    return "Non disponibile";
  }
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) {
    return value;
  }
  return new Intl.DateTimeFormat("it-IT", {
    hour: "2-digit",
    minute: "2-digit",
  }).format(date);
}

function todayIsoDate(): string {
  const now = new Date();
  const local = new Date(now.getTime() - now.getTimezoneOffset() * 60_000);
  return local.toISOString().slice(0, 10);
}

function mondayIsoDate(): string {
  const now = new Date();
  const day = (now.getDay() + 6) % 7;
  now.setDate(now.getDate() - day);
  const local = new Date(now.getTime() - now.getTimezoneOffset() * 60_000);
  return local.toISOString().slice(0, 10);
}

export function TimeclockPage() {
  const { currentUser } = usePortalSession();
  const canManageTeam = currentUser?.role === "owner" || currentUser?.role === "super_admin";
  const showPersonalClock = !canManageTeam;
  const [status, setStatus] = useState<TimeclockStatusResponse | null>(null);
  const [overview, setOverview] = useState<TimeclockOverviewResponse | null>(null);
  const [users, setUsers] = useState<TenantStaffUser[]>([]);
  const [selectedUserId, setSelectedUserId] = useState<string>("");
  const [rangeStart, setRangeStart] = useState<string>(mondayIsoDate());
  const [rangeEnd, setRangeEnd] = useState<string>(todayIsoDate());
  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [statusMessage, setStatusMessage] = useState<string | null>(null);
  const [tick, setTick] = useState<number>(Date.now());

  const activeEntry = status?.active_entry ?? null;
  const liveActiveSeconds = useMemo(() => {
    if (!activeEntry?.started_at) {
      return 0;
    }
    const startedAt = new Date(activeEntry.started_at).getTime();
    if (Number.isNaN(startedAt)) {
      return activeEntry.duration_seconds ?? 0;
    }
    return Math.max(Math.floor((tick - startedAt) / 1000), 0);
  }, [activeEntry, tick]);

  useEffect(() => {
    if (!activeEntry) {
      return;
    }
    const handle = window.setInterval(() => setTick(Date.now()), 1000);
    return () => window.clearInterval(handle);
  }, [activeEntry]);

  async function loadData() {
    const [nextStatus, nextOverview] = await Promise.all([
      fetchTimeclockStatus(portalRuntimeConfig.apiHubBaseUrl),
      fetchTimeclockOverview(portalRuntimeConfig.apiHubBaseUrl, {
        user_id: selectedUserId || undefined,
        start_date: rangeStart || undefined,
        end_date: rangeEnd || undefined,
        limit: 300,
      }),
    ]);
    setStatus(nextStatus);
    setOverview(nextOverview);

    if (canManageTeam) {
      const nextUsers = await fetchTenantUsers(portalRuntimeConfig.apiHubBaseUrl);
      setUsers(nextUsers.filter((user) => user.role === "staff"));
    }
  }

  useEffect(() => {
    let cancelled = false;
    async function bootstrap() {
      try {
        setLoading(true);
        setError(null);
        await loadData();
      } catch (nextError) {
        if (!cancelled) {
          setError(nextError instanceof Error ? nextError.message : "Cartellino non disponibile.");
        }
      } finally {
        if (!cancelled) {
          setLoading(false);
        }
      }
    }
    void bootstrap();
    return () => {
      cancelled = true;
    };
  }, [selectedUserId, rangeStart, rangeEnd, canManageTeam]);

  async function handleStart() {
    try {
      setBusy(true);
      setError(null);
      setStatusMessage(null);
      const nextStatus = await startTimeclockShift(portalRuntimeConfig.apiHubBaseUrl);
      setStatus(nextStatus);
      setTick(Date.now());
      setStatusMessage("Turno avviato.");
      const nextOverview = await fetchTimeclockOverview(portalRuntimeConfig.apiHubBaseUrl, {
        user_id: selectedUserId || undefined,
        start_date: rangeStart || undefined,
        end_date: rangeEnd || undefined,
        limit: 300,
      });
      setOverview(nextOverview);
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : "Avvio turno non riuscito.");
    } finally {
      setBusy(false);
    }
  }

  async function handleStop() {
    try {
      setBusy(true);
      setError(null);
      setStatusMessage(null);
      const nextStatus = await stopTimeclockShift(portalRuntimeConfig.apiHubBaseUrl);
      setStatus(nextStatus);
      setTick(Date.now());
      setStatusMessage("Turno chiuso.");
      const nextOverview = await fetchTimeclockOverview(portalRuntimeConfig.apiHubBaseUrl, {
        user_id: selectedUserId || undefined,
        start_date: rangeStart || undefined,
        end_date: rangeEnd || undefined,
        limit: 300,
      });
      setOverview(nextOverview);
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : "Chiusura turno non riuscita.");
    } finally {
      setBusy(false);
    }
  }

  const visibleEntries = useMemo(() => {
    if (overview?.entries?.length) {
      return overview.entries;
    }
    return status?.recent_entries ?? [];
  }, [overview?.entries, status?.recent_entries]);

  const filteredHoursTotal = useMemo(
    () => (overview?.summary_by_user ?? []).reduce((total, item) => total + Number(item.total_hours ?? 0), 0),
    [overview?.summary_by_user]
  );
  const activeTeamCount = overview?.active_entries?.length ?? 0;
  const filteredUsersCount = overview?.summary_by_user?.length ?? 0;
  const filteredEntriesCount = overview?.entries?.length ?? 0;

  if (loading) {
    return (
      <section className="panel narrow-panel stack-md">
        <p className="eyebrow">Cartellino</p>
        <h2 className="page-title">Carico turni e ore lavorate</h2>
        <p className="muted-copy">Sto leggendo il cartellino del locale e lo stato del tuo turno.</p>
      </section>
    );
  }

  return (
    <section className="stack-lg">
      <div className="page-head">
        <h1 className="page-heading">Cartellino</h1>
        <p className="page-subheading">
          {canManageTeam
            ? "Controlla ore lavorate, turni attivi e storico dei dipendenti del locale."
            : "Timbra inizio e fine turno, controlla le ore lavorate e consulta il tuo storico."}
        </p>
      </div>

      <section className="stats-grid">
        {showPersonalClock ? (
          <>
            <article className="stat-card">
              <span>Stato turno</span>
              <strong>{activeEntry ? "In corso" : "Non timbrato"}</strong>
              <small>{activeEntry ? `Partito alle ${formatTime(activeEntry.started_at)}` : "Premi start per iniziare il turno"}</small>
            </article>
            <article className="stat-card">
              <span>Ore oggi</span>
              <strong>{formatHours(status?.today_hours ?? 0)}</strong>
              <small>Somma turni registrati nella giornata corrente</small>
            </article>
            <article className="stat-card">
              <span>Ore settimana</span>
              <strong>{formatHours(status?.week_hours ?? 0)}</strong>
              <small>Dal lunedi di questa settimana a oggi</small>
            </article>
            <article className="stat-card">
              <span>Tempo live</span>
              <strong>{activeEntry ? formatDuration(liveActiveSeconds) : "0h 00m 00s"}</strong>
              <small>{activeEntry ? "Aggiornato in tempo reale" : "Si attiva quando timbri l'inizio turno"}</small>
            </article>
          </>
        ) : (
          <>
            <article className="stat-card">
              <span>Dipendenti</span>
              <strong>{filteredUsersCount}</strong>
              <small>Persone presenti nel riepilogo filtrato</small>
            </article>
            <article className="stat-card">
              <span>Turni attivi</span>
              <strong>{activeTeamCount}</strong>
              <small>Dipendenti che risultano ancora in turno</small>
            </article>
            <article className="stat-card">
              <span>Ore nel filtro</span>
              <strong>{formatHours(filteredHoursTotal)}</strong>
              <small>Somma ore del periodo attualmente selezionato</small>
            </article>
            <article className="stat-card">
              <span>Timbrature</span>
              <strong>{filteredEntriesCount}</strong>
              <small>Righe di cartellino presenti nel periodo filtrato</small>
            </article>
          </>
        )}
      </section>

      {error ? <p className="auth-error">{error}</p> : null}
      {statusMessage ? <div className="callout"><strong>Cartellino</strong>{statusMessage}</div> : null}

      {showPersonalClock ? (
        <section className="panel stack-md">
          <div className="panel-heading">
            <div>
              <p className="eyebrow">Turno personale</p>
              <h3>{activeEntry ? "Turno attivo" : "Avvio turno"}</h3>
            </div>
            <Link to="/home" className="button-secondary">Vai alla Home</Link>
          </div>

          <p className="muted-copy">
            {activeEntry
              ? `Turno in corso dalle ${formatTime(activeEntry.started_at)}. Quando finisci, chiudi il turno da qui.`
              : "Quando arrivi al lavoro, premi Start turno. Dopo puoi usare normalmente il portale."}
          </p>

          <div className="timeclock-action-row">
            {activeEntry ? (
              <button type="button" className="button-primary timeclock-main-button stop" onClick={() => void handleStop()} disabled={busy}>
                Fine turno
              </button>
            ) : (
              <button type="button" className="button-primary timeclock-main-button" onClick={() => void handleStart()} disabled={busy}>
                Start turno
              </button>
            )}
            <div className="timeclock-live-card">
              <strong>{activeEntry ? formatDuration(liveActiveSeconds) : "0h 00m 00s"}</strong>
              <span>{activeEntry ? `Inizio ${formatDateTime(activeEntry.started_at)}` : "Nessun turno attivo"}</span>
            </div>
          </div>
        </section>
      ) : null}

      {canManageTeam ? (
        <section className="panel stack-md">
          <div className="panel-heading">
            <div>
              <p className="eyebrow">Team</p>
              <h3>Ore per dipendente</h3>
            </div>
            <Link to="/home" className="button-secondary">Vai alla Home</Link>
          </div>

          <form className="mock-form timeclock-filter-grid" onSubmit={(event) => event.preventDefault()}>
            <label className="field">
              <span>Dipendente</span>
              <select value={selectedUserId} onChange={(event) => setSelectedUserId(event.target.value)}>
                <option value="">Tutti</option>
                {users.map((user) => (
                  <option key={user.id} value={user.id}>
                    {user.name ?? user.email}
                  </option>
                ))}
              </select>
            </label>
            <label className="field">
              <span>Dal</span>
              <input type="date" value={rangeStart} onChange={(event) => setRangeStart(event.target.value)} />
            </label>
            <label className="field">
              <span>Al</span>
              <input type="date" value={rangeEnd} onChange={(event) => setRangeEnd(event.target.value)} />
            </label>
          </form>

          <div className="stats-grid">
            {(overview?.summary_by_user ?? []).map((summary) => (
              <article key={summary.user_id} className="stat-card">
                <span>{summary.user_name ?? summary.username ?? summary.user_email ?? "Dipendente"}</span>
                <strong>{formatHours(summary.total_hours)}</strong>
                <small>
                  {summary.entries} turni
                  {summary.active_entries > 0 ? ` · ${summary.active_entries} attivi` : ""}
                </small>
              </article>
            ))}
          </div>
        </section>
      ) : null}

      <section className="panel stack-md">
        <div className="panel-heading">
          <div>
            <p className="eyebrow">{canManageTeam ? "Storico team" : "Storico personale"}</p>
            <h3>Timbrature registrate</h3>
          </div>
        </div>

        {visibleEntries.length === 0 ? (
          <p className="muted-copy">Non vedo ancora timbrature nel perimetro selezionato.</p>
        ) : (
          <div className="timeclock-entry-list">
            {visibleEntries.map((entry: TimeclockEntry) => (
              <article key={entry.id} className="timeclock-entry-card">
                <div className="timeclock-entry-main">
                  <strong>{entry.user_name ?? entry.username ?? entry.user_email ?? "Dipendente"}</strong>
                  <span>
                    {formatDateTime(entry.started_at)}
                    {entry.ended_at ? ` → ${formatDateTime(entry.ended_at)}` : " → turno aperto"}
                  </span>
                </div>
                <div className="timeclock-entry-meta">
                  <span>{formatDuration(entry.duration_seconds ?? 0)}</span>
                  <span>{entry.is_active ? "Attivo" : "Chiuso"}</span>
                </div>
              </article>
            ))}
          </div>
        )}
      </section>
    </section>
  );
}
