"use client";

import { useEffect, useRef, useState, type ReactNode } from "react";
import { useRouter } from "next/navigation";
import {
  authDestination,
  getAuthSessionVersion,
  isAuthSessionCurrent,
  renewAuthSession,
  type SafeAuthSession,
} from "./auth-client";

export function SessionMonitor({ session }: { session: SafeAuthSession }) {
  const router = useRouter();
  const [error, setError] = useState("");
  const [busy, setBusy] = useState(false);
  const retry = useRef<() => void>(() => {});

  useEffect(() => {
    let active = true;
    let working = false;
    const version = getAuthSessionVersion();
    let deadline = session.expiresAtMs;
    let timer: ReturnType<typeof setTimeout> | undefined;

    function schedule(delay: number) {
      if (timer) clearTimeout(timer);
      timer = setTimeout(() => void attempt(), Math.max(1000, delay));
    }

    async function attempt() {
      if (!active || working || !isAuthSessionCurrent(version)) return;
      working = true;
      setBusy(true);
      const result = await renewAuthSession(version);
      working = false;
      if (!active) return;
      setBusy(false);
      if (!isAuthSessionCurrent(version) || (!result.ok && result.cancelled)) {
        return;
      }
      if (result.ok && result.session) {
        setError("");
        deadline = result.session.expiresAtMs;
        schedule(deadline - Date.now() - 60_000);
        if (result.session.passwordSetupRequired) router.replace("/set-password");
        router.refresh();
        return;
      }
      if (!result.ok && (result.status === 401 || result.status === 403)) {
        router.replace("/signin");
        router.refresh();
        return;
      }
      setError(
        result.ok
          ? "Your session could not be renewed. Please sign in again."
          : result.error,
      );
      schedule(30_000);
    }

    function resume() {
      if (
        document.visibilityState === "visible" &&
        Date.now() >= deadline - 60_000
      ) {
        void attempt();
      }
    }

    retry.current = () => void attempt();
    schedule(deadline - Date.now() - 60_000);
    window.addEventListener("focus", resume);
    document.addEventListener("visibilitychange", resume);
    return () => {
      active = false;
      if (timer) clearTimeout(timer);
      window.removeEventListener("focus", resume);
      document.removeEventListener("visibilitychange", resume);
    };
  }, [router, session.expiresAtMs]);

  if (!error) return null;
  return (
    <div
      role="status"
      className="mb-4 rounded-lg border border-destructive/30 bg-card p-3 text-sm"
    >
      {error}{" "}
      <button
        type="button"
        disabled={busy}
        onClick={() => retry.current()}
        className="underline disabled:opacity-50"
      >
        {busy ? "Retrying…" : "Retry"}
      </button>
    </div>
  );
}

export function SessionRecovery({
  enabled,
  children,
}: {
  enabled: boolean;
  children: ReactNode;
}) {
  const router = useRouter();
  const [message, setMessage] = useState(
    enabled ? "Restoring your session…" : "",
  );

  useEffect(() => {
    if (!enabled) return;
    let active = true;
    const version = getAuthSessionVersion();
    void renewAuthSession(version).then((result) => {
      if (
        !active ||
        !isAuthSessionCurrent(version) ||
        (!result.ok && result.cancelled)
      ) {
        return;
      }
      if (result.ok && result.session) {
        router.replace(authDestination(result.session));
        router.refresh();
      } else {
        setMessage(
          result.ok
            ? "Please sign in again."
            : `Session recovery failed: ${result.error}`,
        );
      }
    });
    return () => {
      active = false;
    };
  }, [enabled, router]);

  return (
    <div className="w-full max-w-md">
      {message && (
        <p role="status" className="mb-3 text-sm text-muted-foreground">
          {message}
        </p>
      )}
      {children}
    </div>
  );
}
