"use client";

import { useEffect, useRef, useState, useTransition } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import Link from "next/link";
import { CircleAlert, LoaderCircle, ShieldCheck } from "lucide-react";
import { Button } from "@/components/ui/button";
import { authDestination, postAuthRequest, type AuthRequestResult } from "./auth-client";
import { parseOtpLink, type OtpLink } from "./otp-link-contract";

export function OtpLinkVerification({
  apiEnabled,
  signedInEmail,
  signedInDestination = "/",
  sessionCheckFailed = false,
}: {
  apiEnabled: boolean;
  signedInEmail?: string;
  signedInDestination?: "/" | "/set-password";
  sessionCheckFailed?: boolean;
}) {
  const router = useRouter();
  const params = useSearchParams();
  const [link] = useState<OtpLink | null>(() =>
    parseOtpLink(new URLSearchParams(params.toString())),
  );
  const [attempt, setAttempt] = useState(0);
  const [outcome, setOutcome] = useState<{
    attempt: number;
    result: AuthRequestResult;
  }>();
  const request = useRef<{
    attempt: number;
    promise: Promise<AuthRequestResult>;
  } | null>(null);
  const [signedOut, setSignedOut] = useState(false);
  const [signingOut, setSigningOut] = useState(false);
  const [logoutError, setLogoutError] = useState("");
  const [reviewing, startReview] = useTransition();
  const logoutPending = useRef(false);

  const activeEmail = signedOut ? undefined : signedInEmail;
  const differentAccount = Boolean(
    link && activeEmail && link.email.toLowerCase() !== activeEmail.toLowerCase(),
  );
  const result = outcome?.attempt === attempt ? outcome.result : undefined;

  useEffect(() => {
    // Email links contain a one-time code. Remove it before any later navigation.
    window.history.replaceState(window.history.state, "", "/otp-verify");
  }, []);

  useEffect(() => {
    if (
      !link ||
      !apiEnabled ||
      sessionCheckFailed ||
      differentAccount ||
      reviewing
    ) {
      return;
    }
    if (activeEmail) {
      router.replace(signedInDestination);
      return;
    }
    if (request.current?.attempt !== attempt) {
      request.current = {
        attempt,
        promise: postAuthRequest("verify-link", link),
      };
    }
    let mounted = true;
    void request.current.promise.then((response) => {
      if (!mounted) return;
      setOutcome({ attempt, result: response });
      if (response.ok && response.session) {
        router.replace(authDestination(response.session));
        router.refresh();
      }
    });
    return () => {
      mounted = false;
    };
  }, [
    activeEmail,
    apiEnabled,
    attempt,
    differentAccount,
    link,
    reviewing,
    router,
    sessionCheckFailed,
    signedInDestination,
  ]);

  async function signOutAndContinue() {
    if (logoutPending.current) return;
    logoutPending.current = true;
    setSigningOut(true);
    setLogoutError("");
    try {
      const response = await postAuthRequest("logout");
      if (!response.ok) {
        setLogoutError(response.error);
        return;
      }
      setSignedOut(true);
      setAttempt((current) => current + 1);
    } finally {
      logoutPending.current = false;
      setSigningOut(false);
    }
  }

  const error = reviewing
    ? ""
    : !apiEnabled
      ? "Authentication is not configured, so this sign-in link cannot be used."
      : sessionCheckFailed
        ? "Your current session could not be checked. Return to sign in and open the original email link again."
        : !link
          ? "This verification link is incomplete or invalid. Request a new code from Sign In."
          : activeEmail
            ? ""
            : result && !result.ok
              ? result.error
              : result?.ok && !result.session
                ? "The authentication service did not return a valid session. Return to Sign In and try again."
                : "";
  const success = result?.ok === true && Boolean(result.session);
  const openingSession = Boolean(
    link && activeEmail && !differentAccount && !error,
  );
  const verifying = Boolean(
    apiEnabled &&
      !sessionCheckFailed &&
      link &&
      !activeEmail &&
      !differentAccount &&
      !result,
  );
  const pending = reviewing || verifying || success || openingSession;
  const Icon = error ? CircleAlert : pending ? LoaderCircle : ShieldCheck;

  return (
    <div className="space-y-5">
      <span
        className={`flex size-12 items-center justify-center rounded-xl ${error ? "bg-destructive/10 text-destructive" : "bg-auth-action/10 text-auth-action"}`}
      >
        <Icon
          aria-hidden="true"
          className={`size-6 ${pending ? "animate-spin motion-reduce:animate-none" : ""}`}
        />
      </span>
      <div
        className="space-y-2"
        role={error ? "alert" : "status"}
        aria-live="polite"
      >
        <h2 className="text-2xl font-semibold sm:text-3xl">
          {reviewing
            ? "Checking current account"
            : error
              ? "Unable to verify link"
              : differentAccount
                ? "Switch account?"
                : success || openingSession
                  ? "Opening your dashboard"
                  : "Verifying your sign-in link"}
        </h2>
        <p className="text-sm leading-relaxed text-muted-foreground">
          {reviewing
            ? "Checking which account is signed in before continuing…"
            : error ||
              (differentAccount
                ? `You are signed in as ${activeEmail}. This link is for ${link?.email}.`
                : success || openingSession
                  ? "You’re signed in. Redirecting you now…"
                  : `Verifying the code for ${link?.email ?? "your account"}…`)}
        </p>
      </div>
      {differentAccount && !error && !reviewing && (
        <>
          <p className="text-sm text-muted-foreground">
            Sign out of the current account to continue with this email link.
          </p>
          {logoutError && (
            <p role="alert" className="rounded-lg bg-destructive/10 p-3 text-sm text-destructive">
              {logoutError}
            </p>
          )}
          <Button
            type="button"
            variant="auth"
            className="w-full"
            disabled={signingOut}
            onClick={() => void signOutAndContinue()}
          >
            {signingOut && (
              <LoaderCircle
                aria-hidden="true"
                className="size-4 animate-spin motion-reduce:animate-none"
              />
            )}
            {signingOut ? "Signing out…" : "Sign Out & Continue"}
          </Button>
          <Button asChild variant="outline" className="w-full">
            <Link href={signedInDestination} prefetch={false}>
              Keep Current Account
            </Link>
          </Button>
        </>
      )}
      {error && (
        <div className="space-y-3">
          {result && !result.ok && result.status === 409 && (
            <Button
              type="button"
              variant="auth"
              className="w-full"
              onClick={() => startReview(() => router.refresh())}
            >
              Review Current Account
            </Button>
          )}
          {link && result && !result.ok && (result.status === 0 || result.status >= 500) && (
            <Button
              type="button"
              variant="auth"
              className="w-full"
              onClick={() => setAttempt((current) => current + 1)}
            >
              Retry Verification
            </Button>
          )}
          <Button asChild variant="outline" className="w-full">
            <Link href="/signin" prefetch={false}>
              Back to Sign In
            </Link>
          </Button>
        </div>
      )}
      {success && result?.ok && result.session && (
        <Button asChild variant="auth" className="w-full">
          <Link href={authDestination(result.session)} prefetch={false}>
            Continue to Dashboard
          </Link>
        </Button>
      )}
    </div>
  );
}
