"use client";

import { useEffect, useState } from "react";
import { ThemeToggle } from "@/components/ui/ThemeToggle";

type LoginStage = "login" | "token" | "password" | "success";

async function postJson(path: string, body?: object) {
  const response = await fetch(path, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(body ?? {}),
  });
  const data: { error?: string } = await response.json();
  if (!response.ok) throw new Error(data.error || "Request failed");
}

export default function LoginPage() {
  const [stage, setStage] = useState<LoginStage>("login");
  const [password, setPassword] = useState("");
  const [confirmPassword, setConfirmPassword] = useState("");
  const [token, setToken] = useState("");
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(false);
  const [setupRequired, setSetupRequired] = useState<boolean | null>(null);

  useEffect(() => {
    fetch("/api/auth/setup-status")
      .then((response) => response.json())
      .then((data) => setSetupRequired(data.setupRequired))
      .catch(() => setSetupRequired(false));
  }, []);

  async function run(action: () => Promise<void>) {
    setError("");
    setLoading(true);
    try {
      await action();
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "Network error. Please try again.");
    } finally {
      setLoading(false);
    }
  }

  function handleLogin(event: React.FormEvent) {
    event.preventDefault();
    void run(async () => {
      await postJson("/api/auth/login", { password });
      window.location.href = "/";
    });
  }

  function beginReset() {
    void run(async () => {
      await postJson("/api/auth/password-reset/request");
      setToken("");
      setStage("token");
    });
  }

  function handleToken(event: React.FormEvent) {
    event.preventDefault();
    void run(async () => {
      await postJson("/api/auth/password-reset/verify", { token: token.trim() });
      setPassword("");
      setConfirmPassword("");
      setStage("password");
    });
  }

  function handlePasswordReset(event: React.FormEvent) {
    event.preventDefault();
    void run(async () => {
      await postJson("/api/auth/password-reset/complete", {
        password,
        confirmPassword,
      });
      setToken("");
      setPassword("");
      setConfirmPassword("");
      setStage("success");
    });
  }

  function returnToLogin() {
    setStage("login");
    setError("");
    setToken("");
    setPassword("");
    setConfirmPassword("");
  }

  if (setupRequired === null) {
    return (
      <div className="flex min-h-screen items-center justify-center p-4">
        <div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" />
      </div>
    );
  }

  const title =
    stage === "token"
      ? "Enter reset token"
      : stage === "password"
        ? "Choose a new password"
        : stage === "success"
          ? "Password updated"
          : setupRequired
            ? "Welcome to Study Desk"
            : "Welcome back";

  const description =
    stage === "token"
      ? "Find the token in the Study Desk Docker logs. It expires after 15 minutes."
      : stage === "password"
        ? "Use at least eight characters and enter the password twice."
        : stage === "success"
          ? "Your old password and existing sessions are no longer valid."
          : setupRequired
            ? "Please set your admin password for the first time."
            : "Open your notes, decks, and practice quizzes.";

  return (
    <div className="relative flex min-h-screen items-center justify-center overflow-hidden p-4 sm:p-8">
      <div className="absolute inset-0 paper-grid opacity-70" />
      <div className="absolute -left-24 top-1/4 h-80 w-80 rounded-full bg-primary/15 blur-3xl" />
      <div className="absolute -right-24 bottom-0 h-72 w-72 rounded-full bg-accent/15 blur-3xl" />
      <div className="absolute right-4 top-4 z-10"><ThemeToggle /></div>

      <main className="relative w-full max-w-md animate-fade-in">
        <header className="mb-7 text-center">
          <div className="mb-4 inline-grid h-14 w-14 place-items-center rounded-2xl bg-primary text-xl font-black text-white shadow-[0_12px_30px_color-mix(in_srgb,var(--theme-primary)_30%,transparent)]">S</div>
          <p className="text-xs font-bold uppercase tracking-[0.2em] text-primary">Personal workspace</p>
          <h1 className="editorial-title mt-2 text-4xl text-text-heading">{title}</h1>
          <p className="mt-1 text-sm text-text-muted">{description}</p>
        </header>

        <div className="rounded-[2rem] border border-border-light bg-bg-surface/90 p-6 shadow-[var(--shadow-modal)] backdrop-blur sm:p-8">
          {stage === "login" && (
            <form onSubmit={handleLogin} className="space-y-4">
              <PasswordField
                id="password"
                label="Password"
                value={password}
                onChange={setPassword}
                placeholder={setupRequired ? "Create a new password" : "Enter your password"}
                autoFocus
              />
              <ErrorMessage message={error} />
              <PrimaryButton loading={loading} disabled={password.length < 8}>
                {setupRequired ? "Save Password & Login" : "Sign In"}
              </PrimaryButton>
              {!setupRequired && (
                <button
                  type="button"
                  onClick={beginReset}
                  disabled={loading}
                  className="w-full rounded-lg py-2 text-sm font-semibold text-primary hover:text-primary-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:opacity-50"
                >
                  Forgot password?
                </button>
              )}
            </form>
          )}

          {stage === "token" && (
            <form onSubmit={handleToken} className="space-y-4">
              <div>
                <label htmlFor="reset-token" className="mb-1.5 block text-sm font-medium text-text-secondary">Reset token</label>
                <input
                  id="reset-token"
                  value={token}
                  onChange={(event) => setToken(event.target.value)}
                  autoComplete="one-time-code"
                  autoFocus
                  className="min-h-12 w-full rounded-xl border border-border bg-bg-surface-alt/60 px-4 font-mono text-text-heading placeholder:text-text-muted focus:border-primary"
                  placeholder="Paste the token from Docker logs"
                />
              </div>
              <ErrorMessage message={error} />
              <PrimaryButton loading={loading} disabled={!token.trim()}>Validate Token</PrimaryButton>
              <SecondaryButton onClick={returnToLogin}>Back to sign in</SecondaryButton>
            </form>
          )}

          {stage === "password" && (
            <form onSubmit={handlePasswordReset} className="space-y-4">
              <div>
                <PasswordField
                  id="new-password"
                  label="New password"
                  value={password}
                  onChange={setPassword}
                  describedBy="password-length-status"
                  invalid={password.length < 8}
                  autoFocus
                />
                <ValidationMessage
                  id="password-length-status"
                  valid={password.length >= 8}
                  validText="Password meets the length requirement."
                  invalidText="Password must be at least 8 characters."
                />
              </div>
              <div>
                <PasswordField
                  id="confirm-password"
                  label="Confirm new password"
                  value={confirmPassword}
                  onChange={setConfirmPassword}
                  describedBy={confirmPassword ? "password-match-status" : undefined}
                  invalid={confirmPassword.length > 0 && confirmPassword !== password}
                />
                {confirmPassword && (
                  <ValidationMessage
                    id="password-match-status"
                    valid={confirmPassword === password}
                    validText="Passwords match."
                    invalidText="Passwords do not match."
                  />
                )}
              </div>
              <ErrorMessage message={error} />
              <PrimaryButton
                loading={loading}
                disabled={password.length < 8 || confirmPassword !== password}
              >
                Set New Password
              </PrimaryButton>
              <SecondaryButton onClick={returnToLogin}>Cancel</SecondaryButton>
            </form>
          )}

          {stage === "success" && (
            <div className="space-y-4 text-center">
              <div className="rounded-xl bg-success-bg px-4 py-3 text-sm text-success" role="status">
                Your password has been reset successfully.
              </div>
              <PrimaryButton loading={false} onClick={returnToLogin}>Sign In</PrimaryButton>
            </div>
          )}
        </div>
      </main>
    </div>
  );
}

