import { X } from 'lucide-react';
import { useEffect, useState } from 'react';

import type { PlatformTheme } from '../../../packages/shared/src/contracts/runtime';
import type {
  AuthCaptchaChallenge,
  AuthLoginMethod,
} from '../../services/authService';
import { getStoredLastLoginPhone } from '../../services/authService';
import { CaptchaChallengeField } from './CaptchaChallengeField';

type SmsScene = 'login' | 'reset_password';
type LoginTab = 'phone' | 'password' | 'register';

type LoginScreenProps = {
  isOpen: boolean;
  platformTheme: PlatformTheme;
  availableLoginMethods: AuthLoginMethod[];
  sendingCode: boolean;
  loggingIn: boolean;
  wechatLoading: boolean;
  error: string;
  captchaChallenge: AuthCaptchaChallenge | null;
  initialMode?: 'login' | 'register';
  initialInviteCode?: string;
  onClose: () => void;
  onSendCode: (
    phone: string,
    scene: SmsScene,
    captcha?: {
      challengeId?: string;
      answer?: string;
    },
  ) => Promise<{
    cooldownSeconds: number;
    expiresInSeconds: number;
  }>;
  onPhoneSubmit: (
    phone: string,
    code: string,
    inviteCode?: string,
  ) => Promise<void>;
  onPasswordSubmit: (phone: string, password: string) => Promise<void>;
  onResetPassword: (
    phone: string,
    code: string,
    newPassword: string,
  ) => Promise<void>;
  onStartWechatLogin: () => Promise<void>;
};

