"use client";

import { ShieldCheckIcon, TriangleAlertIcon } from "lucide-react";
import { useRouter } from "next/navigation";
import { useCallback, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";
import { isAxiosError } from "axios";

import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
import { AdminLanguageSwitcher } from "@/components/admin/admin-language-switcher";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { getAdminCaptcha, postAdminLogin } from "@/api";
import { readToken } from "@/stores/admin-token";
import { authModuleMeta } from "@/modules/auth/meta";
import { useAdminSessionStore } from "@/stores/admin-session";
import { LotteryApiBizError } from "@/types/api/errors";

export function LoginForm() {
  const { t } = useTranslation("auth");
  const router = useRouter();
  const setBearerToken = useAdminSessionStore((s) => s.setBearerToken);
  const setAdminProfile = useAdminSessionStore((s) => s.setAdminProfile);

  const apiConfigured =
    process.env.NEXT_PUBLIC_LOTTERY_API_BASE_URL?.trim() !== "" &&
    process.env.NEXT_PUBLIC_LOTTERY_API_BASE_URL !== undefined;

  const [account, setAccount] = useState("");
  const [password, setPassword] = useState("");
  const [captchaCode, setCaptchaCode] = useState("");
  const [captchaKey, setCaptchaKey] = useState<string | null>(null);
  const [captchaSrc, setCaptchaSrc] = useState<string | null>(null);

  const [loadingCaptcha, setLoadingCaptcha] = useState(false);
  const [submitting, setSubmitting] = useState(false);

  const loadCaptcha = useCallback(async () => {
    if (!apiConfigured) {
      return;
    }
    setLoadingCaptcha(true);
    try {
      const data = await getAdminCaptcha();
      if (!data) {
        toast.error(t("captchaLoadFailed"));
        setCaptchaKey(null);
        setCaptchaSrc(null);

        return;
      }
      setCaptchaKey(data.captcha_key);
      setCaptchaSrc(`data:image/svg+xml;base64,${data.image_base64}`);
      setCaptchaCode("");
    } finally {
      setLoadingCaptcha(false);
    }
  }, [apiConfigured, t]);

  useEffect(() => {
    if (readToken()) {
      router.replace("/admin");

      return;
    }
    const t = window.setTimeout(() => {
      void loadCaptcha();
    }, 0);

    return () => window.clearTimeout(t);
  }, [loadCaptcha, router]);

  async function onSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    if (!apiConfigured) {
      toast.error(t("apiBaseMissingToast"));

      return;
    }
    if (!captchaKey || !captchaSrc) {
      toast.error(t("captchaRequired"));
      void loadCaptcha();

      return;
    }

    setSubmitting(true);
    try {
      const result = await postAdminLogin({
        account: account.trim(),
        password,
        captcha_key: captchaKey,
        captcha_code: captchaCode.trim(),
      });
      setBearerToken(result.token);
      setAdminProfile(result.admin);
      toast.success(
        t("welcome", { name: result.admin.nickname || result.admin.username }),
      );
      router.replace("/admin");
      router.refresh();
    } catch (err) {
      void loadCaptcha();
      if (err instanceof LotteryApiBizError) {
        toast.error(err.message);

        return;
      }
      if (isAxiosError(err)) {
        toast.error(err.message || t("networkFailed"));

        return;
      }
      toast.error(t("loginFailed"));
    } finally {
      setSubmitting(false);
    }
  }

  return (
    <div className="relative flex min-h-full flex-1 flex-col items-center justify-center overflow-hidden px-4 py-14 sm:py-20">
      <div className="absolute right-4 top-4 z-20 sm:right-6 sm:top-6">
        <AdminLanguageSwitcher />
      </div>
      <div
        aria-hidden
        className="pointer-events-none absolute inset-0 bg-[radial-gradient(ellipse_85%_50%_at_50%_-5%,rgb(59_130_246/0.09),transparent)] dark:bg-[radial-gradient(ellipse_85%_50%_at_50%_-5%,rgb(56_189_248/0.12),transparent)]"
      />
      <div
        aria-hidden
        className="pointer-events-none absolute inset-0 bg-[linear-gradient(to_bottom,transparent_0%,var(--background)_100%)] opacity-90"
      />
      <div
        aria-hidden
        className="pointer-events-none absolute inset-0 opacity-[0.35] dark:opacity-[0.2]"
        style={{
          backgroundImage: `linear-gradient(to right, var(--border) 1px, transparent 1px),
            linear-gradient(to bottom, var(--border) 1px, transparent 1px)`,
          backgroundSize: "48px 48px",
        }}
      />

      <Card className="relative w-full max-w-[420px] rounded-2xl border border-border/70 bg-card/90 shadow-2xl shadow-black/[0.06] ring-1 ring-black/[0.03] backdrop-blur-md dark:border-border/50 dark:bg-card/85 dark:shadow-black/25 dark:ring-white/[0.06]">
        <CardHeader className="space-y-5 pb-2 text-center sm:px-8 sm:pt-10">
          <div className="mx-auto flex size-12 items-center justify-center rounded-2xl bg-primary/8 text-primary shadow-inner ring-1 ring-primary/10 dark:bg-primary/15 dark:ring-primary/20">
            <ShieldCheckIcon className="size-6" strokeWidth={1.75} aria-hidden />
          </div>
          <div className="space-y-1.5">
            <CardTitle className="text-balance text-2xl font-semibold tracking-tight">
              {t("loginTitle", { defaultValue: authModuleMeta.title })}
            </CardTitle>
          </div>
        </CardHeader>
        <form onSubmit={onSubmit}>
          <CardContent className="flex flex-col gap-5 sm:px-8">
            {!apiConfigured ? (
              <Alert variant="destructive" className="text-left">
                <TriangleAlertIcon />
                <AlertTitle>{t("apiMissingTitle")}</AlertTitle>
                <AlertDescription>
                  {t("apiMissingDescriptionPrefix")}{" "}
                  <code className="rounded bg-muted px-1 py-0.5 text-xs">
                    NEXT_PUBLIC_LOTTERY_API_BASE_URL
                  </code>{" "}
                  {t("apiMissingDescriptionSuffix")}
                </AlertDescription>
              </Alert>
            ) : null}
            <div className="flex flex-col gap-2">
              <Label htmlFor="admin-account" className="text-sm font-medium">
                {t("account")}
              </Label>
              <Input
                id="admin-account"
                name="account"
                autoComplete="username"
                value={account}
                onChange={(ev) => setAccount(ev.target.value)}
                placeholder={t("accountPlaceholder")}
                required
                disabled={submitting}
                className="h-11 transition-shadow focus-visible:ring-2 focus-visible:ring-primary/25"
              />
            </div>
            <div className="flex flex-col gap-2">
              <Label htmlFor="admin-password" className="text-sm font-medium">
                {t("password")}
              </Label>
              <Input
                id="admin-password"
                name="password"
                type="password"
                autoComplete="current-password"
                value={password}
                onChange={(ev) => setPassword(ev.target.value)}
                placeholder={t("passwordPlaceholder")}
                required
                disabled={submitting}
                className="h-11 transition-shadow focus-visible:ring-2 focus-visible:ring-primary/25"
              />
            </div>
            <div className="mb-8 flex flex-col gap-2">
              <Label htmlFor="admin-captcha" className="text-sm font-medium">
                {t("captcha")}
              </Label>
              <div className="flex flex-wrap items-center gap-3">
                <Input
                  id="admin-captcha"
                  name="captcha"
                  autoComplete="off"
                  value={captchaCode}
                  onChange={(ev) => setCaptchaCode(ev.target.value)}
                  placeholder={t("captchaPlaceholder")}
                  maxLength={32}
                  required
                  disabled={submitting}
                  className="h-11 min-w-0 flex-1 transition-shadow focus-visible:ring-2 focus-visible:ring-primary/25 sm:max-w-[12rem]"
                />
                <button
                  type="button"
                  className="flex h-11 min-w-[156px] shrink-0 cursor-pointer items-center justify-center overflow-hidden rounded-xl border border-border/80 bg-muted/35 px-2 shadow-[inset_0_1px_2px_rgba(0,0,0,0.04)] ring-1 ring-black/[0.03] transition-[box-shadow,transform] hover:bg-muted/45 active:scale-[0.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30 disabled:pointer-events-none disabled:opacity-50 dark:bg-muted/25 dark:shadow-[inset_0_1px_2px_rgba(0,0,0,0.2)] dark:ring-white/[0.06] dark:hover:bg-muted/35"
                  onClick={() => void loadCaptcha()}
                  disabled={
                    loadingCaptcha || !apiConfigured || submitting
                  }
                  aria-label={loadingCaptcha ? t("captchaLoading") : t("captchaRefresh")}
                >
                  {captchaSrc ? (
                    // eslint-disable-next-line @next/next/no-img-element -- data URL from API
                    <img
                      src={captchaSrc}
                      alt=""
                      width={160}
                      height={48}
                      className="pointer-events-none block"
                    />
                  ) : (
                    <span className="px-2 text-xs text-muted-foreground">
                      {loadingCaptcha ? t("captchaLoading") : t("captchaFetch")}
                    </span>
                  )}
                </button>
              </div>
            </div>
          </CardContent>
          <CardFooter className="flex-col gap-0 border-t border-border/60 pb-10 pt-8 sm:px-8">
            <Button
              type="submit"
              size="lg"
              className="h-11 w-full text-base font-medium shadow-sm"
              disabled={submitting || !apiConfigured}
            >
              {submitting ? t("submitting") : t("submit")}
            </Button>
          </CardFooter>
        </form>
      </Card>
    </div>
  );
}
