import React, { useEffect, useMemo, useState } from "react";
import { marked } from "marked";

const API_BASE = import.meta.env.VITE_API_BASE || "http://localhost:8080";
marked.setOptions({ breaks: true });

const icons = {
  account: (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <circle cx="12" cy="8" r="4" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M4 20c1.5-3.5 5-5 8-5s6.5 1.5 8 5" fill="none" stroke="currentColor" strokeWidth="1.8" />
    </svg>
  ),
  password: (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <rect x="5" y="10" width="14" height="10" rx="2" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M8 10V7a4 4 0 0 1 8 0v3" fill="none" stroke="currentColor" strokeWidth="1.8" />
    </svg>
  ),
  username: (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <circle cx="9" cy="8" r="3" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M3 20c1-3 4-4.5 6-4.5" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M14 7h7M14 11h7M14 15h5" fill="none" stroke="currentColor" strokeWidth="1.8" />
    </svg>
  ),
  email: (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <rect x="3" y="6" width="18" height="12" rx="2" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M3 8l9 6 9-6" fill="none" stroke="currentColor" strokeWidth="1.8" />
    </svg>
  ),
  coins: (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <ellipse cx="12" cy="7" rx="7" ry="3.5" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M5 7v5c0 1.9 3.1 3.5 7 3.5s7-1.6 7-3.5V7" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M5 12v5c0 1.9 3.1 3.5 7 3.5s7-1.6 7-3.5v-5" fill="none" stroke="currentColor" strokeWidth="1.8" />
    </svg>
  ),
  phone: (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <rect x="7" y="3" width="10" height="18" rx="2" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <circle cx="12" cy="17" r="1" fill="currentColor" />
    </svg>
  ),
  avatar: (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <rect x="3" y="5" width="18" height="14" rx="2" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <circle cx="9" cy="10" r="2" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M3 17l5-4 4 3 4-5 5 6" fill="none" stroke="currentColor" strokeWidth="1.8" />
    </svg>
  ),
  bio: (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <path d="M6 4h8l4 4v12H6z" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M14 4v4h4" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M8 12h8M8 16h6" fill="none" stroke="currentColor" strokeWidth="1.8" />
    </svg>
  ),
  token: (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <circle cx="7" cy="12" r="4" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M11 12h10M17 12v4M20 12v2" fill="none" stroke="currentColor" strokeWidth="1.8" />
    </svg>
  ),
  level: (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <circle cx="12" cy="12" r="8" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M9 15h6M9 9h6M9 12h6" fill="none" stroke="currentColor" strokeWidth="1.8" />
    </svg>
  ),
  secondaryEmail: (
    <svg viewBox="0 0 24 24" aria-hidden="true">
      <rect x="4" y="6" width="14" height="10" rx="2" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <path d="M4 8l7 4 7-4" fill="none" stroke="currentColor" strokeWidth="1.8" />
      <rect x="8" y="10" width="12" height="10" rx="2" fill="none" stroke="currentColor" strokeWidth="1.8" />
    </svg>
  )
};

const emptyForm = {
  account: "",
  password: "",
  username: "",
  email: "",
  level: 0,
  sproutCoins: 0,
  secondaryEmails: "",
  phone: "",
  avatarUrl: "",
  bio: ""
};

function App() {
  const isAdmin = window.location.pathname.startsWith("/admin");
  const [booting, setBooting] = useState(true);

  const markReady = () => {
    setBooting(false);
  };

  useEffect(() => {
    const timer = setTimeout(() => setBooting(false), 4000);
    return () => clearTimeout(timer);
  }, []);

  return (
    <div className="app-shell">
      {booting && <SplashScreen />}
      <div className="app">
        <header className="app-header">
          <div>
            <h1>萌芽账户认证中心</h1>
            <p>统一认证 · 账户管理 · 简洁可用</p>
          </div>
          <nav>
            <a href="/">用户中心</a>
            <a href="/admin?token=shumengya520">管理员</a>
          </nav>
        </header>
        {isAdmin ? <AdminPanel onReady={markReady} /> : <UserPortal onReady={markReady} />}
      </div>
    </div>
  );
}