export function LoginScreen({
  isOpen,
  platformTheme,
  availableLoginMethods,
  sendingCode,
  loggingIn,
  wechatLoading,
  error,
  captchaChallenge,
  initialMode = 'login',
  initialInviteCode = '',
  onClose,
  onSendCode,
  onPhoneSubmit,
  onPasswordSubmit,
  onResetPassword,
  onStartWechatLogin,
}: LoginScreenProps) {
  const [isResetPanelOpen, setIsResetPanelOpen] = useState(false);
  const [phone, setPhone] = useState(() => getStoredLastLoginPhone());
  const [password, setPassword] = useState('');
  const [code, setCode] = useState('');
  const [resetPhone, setResetPhone] = useState('');
  const [resetCode, setResetCode] = useState('');
  const [resetPasswordValue, setResetPasswordValue] = useState('');
  const [inviteCode, setInviteCode] = useState(initialInviteCode);
  const [captchaAnswer, setCaptchaAnswer] = useState('');
  const [cooldownSeconds, setCooldownSeconds] = useState(0);
  const [resetCooldownSeconds, setResetCooldownSeconds] = useState(0);
  const [hint, setHint] = useState('');
  const passwordLoginEnabled = availableLoginMethods.includes('password');
  const phoneLoginEnabled = availableLoginMethods.includes('phone');
  const wechatLoginEnabled = availableLoginMethods.includes('wechat');
  const [activeLoginTab, setActiveLoginTab] = useState<LoginTab>('phone');

  useEffect(() => {
    if (!isOpen) {
      return;
    }

    // 每次重新打开弹窗都丢弃上一次未完成的表单草稿，只保留最近成功登录手机号回填。
    setIsResetPanelOpen(false);
    setPhone(getStoredLastLoginPhone());
    setPassword('');
    setCode('');
    setResetPhone('');
    setResetCode('');
    setResetPasswordValue('');
    setInviteCode(initialInviteCode);
    setCaptchaAnswer('');
    setCooldownSeconds(0);
    setResetCooldownSeconds(0);
    setHint('');
    setActiveLoginTab(
      initialMode === 'register' && phoneLoginEnabled
        ? 'register'
        : phoneLoginEnabled
          ? 'phone'
          : 'password',
    );
  }, [initialInviteCode, initialMode, isOpen, phoneLoginEnabled]);

  useEffect(() => {
    if (
      (activeLoginTab === 'phone' || activeLoginTab === 'register') &&
      !phoneLoginEnabled &&
      passwordLoginEnabled
    ) {
      setActiveLoginTab('password');
      return;
    }

    if (
      activeLoginTab === 'password' &&
      !passwordLoginEnabled &&
      phoneLoginEnabled
    ) {
      setActiveLoginTab('phone');
    }
  }, [activeLoginTab, passwordLoginEnabled, phoneLoginEnabled]);

  useEffect(() => {
    if (cooldownSeconds <= 0) {
      return;
    }

    const timeoutId = window.setTimeout(() => {
      setCooldownSeconds((current) => Math.max(0, current - 1));
    }, 1000);

    return () => window.clearTimeout(timeoutId);
  }, [cooldownSeconds]);

  useEffect(() => {
    if (resetCooldownSeconds <= 0) {
      return;
    }

    const timeoutId = window.setTimeout(() => {
      setResetCooldownSeconds((current) => Math.max(0, current - 1));
    }, 1000);

    return () => window.clearTimeout(timeoutId);
  }, [resetCooldownSeconds]);

  if (!isOpen) {
    return null;
  }

  const submitDisabled = loggingIn || sendingCode;

  return (
    <div
      className={`platform-theme platform-theme--${platformTheme} platform-overlay fixed inset-0 z-[120] flex items-end justify-center px-3 py-4 text-[var(--platform-text-strong)] backdrop-blur-sm sm:items-center sm:p-4`}
      onClick={onClose}
    >
      <div
        role="dialog"
        aria-modal="true"
        aria-labelledby="auth-login-dialog-title"
        className="platform-auth-card w-full max-w-md overflow-hidden rounded-[2rem]"
        onClick={(event) => event.stopPropagation()}
      >
        <div className="flex items-center justify-between gap-3 border-b border-[var(--platform-subpanel-border)] px-5 py-4">
          <div
            id="auth-login-dialog-title"
            className="text-lg font-semibold text-[var(--platform-text-strong)]"
          >
            {isResetPanelOpen ? '重置密码' : '账号入口'}
          </div>
          <button
            type="button"
            onClick={onClose}
            className="platform-icon-button p-2"
            aria-label="关闭登录弹窗"
          >
            <X className="h-4 w-4" />
          </button>
        </div>

        {isResetPanelOpen ? (
          <PasswordResetPanel
            phone={resetPhone}
            code={resetCode}
            password={resetPasswordValue}
            sendingCode={sendingCode}
            loggingIn={loggingIn}
            cooldownSeconds={resetCooldownSeconds}
            error={error}
            onPhoneChange={setResetPhone}
            onCodeChange={setResetCode}
            onPasswordChange={setResetPasswordValue}
            onBack={() => setIsResetPanelOpen(false)}
            onSendCode={async () => {
              const result = await onSendCode(resetPhone, 'reset_password');
              setResetCooldownSeconds(result.cooldownSeconds);
            }}
            onSubmit={() =>
              onResetPassword(resetPhone, resetCode, resetPasswordValue)
            }
          />
        ) : (
          <div className="flex flex-col gap-5 px-5 py-5">
            {phoneLoginEnabled ? (
              <div
                className={`grid gap-2 ${
                  passwordLoginEnabled ? 'grid-cols-3' : 'grid-cols-2'
                }`}
                role="tablist"
                aria-label="登录方式"
              >
                <LoginTabButton
                  active={activeLoginTab === 'phone'}
                  onClick={() => setActiveLoginTab('phone')}
                >
                  短信登录
                </LoginTabButton>
                {passwordLoginEnabled ? (
                  <LoginTabButton
                    active={activeLoginTab === 'password'}
                    onClick={() => setActiveLoginTab('password')}
                  >
                    密码登录
                  </LoginTabButton>
                ) : null}
                <LoginTabButton
                  active={activeLoginTab === 'register'}
                  onClick={() => setActiveLoginTab('register')}
                >
                  注册
                </LoginTabButton>
              </div>
            ) : null}

            {passwordLoginEnabled && activeLoginTab === 'password' ? (
              <form
                className="flex flex-col gap-4"
                onSubmit={(event) => {
                  event.preventDefault();
                  void onPasswordSubmit(phone, password);
                }}
              >
                <label className="grid gap-2 text-sm text-[var(--platform-text-base)]">
                  <span>手机号</span>
                  <input
                    className="platform-input"
                    autoComplete="tel"
                    inputMode="numeric"
                    value={phone}
                    onChange={(event) => setPhone(event.target.value)}
                    placeholder="13800000000"
                  />
                </label>
                <label className="grid gap-2 text-sm text-[var(--platform-text-base)]">
                  <span>密码</span>
                  <input
                    className="platform-input"
                    autoComplete="current-password"
                    type="password"
                    value={password}
                    onChange={(event) => setPassword(event.target.value)}
                    placeholder="输入密码"
                  />
                </label>

                {error ? <ErrorBanner message={error} /> : null}

                <div className="flex flex-col gap-2">
                  <button
                    type="submit"
                    disabled={
                      submitDisabled || !phone.trim() || !password.trim()
                    }
                    className="platform-button platform-button--primary h-12 px-4 text-base disabled:cursor-not-allowed disabled:opacity-60"
                  >
                    {loggingIn ? '登录中' : '登录'}
                  </button>
                  <button
                    type="button"
                    className="self-end text-sm text-[var(--platform-accent)]"
                    onClick={() => setIsResetPanelOpen(true)}
                  >
                    忘记密码
                  </button>
                </div>

                {wechatLoginEnabled ? (
                  <WechatButton
                    loading={wechatLoading}
                    disabled={submitDisabled}
                    onClick={onStartWechatLogin}
                  />
                ) : null}
              </form>
            ) : null}

            {phoneLoginEnabled && activeLoginTab === 'phone' ? (
              <PhoneCodeForm
                phone={phone}
                code={code}
                captchaAnswer={captchaAnswer}
                captchaChallenge={captchaChallenge}
                cooldownSeconds={cooldownSeconds}
                sendingCode={sendingCode}
                loggingIn={loggingIn}
                error={error}
                hint={hint}
                submitLabel="登录"
                enabled={phoneLoginEnabled}
                showPhoneField
                onPhoneChange={setPhone}
                onCodeChange={setCode}
                onCaptchaAnswerChange={setCaptchaAnswer}
                onSendCode={async () => {
                  setHint('');
                  const result = await onSendCode(phone, 'login', {
                    challengeId: captchaChallenge?.challengeId,
                    answer: captchaAnswer,
                  });
                  setCooldownSeconds(result.cooldownSeconds);
                  setHint(
                    `短信请求已提交，验证码有效期约 ${Math.max(1, Math.round(result.expiresInSeconds / 60))} 分钟。`,
                  );
                  setCaptchaAnswer('');
                }}
                onSubmit={() => onPhoneSubmit(phone, code)}
              />
            ) : null}

            {phoneLoginEnabled && activeLoginTab === 'register' ? (
              <PhoneCodeForm
                phone={phone}
                code={code}
                inviteCode={inviteCode}
                captchaAnswer={captchaAnswer}
                captchaChallenge={captchaChallenge}
                cooldownSeconds={cooldownSeconds}
                sendingCode={sendingCode}
                loggingIn={loggingIn}
                error={error}
                hint={hint}
                submitLabel="注册"
                enabled={phoneLoginEnabled}
                showPhoneField
                showInviteCodeField
                onPhoneChange={setPhone}
                onCodeChange={setCode}
                onInviteCodeChange={setInviteCode}
                onCaptchaAnswerChange={setCaptchaAnswer}
                onSendCode={async () => {
                  setHint('');
                  const result = await onSendCode(phone, 'login', {
                    challengeId: captchaChallenge?.challengeId,
                    answer: captchaAnswer,
                  });
                  setCooldownSeconds(result.cooldownSeconds);
                  setHint(
                    `短信请求已提交，验证码有效期约 ${Math.max(1, Math.round(result.expiresInSeconds / 60))} 分钟。`,
                  );
                  setCaptchaAnswer('');
                }}
                onSubmit={() => onPhoneSubmit(phone, code, inviteCode)}
              />
            ) : null}

            {!passwordLoginEnabled &&
            !phoneLoginEnabled &&
            !wechatLoginEnabled ? (
              <div className="platform-subpanel rounded-2xl px-4 py-4 text-sm text-[var(--platform-text-base)]">
                当前登录入口暂不可用。
              </div>
            ) : null}
          </div>
        )}
      </div>
    </div>
  );
}

