import { type ChangeEvent, type FormEvent, useEffect, useMemo, useState } from 'react';
import { Lock, User } from 'lucide-react';
import { useLocation, useNavigate } from 'react-router-dom';

import blueLogo from '../../assets/images/login/blue_logo.png';
import loginBackground from '../../assets/images/login/login_bg.png';
import loginIllustration from '../../assets/images/login/logo.png';
import userIcon from '../../assets/images/login/user_icon.png';

import { useI18n } from '../../i18n';
import TitleBar from '../../components/layout/TitleBar';
import { resolvePostLoginPath } from '../../router/auth';
import {
  createCaptchaState,
  getCaptchaImageUrl,
  loginWithPassword,
  persistLoginTokens,
  type LoginFormValues,
} from './auth';

type FormErrors = Partial<Record<'username' | 'password' | 'code' | 'submit', string>>;

const INITIAL_FORM: LoginFormValues = {
  username: '',
  password: '',
  code: '',
  randomStr: '',
};

const credentialFieldShellClass =
  'flex h-11 items-center rounded-[10px] border border-black/10 bg-gray-50 transition focus-within:border-[#2B7FFF] focus-within:ring-2 focus-within:ring-[#2B7FFF]/10 dark:border-[#2a2a2d] dark:bg-[#222225]';

const credentialFieldIconClass = 'ml-4 mr-3 h-4 w-4 shrink-0 text-[#99A0AE] dark:text-gray-500';

const credentialFieldInputClass =
  'h-full min-w-0 flex-1 border-0 bg-transparent pr-4 text-[14px] text-gray-800 outline-none placeholder:text-[#99A0AE] disabled:cursor-not-allowed dark:text-gray-100 dark:placeholder:text-gray-500';

