import { Check } from 'lucide-react';
import { type ReactNode, 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 { isWechatMiniProgramWebViewRuntime } from '../../services/authService';
import { LegalDocumentModal } from '../common/LegalDocumentModal';
import {
  getLegalDocument,
  type LegalDocumentId,
  persistLegalConsent,
  readStoredLegalConsent,
} from '../common/legalDocuments';
import { PlatformActionButton } from '../common/PlatformActionButton';
import { PlatformEmptyState } from '../common/PlatformEmptyState';
import { PlatformFieldLabel } from '../common/PlatformFieldLabel';
import { PlatformSegmentedTabs } from '../common/PlatformSegmentedTabs';
import { PlatformStatusMessage } from '../common/PlatformStatusMessage';
import { PlatformTextField } from '../common/PlatformTextField';
import { CaptchaChallengeField } from './CaptchaChallengeField';
import { PlatformAuthModalShell } from './PlatformAuthModalShell';

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

const LOGIN_TAB_ITEMS: Array<{ id: LoginTab; label: string }> = [
  { id: 'phone', label: '短信登录' },
  { id: 'password', label: '密码登录' },
];

type LoginScreenProps = {
  isOpen: boolean;
  platformTheme: PlatformTheme;
  availableLoginMethods: AuthLoginMethod[];
  sendingCode: boolean;
  loggingIn: boolean;
  wechatLoading: boolean;
  error: string;
  captchaChallenge: AuthCaptchaChallenge | null;
  onClose: () => void;
  onSendCode: (
    phone: string,
    scene: SmsScene,
    captcha?: {
      challengeId?: string;
      answer?: string;
    },
  ) => Promise<{
    cooldownSeconds: number;
    expiresInSeconds: number;
  }>;
  onPhoneSubmit: (phone: string, code: 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,
  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 [captchaAnswer, setCaptchaAnswer] = useState('');
  const [cooldownSeconds, setCooldownSeconds] = useState(0);
  const [resetCooldownSeconds, setResetCooldownSeconds] = useState(0);
  const [hint, setHint] = useState('');
  const [legalConsentChecked, setLegalConsentChecked] = useState(false);
  const [activeLegalDocumentId, setActiveLegalDocumentId] =
    useState<LegalDocumentId | null>(null);
  const passwordLoginEnabled = true;
  const phoneLoginEnabled = true;
  const wechatLoginEnabled = availableLoginMethods.includes('wechat');
  const miniProgramRuntime = isWechatMiniProgramWebViewRuntime();
  const [activeLoginTab, setActiveLoginTab] = useState<LoginTab>('phone');

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

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

  useEffect(() => {
    if (
      activeLoginTab === 'phone' &&
      !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;
  const activeLegalDocument = activeLegalDocumentId
    ? getLegalDocument(activeLegalDocumentId)
    : null;
  const toggleLegalConsent = () => {
    setLegalConsentChecked((current) => {
      const nextChecked = !current;
      if (nextChecked) {
        persistLegalConsent();
      }
      return nextChecked;
    });
  };
  const legalConsentRow = (
    <LegalConsentRow
      checked={legalConsentChecked}
      onToggle={toggleLegalConsent}
      onOpenDocument={setActiveLegalDocumentId}
    />
  );

  return (
    <>
      <PlatformAuthModalShell
        title={isResetPanelOpen ? '重置密码' : '账号入口'}
        platformTheme={platformTheme}
        onClose={onClose}
        closeLabel="关闭登录弹窗"
        panelClassName="!max-w-md"
      >
        {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 ? (
              <PlatformSegmentedTabs
                items={
                  passwordLoginEnabled
                    ? LOGIN_TAB_ITEMS
                    : LOGIN_TAB_ITEMS.slice(0, 1)
                }
                activeId={activeLoginTab}
                onChange={setActiveLoginTab}
                columns={passwordLoginEnabled ? 'two' : 'one'}
                frame="bare"
                surface="transparent"
                tone="underline"
                size="tab"
                semantics="tabs"
                ariaLabel="登录方式"
              />
            ) : null}

            {passwordLoginEnabled && activeLoginTab === 'password' ? (
              <form
                className="flex flex-col gap-4"
                onSubmit={(event) => {
                  event.preventDefault();
                  if (
                    submitDisabled ||
                    !phone.trim() ||
                    !password.trim() ||
                    !legalConsentChecked
                  ) {
                    return;
                  }
                  void onPasswordSubmit(phone, password);
                }}
              >
                <label className="grid gap-2">
                  <PlatformFieldLabel variant="form" className="mb-0">
                    手机号
                  </PlatformFieldLabel>
                  <PlatformTextField
                    autoComplete="tel"
                    inputMode="numeric"
                    value={phone}
                    onChange={(event) => setPhone(event.target.value)}
                    placeholder="13800000000"
                  />
                </label>
                <label className="grid gap-2">
                  <PlatformFieldLabel variant="form" className="mb-0">
                    密码
                  </PlatformFieldLabel>
                  <PlatformTextField
                    autoComplete="current-password"
                    type="password"
                    value={password}
                    onChange={(event) => setPassword(event.target.value)}
                    placeholder="输入密码"
                  />
                </label>

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

                <div className="flex flex-col gap-2">
                  <PlatformActionButton
                    type="submit"
                    disabled={
                      submitDisabled ||
                      !phone.trim() ||
                      !password.trim() ||
                      !legalConsentChecked
                    }
                    size="lg"
                  >
                    {loggingIn ? '登录中' : '登录'}
                  </PlatformActionButton>
                  <button
                    type="button"
                    className="self-end text-sm text-[var(--platform-accent)]"
                    onClick={() => setIsResetPanelOpen(true)}
                  >
                    忘记密码
                  </button>
                </div>

                {wechatLoginEnabled && !miniProgramRuntime ? (
                  <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}
                legalConsentChecked={legalConsentChecked}
                legalConsentNode={legalConsentRow}
                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}

            {!passwordLoginEnabled &&
            !phoneLoginEnabled &&
            !wechatLoginEnabled &&
            !miniProgramRuntime ? (
              <PlatformEmptyState
                surface="subpanel"
                size="compact"
                className="px-4 py-4"
              >
                当前登录入口暂不可用。
              </PlatformEmptyState>
            ) : null}
          </div>
        )}
      </PlatformAuthModalShell>
      <LegalDocumentModal
        document={activeLegalDocument}
        open={Boolean(activeLegalDocument)}
        platformTheme={platformTheme}
        onClose={() => setActiveLegalDocumentId(null)}
      />
    </>
  );
}

function LegalConsentRow({
  checked,
  onToggle,
  onOpenDocument,
}: {
  checked: boolean;
  onToggle: () => void;
  onOpenDocument: (documentId: LegalDocumentId) => void;
}) {
  const openDocument = (documentId: LegalDocumentId) => {
    onOpenDocument(documentId);
  };

  return (
    <div className="flex items-start gap-2.5 text-xs leading-5 text-[var(--platform-text-base)]">
      <button
        type="button"
        role="switch"
        aria-checked={checked}
        aria-label="同意法律协议"
        onClick={onToggle}
        className={`mt-0.5 flex h-5 w-9 shrink-0 items-center rounded-full border p-0.5 transition ${
          checked
            ? 'justify-end border-[var(--platform-button-primary-border)] [background:var(--platform-profile-action-fill)]'
            : 'justify-start border-[var(--platform-subpanel-border)] [background:var(--platform-button-secondary-fill)]'
        }`}
      >
        <span className="flex h-4 w-4 items-center justify-center rounded-full bg-[var(--platform-button-primary-text)] text-[var(--platform-cool-text)] shadow-sm">
          {checked ? <Check className="h-3 w-3" /> : null}
        </span>
      </button>
      <div>
        我已阅读并同意
        <LegalLink
          label="《用户协议》"
          onClick={() => openDocument('user-agreement')}
        />
        <LegalLink
          label="《隐私政策》"
          onClick={() => openDocument('privacy-policy')}
        />
        和
        <LegalLink
          label="《免责声明》"
          onClick={() => openDocument('disclaimer')}
        />
      </div>
    </div>
  );
}

function LegalLink({ label, onClick }: { label: string; onClick: () => void }) {
  return (
    <button
      type="button"
      className="mx-0.5 align-baseline font-semibold text-[var(--platform-cool-text)] underline-offset-2 hover:underline"
      onClick={onClick}
    >
      {label}
    </button>
  );
}

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

  const submitBlocked =
    loggingIn || !phone.trim() || !code.trim() || !legalConsentChecked;

  return (
    <form
      className="flex flex-col gap-4"
      onSubmit={(event) => {
        event.preventDefault();
        if (submitBlocked) {
          return;
        }
        void onSubmit();
      }}
    >
      {showPhoneField ? (
        <label className="grid gap-2">
          <PlatformFieldLabel variant="form" className="mb-0">
            手机号
          </PlatformFieldLabel>
          <PlatformTextField
            autoComplete="tel"
            inputMode="numeric"
            value={phone}
            onChange={(event) => onPhoneChange(event.target.value)}
            placeholder="13800000000"
          />
        </label>
      ) : null}

      <label className="grid gap-2">
        <PlatformFieldLabel variant="form" className="mb-0">
          验证码
        </PlatformFieldLabel>
        <div className="flex gap-3">
          <PlatformTextField
            className="min-w-0 flex-1"
            inputMode="numeric"
            value={code}
            onChange={(event) => onCodeChange(event.target.value)}
            placeholder="输入验证码"
          />
          <PlatformActionButton
            disabled={sendingCode || cooldownSeconds > 0 || !phone.trim()}
            tone="secondary"
            size="lg"
            className="shrink-0 text-sm"
            onClick={() => void onSendCode()}
          >
            {sendingCode
              ? '发送中'
              : cooldownSeconds > 0
                ? `${cooldownSeconds}s`
                : '获取验证码'}
          </PlatformActionButton>
        </div>
      </label>

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

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

      <PlatformActionButton type="submit" disabled={submitBlocked} size="lg">
        {loggingIn ? '处理中' : submitLabel}
      </PlatformActionButton>
    </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">
        <PlatformFieldLabel variant="form" className="mb-0">
          手机号
        </PlatformFieldLabel>
        <PlatformTextField
          autoComplete="tel"
          inputMode="numeric"
          value={phone}
          onChange={(event) => onPhoneChange(event.target.value)}
          placeholder="13800000000"
        />
      </label>
      <label className="grid gap-2">
        <PlatformFieldLabel variant="form" className="mb-0">
          验证码
        </PlatformFieldLabel>
        <div className="flex gap-3">
          <PlatformTextField
            className="min-w-0 flex-1"
            inputMode="numeric"
            value={code}
            onChange={(event) => onCodeChange(event.target.value)}
            placeholder="输入验证码"
          />
          <PlatformActionButton
            disabled={sendingCode || cooldownSeconds > 0 || !phone.trim()}
            tone="secondary"
            size="lg"
            className="shrink-0 text-sm"
            onClick={() => void onSendCode()}
          >
            {sendingCode
              ? '发送中'
              : cooldownSeconds > 0
                ? `${cooldownSeconds}s`
                : '获取验证码'}
          </PlatformActionButton>
        </div>
      </label>
      <label className="grid gap-2">
        <PlatformFieldLabel variant="form" className="mb-0">
          新密码
        </PlatformFieldLabel>
        <PlatformTextField
          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">
        <PlatformActionButton tone="secondary" size="lg" onClick={onBack}>
          返回
        </PlatformActionButton>
        <PlatformActionButton
          type="submit"
          disabled={
            loggingIn || !phone.trim() || !code.trim() || !password.trim()
          }
          size="lg"
        >
          {loggingIn ? '处理中' : '重置密码'}
        </PlatformActionButton>
      </div>
    </form>
  );
}

function WechatButton({
  loading,
  disabled,
  onClick,
}: {
  loading: boolean;
  disabled: boolean;
  onClick: () => Promise<void>;
}) {
  return (
    <PlatformActionButton
      disabled={loading || disabled}
      tone="secondary"
      size="lg"
      onClick={() => void onClick()}
    >
      {loading ? '跳转中' : '微信登录'}
    </PlatformActionButton>
  );
}

function ErrorBanner({ message }: { message: string }) {
  return (
    <PlatformStatusMessage tone="error" surface="profile">
      {message}
    </PlatformStatusMessage>
  );
}

function SuccessBanner({ message }: { message: string }) {
  return (
    <PlatformStatusMessage tone="success" surface="profile">
      {message}
    </PlatformStatusMessage>
  );
}
