import { useEffect, useState, type FormEvent } from 'react';
import * as memberApi from '../../api/member';
import { ApiError } from '../../api/http';
import { TotpQrPanel } from '../../components/TotpQrPanel';

export function SecurityPage() {
  const [me, setMe] = useState<memberApi.MemberMe | null>(null);
  const [totp, setTotp] = useState<memberApi.TOTPStatus | null>(null);
  const [enrollInfo, setEnrollInfo] = useState<memberApi.TOTPEnrollStart | null>(
    null,
  );
  const [backupCodes, setBackupCodes] = useState<string[]>([]);

  const [emailTarget, setEmailTarget] = useState('');
  const [emailChallenge, setEmailChallenge] = useState('');
  const [emailCode, setEmailCode] = useState('');

  const [phoneTarget, setPhoneTarget] = useState('');
  const [phoneChallenge, setPhoneChallenge] = useState('');
  const [phoneCode, setPhoneCode] = useState('');

  const [totpCode, setTotpCode] = useState('');
  const [pwdStepUpCode, setPwdStepUpCode] = useState('');
  const [pwdStepUpToken, setPwdStepUpToken] = useState('');
  const [pwdStepVerified, setPwdStepVerified] = useState(false);
  const [pwdVerifyLoading, setPwdVerifyLoading] = useState(false);
  const [currentPassword, setCurrentPassword] = useState('');
  const [newPassword, setNewPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');
  const [msg, setMsg] = useState('');
  const [error, setError] = useState('');

  const reload = async () => {
    const [profile, totpStatus] = await Promise.all([
      memberApi.getMe().catch(() => null),
      memberApi.getTOTPStatus().catch(() => null),
    ]);
    setMe(profile);
    setTotp(totpStatus);
    if (profile?.zitadel_email && !emailTarget) {
      setEmailTarget(profile.zitadel_email);
    }
  };

  useEffect(() => {
    reload();
  }, []);

  const showErr = (e: unknown) =>
    setError(e instanceof ApiError ? e.message : '操作失敗');

  const startEmail = async (e: FormEvent) => {
    e.preventDefault();
    setError('');
    setMsg('');
    try {
      const r = await memberApi.startEmailVerification(emailTarget);
      setEmailChallenge(r.challenge_id);
      setMsg('Email 驗證碼已寄出');
    } catch (e) {
      showErr(e);
    }
  };

  const confirmEmail = async (e: FormEvent) => {
    e.preventDefault();
    setError('');
    try {
      await memberApi.confirmEmailVerification(emailChallenge, emailCode);
      setMsg('商業 Email 已驗證');
      await reload();
    } catch (e) {
      showErr(e);
    }
  };

  const startPhone = async (e: FormEvent) => {
    e.preventDefault();
    setError('');
    setMsg('');
    try {
      const r = await memberApi.startPhoneVerification(phoneTarget);
      setPhoneChallenge(r.challenge_id);
      setMsg('簡訊驗證碼已送出（開發環境請查 Redis / mock）');
    } catch (e) {
      showErr(e);
    }
  };

  const confirmPhone = async (e: FormEvent) => {
    e.preventDefault();
    setError('');
    try {
      await memberApi.confirmPhoneVerification(phoneChallenge, phoneCode);
      setMsg('商業手機已驗證');
    } catch (e) {
      showErr(e);
    }
  };

  const startTotp = async () => {
    setError('');
    setEnrollInfo(null);
    try {
      const r = await memberApi.startTOTPEnroll();
      setEnrollInfo(r);
      setMsg('請用 Authenticator 掃描 QR Code，再輸入 6 位驗證碼完成綁定');
    } catch (e) {
      showErr(e);
    }
  };

  const confirmTotp = async (e: FormEvent) => {
    e.preventDefault();
    setError('');
    try {
      const r = await memberApi.confirmTOTPEnroll(totpCode);
      setBackupCodes(r.backup_codes);
      setMsg('TOTP 已啟用，請妥善保存備援碼');
      setEnrollInfo(null);
      setTotpCode('');
      await reload();
    } catch (e) {
      showErr(e);
    }
  };

  const disableTotp = async () => {
    if (!confirm('確定停用 TOTP？')) return;
    setError('');
    try {
      await memberApi.disableTOTP();
      setEnrollInfo(null);
      setBackupCodes([]);
      await reload();
      setMsg('TOTP 已停用');
    } catch (e) {
      showErr(e);
    }
  };

  const verifyForPasswordChange = async (e: FormEvent) => {
    e.preventDefault();
    setError('');
    setMsg('');
    setPwdVerifyLoading(true);
    try {
      const r = await memberApi.verifyTOTP(
        pwdStepUpCode.replace(/\s/g, ''),
        'change_password',
      );
      const token = memberApi.pickStepUpToken(r);
      if (!token) {
        setError(
          '驗證已通過但未取得授權憑證，請執行 make dev-restart-gateway 更新後端後再試',
        );
        return;
      }
      setPwdStepUpToken(token);
      setPwdStepVerified(true);
      setPwdStepUpCode('');
      setMsg('驗證成功，請在下方輸入新密碼（約 5 分鐘內有效）');
    } catch (e) {
      showErr(e);
    } finally {
      setPwdVerifyLoading(false);
    }
  };

  const changePassword = async (e: FormEvent) => {
    e.preventDefault();
    if (newPassword !== confirmPassword) {
      setError('兩次輸入的新密碼不一致');
      return;
    }
    if (totpActive && !pwdStepVerified) {
      setError('請先完成 TOTP 驗證');
      return;
    }
    setError('');
    setMsg('');
    try {
      await memberApi.changePassword(currentPassword, newPassword, {
        stepUpToken: pwdStepUpToken || undefined,
      });
      setPwdStepUpToken('');
      setPwdStepVerified(false);
      setCurrentPassword('');
      setNewPassword('');
      setConfirmPassword('');
      setMsg('密碼已更新');
    } catch (e) {
      showErr(e);
    }
  };

  const resetPasswordFlow = () => {
    setPwdStepUpToken('');
    setPwdStepVerified(false);
    setPwdStepUpCode('');
    setCurrentPassword('');
    setNewPassword('');
    setConfirmPassword('');
    setError('');
  };

  const canChangePassword = me?.origin === 'platform_native';
  const totpActive = Boolean(me?.totp_enrolled ?? totp?.enrolled);
  const passwordNeedsTotp = totpActive && !pwdStepVerified;

  return (
    <div>
      <h1>安全設定</h1>
      {msg && <p className="form-ok">{msg}</p>}
      {error && <p className="form-error">{error}</p>}

      <section className="section">
        <h2>登入密碼</h2>
        {canChangePassword ? (
          <>
            {!totpActive ? (
              <p className="hint">
                變更登入密碼前須先完成下方「雙因素驗證 (TOTP)」綁定。
              </p>
            ) : (
              <p className="hint">
                已啟用雙因素驗證：變更密碼前須先輸入驗證器或備援碼。
              </p>
            )}
            {!totpActive ? null : passwordNeedsTotp ? (
              <form onSubmit={verifyForPasswordChange} className="form">
                <label>
                  驗證碼（TOTP / 備援碼）
                  <input
                    value={pwdStepUpCode}
                    onChange={(e) => setPwdStepUpCode(e.target.value)}
                    inputMode="numeric"
                    autoComplete="one-time-code"
                    autoFocus
                    required
                    minLength={6}
                    maxLength={32}
                    placeholder="000000"
                    disabled={pwdVerifyLoading}
                  />
                </label>
                <button
                  type="submit"
                  className="btn-primary"
                  disabled={pwdVerifyLoading}
                >
                  {pwdVerifyLoading ? '驗證中…' : '驗證並繼續'}
                </button>
              </form>
            ) : (
              <form onSubmit={changePassword} className="form">
                {totpActive && (
                  <p className="form-ok">TOTP 已驗證，請輸入新密碼。</p>
                )}
                <label>
                  目前密碼
                  <input
                    type="password"
                    value={currentPassword}
                    onChange={(e) => setCurrentPassword(e.target.value)}
                    autoComplete="current-password"
                    required
                  />
                </label>
                <label>
                  新密碼
                  <input
                    type="password"
                    value={newPassword}
                    onChange={(e) => setNewPassword(e.target.value)}
                    autoComplete="new-password"
                    required
                    minLength={8}
                  />
                </label>
                <label>
                  確認新密碼
                  <input
                    type="password"
                    value={confirmPassword}
                    onChange={(e) => setConfirmPassword(e.target.value)}
                    autoComplete="new-password"
                    required
                    minLength={8}
                  />
                </label>
                <div className="form-actions">
                  <button type="submit" className="btn-primary">
                    更新密碼
                  </button>
                  {totpActive && (
                    <button
                      type="button"
                      className="btn-ghost"
                      onClick={resetPasswordFlow}
                    >
                      重新驗證 TOTP
                    </button>
                  )}
                </div>
              </form>
            )}
          </>
        ) : (
          <p className="hint">
            您的帳號由第三方或企業目錄登入，無法在此變更密碼。
          </p>
        )}
      </section>

      <section className="section">
        <h2>商業聯絡 Email</h2>
        <p className="hint">
          註冊時驗證的是<strong>登入信箱</strong>（ZITADEL）；此處為<strong>業務聯絡信箱</strong>（通知、帳務等）。
          若與註冊信箱相同，完成註冊 OTP 後會自動標為已驗證。
        </p>
        {me?.business_email_verified ? (
          <p className="form-ok">
            已驗證：{me.business_email || me.zitadel_email}
          </p>
        ) : (
          <>
            {me?.zitadel_email && (
              <p className="hint">
                登入信箱：{me.zitadel_email}
                {me.business_email && me.business_email !== me.zitadel_email
                  ? ` · 目前商業信箱：${me.business_email}（未驗證）`
                  : ''}
              </p>
            )}
            <form onSubmit={startEmail} className="form-inline">
              <input
                type="email"
                placeholder={me?.zitadel_email ?? 'biz@example.com'}
                value={emailTarget}
                onChange={(e) => setEmailTarget(e.target.value)}
                required
              />
              <button type="submit">寄送驗證碼</button>
            </form>
            {emailChallenge && (
              <form onSubmit={confirmEmail} className="form-inline">
                <input
                  placeholder="6 位驗證碼（MailHog :8025）"
                  value={emailCode}
                  onChange={(e) => setEmailCode(e.target.value)}
                  maxLength={6}
                />
                <button type="submit">確認</button>
              </form>
            )}
          </>
        )}
      </section>

      <section className="section">
        <h2>商業手機驗證</h2>
        <form onSubmit={startPhone} className="form-inline">
          <input
            placeholder="+886912345678"
            value={phoneTarget}
            onChange={(e) => setPhoneTarget(e.target.value)}
            required
          />
          <button type="submit">寄送驗證碼</button>
        </form>
        {phoneChallenge && (
          <form onSubmit={confirmPhone} className="form-inline">
            <input
              placeholder="6 位驗證碼"
              value={phoneCode}
              onChange={(e) => setPhoneCode(e.target.value)}
              maxLength={6}
            />
            <button type="submit">確認</button>
          </form>
        )}
      </section>

      <section className="section">
        <h2>雙因素驗證 (TOTP)</h2>
        <p>
          狀態：{totp?.enrolled ? '已啟用' : '未啟用'}
          {totp?.enrolled &&
            ` · 備援碼剩餘 ${totp.backup_codes_remaining} 組`}
        </p>
        {totp?.enrolled && (
          <p className="form-ok">
            下次登入時，輸入密碼後會進入「雙因素驗證」步驟，需再輸入驗證器或備援碼。
          </p>
        )}
        {!totp?.enrolled ? (
          <>
            <button type="button" className="btn-primary" onClick={startTotp}>
              開始綁定
            </button>
            {enrollInfo && (
              <TotpQrPanel
                otpauthUrl={enrollInfo.otpauth_url}
                issuer={enrollInfo.issuer}
                account={enrollInfo.account}
              />
            )}
            {enrollInfo && (
              <form onSubmit={confirmTotp} className="form-inline">
                <input
                  placeholder="Authenticator 6 碼"
                  value={totpCode}
                  onChange={(e) => setTotpCode(e.target.value)}
                />
                <button type="submit">完成綁定</button>
              </form>
            )}
          </>
        ) : (
          <button type="button" className="btn-danger" onClick={disableTotp}>
            停用 TOTP
          </button>
        )}
        {backupCodes.length > 0 && (
          <pre className="backup-codes">{backupCodes.join('\n')}</pre>
        )}
      </section>
    </div>
  );
}
