"use client";
import { useRef, useState } from "react";
import { useRouter } from "next/navigation";
import { Eye, EyeOff, Loader2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
} from "@/components/ui/dialog";
import { roles, validateSignIn, type SignInInput } from "./validation";

import { authDestination, postAuthRequest } from "./auth-client";

export function SignInForm({ apiEnabled }: { apiEnabled: boolean }) {
  const router = useRouter();
  const pending = useRef(false);
  const [mode, setMode] = useState<SignInInput["mode"]>("otp");
  const [role, setRole] = useState("");
  const [email, setEmail] = useState("");
  const [show, setShow] = useState(false);
  const [busy, setBusy] = useState(false);
  const [errors, setErrors] = useState<ReturnType<typeof validateSignIn>>({});
  const [dialog, setDialog] = useState<"otp" | "forgot" | null>(null);
  const [otp, setOtp] = useState("");
  const [otpError, setOtpError] = useState("");
  const [otpNotice, setOtpNotice] = useState("");
  const [serverError, setServerError] = useState("");
  const [resetError, setResetError] = useState("");
  const [resetMessage, setResetMessage] = useState("");
  async function submit(event: React.FormEvent<HTMLFormElement>) {
    event.preventDefault();
    if (pending.current) return;
    const submittedForm = event.currentTarget;
    const form = new FormData(submittedForm);
    const next = validateSignIn({
      email,
      role,
      mode,
      password: String(form.get("password") ?? ""),
    });
    setErrors(next);
    if (Object.keys(next).length) return;
    setServerError("");
    if (!apiEnabled) {
      if (mode === "otp") setDialog("otp");
      else router.push("/");
      return;
    }
    pending.current = true;
    setBusy(true);
    const result =
      mode === "otp"
        ? await postAuthRequest("/api/auth/otp", {
            email: email.trim(),
            role,
          })
        : await postAuthRequest("/api/auth/login", {
            email: email.trim(),
            password: String(form.get("password") ?? ""),
            role,
          });
    pending.current = false;
    setBusy(false);
    if (!result.ok) {
      setServerError(result.error);
      return;
    }
    if (mode === "otp") {
      setOtp("");
      setOtpError("");
      setOtpNotice("");
      setDialog("otp");
      return;
    }
    if (!result.session) {
      setServerError(
        "The authentication service did not return a valid session. Please try again.",
      );
      return;
    }
    submittedForm.reset();
    router.replace(authDestination(result.session));
    router.refresh();
  }
  return (
    <div className="auth-panel w-full max-w-md rounded-2xl border border-input/70 bg-card/80 p-6 backdrop-blur-xl sm:p-8">
      <h1 className="text-3xl font-semibold sm:text-4xl">Sign In</h1>
      <p className="mt-2 text-sm text-auth-muted">
        {mode === "otp"
          ? "Enter your email to receive a one-time passcode."
          : "Use your password and keep the same role selection as OTP sign-in."}
      </p>
      <div
        className="mb-5 mt-5 grid grid-cols-2 gap-2 rounded-xl bg-auth-action/8 p-1 sm:mt-8 dark:bg-white/5"
        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-4 py-2 text-sm font-medium ${mode === value ? "bg-auth-action text-white shadow-[0_10px_20px_var(--auth-shadow)]" : "text-auth-muted"}`}
          >
            Use {value === "otp" ? "OTP" : "Password"}
          </button>
        ))}
      </div>
      <form onSubmit={submit} noValidate>
        <fieldset disabled={busy} className="space-y-6">
          <div className="flex flex-col gap-4 sm:flex-row">
            <div className="min-w-0 flex-1">
              <label className="field-label text-auth-muted" htmlFor="email">
                Email <span className="text-destructive">*</span>
              </label>
              <Input
                id="email"
                name="email"
                type="email"
                className="rounded-xl"
                autoComplete="username"
                placeholder="info@gmail.com"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                aria-invalid={!!errors.email}
                aria-describedby={errors.email ? "email-error" : undefined}
              />
              {errors.email && (
                <p id="email-error" className="mt-1 text-xs text-destructive">
                  {errors.email}
                </p>
              )}
            </div>
            <div className="sm:w-44">
              <label className="field-label text-auth-muted" htmlFor="role">
                Sign In as...
              </label>
              <Select value={role} onValueChange={setRole}>
                <SelectTrigger
                  id="role"
                  className="w-full rounded-xl"
                  aria-invalid={!!errors.role}
                  aria-describedby={errors.role ? "role-error" : undefined}
                >
                  <SelectValue placeholder="Select role" />
                </SelectTrigger>
                <SelectContent>
                  {roles.map((r) => (
                    <SelectItem key={r.value} value={r.value}>
                      {r.label}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
              {errors.role && (
                <p id="role-error" className="mt-1 text-xs text-destructive">
                  {errors.role}
                </p>
              )}
            </div>
          </div>
          {mode === "password" && (
            <div>
              <label className="field-label text-auth-muted" htmlFor="password">
                Password <span className="text-destructive">*</span>
              </label>
              <div className="relative">
                <Input
                  id="password"
                  name="password"
                  type={show ? "text" : "password"}
                  autoComplete="current-password"
                  placeholder="Enter your password"
                  className="pr-12"
                  aria-invalid={!!errors.password}
                  aria-describedby={
                    errors.password ? "password-error" : undefined
                  }
                />
                <button
                  type="button"
                  onClick={() => setShow(!show)}
                  aria-label={show ? "Hide password" : "Show password"}
                  aria-pressed={show}
                  className="absolute right-0 top-0 flex size-11 items-center justify-center text-auth-muted"
                >
                  {show ? (
                    <EyeOff className="size-5" />
                  ) : (
                    <Eye className="size-5" />
                  )}
                </button>
              </div>
              {errors.password && (
                <p
                  id="password-error"
                  className="mt-1 text-xs text-destructive"
                >
                  {errors.password}
                </p>
              )}
              <div className="mt-3 text-right">
                <button
                  type="button"
                  className="text-auth-action hover:underline"
                  onClick={() => setDialog("forgot")}
                >
                  Forgot password?
                </button>
              </div>
            </div>
          )}
          {serverError && (
            <p role="alert" className="text-sm text-destructive">
              {serverError}
            </p>
          )}
          <Button
            variant="auth"
            className="w-full shadow-[0_10px_20px_var(--auth-shadow)]"
            disabled={busy}
          >
            {busy && <Loader2 className="animate-spin" />}
            {busy
              ? mode === "otp"
                ? "Sending OTP..."
                : "Signing in..."
              : mode === "otp"
                ? "Send OTP"
                : "Sign In with Password"}
          </Button>
        </fieldset>
      </form>
      <Dialog
        open={dialog !== null}
        onOpenChange={(open) => {
          if (!open && !pending.current) {
            setDialog(null);
            setOtp("");
            setOtpError("");
            setOtpNotice("");
            setResetError("");
            setResetMessage("");
          }
        }}
      >
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>
              {dialog === "otp" ? "OTP Verification" : "Forgot Password"}
            </DialogTitle>
            <DialogDescription>
              {dialog === "otp"
                ? apiEnabled
                  ? `Enter the one-time passcode sent to ${email}.`
                  : `Enter the verification code for ${email}. For this UI preview, use 123456.`
                : apiEnabled
                  ? "Enter your email to request password reset instructions."
                  : "Password recovery is shown as a UI preview. No email will be sent."}
            </DialogDescription>
          </DialogHeader>
          {dialog === "otp" ? (
            <form
              className="space-y-4"
              onSubmit={async (e) => {
                e.preventDefault();
                if (pending.current) return;
                if (!apiEnabled && otp !== "123456") {
                  setOtpError("Invalid verification code");
                  return;
                }
                if (!apiEnabled) {
                  router.push("/");
                  return;
                }
                pending.current = true;
                setBusy(true);
                setOtpError("");
                setOtpNotice("");
                const result = await postAuthRequest("/api/auth/verify", {
                  email: email.trim(),
                  code: otp,
                });
                pending.current = false;
                setBusy(false);
                if (!result.ok) {
                  setOtpError(result.error);
                  return;
                }
                if (!result.session) {
                  setOtpError(
                    "The authentication service did not return a valid session. Please try again.",
                  );
                  return;
                }
                setOtp("");
                setDialog(null);
                router.replace(authDestination(result.session));
                router.refresh();
              }}
            >
              <label htmlFor="otp" className="field-label text-auth-muted">
                Verification code
              </label>
              <Input
                id="otp"
                inputMode="numeric"
                autoComplete="one-time-code"
                maxLength={6}
                required
                disabled={busy}
                aria-describedby={otpError ? "otp-error" : undefined}
                value={otp}
                onChange={(e) => setOtp(e.target.value)}
                aria-invalid={!!otpError}
              />
              {otpError && (
                <p id="otp-error" role="alert" className="text-destructive">
                  {otpError}
                </p>
              )}
              <Button variant="auth" className="w-full" disabled={busy}>
                {busy ? "Verifying..." : "Verify OTP"}
              </Button>
              {otpNotice && (
                <p role="status" className="text-sm text-muted-foreground">
                  {otpNotice}
                </p>
              )}
              <Button
                variant="ghost"
                type="button"
                disabled={busy}
                onClick={async () => {
                  if (pending.current) return;
                  setOtpError("");
                  setOtpNotice("");
                  if (!apiEnabled) {
                    setOtp("");
                    return;
                  }
                  pending.current = true;
                  setBusy(true);
                  const result = await postAuthRequest("/api/auth/otp", {
                    email: email.trim(),
                    role,
                  });
                  pending.current = false;
                  setBusy(false);
                  if (!result.ok) {
                    setOtpError(result.error);
                    return;
                  }
                  setOtp("");
                  setOtpNotice("A new verification code was requested.");
                }}
              >
                Resend OTP
              </Button>
            </form>
          ) : (
            <form
              className="space-y-4"
              onSubmit={async (e) => {
                e.preventDefault();
                if (pending.current) return;
                setResetError("");
                setResetMessage("");
                if (!apiEnabled) {
                  setDialog(null);
                  return;
                }
                const recoveryEmail = String(
                  new FormData(e.currentTarget).get("recovery-email") ?? "",
                ).trim();
                pending.current = true;
                setBusy(true);
                const result = await postAuthRequest("/api/auth/reset", {
                  email: recoveryEmail,
                });
                pending.current = false;
                setBusy(false);
                if (!result.ok) {
                  setResetError(result.error);
                  return;
                }
                setResetMessage(
                  "If the account is eligible, reset instructions will be sent.",
                );
              }}
            >
              <label
                htmlFor="recovery-email"
                className="field-label text-auth-muted"
              >
                Email <span className="text-destructive">*</span>
              </label>
              <Input
                id="recovery-email"
                name="recovery-email"
                type="email"
                defaultValue={email}
                disabled={busy}
                required
              />
              {resetError && (
                <p role="alert" className="text-sm text-destructive">
                  {resetError}
                </p>
              )}
              {resetMessage && (
                <p role="status" className="text-sm text-muted-foreground">
                  {resetMessage}
                </p>
              )}
              <Button variant="auth" className="w-full" disabled={busy}>
                {busy ? "Sending..." : "Send reset link"}
              </Button>
            </form>
          )}
        </DialogContent>
      </Dialog>
    </div>
  );
}