function PasswordField({
  id,
  label,
  value,
  onChange,
  placeholder,
  describedBy,
  invalid = false,
  autoFocus = false,
}: {
  id: string;
  label: string;
  value: string;
  onChange: (value: string) => void;
  placeholder?: string;
  describedBy?: string;
  invalid?: boolean;
  autoFocus?: boolean;
}) {
  return (
    <div>
      <label htmlFor={id} className="mb-1.5 block text-sm font-medium text-text-secondary">{label}</label>
      <input
        id={id}
        type="password"
        value={value}
        onChange={(event) => onChange(event.target.value)}
        placeholder={placeholder}
        autoComplete={id === "password" ? "current-password" : "new-password"}
        aria-describedby={describedBy}
        aria-invalid={invalid}
        autoFocus={autoFocus}
        className="min-h-12 w-full rounded-xl border border-border bg-bg-surface-alt/60 px-4 text-text-heading placeholder:text-text-muted focus:border-primary"
      />
    </div>
  );
}

function ValidationMessage({ id, valid, validText, invalidText }: {
  id: string;
  valid: boolean;
  validText: string;
  invalidText: string;
}) {
  return (
    <p
      id={id}
      aria-live="polite"
      className={`mt-1.5 text-sm ${valid ? "text-success" : "text-error"}`}
    >
      {valid ? validText : invalidText}
    </p>
  );
}

function ErrorMessage({ message }: { message: string }) {
  if (!message) return null;
  return <div role="alert" className="rounded-lg bg-error-bg px-3 py-2.5 text-sm text-error">{message}</div>;
}

function PrimaryButton({ loading, disabled = false, onClick, children }: {
  loading: boolean;
  disabled?: boolean;
  onClick?: () => void;
  children: React.ReactNode;
}) {
  return (
    <button
      type={onClick ? "button" : "submit"}
      onClick={onClick}
      disabled={loading || disabled}
      className="min-h-12 w-full rounded-xl bg-primary px-4 font-bold text-white transition-colors hover:bg-primary-hover focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:cursor-not-allowed disabled:opacity-50"
    >
      {loading ? "Working..." : children}
    </button>
  );
}

function SecondaryButton({ onClick, children }: { onClick: () => void; children: React.ReactNode }) {
  return (
    <button type="button" onClick={onClick} className="min-h-11 w-full rounded-xl border border-border px-4 font-semibold text-text-secondary hover:bg-bg-surface-alt focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary">
      {children}
    </button>
  );
}
