"use client";

import { useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useRef, useState } from "react";
import { useTranslation } from "react-i18next";
import { toast } from "sonner";

import { getPlayerMe } from "@/api/player";
import { getPlayerAuthCaptcha, postPlayerAuthLogin } from "@/api/player-auth";
import { getPublicCurrencies } from "@/api/currency";
import { LanguageSwitcher } from "@/components/language-switcher";
import { EntryHeroBanner } from "@/features/player/entry-hero-banner";
import { PlayerLoginDesktop } from "@/features/player/player-login-desktop";
import { PlayerLoginForm } from "@/features/player/player-login-form";
import { usePlayerSessionStore } from "@/stores/player-session-store";
import {
  validatePlayerLoginPassword,
  validatePlayerLoginUsername,
} from "@/lib/player-input-validation";
import { LotteryApiBizError } from "@/types/api/errors";
import "@/i18n";

function stripSearchParamFromBrowserUrl(name: string): void {
  if (typeof window === "undefined") return;
  const url = new URL(window.location.href);
  if (!url.searchParams.has(name)) return;
  url.searchParams.delete(name);
  const next = `${url.pathname}${url.search}${url.hash}`;
  window.history.replaceState(null, "", next);
}

export function PlayerLoginScreen(): React.ReactElement {
  const { t } = useTranslation("entry");
  const tRef = useRef(t);
  useEffect(() => {
    tRef.current = t;
  }, [t]);
  const router = useRouter();
  const searchParams = useSearchParams();
  const setBearerToken = usePlayerSessionStore((s) => s.setBearerToken);
  const setProfile = usePlayerSessionStore((s) => s.setProfile);
  const clearBearerToken = usePlayerSessionStore((s) => s.clearBearerToken);
  const sessionExpiredHandled = useRef(false);

  const [username, setUsername] = 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 [loading, setLoading] = useState(false);

  const loadCaptcha = useCallback(async () => {
    setLoadingCaptcha(true);
    try {
      const data = await getPlayerAuthCaptcha();
      setCaptchaKey(data.captcha_key);
      setCaptchaSrc(`data:image/svg+xml;base64,${data.image_base64}`);
      setCaptchaCode("");
    } catch {
      toast.error(tRef.current("login.captchaLoadFailed"));
      setCaptchaKey(null);
      setCaptchaSrc(null);
    } finally {
      setLoadingCaptcha(false);
    }
  }, []);

  useEffect(() => {
    let cancelled = false;

    void (async () => {
      if (cancelled) {
        return;
      }
      await loadCaptcha();
    })();

    return () => {
      cancelled = true;
    };
  }, [loadCaptcha]);

  useEffect(() => {
    if (sessionExpiredHandled.current) return;
    if (searchParams.get("session") !== "expired") return;

    sessionExpiredHandled.current = true;
    clearBearerToken();
    toast.error(t("errors.sessionExpired"));
    stripSearchParamFromBrowserUrl("session");
  }, [clearBearerToken, searchParams, t]);

  async function handleSubmit(event: React.FormEvent): Promise<void> {
    event.preventDefault();
    if (!username.trim() || !password) {
      toast.error(t("login.missingFields"));
      return;
    }

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

    if (!captchaCode.trim()) {
      toast.error(t("login.captchaRequired"));
      return;
    }

    const usernameIssue = validatePlayerLoginUsername(username);
    if (usernameIssue === "invalid_charset") {
      toast.error(t("login.usernameInvalidCharset"));
      return;
    }

    const passwordIssue = validatePlayerLoginPassword(password);
    if (passwordIssue === "too_short") {
      toast.error(t("login.passwordMinLength"));
      return;
    }

    setLoading(true);
    try {
      const data = await postPlayerAuthLogin({
        username: username.trim(),
        password,
        captcha_key: captchaKey,
        captcha_code: captchaCode.trim(),
      });
      setBearerToken(data.access_token);
      const me = await getPlayerMe();
      setProfile(me);
      try {
        const currencies = await getPublicCurrencies();
        usePlayerSessionStore.getState().setCurrencies(currencies.items);
      } catch {
        // 不阻断登录
      }
      router.replace("/hall");
    } catch (e) {
      toast.error(e instanceof LotteryApiBizError ? e.message : t("login.failed"));
      void loadCaptcha();
    } finally {
      setLoading(false);
    }
  }

  const formProps = {
    t,
    username,
    password,
    captchaCode,
    captchaSrc,
    loading,
    loadingCaptcha,
    onUsernameChange: setUsername,
    onPasswordChange: setPassword,
    onCaptchaCodeChange: setCaptchaCode,
    onRefreshCaptcha: () => void loadCaptcha(),
    onSubmit: (event: React.FormEvent) => void handleSubmit(event),
  };

  return (
    <>
      <PlayerLoginDesktop {...formProps} />

      <div className="relative flex min-h-0 flex-1 flex-col overflow-y-auto overscroll-y-contain bg-white lg:hidden">
        <EntryHeroBanner src="/entry/image1.png" alt="" className="bg-[#f8fafc]">
          <div className="absolute left-0 right-0 top-0 z-20 flex items-center px-4 py-3">
            <LanguageSwitcher variant="header" showFlag={false} />
          </div>
        </EntryHeroBanner>

        <div className="mx-auto flex w-full max-w-md flex-1 flex-col px-4 py-8">
          <div className="w-full max-w-md">
            <h1 className="text-xl font-bold text-gray-900">{t("login.title")}</h1>
            <p className="mt-2 text-sm text-muted-foreground">{t("login.hint")}</p>

            <PlayerLoginForm variant="mobile" {...formProps} />
          </div>
        </div>
      </div>
    </>
  );
}