function LoginTabButton({
  active,
  children,
  onClick,
}: {
  active: boolean;
  children: string;
  onClick: () => void;
}) {
  return (
    <button
      type="button"
      role="tab"
      aria-selected={active}
      className={`relative h-12 text-base font-semibold transition-colors sm:text-lg ${
        active
          ? 'text-[var(--platform-text-strong)]'
          : 'text-[var(--platform-text-muted)]'
      }`}
      onClick={onClick}
    >
      <span>{children}</span>
      {active ? (
        <span className="absolute bottom-1 left-1/2 h-1 w-12 -translate-x-1/2 rounded-full bg-[var(--platform-accent)]" />
      ) : null}
    </button>
  );
}

function PhoneCodeForm({
  phone,
  code,
  inviteCode = '',
  captchaAnswer,
  captchaChallenge,
  cooldownSeconds,
  sendingCode,
  loggingIn,
  error,
  hint,
  submitLabel,
  enabled,
  showPhoneField,
  showInviteCodeField = false,
  onPhoneChange,
  onCodeChange,
  onInviteCodeChange,
  onCaptchaAnswerChange,
  onSendCode,
  onSubmit,
}: {
  phone: string;
  code: string;
  inviteCode?: string;
  captchaAnswer: string;
  captchaChallenge: AuthCaptchaChallenge | null;
  cooldownSeconds: number;
  sendingCode: boolean;
  loggingIn: boolean;
  error: string;
  hint: string;
  submitLabel: string;
  enabled: boolean;
  showPhoneField: boolean;
  showInviteCodeField?: boolean;
  onPhoneChange: (value: string) => void;
  onCodeChange: (value: string) => void;
  onInviteCodeChange?: (value: string) => void;
  onCaptchaAnswerChange: (value: string) => void;
  onSendCode: () => Promise<void>;
  onSubmit: () => Promise<void>;
}) {
  if (!enabled) {
    return null;
  }

  return (
    <form
      className="flex flex-col gap-4"
      onSubmit={(event) => {
        event.preventDefault();
        void onSubmit();
      }}
    >
      {showPhoneField ? (
        <label className="grid gap-2 text-sm text-[var(--platform-text-base)]">
          <span>手机号</span>
          <input
            className="platform-input"
            autoComplete="tel"
            inputMode="numeric"
            value={phone}
            onChange={(event) => onPhoneChange(event.target.value)}
            placeholder="13800000000"
          />
        </label>
      ) : null}

      {showInviteCodeField ? (
        <label className="grid gap-2 text-sm text-[var(--platform-text-base)]">
          <span>邀请码</span>
          <input
            className="platform-input"
            autoComplete="off"
            value={inviteCode}
            onChange={(event) => onInviteCodeChange?.(event.target.value)}
            placeholder="邀请码"
          />
        </label>
      ) : null}

      <label className="grid gap-2 text-sm text-[var(--platform-text-base)]">
        <span>验证码</span>
        <div className="flex gap-3">
          <input
            className="platform-input min-w-0 flex-1"
            inputMode="numeric"
            value={code}
            onChange={(event) => onCodeChange(event.target.value)}
            placeholder="输入验证码"
          />
          <button
            type="button"
            disabled={sendingCode || cooldownSeconds > 0 || !phone.trim()}
            className="platform-button platform-button--secondary h-12 shrink-0 px-4 text-sm disabled:cursor-not-allowed disabled:opacity-55"
            onClick={() => void onSendCode()}
          >
            {sendingCode
              ? '发送中'
              : cooldownSeconds > 0
                ? `${cooldownSeconds}s`
                : '获取验证码'}
          </button>
        </div>
      </label>

      <CaptchaChallengeField
        challenge={captchaChallenge}
        answer={captchaAnswer}
        onAnswerChange={onCaptchaAnswerChange}
      />

      {hint ? <SuccessBanner message={hint} /> : null}
      {error ? <ErrorBanner message={error} /> : null}

      <button
        type="submit"
        disabled={loggingIn || !phone.trim() || !code.trim()}
        className="platform-button platform-button--primary h-12 px-4 text-base disabled:cursor-not-allowed disabled:opacity-60"
      >
        {loggingIn ? '处理中' : submitLabel}
      </button>
    </form>
  );
}

