import React, { useEffect, useMemo, useState } from "react";
import { API_BASE, emptyForm, formatIsoDateTimeReadable, parseEmailList } from "../config";
import icons from "../icons";
import { IconLabel, MailtoEmail, TableCell } from "./common";

export default 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 [editorOpen, setEditorOpen] = useState(false);
  const [editorMode, setEditorMode] = useState("create");
  const [loading, setLoading] = useState(false);
  const [configLoading, setConfigLoading] = useState(false);
  const [configSaving, setConfigSaving] = useState(false);
  const [error, setError] = useState("");
  const [configError, setConfigError] = useState("");
  const [message, setMessage] = useState("");
  const [configMessage, setConfigMessage] = useState("");
  const [checkInConfig, setCheckInConfig] = useState({ rewardCoins: 1 });
  const [readySent, setReadySent] = useState(false);

  const [regLoading, setRegLoading] = useState(false);
  const [regSaving, setRegSaving] = useState(false);
  const [regInvCreating, setRegInvCreating] = useState(false);
  const [regError, setRegError] = useState("");
  const [regMessage, setRegMessage] = useState("");
  const [requireInviteReg, setRequireInviteReg] = useState(false);
  const [inviteList, setInviteList] = useState([]);
  const [newInvNote, setNewInvNote] = useState("");
  const [newInvMax, setNewInvMax] = useState(0);
  const [newInvExp, setNewInvExp] = useState("");

  useEffect(() => {
    if (token) {
      localStorage.setItem("sproutgate_admin_token", token);
      loadUsers();
      loadCheckInConfig();
      loadRegistration();
    } 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 loadCheckInConfig = async () => {
    if (!token) return;
    setConfigLoading(true);
    setConfigError("");
    try {
      const res = await fetch(`${API_BASE}/api/admin/check-in/config`, {
        headers: { "X-Admin-Token": token }
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "加载签到配置失败");
      setCheckInConfig({ rewardCoins: Number(data.rewardCoins) || 1 });
    } catch (err) {
      setConfigError(err.message);
    } finally {
      setConfigLoading(false);
    }
  };

  const loadRegistration = async () => {
    if (!token) return;
    setRegLoading(true);
    setRegError("");
    try {
      const res = await fetch(`${API_BASE}/api/admin/registration`, {
        headers: { "X-Admin-Token": token }
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "加载注册策略失败");
      setRequireInviteReg(Boolean(data.requireInviteCode));
      setInviteList(data.invites || []);
    } catch (err) {
      setRegError(err.message);
    } finally {
      setRegLoading(false);
    }
  };

  const saveRegPolicy = async () => {
    if (!token) return;
    setRegMessage("");
    setRegError("");
    setRegSaving(true);
    try {
      const res = await fetch(`${API_BASE}/api/admin/registration`, {
        method: "PUT",
        headers: { "Content-Type": "application/json", "X-Admin-Token": token },
        body: JSON.stringify({ requireInviteCode: requireInviteReg })
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "保存失败");
      setRequireInviteReg(Boolean(data.requireInviteCode));
      setRegMessage("注册策略已保存");
    } catch (err) {
      setRegError(err.message);
    } finally {
      setRegSaving(false);
    }
  };

  const handleCreateInvite = async () => {
    if (!token) return;
    setRegMessage("");
    setRegError("");
    let expiresAt = "";
    if (newInvExp.trim()) {
      const d = new Date(newInvExp);
      if (Number.isNaN(d.getTime())) {
        setRegError("过期时间无效");
        return;
      }
      expiresAt = d.toISOString();
    }
    setRegInvCreating(true);
    try {
      const res = await fetch(`${API_BASE}/api/admin/registration/invites`, {
        method: "POST",
        headers: { "Content-Type": "application/json", "X-Admin-Token": token },
        body: JSON.stringify({
          note: newInvNote.trim(),
          maxUses: Number(newInvMax) || 0,
          expiresAt
        })
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "生成失败");
      const inv = data.invite;
      setInviteList((prev) => [...prev, inv]);
      setRegMessage(`已生成邀请码：${inv.code}（请复制保存）`);
      setNewInvNote("");
      setNewInvMax(0);
      setNewInvExp("");
    } catch (err) {
      setRegError(err.message);
    } finally {
      setRegInvCreating(false);
    }
  };

  const handleDeleteInvite = async (code) => {
    if (!token || !code) return;
    if (!window.confirm(`确认删除邀请码 ${code} 吗？`)) return;
    setRegMessage("");
    setRegError("");
    try {
      const res = await fetch(
        `${API_BASE}/api/admin/registration/invites/${encodeURIComponent(code)}`,
        { method: "DELETE", headers: { "X-Admin-Token": token } }
      );
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "删除失败");
      setInviteList((prev) => prev.filter((x) => x.code !== code));
      setRegMessage("已删除邀请码");
    } catch (err) {
      setRegError(err.message);
    }
  };

  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 || "",
      websiteUrl: user.websiteUrl || "",
      bio: user.bio || "",
      banned: Boolean(user.banned),
      banReason: user.banReason || ""
    });
    setMessage("");
    setError("");
    setEditorMode("edit");
    setEditorOpen(true);
  };

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

  const openCreateUser = () => {
    clearSelection();
    setEditorMode("create");
    setMessage("");
    setError("");
    setEditorOpen(true);
  };

  const closeEditor = () => {
    setEditorOpen(false);
    clearSelection();
    setError("");
  };

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

  const handleCheckInConfigChange = (value) => {
    setCheckInConfig({ rewardCoins: value });
  };

  const handleSaveCheckInConfig = async () => {
    setConfigMessage("");
    setConfigError("");
    const rewardCoins = Number(checkInConfig.rewardCoins) || 0;
    if (rewardCoins <= 0) { setConfigError("奖励萌芽币必须大于 0"); return; }
    try {
      setConfigSaving(true);
      const res = await fetch(`${API_BASE}/api/admin/check-in/config`, {
        method: "PUT",
        headers: { "Content-Type": "application/json", "X-Admin-Token": token },
        body: JSON.stringify({ rewardCoins })
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "保存签到配置失败");
      setCheckInConfig({ rewardCoins: Number(data.rewardCoins) || rewardCoins });
      setConfigMessage("签到配置已保存");
    } catch (err) {
      setConfigError(err.message);
    } finally {
      setConfigSaving(false);
    }
  };

  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,
          websiteUrl: form.websiteUrl,
          bio: form.bio
        })
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || "创建失败");
      setMessage("创建成功");
      closeEditor();
      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,
      websiteUrl: form.websiteUrl,
      bio: form.bio,
      banned: Boolean(form.banned),
      banReason: (form.banReason || "").trim()
    };
    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: "" }));
      closeEditor();
      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);
    }
  };

  const editingUser = users.find((u) => u.account === selectedAccount);
  const editingAuthClients = editingUser?.authClients || [];

  return (
    <section className="panel">
      <div className="admin-console form">
        <div className="panel-title">管理员控制台</div>

        <div className="admin-section">
          <h2 className="admin-section-heading">管理员 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="admin-section">
          <h2 className="admin-section-heading">签到设置</h2>
          <label>
            <IconLabel icon={icons.coins} text="签到奖励（萌芽币）" />
            <input
              type="number"
              min="1"
              value={checkInConfig.rewardCoins}
              onChange={(e) => handleCheckInConfigChange(e.target.value)}
              disabled={!token || configLoading}
            />
          </label>
          <div className="hint">用户每天首次签到会获得这里设置的奖励。</div>
          {configError && <div className="error">{configError}</div>}
          {configMessage && <div className="success">{configMessage}</div>}
          <div className="actions">
            <button className="primary" onClick={handleSaveCheckInConfig} disabled={!token || configSaving}>
              {configSaving ? "保存中..." : "保存设置"}
            </button>
          </div>
        </div>

        <div className="admin-section">
          <h2 className="admin-section-heading">注册与邀请码</h2>
          <label className="admin-ban-row">
            <IconLabel icon={icons.token} text="强制邀请码" />
            <span className="admin-ban-toggle">
              <input
                type="checkbox"
                checked={requireInviteReg}
                onChange={(e) => setRequireInviteReg(e.target.checked)}
                disabled={!token || regLoading}
              />
              <span>开启后，用户自助注册必须填写有效邀请码（管理员创建用户不受影响）</span>
            </span>
          </label>
          <div className="actions compact">
            <button type="button" className="primary" onClick={saveRegPolicy} disabled={!token || regSaving || regLoading}>
              {regSaving ? "保存中…" : "保存注册策略"}
            </button>
            <button type="button" className="ghost" onClick={loadRegistration} disabled={!token || regLoading}>
              {regLoading ? "加载中…" : "刷新列表"}
            </button>
          </div>
          <div className="hint">公开接口 <code className="inline-code">GET /api/public/registration-policy</code> 供前端判断是否显示邀请码输入框。</div>
          {regError && <div className="error">{regError}</div>}
          {regMessage && <div className="success">{regMessage}</div>}

          <h3 className="admin-subheading">生成新邀请码</h3>
          <label>
            <IconLabel icon={icons.username} text="备注（可选）" />
            <input value={newInvNote} onChange={(e) => setNewInvNote(e.target.value)} placeholder="例如：内测批次 A" disabled={!token || regInvCreating} />
          </label>
          <label>
            <IconLabel icon={icons.level} text="最大使用次数" hint="（0 表示不限）" />
            <input
              type="number"
              min="0"
              value={newInvMax}
              onChange={(e) => setNewInvMax(e.target.value)}
              disabled={!token || regInvCreating}
            />
          </label>
          <label>
            <IconLabel icon={icons.calendar} text="过期时间（可选）" />
            <input
              type="datetime-local"
              value={newInvExp}
              onChange={(e) => setNewInvExp(e.target.value)}
              disabled={!token || regInvCreating}
            />
          </label>
          <div className="actions">
            <button type="button" className="primary" onClick={handleCreateInvite} disabled={!token || regInvCreating}>
              {regInvCreating ? "生成中…" : "生成邀请码"}
            </button>
          </div>

          <h3 className="admin-subheading">已有邀请码</h3>
          {inviteList.length === 0 ? (
            <div className="hint">暂无邀请码</div>
          ) : (
            <div className="admin-invite-list">
              {inviteList.map((inv) => (
                <div key={inv.code} className="admin-invite-row">
                  <div>
                    <span className="mono admin-invite-code">{inv.code}</span>
                    {inv.note ? <span className="muted"> · {inv.note}</span> : null}
                    <div className="hint admin-invite-meta">
                      已用 {inv.uses ?? 0}
                      {inv.maxUses > 0 ? ` / 上限 ${inv.maxUses}` : " / 不限次数"}
                      {inv.expiresAt ? ` · 过期 ${formatIsoDateTimeReadable(inv.expiresAt)}` : ""}
                    </div>
                  </div>
                  <button type="button" className="danger ghost" onClick={() => handleDeleteInvite(inv.code)}>
                    删除
                  </button>
                </div>
              ))}
            </div>
          )}
        </div>

        <div className="admin-section">
          <div className="list-header">
            <h2 className="admin-section-heading admin-section-heading-inline">用户列表</h2>
            <div className="actions compact">
              <button className="primary" onClick={openCreateUser}>添加用户</button>
            </div>
          </div>
          {message && <div className="success">{message}</div>}
          {users.length === 0 && <div className="hint">暂无用户</div>}
          <div className="table admin-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>
            <TableCell icon={icons.ban}>状态</TableCell>
            <TableCell icon={icons.visitIp}>最近 IP</TableCell>
            <TableCell icon={icons.visitGeo}>最近位置</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}>
                <span className="admin-email-cell">
                  {u.email ? (
                    <MailtoEmail address={u.email} className="profile-external-link">{u.email}</MailtoEmail>
                  ) : (
                    <span>-</span>
                  )}
                  {(u.secondaryEmails || []).length > 0 && (
                    <>
                      <span className="muted"> / </span>
                      {(u.secondaryEmails || []).map((em, idx) => (
                        <React.Fragment key={em}>
                          {idx > 0 ? <span className="muted">, </span> : null}
                          <MailtoEmail address={em} className="profile-external-link">{em}</MailtoEmail>
                        </React.Fragment>
                      ))}
                    </>
                  )}
                </span>
              </TableCell>
              <TableCell icon={icons.level}>{u.level ?? 0} 级</TableCell>
              <TableCell icon={icons.coins}>{u.sproutCoins}</TableCell>
              <TableCell icon={icons.ban}>
                {u.banned ? (
                  <span className="admin-user-banned" title={u.banReason || "已封禁"}>封禁</span>
                ) : (
                  "正常"
                )}
              </TableCell>
              <TableCell icon={icons.visitIp}><span className="mono">{u.lastVisitIp || "-"}</span></TableCell>
              <TableCell icon={icons.visitGeo}>{u.lastVisitDisplayLocation || "-"}</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>

      {editorOpen && (
        <div className="modal-backdrop" onClick={closeEditor}>
          <div className="modal-card" onClick={(e) => e.stopPropagation()}>
            <div className="modal-header">
              <div>
                <h2>{editorMode === "edit" ? "编辑用户" : "新建用户配置"}</h2>
                <p>{editorMode === "edit" ? "修改账户资料后保存" : "点击保存后创建新用户"}</p>
              </div>
              <button className="ghost modal-close" onClick={closeEditor} type="button">关闭</button>
            </div>
            <div className="modal-body">
              <label>
                <IconLabel icon={icons.account} text="账户" />
                <input value={form.account} onChange={(e) => handleChange("account", e.target.value)} placeholder="唯一账户" disabled={editorMode === "edit"} />
              </label>
              <label>
                <IconLabel icon={icons.password} text="密码" hint={editorMode === "edit" ? "（留空不修改）" : ""} />
                <input type="password" value={form.password} onChange={(e) => handleChange("password", e.target.value)} placeholder={editorMode === "edit" ? "输入新密码" : "初始密码"} />
              </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 className="full-span">
                <IconLabel icon={icons.link} text="个人主页网站（http/https）" />
                <input value={form.websiteUrl} onChange={(e) => handleChange("websiteUrl", e.target.value)} placeholder="留空表示无" />
              </label>
              <label className="full-span">
                <IconLabel icon={icons.bio} text="个人简介（支持 Markdown）" />
                <textarea value={form.bio} onChange={(e) => handleChange("bio", e.target.value)} rows={4} />
              </label>
              {editorMode === "edit" && (
                <>
                  <label className="admin-ban-row">
                    <IconLabel icon={icons.ban} text="封禁账户" />
                    <span className="admin-ban-toggle">
                      <input
                        type="checkbox"
                        checked={Boolean(form.banned)}
                        onChange={(e) => handleChange("banned", e.target.checked)}
                      />
                      <span>禁止登录与使用需登录的接口</span>
                    </span>
                  </label>
                  <label className="full-span">
                    <IconLabel icon={icons.ban} text="封禁理由（对用户登录错误提示可见）" />
                    <textarea
                      value={form.banReason}
                      onChange={(e) => handleChange("banReason", e.target.value)}
                      rows={3}
                      placeholder="填写封禁原因；解封请取消勾选「封禁账户」并保存"
                      disabled={!form.banned}
                    />
                  </label>
                </>
              )}
              {editorMode === "edit" && editingAuthClients.length > 0 && (
                <div className="full-span admin-readonly-auth-clients">
                  <IconLabel icon={icons.apps} text="应用接入记录（只读）" />
                  <ul className="admin-auth-client-list">
                    {[...editingAuthClients]
                      .sort((a, b) => new Date(b.lastSeenAt || 0) - new Date(a.lastSeenAt || 0))
                      .map((row) => (
                        <li key={row.clientId}>
                          <strong>{row.clientId}</strong>
                          {row.displayName ? <span className="muted"> · {row.displayName}</span> : null}
                          <div className="muted admin-auth-client-meta">
                            首次 {formatIsoDateTimeReadable(row.firstSeenAt)} · 最近 {formatIsoDateTimeReadable(row.lastSeenAt)}
                          </div>
                        </li>
                      ))}
                  </ul>
                </div>
              )}
              {error && <div className="error">{error}</div>}
              {message && <div className="success">{message}</div>}
            </div>
            <div className="modal-actions">
              <button className="primary" onClick={editorMode === "edit" ? handleUpdate : handleCreate} type="button">
                {editorMode === "edit" ? "保存修改" : "创建用户"}
              </button>
              <button className="ghost" onClick={closeEditor} type="button">取消</button>
            </div>
          </div>
        </div>
      )}
    </section>
  );
}