function SplashScreen() {
  return (
    <div className="splash">
      <div className="splash-glow" aria-hidden="true" />
      <div className="splash-content">
        <div className="splash-logo-wrap">
          <div className="splash-rings" aria-hidden="true">
            <span />
            <span />
            <span />
          </div>
          <img className="splash-logo" src="/logo192.png" alt="SproutGate" />
        </div>
        <div className="splash-title">萌芽账户认证中心</div>
        <div className="splash-subtitle">加载中</div>
        <div className="splash-dots" aria-label="加载中">
          <span />
          <span />
          <span />
        </div>
      </div>
    </div>
  );
}

function IconLabel({ icon, text, hint }) {
  return (
    <span className="label-text">
      <span className="icon">{icon}</span>
      <span>{text}</span>
      {hint && <span className="hint">{hint}</span>}
    </span>
  );
}

function InfoLabel({ icon, text }) {
  return (
    <span className="info-label">
      <span className="icon">{icon}</span>
      <span>{text}</span>
    </span>
  );
}

function TableCell({ icon, children, onClick }) {
  return (
    <span className="table-cell" onClick={onClick}>
      <span className="icon">{icon}</span>
      <span>{children}</span>
    </span>
  );
}

const parseEmailList = (value) =>
  value
    .split(",")
    .map((item) => item.trim())
    .filter(Boolean);