function PasswordResetPanel({
  phone,
  code,
  password,
  sendingCode,
  loggingIn,
  cooldownSeconds,
  error,
  onPhoneChange,
  onCodeChange,
  onPasswordChange,
  onBack,
  onSendCode,
  onSubmit,
}: {
  phone: string;
  code: string;
  password: string;
  sendingCode: boolean;
  loggingIn: boolean;
  cooldownSeconds: number;
  error: string;
  onPhoneChange: (value: string) => void;
  onCodeChange: (value: string) => void;
  onPasswordChange: (value: string) => void;
  onBack: () => void;
  onSendCode: () => Promise<void>;
  onSubmit: () => Promise<void>;
}) {
  return (
    <form
      className="flex flex-col gap-4 px-5 py-5"
      onSubmit={(event) => {
        event.preventDefault();
        void onSubmit();
      }}
    >
      <label className="grid gap-2 text-sm text-[var(--platform-text-base)]">
        <span>手机号</span>
        <input
          className="platform-input"
          autoComplete="tel"
          inputMode="numeric"
          value={phone}
          onChange={(event) => onPhoneChange(event.target.value)}
          placeholder="13800000000"
        />
      </label>
      <label className="grid gap-2 text-sm text-[var(--platform-text-base)]">
        <span>验证码</span>
        <div className="flex gap-3">
          <input
            className="platform-input min-w-0 flex-1"
            inputMode="numeric"
            value={code}
            onChange={(event) => onCodeChange(event.target.value)}
            placeholder="输入验证码"
          />
          <button
            type="button"
            disabled={sendingCode || cooldownSeconds > 0 || !phone.trim()}
            className="platform-button platform-button--secondary h-12 shrink-0 px-4 text-sm disabled:cursor-not-allowed disabled:opacity-55"
            onClick={() => void onSendCode()}
          >
            {sendingCode
              ? '发送中'
              : cooldownSeconds > 0
                ? `${cooldownSeconds}s`
                : '获取验证码'}
          </button>
        </div>
      </label>
      <label className="grid gap-2 text-sm text-[var(--platform-text-base)]">
        <span>新密码</span>
        <input
          className="platform-input"
          autoComplete="new-password"
          type="password"
          value={password}
          onChange={(event) => onPasswordChange(event.target.value)}
          placeholder="设置新密码"
        />
      </label>

      {error ? <ErrorBanner message={error} /> : null}

      <div className="grid grid-cols-2 gap-3">
        <button
          type="button"
          className="platform-button platform-button--secondary h-12 px-4 text-base"
          onClick={onBack}
        >
          返回
        </button>
        <button
          type="submit"
          disabled={
            loggingIn || !phone.trim() || !code.trim() || !password.trim()
          }
          className="platform-button platform-button--primary h-12 px-4 text-base disabled:cursor-not-allowed disabled:opacity-60"
        >
          {loggingIn ? '处理中' : '重置密码'}
        </button>
      </div>
    </form>
  );
}

function WechatButton({
  loading,
  disabled,
  onClick,
}: {
  loading: boolean;
  disabled: boolean;
  onClick: () => Promise<void>;
}) {
  return (
    <button
      type="button"
      disabled={loading || disabled}
      className="platform-button platform-button--secondary h-12 px-4 text-base disabled:cursor-not-allowed disabled:opacity-60"
      onClick={() => void onClick()}
    >
      {loading ? '跳转中' : '微信登录'}
    </button>
  );
}

function ErrorBanner({ message }: { message: string }) {
  return (
    <div className="platform-banner platform-banner--danger text-sm">
      {message}
    </div>
  );
}

function SuccessBanner({ message }: { message: string }) {
  return (
    <div className="platform-banner platform-banner--success text-sm">
      {message}
    </div>
  );
}