export default function LoginPage() {
  const { t } = useI18n();
  const navigate = useNavigate();
  const location = useLocation();
  const platform = (window as any).api?.platform ?? '';
  const [form, setForm] = useState<LoginFormValues>(INITIAL_FORM);
  const [errors, setErrors] = useState<FormErrors>({});
  const [submitting, setSubmitting] = useState(false);
  const [showDecorations, setShowDecorations] = useState(false);

  const captchaUrl = useMemo(
    () => (form.randomStr ? getCaptchaImageUrl(form.randomStr) : ''),
    [form.randomStr],
  );

  useEffect(() => {
    const frameId = window.requestAnimationFrame(() => {
      setShowDecorations(true);
      setForm((current) => ({ ...current, ...createCaptchaState() }));
    });

    return () => {
      window.cancelAnimationFrame(frameId);
    };
  }, []);

  function refreshCaptcha(clearSubmitError = true): void {
    setForm((current) => ({
      ...current,
      code: '',
      ...createCaptchaState(),
    }));
    setErrors((current) => ({
      ...current,
      code: undefined,
      submit: clearSubmitError ? undefined : current.submit,
    }));
  }

  function updateField<K extends keyof LoginFormValues>(key: K, value: LoginFormValues[K]): void {
    setForm((current) => ({ ...current, [key]: value }));
    setErrors((current) => ({ ...current, [key]: undefined, submit: undefined }));
  }

  function validate(values: LoginFormValues): FormErrors {
    const nextErrors: FormErrors = {};

    if (!values.username.trim()) nextErrors.username = t('login.usernameRequired');
    if (!values.password.trim()) nextErrors.password = t('login.passwordRequired');
    if (!values.code.trim()) nextErrors.code = t('login.codeRequired');

    return nextErrors;
  }

  async function handleSubmit(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();

    const trimmedValues: LoginFormValues = {
      ...form,
      username: form.username.trim(),
      password: form.password.trim(),
      code: form.code.trim(),
    };

    const nextErrors = validate(trimmedValues);
    if (Object.keys(nextErrors).length > 0) {
      setErrors(nextErrors);
      return;
    }

    setSubmitting(true);
    setErrors({});

    try {
      const result = await loginWithPassword(trimmedValues);
      persistLoginTokens(result);
      navigate(resolvePostLoginPath(location.state as { from?: string } | null), { replace: true });
    } catch (error) {
      setErrors({
        submit: error instanceof Error ? error.message : t('login.submitFailed'),
      });
      refreshCaptcha(false);
    } finally {
      setSubmitting(false);
    }
  }

  function handleInputChange(
    key: 'username' | 'password' | 'code',
    event: ChangeEvent<HTMLInputElement>,
  ): void {
    updateField(key, event.target.value);
  }

  return (
    <div
      className="relative flex h-screen flex-col overflow-hidden bg-[linear-gradient(135deg,#eef5ff_0%,#f8fbff_42%,#ffffff_100%)] dark:bg-[#111214]"
    >
      {showDecorations ? (
        <img
          aria-hidden="true"
          alt=""
          className="pointer-events-none absolute inset-0 h-full w-full object-cover"
          decoding="async"
          fetchPriority="low"
          src={loginBackground}
        />
      ) : null}

      <div className="relative z-20">
        <TitleBar variant="light" controlsTheme="white" />
      </div>

      <main
        className={['relative z-10 box-border flex flex-auto pl-2 pr-2 pb-2', platform !== 'linux' ? 'pt-2' : 'pt-11'].join(' ')}
      >
        <div className="box-border w-[836px] rounded-2xl border border-black/5 bg-white/95 p-8 shadow-[0_18px_50px_rgba(15,23,42,0.12)] backdrop-blur-sm dark:border-[#2a2a2d] dark:bg-[#1b1b1d]/95">
          <div className="flex items-center">
            <img className="h-12 w-12" src={blueLogo} alt="zn-ai" />
          </div>

          <div className="mb-6 box-border flex flex-col items-center justify-center pt-10">
            <img className="mb-3 h-20 w-20" src={userIcon} alt="" />
            <div className="mb-1 text-[24px] leading-[32px] font-medium text-gray-800 dark:text-gray-100">
              {t('login.title')}
            </div>
            <div className="text-[16px] leading-[24px] text-gray-500 dark:text-gray-400">
              {t('login.subtitle')}
            </div>
          </div>

          <form className="mx-auto flex w-[392px] flex-col gap-4" onSubmit={handleSubmit}>
            <div>
              <label className="mb-2 block text-[14px] text-gray-600 dark:text-gray-300" htmlFor="login-username">
                {t('login.username')}
              </label>
              <div className={credentialFieldShellClass}>
                <User aria-hidden="true" className={credentialFieldIconClass} />
                <input
                  id="login-username"
                  className={credentialFieldInputClass}
                  autoComplete="username"
                  disabled={submitting}
                  placeholder={t('login.usernamePlaceholder')}
                  value={form.username}
                  onChange={(event) => handleInputChange('username', event)}
                />
              </div>
              {errors.username ? <div className="pt-2 text-[12px] text-[#dc2626]">{errors.username}</div> : null}
            </div>

            <div>
              <label className="mb-2 block text-[14px] text-gray-600 dark:text-gray-300" htmlFor="login-password">
                {t('login.password')}
              </label>
              <div className={credentialFieldShellClass}>
                <Lock aria-hidden="true" className={credentialFieldIconClass} />
                <input
                  id="login-password"
                  className={credentialFieldInputClass}
                  autoComplete="current-password"
                  disabled={submitting}
                  placeholder={t('login.passwordPlaceholder')}
                  type="password"
                  value={form.password}
                  onChange={(event) => handleInputChange('password', event)}
                />
              </div>
              {errors.password ? <div className="pt-2 text-[12px] text-[#dc2626]">{errors.password}</div> : null}
            </div>

            <div>
              <label className="mb-2 block text-[14px] text-gray-600 dark:text-gray-300" htmlFor="login-code">
                {t('login.verificationCode')}
              </label>
              <div className="flex gap-3">
                <input
                  id="login-code"
                  className="h-10 min-w-0 flex-1 rounded-[10px] border border-black/10 bg-gray-50 px-4 text-[14px] text-gray-800 outline-none transition focus:border-[#2B7FFF] dark:border-[#2a2a2d] dark:bg-[#222225] dark:text-gray-100"
                  autoComplete="off"
                  disabled={submitting}
                  placeholder={t('login.verificationCodePlaceholder')}
                  value={form.code}
                  onChange={(event) => handleInputChange('code', event)}
                />
                <button
                  type="button"
                  className="h-10 w-24 overflow-hidden rounded-[10px] border border-black/10 bg-white p-0 transition hover:border-[#2B7FFF] disabled:cursor-not-allowed dark:border-[#2a2a2d] dark:bg-[#222225]"
                  disabled={submitting || !captchaUrl}
                  onClick={refreshCaptcha}
                >
                  {captchaUrl ? (
                    <img
                      className="h-full w-full object-cover"
                      src={captchaUrl}
                      alt={t('login.captchaAlt')}
                    />
                  ) : (
                    <span className="text-[12px] text-[#99A0AE]">{t('login.loadingCaptcha')}</span>
                  )}
                </button>
              </div>
              {errors.code ? <div className="pt-2 text-[12px] text-[#dc2626]">{errors.code}</div> : null}
            </div>

            {errors.submit ? (
              <div className="rounded-[10px] border border-[#fecaca] bg-[#fef2f2] px-3 py-2 text-[13px] text-[#b91c1c]">
                {errors.submit}
              </div>
            ) : null}

            <button
              type="submit"
              className="mt-4 w-full rounded-lg bg-blue-600 py-2 text-white transition hover:bg-blue-700 disabled:cursor-not-allowed disabled:bg-blue-300"
              disabled={submitting}
            >
              {submitting ? t('login.submitting') : t('login.submit')}
            </button>
          </form>
        </div>

        {showDecorations ? (
          <img
            aria-hidden="true"
            alt=""
            className="ml-2 w-[540px] max-w-[48vw] self-center object-contain"
            decoding="async"
            fetchPriority="low"
            loading="eager"
            src={loginIllustration}
          />
        ) : null}
      </main>
    </div>
  );
}
