// Admin Dashboard page component
// Full CRUD management + statistics dashboard
// Renders inside main content area via React component

const { useState, useEffect, useMemo } = React;

// -----------------------------
// Confirm Dialog
// -----------------------------
function ConfirmDialog({ isOpen, title, message, onConfirm, onCancel, danger }) {
  if (!isOpen) return null;
  return (
    <div style={confirmOverlayStyle} onClick={onCancel}>
      <div style={confirmBoxStyle} onClick={(e) => e.stopPropagation()}>
        <h3 style={{ margin: 0, color: 'var(--text-0)', fontSize: 16, marginBottom: 10 }}>{title}</h3>
        <p style={{ color: 'var(--text-1)', fontSize: 13, marginBottom: 18, lineHeight: 1.6 }}>{message}</p>
        <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end' }}>
          <button style={btnSecondaryStyle} onClick={onCancel}>取消</button>
          <button
            style={{ ...btnPrimaryStyle, ...(danger ? { background: 'linear-gradient(135deg, var(--danger), #a03030)', borderColor: 'var(--danger)' } : {}) }}
            onClick={onConfirm}
          >
            确认
          </button>
        </div>
      </div>
    </div>
  );
}

const confirmOverlayStyle = {
  position: 'fixed', inset: 0, zIndex: 1000,
  background: 'rgba(0,0,0,0.6)',
  display: 'flex', alignItems: 'center', justifyContent: 'center',
  backdropFilter: 'blur(2px)',
};
const confirmBoxStyle = {
  background: 'linear-gradient(180deg, var(--bg-2), var(--bg-1))',
  border: '1px solid var(--border-1)',
  borderRadius: 6, padding: 24,
  width: 420, maxWidth: '90vw',
  boxShadow: '0 20px 60px rgba(0,0,0,0.5), 0 0 40px rgba(196,90,58,0.1)',
};
const btnPrimaryStyle = {
  padding: '7px 18px',
  background: 'linear-gradient(135deg, var(--accent-rust), var(--accent-rust-dim))',
  border: '1px solid var(--accent-rust)',
  borderRadius: 3, color: '#fff', cursor: 'pointer',
  fontSize: 12, fontWeight: 500,
  boxShadow: '0 2px 6px rgba(196,90,58,0.3)',
  fontFamily: 'var(--sans)',
};
const btnSecondaryStyle = {
  padding: '7px 18px',
  background: 'var(--bg-2)',
  border: '1px solid var(--border-1)',
  borderRadius: 3, color: 'var(--text-1)', cursor: 'pointer',
  fontSize: 12, fontFamily: 'var(--sans)',
};
const btnGhostStyle = {
  padding: '4px 12px',
  background: 'transparent',
  border: '1px solid var(--border-1)',
  borderRadius: 2, color: 'var(--text-2)', cursor: 'pointer',
  fontSize: 11, fontFamily: 'var(--sans)',
};
const inputStyle = {
  width: '100%', height: 36, padding: '0 10px',
  background: 'var(--bg-0)', border: '1px solid var(--border-1)',
  borderRadius: 3, color: 'var(--text-0)',
  fontSize: 12, fontFamily: 'var(--sans)',
  outline: 'none',
};
const labelStyle = {
  display: 'block', color: 'var(--text-2)', fontSize: 11,
  marginBottom: 5, letterSpacing: 0.5,
};
const tableStyle = {
  width: '100%', borderCollapse: 'collapse',
  background: 'var(--bg-1)', fontSize: 12,
};
const thStyle = {
  background: 'linear-gradient(180deg, var(--bg-2), var(--bg-3))',
  padding: '10px 12px', textAlign: 'left',
  color: 'var(--accent-mustard)', fontWeight: 600,
  borderBottom: '2px solid var(--accent-rust-dim)',
  fontSize: 12, whiteSpace: 'nowrap',
};
const tdStyle = {
  padding: '8px 12px', borderBottom: '1px solid var(--border-0)',
  color: 'var(--text-1)', fontFamily: 'var(--sans)',
};

// -----------------------------
// Admin Login Page
// -----------------------------
function AdminLoginPage({ onLogin }) {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);
    setError('');
    try {
      const data = await window.api.adminLogin(username, password);
      if (data.success) {
        localStorage.setItem('admin_token', data.token);
        onLogin(data.admin, data.token);
      } else {
        setError('账号或密码错误，请重试');
      }
    } catch (err) {
      setError('网络错误，请检查后端服务是否运行');
    }
    setLoading(false);
  };

  return (
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '70vh' }}>
      <div style={loginBoxStyle}>
        <div style={{ textAlign: 'center', marginBottom: 24 }}>
          <div style={{ fontSize: 28, marginBottom: 8 }}>🔐</div>
          <h2 style={{ color: 'var(--text-0)', fontSize: 20, letterSpacing: 1, marginBottom: 4 }}>管理员登录</h2>
          <p style={{ color: 'var(--text-2)', fontSize: 11, fontFamily: 'var(--mono)', letterSpacing: 1 }}>ADMIN LOGIN</p>
        </div>
        <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <div>
            <label style={{ display: 'block', color: 'var(--text-2)', fontSize: 11, marginBottom: 6, letterSpacing: 0.5 }}>
              用户名
            </label>
            <input
              type="text" value={username}
              onChange={(e) => setUsername(e.target.value)}
              style={inputStyle} placeholder="admin"
              autoFocus
            />
          </div>
          <div>
            <label style={{ display: 'block', color: 'var(--text-2)', fontSize: 11, marginBottom: 6, letterSpacing: 0.5 }}>
              密码
            </label>
            <input
              type="password" value={password}
              onChange={(e) => setPassword(e.target.value)}
              style={inputStyle} placeholder="admin123"
            />
          </div>
          {error && (
            <div style={{
              padding: 8, background: 'rgba(214,69,69,0.1)',
              border: '1px solid var(--danger)', borderRadius: 3,
              color: 'var(--danger)', fontSize: 12, textAlign: 'center',
            }}>
              {error}
            </div>
          )}
          <button
            type="submit"
            style={{
              ...btnPrimaryStyle, padding: '10px 0', fontSize: 13,
              marginTop: 6, opacity: loading ? 0.6 : 1,
            }}
            disabled={loading}
          >
            {loading ? '登录中...' : '登 录'}
          </button>
        </form>
        <div style={{ marginTop: 18, textAlign: 'center', color: 'var(--text-3)', fontSize: 10, fontFamily: 'var(--mono)' }}>
          默认账号 admin / admin123
        </div>
      </div>
    </div>
  );
}

