"use client";

import Link from "next/link";
import { useState, type FormEvent } from "react";
import { Button, Field, Input } from "@/components/ui/kit";
import { api, ApiError } from "@/lib/api";

function goNext() {
  const next = new URLSearchParams(window.location.search).get("next");
  // Only follow same-site relative paths.
  window.location.href = next && next.startsWith("/") && !next.startsWith("//") ? next : "/dashboard";
}

export default function LoginPage() {
  const [step, setStep] = useState<"password" | "code">("password");
  const [useRecovery, setUseRecovery] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [fields, setFields] = useState<Record<string, string>>({});
  const [loading, setLoading] = useState(false);

  function fail(err: unknown) {
    if (err instanceof ApiError) {
      // A locked-out second step starts over with the password.
      if (err.code === "two_factor_locked" || err.status === 401) setStep("password");
      setFields(err.fields);
      if (!Object.keys(err.fields).length) setError(err.message);
    } else setError("Could not reach the server. Check your connection and try again.");
    setLoading(false);
  }

  async function onPassword(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const form = new FormData(e.currentTarget);
    setLoading(true);
    setError(null);
    setFields({});
    try {
      const r = await api.post<{ ok: boolean; two_factor_required?: boolean }>("/auth/login", { email: form.get("email"), password: form.get("password") });
      if (r.two_factor_required) {
        setStep("code");
        setLoading(false);
      } else goNext();
    } catch (err) {
      fail(err);
    }
  }

  async function onCode(e: FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const value = String(new FormData(e.currentTarget).get("code") ?? "").trim();
    setLoading(true);
    setError(null);
    setFields({});
    try {
      await api.post("/auth/2fa/verify", useRecovery ? { recovery_code: value } : { code: value.replace(/\s/g, "") });
      goNext();
    } catch (err) {
      fail(err);
    }
  }

  const alert = error && (
    <div role="alert" className="rounded-md bg-brick-soft px-3 py-2.5 text-sm text-brick">
      {error}
    </div>
  );

  if (step === "code") {
    return (
      <>
        <h1 className="text-2xl font-semibold tracking-[-0.01em] text-ink">Two-step sign-in</h1>
        <p className="mt-1 text-sm text-muted">{useRecovery ? "Enter one of the recovery codes you saved when you turned on two-step sign-in. Each code works once." : "Open your authenticator app and enter the 6-digit code for Devwebs."}</p>
        <form onSubmit={onCode} className="mt-8 space-y-4" noValidate key={useRecovery ? "recovery" : "code"}>
          {alert}
          <Field label={useRecovery ? "Recovery code" : "Code"} htmlFor="code" error={fields.code ?? fields.recovery_code}>
            <Input
              id="code"
              name="code"
              autoComplete="one-time-code"
              inputMode={useRecovery ? "text" : "numeric"}
              pattern={useRecovery ? undefined : "[0-9 ]*"}
              maxLength={useRecovery ? 20 : 7}
              placeholder={useRecovery ? "xxxx-xxxx-xxxx" : "123456"}
              invalid={!!(fields.code ?? fields.recovery_code)}
              autoFocus
              className="tabular tracking-widest"
            />
          </Field>
          <Button type="submit" variant="primary" loading={loading} className="w-full">
            Verify and sign in
          </Button>
        </form>
        <div className="mt-6 flex flex-wrap justify-between gap-2 text-sm">
          <button type="button" className="font-medium text-teal hover:underline" onClick={() => (setUseRecovery((v) => !v), setError(null), setFields({}))}>
            {useRecovery ? "Use the authenticator app" : "Use a recovery code"}
          </button>
          <button type="button" className="text-muted hover:text-ink" onClick={() => (setStep("password"), setError(null), setFields({}))}>
            Start over
          </button>
        </div>
      </>
    );
  }

  return (
    <>
      <h1 className="text-2xl font-semibold tracking-[-0.01em] text-ink">Sign in</h1>
      <p className="mt-1 text-sm text-muted">Welcome back. Use the email you registered with.</p>
      <form onSubmit={onPassword} className="mt-8 space-y-4" noValidate>
        {alert}
        <Field label="Email" htmlFor="email" error={fields.email}>
          <Input id="email" name="email" type="email" autoComplete="email" required invalid={!!fields.email} autoFocus />
        </Field>
        <Field label="Password" htmlFor="password" error={fields.password}>
          <Input id="password" name="password" type="password" autoComplete="current-password" required invalid={!!fields.password} />
        </Field>
        <div className="-mt-1 text-right text-sm">
          <Link href="/forgot-password" className="font-medium text-teal hover:underline">
            Forgot your password?
          </Link>
        </div>
        <Button type="submit" variant="primary" loading={loading} className="w-full">
          Sign in
        </Button>
      </form>
      <p className="mt-6 text-sm text-muted">
        New to Devwebs?{" "}
        <Link href="/register" className="font-medium text-teal hover:underline">
          Create an account
        </Link>
      </p>
    </>
  );
}
