"use client";

import { useRef, useState, type FormEvent } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import Link from "next/link";
import { Button } from "@/components/ui/button";
import { Field, SelectField } from "@/components/shared/field";
import { parseRole } from "@/lib/preview";
import {
  authRoles,
  emailError,
  normalizeEmail,
  toAuthRole,
  type AuthFormRole,
} from "./model";
import { authDestination, postAuthRequest } from "./auth-client";
import { PasswordField } from "./password-field";

type SignInMode = "otp" | "password";

export function SignInForm({
  apiEnabled,
  sessionCheckFailed = false,
}: {
  apiEnabled: boolean;
  sessionCheckFailed?: boolean;
}) {
  const router = useRouter();
  const params = useSearchParams();
  const pending = useRef(false);
  const [mode, setMode] = useState<SignInMode>("otp");
  const [email, setEmail] = useState(params.get("email") ?? "");
  const [role, setRole] = useState<AuthFormRole | "">(() => {
    const value = params.get("role");
    return value ? parseRole(value) : "";
  });
  const [password, setPassword] = useState("");
  const [errors, setErrors] = useState<{
    email?: string;
    role?: string;
    password?: string;
  }>({});
  const [serverError, setServerError] = useState("");
  const [busy, setBusy] = useState(false);

  async function submit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (pending.current) return;
    const nextErrors: typeof errors = {};
    const invalidEmail = emailError(email);
    if (invalidEmail) nextErrors.email = invalidEmail;
    if (!role) nextErrors.role = "Please select a role.";
    if (mode === "password" && !password) {
      nextErrors.password = "Password is required.";
    }
    setErrors(nextErrors);
    setServerError("");
    if (Object.keys(nextErrors).length > 0 || !role) return;

    const normalizedEmail = normalizeEmail(email);
    if (!apiEnabled) return;

    pending.current = true;
    setBusy(true);
    const result =
      mode === "otp"
        ? await postAuthRequest("otp", {
            email: normalizedEmail,
            role: toAuthRole(role),
          })
        : await postAuthRequest("login", {
            email: normalizedEmail,
            password,
            role: toAuthRole(role),
          });
    pending.current = false;
    setBusy(false);
    if (!result.ok) {
      setServerError(result.error);
      return;
    }
    if (mode === "otp") {
      router.push(
        "/otp-verify?" +
          new URLSearchParams({ email: normalizedEmail, role }),
      );
      return;
    }
    if (!result.session) {
      setServerError(
        "The authentication service did not return a valid session. Please try again.",
      );
      return;
    }
    setPassword("");
    router.replace(authDestination(result.session));
    router.refresh();
  }

  const roleOptions = [
    { value: "", label: "Select role" },
    ...authRoles,
  ] as const;

  if (!apiEnabled) {
    return (
      <p role="alert" className="rounded-lg border border-destructive/30 bg-card p-3 text-sm leading-6">
        Authentication is unavailable because the authentication service is not configured.
      </p>
    );
  }

  return (
    <div className="space-y-5">
      {sessionCheckFailed && (
        <p role="status" className="rounded-lg border border-destructive/30 bg-card p-3 text-sm">
          Your current session could not be checked. Sign in again if you were
          expecting to continue an existing session.
        </p>
      )}
      <div
        className="grid grid-cols-2 gap-1 rounded-xl bg-muted p-1"
        role="group"
        aria-label="Sign-in method"
      >
        {(["otp", "password"] as const).map((value) => (
          <button
            key={value}
            type="button"
            disabled={busy}
            aria-pressed={mode === value}
            onClick={() => {
              setMode(value);
              setErrors({});
              setServerError("");
            }}
            className={`rounded-lg px-3 py-2.5 text-sm font-medium ${mode === value ? "bg-auth-action text-white shadow-sm" : "text-muted-foreground"}`}
          >
            Use {value === "otp" ? "OTP" : "Password"}
          </button>
        ))}
      </div>
      <form onSubmit={submit} noValidate>
        <fieldset disabled={busy} className="space-y-5" aria-busy={busy}>
          <Field
            label="Email"
            name="email"
            type="email"
            autoComplete="username"
            placeholder="info@gmail.com"
            value={email}
            onChange={(event) => setEmail(event.target.value)}
            aria-invalid={Boolean(errors.email)}
            aria-describedby={errors.email ? "signin-email-error" : undefined}
            required
          />
          {errors.email && (
            <p id="signin-email-error" className="-mt-4 text-xs text-destructive">
              {errors.email}
            </p>
          )}
          <div>
            <SelectField
              label="Sign in as"
              options={roleOptions}
              value={role}
              onChange={(event) =>
                setRole(
                  event.target.value === ""
                    ? ""
                    : (parseRole(event.target.value) as AuthFormRole),
                )
              }
              required
              aria-invalid={Boolean(errors.role)}
              aria-describedby={errors.role ? "signin-role-error" : undefined}
            />
            {errors.role && (
              <p id="signin-role-error" className="mt-1 text-xs text-destructive">
                {errors.role}
              </p>
            )}
          </div>
          {mode === "password" && (
            <div>
              <PasswordField
                label="Password"
                value={password}
                onChange={setPassword}
                autoComplete="current-password"
                disabled={busy}
                error={errors.password}
              />
              <div className="mt-3 text-right">
                <Link
                  className="text-sm text-auth-action hover:underline"
                  href={
                    "/forgot-password?" +
                    new URLSearchParams({ email, role: role || "admin" })
                  }
                >
                  Forgot password?
                </Link>
              </div>
            </div>
          )}
          {serverError && (
            <p role="alert" className="text-sm text-destructive">
              {serverError}
            </p>
          )}
          <Button variant="auth" className="w-full" disabled={busy}>
            {busy
              ? mode === "otp"
                ? "Sending OTP…"
                : "Signing in…"
              : mode === "otp"
                ? "Send OTP"
                : "Sign In"}
          </Button>
        </fieldset>
      </form>
    </div>
  );
}