const loginBoxStyle = {
  width: 380, maxWidth: '90vw',
  padding: 32,
  background: 'linear-gradient(180deg, var(--bg-1), var(--bg-2))',
  border: '1px solid var(--border-0)',
  borderRadius: 6,
  boxShadow: '0 20px 60px rgba(0,0,0,0.4), 0 0 40px rgba(196,90,58,0.08)',
  position: 'relative',
};

// -----------------------------
// Admin Sidebar
// -----------------------------
function AdminSidebar({ activeTab, onTabChange, admin, onLogout }) {
  const tabs = [
    { key: 'dashboard', label: '统计面板', icon: '📊' },
    { key: 'items', label: '物品管理', icon: '📦' },
    { key: 'recipes', label: '合成配方', icon: '⚗️' },
    { key: 'medicines', label: '药品效果', icon: '💊' },
    { key: 'buildings', label: '建筑耐久', icon: '🏗️' },
    { key: 'players', label: '玩家管理', icon: '👥' },
    { key: 'password', label: '修改密码', icon: '🔑' },
    { key: 'data', label: '数据管理', icon: '💾' },
  ];

  return (
    <div style={{
      width: 200, flexShrink: 0,
      background: 'linear-gradient(180deg, var(--bg-sidebar), #14180d)',
      borderRight: '1px solid var(--border-0)',
      padding: '20px 0',
    }}>
      <div style={{ padding: '0 16px 16px', borderBottom: '1px solid var(--border-0)', marginBottom: 8 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <div style={{
            width: 32, height: 32, borderRadius: '50%',
            background: 'linear-gradient(135deg, var(--accent-rust), var(--accent-mustard))',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontWeight: 700, color: '#fff', fontSize: 13,
          }}>
            {admin.username.charAt(0).toUpperCase()}
          </div>
          <div>
            <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--text-0)' }}>{admin.username}</div>
            <div style={{ fontSize: 10, color: 'var(--accent-green)', fontFamily: 'var(--mono)' }}>ADMIN</div>
          </div>
        </div>
      </div>
      {tabs.map((t) => (
        <div
          key={t.key}
          onClick={() => onTabChange(t.key)}
          style={{
            display: 'flex', alignItems: 'center', gap: 10,
            padding: '10px 18px', cursor: 'pointer',
            fontSize: 13,
            color: activeTab === t.key ? 'var(--accent-mustard)' : 'var(--text-1)',
            background: activeTab === t.key ? 'rgba(196,90,58,0.12)' : 'transparent',
            borderLeft: activeTab === t.key ? '3px solid var(--accent-rust)' : '3px solid transparent',
            transition: 'all 0.15s',
          }}
        >
          <span style={{ fontSize: 16 }}>{t.icon}</span>
          {t.label}
        </div>
      ))}
      <div style={{ marginTop: 20, paddingTop: 12, borderTop: '1px solid var(--border-0)' }}>
        <div
          onClick={onLogout}
          style={{
            display: 'flex', alignItems: 'center', gap: 10,
            padding: '10px 18px', cursor: 'pointer',
            fontSize: 13, color: 'var(--danger)',
          }}
        >
          <span style={{ fontSize: 16 }}>🚪</span>
          退出登录
        </div>
      </div>
    </div>
  );
}

// -----------------------------
// Generic CRUD Table
// -----------------------------
function GenericCrudPage({ title, description, columns, data, onAdd, onEdit, onDelete, searchable = true, addLabel = '新增' }) {
  const [search, setSearch] = useState('');
  const [confirmDelete, setConfirmDelete] = useState(null);

  const filtered = useMemo(() => {
    if (!search || !searchable) return data;
    const s = search.toLowerCase();
    return data.filter(row =>
      columns.some(col =>
        col.key && row[col.key]?.toString().toLowerCase().includes(s)
      )
    );
  }, [data, search, columns, searchable]);

  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
        <div>
          <h3 style={{ color: 'var(--text-0)', fontSize: 18, marginBottom: 4 }}>{title}</h3>
          <p style={{ color: 'var(--text-2)', fontSize: 12 }}>{description}</p>
        </div>
        <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
          {searchable && (
            <input
              type="text" placeholder="搜索..."
              value={search} onChange={(e) => setSearch(e.target.value)}
              style={{ ...inputStyle, width: 200 }}
            />
          )}
          <button style={btnPrimaryStyle} onClick={onAdd}>
            + {addLabel}
          </button>
        </div>
      </div>
      <div style={{ border: '1px solid var(--border-0)', borderRadius: 4, overflow: 'hidden', background: 'var(--bg-1)' }}>
        <div style={{ maxHeight: '60vh', overflowY: 'auto' }}>
          <table style={tableStyle}>
            <thead style={{ position: 'sticky', top: 0, zIndex: 1 }}>
              <tr>
                {columns.map(c => (
                  <th key={c.key || c.label} style={thStyle}>{c.label}</th>
                ))}
                <th style={thStyle}>操作</th>
              </tr>
            </thead>
            <tbody>
              {filtered.length === 0 && (
                <tr><td colSpan={columns.length + 1} style={{ ...tdStyle, textAlign: 'center', padding: 40, color: 'var(--text-3)' }}>
                  暂无数据
                </td></tr>
              )}
              {filtered.map((row, i) => (
                <tr key={row.id || i} style={{ background: i % 2 ? 'rgba(0,0,0,0.04)' : 'transparent' }}>
                  {columns.map(c => (
                    <td key={c.key || c.label} style={tdStyle}>
                      {c.render ? c.render(row) : row[c.key]}
                    </td>
                  ))}
                  <td style={{ ...tdStyle, whiteSpace: 'nowrap' }}>
                    <button style={btnGhostStyle} onClick={() => onEdit(row)}>编辑</button>
                    <button style={{ ...btnGhostStyle, color: 'var(--danger)', borderColor: 'rgba(214,69,69,0.3)', marginLeft: 6 }}
                            onClick={() => setConfirmDelete(row)}>
                      删除
                    </button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div style={{ padding: '8px 12px', background: 'var(--bg-0)', borderTop: '1px solid var(--border-0)', fontSize: 11, color: 'var(--text-3)', fontFamily: 'var(--mono)' }}>
          共 {filtered.length} 条数据
        </div>
      </div>
      {confirmDelete && (
        <ConfirmDialog
          isOpen={!!confirmDelete}
          title="确认删除"
          message={`确定要删除「${confirmDelete.name_en || confirmDelete.result_en || confirmDelete.name_zh || confirmDelete.game_id || confirmDelete.id}」吗？此操作不可撤销。`}
          danger
          onConfirm={() => { onDelete(confirmDelete); setConfirmDelete(null); }}
          onCancel={() => setConfirmDelete(null)}
        />
      )}
    </div>
  );
}

// -----------------------------
// Item Form Dialog
// -----------------------------
function ItemFormDialog({ item, categories, onSave, onClose }) {
  const [form, setForm] = useState(item || { item_id: '', name_en: '', name_zh: '', category: 'head' });
  const [error, setError] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError('');
    const result = await onSave(form);
    if (result?.error) setError(result.error);
  };

  return (
    <div style={confirmOverlayStyle} onClick={onClose}>
      <div style={{ ...confirmBoxStyle, width: 480 }} onClick={(e) => e.stopPropagation()}>
        <h3 style={{ margin: 0, color: 'var(--text-0)', fontSize: 16, marginBottom: 16 }}>
          {item ? '编辑物品' : '新增物品'}
        </h3>
        <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <div>
              <label style={labelStyle}>物品 ID</label>
              <input type="number" style={inputStyle} value={form.item_id}
                     onChange={(e) => setForm({ ...form, item_id: e.target.value })} required />
            </div>
            <div>
              <label style={labelStyle}>分类</label>
              <select style={inputStyle} value={form.category}
                      onChange={(e) => setForm({ ...form, category: e.target.value })}>
                {categories.map(c => (
                  <option key={c.key} value={c.key}>{c.name_zh} ({c.name_en})</option>
                ))}
              </select>
            </div>
          </div>
          <div>
            <label style={labelStyle}>英文名称</label>
            <input type="text" style={inputStyle} value={form.name_en}
                   onChange={(e) => setForm({ ...form, name_en: e.target.value })} required />
          </div>
          <div>
            <label style={labelStyle}>中文名称</label>
            <input type="text" style={inputStyle} value={form.name_zh}
                   onChange={(e) => setForm({ ...form, name_zh: e.target.value })} required />
          </div>
          {error && <div style={{ color: 'var(--danger)', fontSize: 12 }}>{error}</div>}
          <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', marginTop: 6 }}>
            <button type="button" style={btnSecondaryStyle} onClick={onClose}>取消</button>
            <button type="submit" style={btnPrimaryStyle}>保存</button>
          </div>
        </form>
      </div>
    </div>
  );
}

// -----------------------------
// Medicine Form Dialog
// -----------------------------
function MedicineFormDialog({ item, onSave, onClose }) {
  const [form, setForm] = useState(item || { name_en: '', name_zh: '', health: 0, radiation: 0, tier: 'low', special_effects: [] });

  const toggleEffect = (eff) => {
    const effects = form.special_effects || [];
    const has = effects.includes(eff);
    setForm({
      ...form,
      special_effects: has ? effects.filter(e => e !== eff) : [...effects, eff],
    });
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    onSave(form);
  };

  return (
    <div style={confirmOverlayStyle} onClick={onClose}>
      <div style={{ ...confirmBoxStyle, width: 500 }} onClick={(e) => e.stopPropagation()}>
        <h3 style={{ margin: 0, color: 'var(--text-0)', fontSize: 16, marginBottom: 16 }}>
          {item ? '编辑药品' : '新增药品'}
        </h3>
        <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div>
            <label style={labelStyle}>英文名称</label>
            <input type="text" style={inputStyle} value={form.name_en}
                   onChange={(e) => setForm({ ...form, name_en: e.target.value })} required />
          </div>
          <div>
            <label style={labelStyle}>中文名称</label>
            <input type="text" style={inputStyle} value={form.name_zh}
                   onChange={(e) => setForm({ ...form, name_zh: e.target.value })} required />
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
            <div>
              <label style={labelStyle}>回血 %</label>
              <input type="number" style={inputStyle} value={form.health}
                     onChange={(e) => setForm({ ...form, health: parseInt(e.target.value) || 0 })} />
            </div>
            <div>
              <label style={labelStyle}>辐射 %</label>
              <input type="number" style={inputStyle} value={form.radiation}
                     onChange={(e) => setForm({ ...form, radiation: parseInt(e.target.value) || 0 })} />
            </div>
            <div>
              <label style={labelStyle}>等级</label>
              <select style={inputStyle} value={form.tier}
                      onChange={(e) => setForm({ ...form, tier: e.target.value })}>
                <option value="high">高级</option>
                <option value="mid">中级</option>
                <option value="low">初级</option>
                <option value="berry">浆果</option>
                <option value="special">特殊</option>
              </select>
            </div>
          </div>
          <div>
            <label style={labelStyle}>特殊效果</label>
            <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
              {[['bleed', '止血'], ['brokenLeg', '治断腿'], ['stamina', '回体力']].map(([k, v]) => (
                <label key={k} style={{
                  display: 'flex', alignItems: 'center', gap: 5,
                  padding: '4px 10px', border: '1px solid var(--border-1)',
                  borderRadius: 20, fontSize: 12, color: 'var(--text-1)',
                  cursor: 'pointer',
                  background: (form.special_effects || []).includes(k) ? 'rgba(106,138,74,0.15)' : 'var(--bg-0)',
                  borderColor: (form.special_effects || []).includes(k) ? 'var(--accent-green)' : 'var(--border-1)',
                }}>
                  <input type="checkbox" checked={(form.special_effects || []).includes(k)}
                         onChange={() => toggleEffect(k)} style={{ marginRight: 4 }} />
                  {v}
                </label>
              ))}
            </div>
          </div>
          <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', marginTop: 6 }}>
            <button type="button" style={btnSecondaryStyle} onClick={onClose}>取消</button>
            <button type="submit" style={btnPrimaryStyle}>保存</button>
          </div>
        </form>
      </div>
    </div>
  );
}

// -----------------------------
// Recipe Form Dialog
// -----------------------------
function RecipeFormDialog({ recipe, onSave, onClose }) {
  const [form, setForm] = useState(recipe || {
    result_zh: '',
    result_en: '',
    category: 'tools',
    craftsman_level: 1,
    result_count: 1,
    materials: [{ name_zh: '', name_en: '', count: 1 }]
  });
  const [error, setError] = useState('');

  const handleMaterialChange = (index, field, value) => {
    const newMaterials = [...form.materials];
    newMaterials[index][field] = value;
    setForm({ ...form, materials: newMaterials });
  };

  const addMaterial = () => {
    setForm({
      ...form,
      materials: [...form.materials, { name_zh: '', name_en: '', count: 1 }]
    });
  };

  const removeMaterial = (index) => {
    if (form.materials.length <= 1) return;
    const newMaterials = form.materials.filter((_, i) => i !== index);
    setForm({ ...form, materials: newMaterials });
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError('');
    for (const m of form.materials) {
      if (!m.name_zh.trim() || !m.name_en.trim() || m.count < 1) {
        return setError('请完整填写所有材料（名称和数量）');
      }
    }
    const result = await onSave(form);
    if (result?.error) setError(result.error);
  };

  const categoriesList = [
    { key: 'medicine', name_zh: '药品', name_en: 'Medicine' },
    { key: 'building', name_zh: '建筑', name_en: 'Building' },
    { key: 'storage', name_zh: '储物', name_en: 'Storage' },
    { key: 'defense', name_zh: '防御', name_en: 'Defense' },
    { key: 'tools', name_zh: '工具', name_en: 'Tools' },
    { key: 'components', name_zh: '材料', name_en: 'Components' },
    { key: 'military', name_zh: '军用', name_en: 'Military' },
    { key: 'clothes', name_zh: '衣物', name_en: 'Clothes' },
    { key: 'furniture', name_zh: '家具', name_en: 'Furniture' },
  ];

  return (
    <div style={confirmOverlayStyle} onClick={onClose}>
      <div style={{ ...confirmBoxStyle, width: 600, maxHeight: '90vh', overflowY: 'auto' }} onClick={(e) => e.stopPropagation()}>
        <h3 style={{ margin: 0, color: 'var(--text-0)', fontSize: 16, marginBottom: 16 }}>
          {recipe ? '编辑配方' : '新增配方'}
        </h3>
        <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
            <div>
              <label style={labelStyle}>产物（中文）</label>
              <input type="text" style={inputStyle} value={form.result_zh}
                     onChange={(e) => setForm({ ...form, result_zh: e.target.value })} required />
            </div>
            <div>
              <label style={labelStyle}>产物（英文）</label>
              <input type="text" style={inputStyle} value={form.result_en}
                     onChange={(e) => setForm({ ...form, result_en: e.target.value })} required />
            </div>
            <div>
              <label style={labelStyle}>产出数量</label>
              <input type="number" style={inputStyle} value={form.result_count}
                     onChange={(e) => setForm({ ...form, result_count: parseInt(e.target.value) || 1 })} min="1" required />
            </div>
          </div>

          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <div>
              <label style={labelStyle}>分类</label>
              <select style={inputStyle} value={form.category}
                      onChange={(e) => setForm({ ...form, category: e.target.value })}>
                {categoriesList.map(c => (
                  <option key={c.key} value={c.key}>{c.name_zh} ({c.name_en})</option>
                ))}
              </select>
            </div>
            <div>
              <label style={labelStyle}>工匠等级</label>
              <select style={inputStyle} value={form.craftsman_level}
                      onChange={(e) => setForm({ ...form, craftsman_level: parseInt(e.target.value) })}>
                <option value={1}>等级 1</option>
                <option value={2}>等级 2</option>
                <option value={3}>等级 3</option>
                <option value={4}>等级 4</option>
                <option value={5}>等级 5</option>
              </select>
            </div>
          </div>

          <div>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
              <label style={{ ...labelStyle, marginBottom: 0 }}>材料清单</label>
              <button type="button" style={btnGhostStyle} onClick={addMaterial}>+ 添加材料</button>
            </div>
            {form.materials.map((mat, index) => (
              <div key={index} style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 0.5fr auto', gap: 8, marginBottom: 8, alignItems: 'end' }}>
                <div>
                  <label style={{ ...labelStyle, fontSize: 10 }}>中文名</label>
                  <input type="text" style={{ ...inputStyle, height: 32 }} value={mat.name_zh}
                         onChange={(e) => handleMaterialChange(index, 'name_zh', e.target.value)} required />
                </div>
                <div>
                  <label style={{ ...labelStyle, fontSize: 10 }}>英文名</label>
                  <input type="text" style={{ ...inputStyle, height: 32 }} value={mat.name_en}
                         onChange={(e) => handleMaterialChange(index, 'name_en', e.target.value)} required />
                </div>
                <div>
                  <label style={{ ...labelStyle, fontSize: 10 }}>数量</label>
                  <input type="number" style={{ ...inputStyle, height: 32 }} value={mat.count}
                         onChange={(e) => handleMaterialChange(index, 'count', parseInt(e.target.value) || 1)} min="1" required />
                </div>
                <button type="button" style={{ ...btnGhostStyle, padding: '4px 8px', marginBottom: 2 }}
                        onClick={() => removeMaterial(index)} disabled={form.materials.length <= 1}>
                  ✕
                </button>
              </div>
            ))}
          </div>

          {error && <div style={{ color: 'var(--danger)', fontSize: 12 }}>{error}</div>}

          <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', marginTop: 6 }}>
            <button type="button" style={btnSecondaryStyle} onClick={onClose}>取消</button>
            <button type="submit" style={btnPrimaryStyle}>保存</button>
          </div>
        </form>
      </div>
    </div>
  );
}

// -----------------------------
// Player Edit Dialog
// -----------------------------
function PlayerEditDialog({ player, onSave, onClose }) {
  const [form, setForm] = useState({
    qq_number: player?.qq_number || '',
    game_id: player?.game_id || '',
  });
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError('');
    setLoading(true);
    try {
      const updates = {};
      if (form.qq_number !== player.qq_number) updates.qq_number = form.qq_number;
      if (form.game_id !== player.game_id) updates.game_id = form.game_id;
      
      if (Object.keys(updates).length === 0) {
        setError('没有修改任何内容');
        setLoading(false);
        return;
      }
      
      await onSave(player.id, updates);
      setLoading(false);
    } catch (err) {
      setError(err.message || '保存失败');
      setLoading(false);
    }
  };

  return (
    <div style={confirmOverlayStyle} onClick={onClose}>
      <div style={{ ...confirmBoxStyle, width: 440 }} onClick={(e) => e.stopPropagation()}>
        <h3 style={{ margin: 0, color: 'var(--text-0)', fontSize: 16, marginBottom: 16 }}>
          编辑玩家信息
        </h3>
        <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div>
            <label style={labelStyle}>玩家 ID（不可修改）</label>
            <input type="text" style={{ ...inputStyle, opacity: 0.5, cursor: 'not-allowed' }} value={player?.id || ''} disabled />
          </div>
          <div>
            <label style={labelStyle}>QQ 号</label>
            <input type="text" style={inputStyle} value={form.qq_number}
                   onChange={(e) => setForm({ ...form, qq_number: e.target.value })} placeholder="请输入QQ号" />
          </div>
          <div>
            <label style={labelStyle}>游戏 ID</label>
            <input type="text" style={inputStyle} value={form.game_id}
                   onChange={(e) => setForm({ ...form, game_id: e.target.value })} placeholder="请输入游戏ID" />
          </div>
          <div style={{ fontSize: 11, color: 'var(--text-3)', marginTop: -4 }}>
            ⚠️ 修改后立即生效，玩家下次登录时使用新信息。
          </div>
          {error && <div style={{ color: 'var(--danger)', fontSize: 12, padding: 8, background: 'rgba(214,69,69,0.1)', borderRadius: 3 }}>{error}</div>}
          <div style={{ display: 'flex', gap: 10, justifyContent: 'flex-end', marginTop: 6 }}>
            <button type="button" style={btnSecondaryStyle} onClick={onClose}>取消</button>
            <button type="submit" style={btnPrimaryStyle} disabled={loading}>
              {loading ? '保存中...' : '保存'}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

// -----------------------------
// Admin Dashboard
// -----------------------------
function AdminDashboard() {
  const [stats, setStats] = useState(null);
  const [loading, setLoading] = useState(true);

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

  const loadStats = async () => {
    setLoading(true);
    const data = await window.api.getStats();
    setStats(data);
    setLoading(false);
  };

  if (loading) {
    return <div style={{ textAlign: 'center', padding: 60, color: 'var(--text-2)' }}>加载中...</div>;
  }
  if (!stats || stats.error) {
    return <div style={{ textAlign: 'center', padding: 60, color: 'var(--danger)' }}>
      加载失败：{stats?.error || '未知错误'}
    </div>;
  }

  const statCards = [
    { label: '总访问量', value: stats.totalVisits, icon: '📈', color: 'var(--accent-mustard)' },
    { label: '今日访问', value: stats.todayVisits, icon: '📅', color: 'var(--accent-green)' },
    { label: '本周访问', value: stats.weekVisits, icon: '🗓️', color: 'var(--accent-rust)' },
    { label: '注册玩家', value: stats.totalPlayers, icon: '👥', color: '#5ab8d8' },
  ];

  return (
    <div>
      <h3 style={{ color: 'var(--text-0)', fontSize: 18, marginBottom: 16 }}>统计面板</h3>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 14, marginBottom: 24 }}>
        {statCards.map((s, i) => (
          <div key={i} style={{
            background: 'linear-gradient(135deg, var(--bg-1), var(--bg-2))',
            border: '1px solid var(--border-0)', borderRadius: 5, padding: 18,
            boxShadow: '0 2px 8px rgba(0,0,0,0.2)',
          }}>
            <div style={{ fontSize: 26, marginBottom: 6 }}>{s.icon}</div>
            <div style={{
              fontSize: 26, fontWeight: 800, fontFamily: 'var(--mono)',
              color: s.color, textShadow: `0 0 10px currentColor`,
              marginBottom: 4,
            }}>
              {s.value.toLocaleString()}
            </div>
            <div style={{ fontSize: 12, color: 'var(--text-2)' }}>{s.label}</div>
          </div>
        ))}
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20, marginBottom: 24 }}>
        <div style={panelStyle}>
          <h4 style={panelTitleStyle}>🏆 热门物品 Top 10</h4>
          {stats.topItems?.length === 0 && <div style={{ color: 'var(--text-3)', fontSize: 12 }}>暂无数据</div>}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            {stats.topItems?.map((item, i) => (
              <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <div style={{
                  width: 22, height: 22, borderRadius: '50%',
                  background: i < 3 ? 'linear-gradient(135deg, var(--accent-mustard), var(--accent-rust))' : 'var(--bg-3)',
                  color: '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center',
                  fontSize: 11, fontWeight: 700, flexShrink: 0,
                }}>{i + 1}</div>
                <div style={{ flex: 1, fontSize: 12, color: 'var(--text-1)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                  {item.target_name || item.target_id}
                </div>
                <div style={{ fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--accent-mustard)', fontWeight: 600 }}>
                  {item.view_count}
                </div>
              </div>
            ))}
          </div>
        </div>

        <div style={panelStyle}>
          <h4 style={panelTitleStyle}>📊 访问页面分布</h4>
          {stats.topPages?.length === 0 && <div style={{ color: 'var(--text-3)', fontSize: 12 }}>暂无数据</div>}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {stats.topPages?.map((p, i) => {
              const max = Math.max(...stats.topPages.map(x => x.view_count));
              const pct = (p.view_count / max) * 100;
              return (
                <div key={i}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11, marginBottom: 3 }}>
                    <span style={{ color: 'var(--text-1)' }}>{p.page_type}</span>
                    <span style={{ color: 'var(--accent-mustard)', fontFamily: 'var(--mono)' }}>{p.view_count}</span>
                  </div>
                  <div style={{ height: 6, background: 'var(--bg-0)', borderRadius: 3, overflow: 'hidden' }}>
                    <div style={{
                      width: `${pct}%`, height: '100%',
                      background: 'linear-gradient(90deg, var(--accent-rust), var(--accent-mustard))',
                      borderRadius: 3,
                    }}></div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 20 }}>
        <div style={panelStyle}>
          <h4 style={panelTitleStyle}>📈 近7天访问趋势</h4>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            {stats.trend?.length === 0 && <div style={{ color: 'var(--text-3)', fontSize: 12 }}>暂无数据</div>}
            {stats.trend?.map((d, i) => {
              const max = Math.max(...stats.trend.map(x => x.count), 1);
              const pct = (d.count / max) * 100;
              return (
                <div key={i} style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                  <div style={{ width: 70, fontSize: 11, color: 'var(--text-2)', fontFamily: 'var(--mono)' }}>
                    {d.date?.slice(5)}
                  </div>
                  <div style={{ flex: 1, height: 16, background: 'var(--bg-0)', borderRadius: 2, overflow: 'hidden' }}>
                    <div style={{
                      width: `${pct}%`, height: '100%',
                      background: 'linear-gradient(90deg, var(--accent-green-dim), var(--accent-green), var(--accent-mustard))',
                      boxShadow: '0 0 6px rgba(106,138,74,0.4)',
                      transition: 'width 0.5s',
                    }}></div>
                  </div>
                  <div style={{ width: 40, textAlign: 'right', fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--text-1)' }}>
                    {d.count}
                  </div>
                </div>
              );
            })}
          </div>
        </div>

        <div style={panelStyle}>
          <h4 style={panelTitleStyle}>👤 最近注册玩家</h4>
          {stats.recentPlayers?.length === 0 && <div style={{ color: 'var(--text-3)', fontSize: 12 }}>暂无注册</div>}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
            {stats.recentPlayers?.map((p, i) => (
              <div key={i} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '6px 0' }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <div style={{
                    width: 28, height: 28, borderRadius: '50%',
                    background: 'linear-gradient(135deg, var(--accent-green), var(--accent-green-dim))',
                    display: 'flex', alignItems: 'center', justifyContent: 'center',
                    fontSize: 11, fontWeight: 600, color: '#fff',
                  }}>
                    {p.game_id?.charAt(0) || '?'}
                  </div>
                  <div>
                    <div style={{ fontSize: 12, color: 'var(--text-0)', fontWeight: 500 }}>{p.game_id}</div>
                    <div style={{ fontSize: 10, color: 'var(--text-3)', fontFamily: 'var(--mono)' }}>QQ: {p.qq_number}</div>
                  </div>
                </div>
                <div style={{ fontSize: 10, color: 'var(--text-3)', fontFamily: 'var(--mono)' }}>
                  {p.created_at?.slice(5, 10)}
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div style={{ ...panelStyle, marginTop: 20 }}>
        <h4 style={panelTitleStyle}>🕐 最近访问记录</h4>
        <div style={{ maxHeight: 240, overflowY: 'auto' }}>
          {stats.recentVisits?.length === 0 && <div style={{ color: 'var(--text-3)', fontSize: 12 }}>暂无记录</div>}
          {stats.recentVisits?.map((v, i) => (
            <div key={i} style={{
              display: 'flex', justifyContent: 'space-between', alignItems: 'center',
              padding: '6px 0', borderBottom: '1px dashed var(--border-0)',
            }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                <span style={{ fontSize: 13 }}>
                  {v.page_type === 'item' ? '📦' : v.page_type === 'medicine' ? '💊' : v.page_type === 'recipe' ? '⚗️' : v.page_type === 'building' ? '🏗️' : '📄'}
                </span>
                <div>
                  <span style={{ fontSize: 12, color: 'var(--text-1)' }}>
                    {v.target_name || v.page_type}
                  </span>
                  {v.player_game_id && (
                    <span style={{ fontSize: 10, color: 'var(--text-3)', marginLeft: 6 }}>
                      · {v.player_game_id} (QQ: {v.player_qq})
                    </span>
                  )}
                </div>
              </div>
              <span style={{ fontSize: 10, color: 'var(--text-3)', fontFamily: 'var(--mono)' }}>
                {v.created_at?.slice(0, 19).replace('T', ' ')}
              </span>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

const panelStyle = {
  background: 'linear-gradient(180deg, var(--bg-1), var(--bg-2))',
  border: '1px solid var(--border-0)',
  borderRadius: 5,
  padding: 18,
  boxShadow: '0 2px 8px rgba(0,0,0,0.15)',
};
const panelTitleStyle = {
  color: 'var(--text-0)', fontSize: 14, fontWeight: 600,
  margin: '0 0 14px 0', paddingBottom: 10,
  borderBottom: '1px solid var(--border-0)',
};

// -----------------------------
// Password change page
// -----------------------------
function ChangePasswordPage({ onSuccess }) {
  const [oldPw, setOldPw] = useState('');
  const [newPw, setNewPw] = useState('');
  const [confirmPw, setConfirmPw] = useState('');
  const [error, setError] = useState('');
  const [success, setSuccess] = useState('');

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError(''); setSuccess('');
    if (newPw !== confirmPw) return setError('两次输入的新密码不一致');
    if (newPw.length < 6) return setError('新密码至少6位');

    const data = await window.api.adminChangePassword(oldPw, newPw);
    if (data.success) {
      setSuccess('密码修改成功！');
      setOldPw(''); setNewPw(''); setConfirmPw('');
    } else {
      setError(data.error || '修改失败');
    }
  };

  return (
    <div style={{ maxWidth: 440, margin: '40px auto' }}>
      <h3 style={{ color: 'var(--text-0)', fontSize: 18, marginBottom: 4 }}>修改管理员密码</h3>
      <p style={{ color: 'var(--text-2)', fontSize: 12, marginBottom: 20 }}>定期修改密码以保证后台安全</p>
      <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <div>
          <label style={labelStyle}>原密码</label>
          <input type="password" style={inputStyle} value={oldPw} onChange={(e) => setOldPw(e.target.value)} required />
        </div>
        <div>
          <label style={labelStyle}>新密码（至少6位）</label>
          <input type="password" style={inputStyle} value={newPw} onChange={(e) => setNewPw(e.target.value)} required />
        </div>
        <div>
          <label style={labelStyle}>确认新密码</label>
          <input type="password" style={inputStyle} value={confirmPw} onChange={(e) => setConfirmPw(e.target.value)} required />
        </div>
        {error && <div style={{ color: 'var(--danger)', fontSize: 12, padding: 8, background: 'rgba(214,69,69,0.1)', borderRadius: 3 }}>{error}</div>}
        {success && <div style={{ color: 'var(--success)', fontSize: 12, padding: 8, background: 'rgba(90,154,85,0.1)', borderRadius: 3 }}>{success}</div>}
        <button type="submit" style={{ ...btnPrimaryStyle, padding: '10px 0', marginTop: 6 }}>修改密码</button>
      </form>
    </div>
  );
}

// -----------------------------
// Data Management page
// -----------------------------
function DataManagementPage() {
  const [confirmReset, setConfirmReset] = useState(false);
  const [message, setMessage] = useState('');

  const doReset = async () => {
    const data = await window.api.resetData();
    setMessage(data.message || data.error || '操作完成');
    setConfirmReset(false);
  };

  return (
    <div style={{ maxWidth: 560 }}>
      <h3 style={{ color: 'var(--text-0)', fontSize: 18, marginBottom: 4 }}>数据管理</h3>
      <p style={{ color: 'var(--text-2)', fontSize: 12, marginBottom: 20 }}>
        从初始种子数据重建数据库。警告：会覆盖所有手动修改的数据！
      </p>

      <div style={panelStyle}>
        <h4 style={panelTitleStyle}>⚠️ 危险操作</h4>
        <div style={{ marginBottom: 16 }}>
          <p style={{ color: 'var(--text-1)', fontSize: 12, lineHeight: 1.8 }}>
            「一键导入初始数据」会将所有物品、配方、药品、建筑等数据重置为初始版本。
            <br />手动新增或修改的内容将被覆盖。
          </p>
        </div>
        <button style={{ ...btnPrimaryStyle, background: 'linear-gradient(135deg, var(--danger), #a03030)', borderColor: 'var(--danger)' }}
                onClick={() => setConfirmReset(true)}>
          重置为初始数据
        </button>
        {message && <div style={{ marginTop: 14, color: 'var(--success)', fontSize: 12 }}>{message}</div>}
      </div>

      <ConfirmDialog
        isOpen={confirmReset}
        title="确认重置数据？"
        message="此操作将覆盖所有物品、配方、药品、建筑数据为初始版本，所有手动修改将丢失。确定继续吗？"
        danger
        onConfirm={doReset}
        onCancel={() => setConfirmReset(false)}
      />
    </div>
  );
}

// -----------------------------
// Players management page（完整版，含编辑功能）
// -----------------------------
function PlayersPage() {
  const [players, setPlayers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [search, setSearch] = useState('');
  const [editingPlayer, setEditingPlayer] = useState(null);
  const [showEditDialog, setShowEditDialog] = useState(false);

  const load = async () => {
    setLoading(true);
    try {
      const data = await window.api.getPlayers({ limit: 200, q: search });
      setPlayers(data || []);
    } catch (err) {
      console.error('加载玩家失败:', err);
      setPlayers([]);
    }
    setLoading(false);
  };
  useEffect(() => { load(); }, [search]);

  const handleDelete = async (player) => {
    await window.api.deletePlayer(player.id);
    load();
  };

  const handleEdit = (player) => {
    setEditingPlayer(player);
    setShowEditDialog(true);
  };

  const handleSaveEdit = async (id, updates) => {
    await window.api.updatePlayer(id, updates);
    setShowEditDialog(false);
    setEditingPlayer(null);
    load();
  };

  const columns = [
    { key: 'id', label: 'ID' },
    { key: 'qq_number', label: 'QQ号' },
    { key: 'game_id', label: '游戏ID' },
    { key: 'created_at', label: '注册时间', render: (r) => <span style={{ fontFamily: 'var(--mono)', fontSize: 11 }}>{r.created_at?.slice(0,19).replace('T',' ')}</span> },
  ];

  return (
    <>
      <GenericCrudPage
        title="玩家管理"
        description="查看和管理注册玩家列表"
        columns={columns}
        data={players}
        searchable={true}
        addLabel=""
        onAdd={() => {}}
        onEdit={handleEdit}
        onDelete={handleDelete}
      />
      {showEditDialog && editingPlayer && (
        <PlayerEditDialog
          player={editingPlayer}
          onSave={handleSaveEdit}
          onClose={() => { setShowEditDialog(false); setEditingPlayer(null); }}
        />
      )}
    </>
  );
}

// -----------------------------
// Main Admin Page
// -----------------------------
function AdminPage() {
  const [admin, setAdmin] = useState(null);
  const [tab, setTab] = useState('dashboard');
  const [items, setItems] = useState([]);
  const [categories, setCategories] = useState([]);
  const [editItem, setEditItem] = useState(null);
  const [showItemForm, setShowItemForm] = useState(false);

  const [medicines, setMedicines] = useState([]);
  const [editMed, setEditMed] = useState(null);
  const [showMedForm, setShowMedForm] = useState(false);

  const [buildings, setBuildings] = useState([]);
  const [recipes, setRecipes] = useState([]);

  const [editRecipe, setEditRecipe] = useState(null);
  const [showRecipeForm, setShowRecipeForm] = useState(false);
  const [confirmDeleteRecipe, setConfirmDeleteRecipe] = useState(null);

  // Check existing token
  useEffect(() => {
    const token = localStorage.getItem('admin_token');
    if (token) {
      window.api.adminMe().then(data => {
        if (data.admin) setAdmin(data.admin);
      }).catch(() => {});
    }
  }, []);

  const handleLogin = (adminData, token) => {
    setAdmin(adminData);
    loadAll();
    window.dispatchEvent(new CustomEvent('adminLogin', {
      detail: { admin: adminData, token: token }
    }));
  };

  const handleLogout = () => {
    localStorage.removeItem('admin_token');
    setAdmin(null);
    window.location.hash = '#home';
  };

  const loadAll = async () => {
    const [itemData, medData, buildingData, recipeData] = await Promise.all([
      window.api.getItems({ limit: 500 }),
      window.api.getMedicinesAdmin(),
      window.api.getBuildingsAdmin(),
      window.api.getRecipes({ limit: 200 }),
    ]);
    setItems(itemData || []);
    setMedicines(medData || []);
    setBuildings(buildingData || []);
    setRecipes(recipeData || []);

    try {
      const meta = await window.api.getAllData();
      setCategories(meta.categories || []);
    } catch {}
  };

  // Items
  const handleSaveItem = async (form) => {
    let data;
    if (editItem) {
      data = await window.api.updateItem(editItem.id, form);
    } else {
      data = await window.api.createItem(form);
    }
    if (data.error) return { error: data.error };
    loadAll();
    setShowItemForm(false);
    setEditItem(null);
    return {};
  };

  const handleDeleteItem = async (item) => {
    await window.api.deleteItem(item.id);
    loadAll();
  };

  // Medicines
  const handleSaveMed = async (form) => {
    if (editMed) {
      await window.api.updateMedicine(editMed.id, form);
    } else {
      await window.api.createMedicine(form);
    }
    loadAll();
    setShowMedForm(false);
    setEditMed(null);
  };

  const handleDeleteMed = async (item) => {
    await window.api.deleteMedicine(item.id);
    loadAll();
  };

  // Recipes
  const handleSaveRecipe = async (form) => {
    let data;
    if (editRecipe) {
      data = await window.api.updateRecipe(editRecipe.id, form);
    } else {
      data = await window.api.createRecipe(form);
    }
    if (data.error) return { error: data.error };
    loadAll();
    setShowRecipeForm(false);
    setEditRecipe(null);
    return {};
  };

  const handleDeleteRecipe = async (recipe) => {
    await window.api.deleteRecipe(recipe.id);
    loadAll();
    setConfirmDeleteRecipe(null);
  };

  // Buildings
  const handleDeleteBuilding = async (b) => {
    await window.api.deleteBuilding(b.id);
    loadAll();
  };

  if (!admin) {
    return <AdminLoginPage onLogin={handleLogin} />;
  }

  return (
    <div style={{ display: 'flex', height: '100%' }}>
      <AdminSidebar activeTab={tab} onTabChange={setTab} admin={admin} onLogout={handleLogout} />
      <div style={{ flex: 1, padding: 24, overflowY: 'auto' }}>
        {tab === 'dashboard' && <AdminDashboard />}

        {tab === 'items' && (
          <GenericCrudPage
            title="物品管理"
            description="管理所有游戏物品的中英文名称、分类和ID"
            columns={[
              { key: 'id', label: 'ID' },
              { key: 'name_zh', label: '中文名' },
              { key: 'name_en', label: '英文名' },
              { key: 'category_id', label: '分类' }, // 修正列名
            ]}
            data={items}
            onAdd={() => { setEditItem(null); setShowItemForm(true); }}
            onEdit={(item) => { setEditItem(item); setShowItemForm(true); }}
            onDelete={handleDeleteItem}
            addLabel="物品"
          />
        )}

        {tab === 'recipes' && (
          <div>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 16 }}>
              <div>
                <h3 style={{ color: 'var(--text-0)', fontSize: 18, marginBottom: 4 }}>合成配方管理</h3>
                <p style={{ color: 'var(--text-2)', fontSize: 12 }}>管理所有合成配方，支持添加、编辑、删除</p>
              </div>
              <button style={btnPrimaryStyle} onClick={() => {
                setEditRecipe(null);
                setShowRecipeForm(true);
              }}>
                + 新增配方
              </button>
            </div>

            <div style={{ border: '1px solid var(--border-0)', borderRadius: 4, overflow: 'hidden', background: 'var(--bg-1)' }}>
              <div style={{ maxHeight: '60vh', overflowY: 'auto' }}>
                <table style={tableStyle}>
                  <thead style={{ position: 'sticky', top: 0, zIndex: 1 }}>
                    <tr>
                      <th style={thStyle}>ID</th>
                      <th style={thStyle}>产物（中）</th>
                      <th style={thStyle}>产物（英）</th>
                      <th style={thStyle}>分类</th>
                      <th style={thStyle}>等级</th>
                      <th style={thStyle}>数量</th>
                      <th style={thStyle}>材料</th>
                      <th style={thStyle}>操作</th>
                    </tr>
                  </thead>
                  <tbody>
                    {recipes.length === 0 && (
                      <tr><td colSpan={8} style={{ ...tdStyle, textAlign: 'center', padding: 40, color: 'var(--text-3)' }}>
                        暂无配方数据
                      </td></tr>
                    )}
                    {recipes.map((r, i) => (
                      <tr key={r.id || i} style={{ background: i % 2 ? 'rgba(0,0,0,0.04)' : 'transparent' }}>
                        <td style={tdStyle}>{r.id}</td>
                        <td style={tdStyle}>{r.result_zh}</td>
                        <td style={tdStyle}>{r.result_en}</td>
                        <td style={tdStyle}>{r.category}</td>
                        <td style={tdStyle}>{r.craftsman_level}</td>
                        <td style={tdStyle}>{r.result_count}</td>
                        <td style={{ ...tdStyle, maxWidth: 200, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                          {r.materials ? (typeof r.materials === 'string' ? r.materials : JSON.stringify(r.materials)) : '—'}
                        </td>
                        <td style={{ ...tdStyle, whiteSpace: 'nowrap' }}>
                          <button style={btnGhostStyle} onClick={() => {
                            setEditRecipe(r);
                            setShowRecipeForm(true);
                          }}>编辑</button>
                          <button style={{ ...btnGhostStyle, color: 'var(--danger)', borderColor: 'rgba(214,69,69,0.3)', marginLeft: 6 }}
                                  onClick={() => setConfirmDeleteRecipe(r)}>
                            删除
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <div style={{ padding: '8px 12px', background: 'var(--bg-0)', borderTop: '1px solid var(--border-0)', fontSize: 11, color: 'var(--text-3)', fontFamily: 'var(--mono)' }}>
                共 {recipes.length} 条配方
              </div>
            </div>
          </div>
        )}

        {tab === 'medicines' && (
          <GenericCrudPage
            title="药品效果管理"
            description="管理药品的回血、辐射、特殊效果等数据"
            columns={[
              { key: 'id', label: 'ID' },
              { key: 'name_zh', label: '中文名' },
              { key: 'name_en', label: '英文名' },
              { key: 'health', label: '回血%' },
              { key: 'radiation', label: '辐射%' },
              { key: 'tier', label: '等级' },
              { key: 'special_effects', label: '特效', render: (r) => (r.special_effects?.length ? r.special_effects.join(', ') : '—') },
            ]}
            data={medicines}
            onAdd={() => { setEditMed(null); setShowMedForm(true); }}
            onEdit={(m) => { setEditMed(m); setShowMedForm(true); }}
            onDelete={handleDeleteMed}
            addLabel="药品"
          />
        )}

        {tab === 'buildings' && (
          <GenericCrudPage
            title="建筑耐久管理"
            description="管理建筑血量和武器破坏次数（weapon_damage为JSON格式）"
            columns={[
              { key: 'id', label: 'ID' },
              { key: 'name_zh', label: '中文名' },
              { key: 'name_en', label: '英文名' },
              { key: 'hp', label: '血量' },
              { key: 'weapon_damage', label: '武器破坏数据', render: (r) => (
                <span style={{ fontFamily: 'var(--mono)', fontSize: 10, color: 'var(--text-2)' }}>
                  {JSON.stringify(r.weapon_damage)}
                </span>
              )},
            ]}
            data={buildings}
            onAdd={() => alert('建筑数据含复杂JSON，建议直接操作数据库或后续完善表单')}
            onEdit={() => alert('建筑数据含复杂JSON，建议直接操作数据库或后续完善表单')}
            onDelete={handleDeleteBuilding}
            addLabel="建筑"
          />
        )}

        {tab === 'players' && <PlayersPage />}
        {tab === 'password' && <ChangePasswordPage />}
        {tab === 'data' && <DataManagementPage />}
      </div>

      {/* 物品编辑弹窗 */}
      {showItemForm && (
        <ItemFormDialog
          item={editItem}
          categories={categories}
          onSave={handleSaveItem}
          onClose={() => { setShowItemForm(false); setEditItem(null); }}
        />
      )}

      {/* 药品编辑弹窗 */}
      {showMedForm && (
        <MedicineFormDialog
          item={editMed}
          onSave={handleSaveMed}
          onClose={() => { setShowMedForm(false); setEditMed(null); }}
        />
      )}

      {/* 配方编辑弹窗 */}
      {showRecipeForm && (
        <RecipeFormDialog
          recipe={editRecipe}
          onSave={handleSaveRecipe}
          onClose={() => { setShowRecipeForm(false); setEditRecipe(null); }}
        />
      )}

      {/* 配方删除确认 */}
      {confirmDeleteRecipe && (
        <ConfirmDialog
          isOpen={!!confirmDeleteRecipe}
          title="确认删除"
          message={`确定要删除配方「${confirmDeleteRecipe.result_zh || confirmDeleteRecipe.result_en}」吗？此操作不可撤销。`}
          danger
          onConfirm={() => handleDeleteRecipe(confirmDeleteRecipe)}
          onCancel={() => setConfirmDeleteRecipe(null)}
        />
      )}
    </div>
  );
}

window.AdminPage = AdminPage;