function UserPortal({ onReady }) {
  const [account, setAccount] = useState("");
  const [password, setPassword] = useState("");
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [mode, setMode] = useState("login");
  const [registerForm, setRegisterForm] = useState({
    account: "",
    password: "",
    username: "",
    email: "",
    code: ""
  });
  const [registerSent, setRegisterSent] = useState(false);
  const [registerExpiresAt, setRegisterExpiresAt] = useState("");
  const [registerLoading, setRegisterLoading] = useState(false);
  const [registerError, setRegisterError] = useState("");
  const [registerMessage, setRegisterMessage] = useState("");
  const [resetForm, setResetForm] = useState({
    account: "",
    email: "",
    code: "",
    newPassword: ""
  });
  const [resetSent, setResetSent] = useState(false);
  const [resetExpiresAt, setResetExpiresAt] = useState("");
  const [resetLoading, setResetLoading] = useState(false);
  const [resetError, setResetError] = useState("");
  const [resetMessage, setResetMessage] = useState("");
  const [secondaryForm, setSecondaryForm] = useState({
    email: "",
    code: ""
  });
  const [secondarySent, setSecondarySent] = useState(false);
  const [secondaryExpiresAt, setSecondaryExpiresAt] = useState("");
  const [secondaryLoading, setSecondaryLoading] = useState(false);
  const [secondaryError, setSecondaryError] = useState("");
  const [secondaryMessage, setSecondaryMessage] = useState("");
  const [profileForm, setProfileForm] = useState({
    username: "",
    phone: "",
    avatarUrl: "",
    bio: "",
    password: ""
  });
  const [profileLoading, setProfileLoading] = useState(false);
  const [profileError, setProfileError] = useState("");
  const [profileMessage, setProfileMessage] = useState("");

  useEffect(() => {
    let cancelled = false;
    const done = () => {
      if (!cancelled && onReady) {
        onReady();
      }
    };
    const token = localStorage.getItem("sproutgate_token");
    if (token) {
      fetch(`${API_BASE}/api/auth/me`, {
        headers: { Authorization: `Bearer ${token}` }
      })
        .then((res) => res.json())
        .then((data) => {
          if (data.user) {
            setUser(data.user);
          }
        })
        .catch(() => {})
        .finally(() => done());
    } else {
      done();
    }
    return () => {
      cancelled = true;
    };
  }, [onReady]);

  useEffect(() => {
    if (user) {
      setProfileForm({
        username: user.username || "",
        phone: user.phone || "",
        avatarUrl: user.avatarUrl || "",
        bio: user.bio || "",
        password: ""
      });
    }
  }, [user]);

  const handleLogin = async (event) => {
    event.preventDefault();
    setLoading(true);
    setError("");
    try {
      const res = await fetch(`${API_BASE}/api/auth/login`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ account, password })
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "登录失败");
      }
      localStorage.setItem("sproutgate_token", data.token);
      setUser(data.user);
      setAccount("");
      setPassword("");
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  const handleLogout = () => {
    localStorage.removeItem("sproutgate_token");
    setUser(null);
  };

  const handleRegisterChange = (field, value) => {
    setRegisterForm((prev) => ({ ...prev, [field]: value }));
  };

  const handleSendCode = async (event) => {
    event.preventDefault();
    setRegisterLoading(true);
    setRegisterError("");
    setRegisterMessage("");
    if (!registerForm.account || !registerForm.password || !registerForm.email) {
      setRegisterError("请填写账户、密码和邮箱");
      setRegisterLoading(false);
      return;
    }
    try {
      const res = await fetch(`${API_BASE}/api/auth/register`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          account: registerForm.account,
          password: registerForm.password,
          username: registerForm.username,
          email: registerForm.email
        })
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "发送验证码失败");
      }
      setRegisterSent(true);
      setRegisterExpiresAt(data.expiresAt || "");
      setRegisterMessage("验证码已发送，请检查邮箱");
    } catch (err) {
      setRegisterError(err.message);
    } finally {
      setRegisterLoading(false);
    }
  };

  const handleVerifyRegister = async (event) => {
    event.preventDefault();
    setRegisterLoading(true);
    setRegisterError("");
    setRegisterMessage("");
    if (!registerForm.account || !registerForm.code) {
      setRegisterError("请输入账户与验证码");
      setRegisterLoading(false);
      return;
    }
    try {
      const res = await fetch(`${API_BASE}/api/auth/verify-email`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          account: registerForm.account,
          code: registerForm.code
        })
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "验证失败");
      }
      setRegisterMessage("注册成功，请使用账号登录");
      setRegisterSent(false);
      setRegisterForm({
        account: "",
        password: "",
        username: "",
        email: "",
        code: ""
      });
      setMode("login");
    } catch (err) {
      setRegisterError(err.message);
    } finally {
      setRegisterLoading(false);
    }
  };

  const handleResetChange = (field, value) => {
    setResetForm((prev) => ({ ...prev, [field]: value }));
  };

  const handleSendReset = async (event) => {
    event.preventDefault();
    setResetLoading(true);
    setResetError("");
    setResetMessage("");
    if (!resetForm.account || !resetForm.email) {
      setResetError("请填写账户与邮箱");
      setResetLoading(false);
      return;
    }
    try {
      const res = await fetch(`${API_BASE}/api/auth/forgot-password`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          account: resetForm.account,
          email: resetForm.email
        })
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "发送重置邮件失败");
      }
      setResetSent(true);
      setResetExpiresAt(data.expiresAt || "");
      setResetMessage("重置验证码已发送，请检查邮箱");
    } catch (err) {
      setResetError(err.message);
    } finally {
      setResetLoading(false);
    }
  };

  const handleResetPassword = async (event) => {
    event.preventDefault();
    setResetLoading(true);
    setResetError("");
    setResetMessage("");
    if (!resetForm.account || !resetForm.code || !resetForm.newPassword) {
      setResetError("请填写账户、验证码与新密码");
      setResetLoading(false);
      return;
    }
    try {
      const res = await fetch(`${API_BASE}/api/auth/reset-password`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          account: resetForm.account,
          code: resetForm.code,
          newPassword: resetForm.newPassword
        })
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "重置失败");
      }
      setResetMessage("密码已重置，请使用新密码登录");
      setResetSent(false);
      setResetForm({
        account: "",
        email: "",
        code: "",
        newPassword: ""
      });
      setMode("login");
    } catch (err) {
      setResetError(err.message);
    } finally {
      setResetLoading(false);
    }
  };

  const handleSecondaryChange = (field, value) => {
    setSecondaryForm((prev) => ({ ...prev, [field]: value }));
  };

  const handleSendSecondary = async (event) => {
    event.preventDefault();
    setSecondaryLoading(true);
    setSecondaryError("");
    setSecondaryMessage("");
    const token = localStorage.getItem("sproutgate_token");
    if (!token) {
      setSecondaryError("请先登录");
      setSecondaryLoading(false);
      return;
    }
    if (!secondaryForm.email) {
      setSecondaryError("请输入辅助邮箱");
      setSecondaryLoading(false);
      return;
    }
    try {
      const res = await fetch(`${API_BASE}/api/auth/secondary-email/request`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`
        },
        body: JSON.stringify({ email: secondaryForm.email })
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "发送验证码失败");
      }
      setSecondarySent(true);
      setSecondaryExpiresAt(data.expiresAt || "");
      setSecondaryMessage("验证码已发送，请检查邮箱");
    } catch (err) {
      setSecondaryError(err.message);
    } finally {
      setSecondaryLoading(false);
    }
  };

  const handleVerifySecondary = async (event) => {
    event.preventDefault();
    setSecondaryLoading(true);
    setSecondaryError("");
    setSecondaryMessage("");
    const token = localStorage.getItem("sproutgate_token");
    if (!token) {
      setSecondaryError("请先登录");
      setSecondaryLoading(false);
      return;
    }
    if (!secondaryForm.email || !secondaryForm.code) {
      setSecondaryError("请输入邮箱与验证码");
      setSecondaryLoading(false);
      return;
    }
    try {
      const res = await fetch(`${API_BASE}/api/auth/secondary-email/verify`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`
        },
        body: JSON.stringify({
          email: secondaryForm.email,
          code: secondaryForm.code
        })
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "验证失败");
      }
      if (data.user) {
        setUser(data.user);
      }
      setSecondaryMessage("辅助邮箱验证成功");
      setSecondarySent(false);
      setSecondaryForm({ email: "", code: "" });
    } catch (err) {
      setSecondaryError(err.message);
    } finally {
      setSecondaryLoading(false);
    }
  };

  const handleProfileChange = (field, value) => {
    setProfileForm((prev) => ({ ...prev, [field]: value }));
  };

  const handleProfileSave = async (event) => {
    event.preventDefault();
    setProfileLoading(true);
    setProfileError("");
    setProfileMessage("");
    const token = localStorage.getItem("sproutgate_token");
    if (!token) {
      setProfileError("请先登录");
      setProfileLoading(false);
      return;
    }
    const payload = {
      username: profileForm.username,
      phone: profileForm.phone,
      avatarUrl: profileForm.avatarUrl,
      bio: profileForm.bio
    };
    if (profileForm.password) {
      payload.password = profileForm.password;
    }
    try {
      const res = await fetch(`${API_BASE}/api/auth/profile`, {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
          Authorization: `Bearer ${token}`
        },
        body: JSON.stringify(payload)
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "保存失败");
      }
      setUser(data.user);
      setProfileMessage("保存成功");
      setProfileForm((prev) => ({ ...prev, password: "" }));
    } catch (err) {
      setProfileError(err.message);
    } finally {
      setProfileLoading(false);
    }
  };

  return (
    <section className="panel">
      <div className="panel-title">用户中心</div>
      {!user && mode === "login" && (
        <form className="card form" onSubmit={handleLogin}>
          <h2>登录</h2>
          <label>
            <IconLabel icon={icons.account} text="账户" />
            <input value={account} onChange={(e) => setAccount(e.target.value)} placeholder="请输入账户" />
          </label>
          <label>
            <IconLabel icon={icons.password} text="密码" />
            <input
              type="password"
              value={password}
              onChange={(e) => setPassword(e.target.value)}
              placeholder="请输入密码"
            />
          </label>
          {error && <div className="error">{error}</div>}
          <button className="primary" disabled={loading}>
            {loading ? "登录中..." : "登录"}
          </button>
          <button
            type="button"
            className="ghost"
            onClick={() => {
              setMode("register");
              setError("");
            }}
          >
            去注册
          </button>
          <button
            type="button"
            className="ghost"
            onClick={() => {
              setMode("reset");
              setError("");
            }}
          >
            忘记密码
          </button>
        </form>
      )}

      {!user && mode === "register" && (
        <form className="card form" onSubmit={registerSent ? handleVerifyRegister : handleSendCode}>
          <h2>注册账号</h2>
          <label>
            <IconLabel icon={icons.account} text="账户" />
            <input
              value={registerForm.account}
              onChange={(e) => handleRegisterChange("account", e.target.value)}
              placeholder="请输入账户"
            />
          </label>
          <label>
            <IconLabel icon={icons.password} text="密码" />
            <input
              type="password"
              value={registerForm.password}
              onChange={(e) => handleRegisterChange("password", e.target.value)}
              placeholder="请输入密码"
            />
          </label>
          <label>
            <IconLabel icon={icons.username} text="用户名" />
            <input
              value={registerForm.username}
              onChange={(e) => handleRegisterChange("username", e.target.value)}
              placeholder="可选"
            />
          </label>
          <label>
            <IconLabel icon={icons.email} text="邮箱" />
            <input
              value={registerForm.email}
              onChange={(e) => handleRegisterChange("email", e.target.value)}
              placeholder="用于接收验证码"
            />
          </label>
          {registerSent && (
            <label>
              <IconLabel icon={icons.token} text="邮箱验证码" />
              <input
                value={registerForm.code}
                onChange={(e) => handleRegisterChange("code", e.target.value)}
                placeholder="6 位验证码"
              />
            </label>
          )}
          {registerExpiresAt && <div className="hint">验证码有效期至：{registerExpiresAt}</div>}
          {registerError && <div className="error">{registerError}</div>}
          {registerMessage && <div className="success">{registerMessage}</div>}
          <div className="actions">
            <button className="primary" disabled={registerLoading}>
              {registerSent ? "完成注册" : "发送验证码"}
            </button>
            <button
              type="button"
              className="ghost"
              onClick={() => {
                setMode("login");
                setRegisterError("");
                setRegisterMessage("");
              }}
            >
              返回登录
            </button>
          </div>
        </form>
      )}

      {!user && mode === "reset" && (
        <form className="card form" onSubmit={resetSent ? handleResetPassword : handleSendReset}>
          <h2>重置密码</h2>
          <label>
            <IconLabel icon={icons.account} text="账户" />
            <input
              value={resetForm.account}
              onChange={(e) => handleResetChange("account", e.target.value)}
              placeholder="请输入账户"
            />
          </label>
          <label>
            <IconLabel icon={icons.email} text="邮箱" />
            <input
              value={resetForm.email}
              onChange={(e) => handleResetChange("email", e.target.value)}
              placeholder="请输入注册邮箱"
            />
          </label>
          {resetSent && (
            <>
              <label>
                <IconLabel icon={icons.token} text="邮箱验证码" />
                <input
                  value={resetForm.code}
                  onChange={(e) => handleResetChange("code", e.target.value)}
                  placeholder="6 位验证码"
                />
              </label>
              <label>
                <IconLabel icon={icons.password} text="新密码" />
                <input
                  type="password"
                  value={resetForm.newPassword}
                  onChange={(e) => handleResetChange("newPassword", e.target.value)}
                  placeholder="输入新密码"
                />
              </label>
            </>
          )}
          {resetExpiresAt && <div className="hint">验证码有效期至：{resetExpiresAt}</div>}
          {resetError && <div className="error">{resetError}</div>}
          {resetMessage && <div className="success">{resetMessage}</div>}
          <div className="actions">
            <button className="primary" disabled={resetLoading}>
              {resetSent ? "确认重置" : "发送重置邮件"}
            </button>
            <button
              type="button"
              className="ghost"
              onClick={() => {
                setMode("login");
                setResetError("");
                setResetMessage("");
              }}
            >
              返回登录
            </button>
          </div>
        </form>
      )}

      {user && (
        <>
          <div className="card profile">
            <div className="profile-header">
              <img
                src={user.avatarUrl || "https://dummyimage.com/120x120/ddd/fff&text=Avatar"}
                alt="avatar"
              />
              <div>
                <h2>{user.username || user.account}</h2>
                <p>{user.email || "未填写邮箱"}</p>
                <button className="ghost" onClick={handleLogout}>
                  退出登录
                </button>
              </div>
            </div>
            <div className="profile-grid">
              <div>
                <InfoLabel icon={icons.account} text="账户" />
                <strong>{user.account}</strong>
              </div>
              <div>
                <InfoLabel icon={icons.password} text="密码" />
                <strong>已设置（不展示）</strong>
              </div>
              <div>
                <InfoLabel icon={icons.username} text="用户名" />
                <strong>{user.username || "未填写"}</strong>
              </div>
              <div>
                <InfoLabel icon={icons.email} text="邮箱" />
                <strong>{user.email || "未填写"}</strong>
              </div>
              <div>
                <InfoLabel icon={icons.level} text="等级" />
                <strong>{user.level ?? 0} 级</strong>
              </div>
              <div>
                <InfoLabel icon={icons.coins} text="萌芽币" />
                <strong>{user.sproutCoins}</strong>
              </div>
              <div>
                <InfoLabel icon={icons.phone} text="手机号" />
                <strong>{user.phone || "未填写"}</strong>
              </div>
              <div>
                <InfoLabel icon={icons.avatar} text="个人头像" />
                <strong>{user.avatarUrl || "未填写"}</strong>
              </div>
            </div>
            <div className="markdown">
              <h3>个人简介</h3>
              <div
                className="markdown-body"
                dangerouslySetInnerHTML={{
                  __html: marked.parse(user.bio || "暂无简介")
                }}
              />
            </div>
          </div>

          <form className="card form" onSubmit={secondarySent ? handleVerifySecondary : handleSendSecondary}>
            <h2>辅助邮箱</h2>
            <div className="tag-list">
              {(user.secondaryEmails || []).length === 0 && <span className="hint">暂无辅助邮箱</span>}
              {(user.secondaryEmails || []).map((email) => (
                <span className="tag" key={email}>
                  {email}
                </span>
              ))}
            </div>
            <label>
              <IconLabel icon={icons.secondaryEmail} text="辅助邮箱" />
              <input
                value={secondaryForm.email}
                onChange={(e) => handleSecondaryChange("email", e.target.value)}
                placeholder="请输入辅助邮箱"
              />
            </label>
            {secondarySent && (
              <label>
                <IconLabel icon={icons.token} text="邮箱验证码" />
                <input
                  value={secondaryForm.code}
                  onChange={(e) => handleSecondaryChange("code", e.target.value)}
                  placeholder="6 位验证码"
                />
              </label>
            )}
            {secondaryExpiresAt && <div className="hint">验证码有效期至：{secondaryExpiresAt}</div>}
            {secondaryError && <div className="error">{secondaryError}</div>}
            {secondaryMessage && <div className="success">{secondaryMessage}</div>}
            <div className="actions">
              <button className="primary" disabled={secondaryLoading}>
                {secondarySent ? "确认验证" : "发送验证码"}
              </button>
            </div>
          </form>

          <form className="card form" onSubmit={handleProfileSave}>
            <h2>修改资料</h2>
            <label>
              <IconLabel icon={icons.username} text="用户名" />
              <input
                value={profileForm.username}
                onChange={(e) => handleProfileChange("username", e.target.value)}
              />
            </label>
            <label>
              <IconLabel icon={icons.password} text="密码" hint="（留空不修改）" />
              <input
                type="password"
                value={profileForm.password}
                onChange={(e) => handleProfileChange("password", e.target.value)}
                placeholder="输入新密码"
              />
            </label>
            <label>
              <IconLabel icon={icons.phone} text="手机号" />
              <input value={profileForm.phone} onChange={(e) => handleProfileChange("phone", e.target.value)} />
            </label>
            <label>
              <IconLabel icon={icons.avatar} text="个人头像（链接）" />
              <input
                value={profileForm.avatarUrl}
                onChange={(e) => handleProfileChange("avatarUrl", e.target.value)}
              />
            </label>
            <label>
              <IconLabel icon={icons.bio} text="个人简介（支持 Markdown）" />
              <textarea value={profileForm.bio} onChange={(e) => handleProfileChange("bio", e.target.value)} rows={4} />
            </label>
            {profileError && <div className="error">{profileError}</div>}
            {profileMessage && <div className="success">{profileMessage}</div>}
            <div className="actions">
              <button className="primary" disabled={profileLoading}>
                {profileLoading ? "保存中..." : "保存修改"}
              </button>
            </div>
          </form>
        </>
      )}
    </section>
  );
}

