"use client";

import { useEffect, useState, useCallback } from "react";
import { createPortal } from "react-dom";
import { AnimatePresence, motion } from "framer-motion";
import { signIn } from "next-auth/react";
import { X, Phone, KeyRound, Loader2 } from "lucide-react";
import Button from "@/components/ui/Button";
import Logo from "@/components/Logo";
import { cn } from "@/lib/cn";

interface LoginModalProps {
  open: boolean;
  onClose: () => void;
  /** 登录成功回调（默认刷新页面） */
  onSuccess?: () => void;
}

/**
 * 登录 / 注册弹窗。
 * 替代独立 /login 路由，所有"需要登录"的入口统一弹出此组件。
 */
export default function LoginModal({ open, onClose, onSuccess }: LoginModalProps) {
  const [phone, setPhone] = useState("");
  const [code, setCode] = useState("");
  const [countdown, setCountdown] = useState(0);
  const [error, setError] = useState<string | null>(null);
  const [sending, setSending] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [mounted, setMounted] = useState(false);

  useEffect(() => setMounted(true), []);

  const phoneValid = /^1[3-9]\d{9}$/.test(phone);
  const codeValid = /^\d{6}$/.test(code);

  // 打开时重置
  useEffect(() => {
    if (open) {
      setPhone("");
      setCode("");
      setError(null);
      setCountdown(0);
      setSubmitting(false);
      setSending(false);
    }
  }, [open]);

  // ESC + body scroll lock
  useEffect(() => {
    if (!open) return;
    const handler = (e: KeyboardEvent) => {
      if (e.key === "Escape") onClose();
    };
    window.addEventListener("keydown", handler);
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", handler);
      document.body.style.overflow = prev;
    };
  }, [open, onClose]);

  const sendOtp = useCallback(async () => {
    if (!phoneValid) {
      setError("请输入有效的中国大陆手机号");
      return;
    }
    setError(null);
    setSending(true);
    try {
      const res = await fetch("/api/auth/send-otp", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ phone }),
      });
      const data = await res.json();
      if (!data.ok) throw new Error(data.error?.message || "发送失败");
      setCountdown(60);
      const timer = setInterval(() => {
        setCountdown((c) => {
          if (c <= 1) {
            clearInterval(timer);
            return 0;
          }
          return c - 1;
        });
      }, 1000);
    } catch (e) {
      setError(e instanceof Error ? e.message : "发送失败");
    } finally {
      setSending(false);
    }
  }, [phone, phoneValid]);

  const handleLogin = useCallback(
    async (e: React.FormEvent) => {
      e.preventDefault();
      if (!phoneValid || !codeValid) {
        setError("请检查手机号和验证码");
        return;
      }
      setError(null);
      setSubmitting(true);
      try {
        const result = await signIn("phone-otp", {
          phone,
          code,
          redirect: false,
        });
        if (result?.error) {
          console.error("[login] signIn 返回错误:", result);
          // 把 NextAuth 真实错误透出来,避免被"验证码错误或已失效"一刀切掩盖
          // (例如 server config 错误时,会显示 Configuration 而不是误导成验证码问题)
          setError(
            result.error === "CredentialsSignin"
              ? "验证码错误或已失效"
              : `登录失败：${result.error}`,
          );
        } else {
          onClose();
          if (onSuccess) onSuccess();
          else if (typeof window !== "undefined") window.location.reload();
        }
      } catch {
        setError("登录失败，请重试");
      } finally {
        setSubmitting(false);
      }
    },
    [phone, code, phoneValid, codeValid, onClose, onSuccess],
  );

  if (!mounted) return null;

  return createPortal(
    <AnimatePresence>
      {open && (
        <motion.div
          key="login-modal-root"
          className="fixed inset-0 z-[100] flex items-center justify-center px-4"
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          transition={{ duration: 0.2 }}
        >
          {/* 遮罩 */}
          <button
            type="button"
            aria-label="关闭弹窗"
            onClick={onClose}
            className="absolute inset-0 bg-black/75 backdrop-blur-md cursor-default"
          />

          {/* 弹窗主体 */}
          <motion.div
            role="dialog"
            aria-modal="true"
            aria-labelledby="login-modal-title"
            className="relative w-full max-w-md bg-elevated border border-white/14 rounded-2xl p-8 shadow-[0_24px_80px_rgba(0,0,0,0.7),0_0_40px_rgba(139,92,246,0.12)]"
            initial={{ opacity: 0, scale: 0.94, y: 16 }}
            animate={{ opacity: 1, scale: 1, y: 0 }}
            exit={{ opacity: 0, scale: 0.96, y: 8 }}
            transition={{ duration: 0.28, ease: [0.22, 1, 0.36, 1] }}
          >
            <button
              type="button"
              onClick={onClose}
              className="absolute top-3.5 right-4 w-7 h-7 flex items-center justify-center text-white/55 hover:text-white transition-colors"
              aria-label="关闭"
            >
              <X size={18} />
            </button>

            <div className="text-center mb-6">
              <div className="inline-block">
                <Logo size="md" href={null} />
              </div>
              <p
                id="login-modal-title"
                className="font-label text-[10px] tracking-[0.4em] uppercase text-purple-300/80 mt-3"
              >
                Sign in to Vote
              </p>
            </div>

            <form onSubmit={handleLogin} className="space-y-4">
              <div>
                <label className="block font-label text-[10px] tracking-widest uppercase text-white/55 mb-2">
                  手机号
                </label>
                <div className="relative">
                  <Phone
                    size={14}
                    className="absolute left-3.5 top-1/2 -translate-y-1/2 text-white/35"
                  />
                  <input
                    type="tel"
                    inputMode="numeric"
                    autoComplete="tel"
                    placeholder="138 0000 0000"
                    value={phone}
                    maxLength={11}
                    onChange={(e) =>
                      setPhone(
                        e.target.value.replace(/\D/g, "").slice(0, 11),
                      )
                    }
                    className="w-full h-11 pl-10 pr-3 rounded-lg bg-surface border border-white/10 text-white placeholder-white/30 focus:outline-none focus:border-purple-500 focus:shadow-[0_0_16px_rgba(139,92,246,0.25)] transition-all"
                  />
                </div>
              </div>

              <div>
                <label className="block font-label text-[10px] tracking-widest uppercase text-white/55 mb-2">
                  验证码
                </label>
                <div className="flex gap-2">
                  <div className="relative flex-1">
                    <KeyRound
                      size={14}
                      className="absolute left-3.5 top-1/2 -translate-y-1/2 text-white/35"
                    />
                    <input
                      type="text"
                      inputMode="numeric"
                      autoComplete="one-time-code"
                      placeholder="6 位验证码"
                      value={code}
                      maxLength={6}
                      onChange={(e) =>
                        setCode(
                          e.target.value.replace(/\D/g, "").slice(0, 6),
                        )
                      }
                      className="w-full h-11 pl-10 pr-3 rounded-lg bg-surface border border-white/10 text-white placeholder-white/30 focus:outline-none focus:border-purple-500 focus:shadow-[0_0_16px_rgba(139,92,246,0.25)] transition-all tracking-widest"
                    />
                  </div>
                  <button
                    type="button"
                    disabled={!phoneValid || countdown > 0 || sending}
                    onClick={sendOtp}
                    className={cn(
                      "h-11 px-4 rounded-lg font-display text-xs tracking-widest uppercase border transition-all whitespace-nowrap",
                      countdown > 0
                        ? "bg-white/5 border-white/10 text-white/30"
                        : "bg-purple-500/10 border-purple-500/40 text-purple-300 hover:bg-purple-500/15 disabled:opacity-50",
                    )}
                  >
                    {sending ? (
                      <Loader2 size={14} className="animate-spin" />
                    ) : countdown > 0 ? (
                      `${countdown}s`
                    ) : (
                      "发送"
                    )}
                  </button>
                </div>
              </div>

              {error && (
                <div className="px-3 py-2 rounded-lg bg-pink-500/10 border border-pink-500/30 text-pink-300 text-xs">
                  {error}
                </div>
              )}

              {process.env.NODE_ENV !== "production" && (
                <div className="px-3 py-2 rounded-lg bg-purple-500/[0.08] border border-purple-500/25 text-[11px] text-purple-300/80">
                  开发环境：万能验证码 <b className="text-white">123456</b>
                </div>
              )}

              <Button
                type="submit"
                variant="primary"
                size="lg"
                className="w-full"
                disabled={!phoneValid || !codeValid}
                loading={submitting}
              >
                登录 / 注册
              </Button>

              <p className="text-[11px] text-white/40 text-center leading-relaxed">
                未注册手机号将自动创建账号
              </p>
            </form>
          </motion.div>
        </motion.div>
      )}
    </AnimatePresence>,
    document.body,
  );
}