function AdminPanel({ onReady }) {
  const queryToken = useMemo(() => {
    const params = new URLSearchParams(window.location.search);
    return params.get("token") || "";
  }, []);

  const [token, setToken] = useState(queryToken || localStorage.getItem("sproutgate_admin_token") || "");
  const [users, setUsers] = useState([]);
  const [form, setForm] = useState(emptyForm);
  const [selectedAccount, setSelectedAccount] = useState("");
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const [message, setMessage] = useState("");

  const [readySent, setReadySent] = useState(false);

  useEffect(() => {
    if (token) {
      localStorage.setItem("sproutgate_admin_token", token);
      loadUsers();
    } else if (onReady && !readySent) {
      onReady();
      setReadySent(true);
    }
  }, [token, onReady, readySent]);

  const loadUsers = async () => {
    if (!token) return;
    setLoading(true);
    setError("");
    try {
      const res = await fetch(`${API_BASE}/api/admin/users`, {
        headers: { "X-Admin-Token": token }
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "加载用户失败");
      }
      setUsers(data.users || []);
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
      if (onReady && !readySent) {
        onReady();
        setReadySent(true);
      }
    }
  };

  const selectUser = (user) => {
    setSelectedAccount(user.account);
    setForm({
      account: user.account,
      password: "",
      username: user.username || "",
      email: user.email || "",
      level: user.level ?? 0,
      sproutCoins: user.sproutCoins || 0,
      secondaryEmails: (user.secondaryEmails || []).join(","),
      phone: user.phone || "",
      avatarUrl: user.avatarUrl || "",
      bio: user.bio || ""
    });
  };

  const clearSelection = () => {
    setSelectedAccount("");
    setForm(emptyForm);
    setMessage("");
  };

  const handleChange = (field, value) => {
    setForm((prev) => ({ ...prev, [field]: value }));
  };

  const handleCreate = async () => {
    setMessage("");
    setError("");
    if (!form.account || !form.password) {
      setError("新建用户需要账户和密码");
      return;
    }
    try {
      const res = await fetch(`${API_BASE}/api/admin/users`, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "X-Admin-Token": token
        },
        body: JSON.stringify({
          account: form.account,
          password: form.password,
          username: form.username,
          email: form.email,
          level: Number(form.level) || 0,
          sproutCoins: Number(form.sproutCoins) || 0,
          secondaryEmails: parseEmailList(form.secondaryEmails),
          phone: form.phone,
          avatarUrl: form.avatarUrl,
          bio: form.bio
        })
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "创建失败");
      }
      setMessage("创建成功");
      clearSelection();
      loadUsers();
    } catch (err) {
      setError(err.message);
    }
  };

  const handleUpdate = async () => {
    if (!selectedAccount) {
      setError("请选择需要更新的账户");
      return;
    }
    setMessage("");
    setError("");
    const payload = {
      username: form.username,
      email: form.email,
      level: Number(form.level) || 0,
      sproutCoins: Number(form.sproutCoins) || 0,
      secondaryEmails: parseEmailList(form.secondaryEmails),
      phone: form.phone,
      avatarUrl: form.avatarUrl,
      bio: form.bio
    };
    if (form.password) {
      payload.password = form.password;
    }
    try {
      const res = await fetch(`${API_BASE}/api/admin/users/${encodeURIComponent(selectedAccount)}`, {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
          "X-Admin-Token": token
        },
        body: JSON.stringify(payload)
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "更新失败");
      }
      setMessage("更新成功");
      setForm((prev) => ({ ...prev, password: "" }));
      loadUsers();
    } catch (err) {
      setError(err.message);
    }
  };

  const handleDelete = async (account) => {
    if (!account) return;
    if (!window.confirm(`确认删除账户 ${account} 吗？`)) {
      return;
    }
    setMessage("");
    setError("");
    try {
      const res = await fetch(`${API_BASE}/api/admin/users/${encodeURIComponent(account)}`, {
        method: "DELETE",
        headers: { "X-Admin-Token": token }
      });
      const data = await res.json();
      if (!res.ok) {
        throw new Error(data.error || "删除失败");
      }
      setMessage("删除成功");
      if (account === selectedAccount) {
        clearSelection();
      }
      loadUsers();
    } catch (err) {
      setError(err.message);
    }
  };

  return (
    <section className="panel">
      <div className="panel-title">管理员控制台</div>
      <div className="card form">
        <h2>管理员 Token</h2>
        <label>
          <IconLabel icon={icons.token} text="Token" />
          <input value={token} onChange={(e) => setToken(e.target.value.trim())} placeholder="请输入管理员 Token" />
        </label>
        <button className="ghost" onClick={loadUsers} disabled={!token || loading}>
          {loading ? "加载中..." : "刷新用户列表"}
        </button>
      </div>

      <div className="grid">
        <div className="card form">
          <h2>{selectedAccount ? "编辑用户" : "新建用户"}</h2>
          <label>
            <IconLabel icon={icons.account} text="账户" />
            <input
              value={form.account}
              onChange={(e) => handleChange("account", e.target.value)}
              placeholder="唯一账户"
              disabled={!!selectedAccount}
            />
          </label>
          <label>
            <IconLabel icon={icons.password} text="密码" hint={selectedAccount ? "（留空不修改）" : ""} />
            <input
              type="password"
              value={form.password}
              onChange={(e) => handleChange("password", e.target.value)}
              placeholder={selectedAccount ? "输入新密码" : "初始密码"}
            />
          </label>
          <label>
            <IconLabel icon={icons.username} text="用户名" />
            <input value={form.username} onChange={(e) => handleChange("username", e.target.value)} />
          </label>
          <label>
            <IconLabel icon={icons.email} text="邮箱" />
            <input value={form.email} onChange={(e) => handleChange("email", e.target.value)} />
          </label>
          <label>
            <IconLabel icon={icons.level} text="等级" />
            <input
              type="number"
              value={form.level}
              onChange={(e) => handleChange("level", e.target.value)}
            />
          </label>
          <label>
            <IconLabel icon={icons.coins} text="萌芽币" />
            <input
              type="number"
              value={form.sproutCoins}
              onChange={(e) => handleChange("sproutCoins", e.target.value)}
            />
          </label>
          <label>
            <IconLabel icon={icons.secondaryEmail} text="辅助邮箱（逗号分隔）" />
            <input
              value={form.secondaryEmails}
              onChange={(e) => handleChange("secondaryEmails", e.target.value)}
              placeholder="demo2@example.com, demo3@example.com"
            />
          </label>
          <label>
            <IconLabel icon={icons.phone} text="手机号" />
            <input value={form.phone} onChange={(e) => handleChange("phone", e.target.value)} />
          </label>
          <label>
            <IconLabel icon={icons.avatar} text="个人头像（链接）" />
            <input value={form.avatarUrl} onChange={(e) => handleChange("avatarUrl", e.target.value)} />
          </label>
          <label>
            <IconLabel icon={icons.bio} text="个人简介（支持 Markdown）" />
            <textarea value={form.bio} onChange={(e) => handleChange("bio", e.target.value)} rows={4} />
          </label>
          {error && <div className="error">{error}</div>}
          {message && <div className="success">{message}</div>}
          <div className="actions">
            <button className="primary" onClick={selectedAccount ? handleUpdate : handleCreate}>
              {selectedAccount ? "保存修改" : "创建用户"}
            </button>
            <button className="ghost" onClick={clearSelection}>
              清空
            </button>
          </div>
        </div>

        <div className="card list">
          <h2>用户列表</h2>
          {users.length === 0 && <div className="hint">暂无用户</div>}
          <div className="table">
            <div className="table-row header">
              <TableCell icon={icons.account}>账户</TableCell>
              <TableCell icon={icons.username}>用户名</TableCell>
              <TableCell icon={icons.email}>邮箱</TableCell>
              <TableCell icon={icons.level}>等级</TableCell>
              <TableCell icon={icons.coins}>萌芽币</TableCell>
              <span>操作</span>
            </div>
            {users.map((u) => (
              <div className="table-row" key={u.account}>
                <TableCell icon={icons.account} onClick={() => selectUser(u)}>
                  {u.account}
                </TableCell>
                <TableCell icon={icons.username}>{u.username || "-"}</TableCell>
                <TableCell icon={icons.email}>
                  {(u.email || "-") +
                    ((u.secondaryEmails || []).length ? ` / ${(u.secondaryEmails || []).join(", ")}` : "")}
                </TableCell>
                <TableCell icon={icons.level}>{u.level ?? 0} 级</TableCell>
                <TableCell icon={icons.coins}>{u.sproutCoins}</TableCell>
                <span className="row-actions">
                  <button className="ghost" onClick={() => selectUser(u)}>
                    编辑
                  </button>
                  <button className="danger" onClick={() => handleDelete(u.account)}>
                    删除
                  </button>
                </span>
              </div>
            ))}
          </div>
        </div>
      </div>
    </section>
  );
}

export default App;
