import React, { useEffect, useMemo, useState } from 'react';
import { KeyRound, Loader2, Plus, ShieldCheck, Trash2, UserCog } from 'lucide-react';
import {
  createAdminUser,
  deleteAdminUser,
  getAdminUsers,
  getAuditLogs,
  resetDemoFactory,
  updateAdminUser,
  type AdminUser,
  type AuditLog,
} from '../lib/api';
import { cn } from '../lib/utils';
import { useStore } from '../store/useStore';
import { TransientNotice, type NoticeState, type NoticeTone } from './TransientNotice';

const roleLabels: Record<string, string> = {
  admin: '管理员',
  annotator: '标注员',
  viewer: '观察员',
};

function formatTime(value: string): string {
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return value;
  return date.toLocaleString('zh-CN', {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
  });
}

export function UserAdmin() {
  const currentUser = useStore((state) => state.currentUser);
  const setProjects = useStore((state) => state.setProjects);
  const setCurrentProject = useStore((state) => state.setCurrentProject);
  const setFrames = useStore((state) => state.setFrames);
  const setCurrentFrame = useStore((state) => state.setCurrentFrame);
  const setMasks = useStore((state) => state.setMasks);
  const setSelectedMaskIds = useStore((state) => state.setSelectedMaskIds);
  const [users, setUsers] = useState<AdminUser[]>([]);
  const [auditLogs, setAuditLogs] = useState<AuditLog[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [isSaving, setIsSaving] = useState(false);
  const [isResetting, setIsResetting] = useState(false);
  const [notice, setNotice] = useState<NoticeState | null>(null);
  const [newUsername, setNewUsername] = useState('');
  const [newPassword, setNewPassword] = useState('');
  const [newRole, setNewRole] = useState('annotator');
  const [passwordTarget, setPasswordTarget] = useState<AdminUser | null>(null);
  const [nextPassword, setNextPassword] = useState('');
  const [deleteUserTarget, setDeleteUserTarget] = useState<AdminUser | null>(null);
  const [showFactoryResetConfirm, setShowFactoryResetConfirm] = useState(false);
  const [factoryResetText, setFactoryResetText] = useState('');

  const activeCount = useMemo(() => users.filter((user) => user.is_active).length, [users]);
  const showNotice = (message: string, tone: NoticeTone = 'info') => {
    setNotice({ id: Date.now(), message, tone });
  };

  const loadAdminData = async () => {
    setIsLoading(true);
    try {
      const [nextUsers, nextLogs] = await Promise.all([getAdminUsers(), getAuditLogs(100)]);
      setUsers(nextUsers);
      setAuditLogs(nextLogs);
    } catch (err) {
      console.error('Failed to load admin data:', err);
      showNotice('用户管理数据加载失败', 'error');
    } finally {
      setIsLoading(false);
    }
  };

  useEffect(() => {
    void loadAdminData();
  }, []);

  const handleCreateUser = async (event: React.FormEvent) => {
    event.preventDefault();
    if (!newUsername.trim() || newPassword.length < 6) {
      showNotice('请输入用户名，并设置至少 6 位密码', 'error');
      return;
    }
    setIsSaving(true);
    try {
      const created = await createAdminUser({
        username: newUsername.trim(),
        password: newPassword,
        role: newRole,
        is_active: true,
      });
      setUsers((prev) => [...prev, created]);
      setNewUsername('');
      setNewPassword('');
      setNewRole('annotator');
      showNotice('用户已创建', 'success');
      setAuditLogs(await getAuditLogs(100));
    } catch (err: any) {
      showNotice(err?.response?.data?.detail || '创建用户失败', 'error');
    } finally {
      setIsSaving(false);
    }
  };

  const handlePatchUser = async (user: AdminUser, patch: Parameters<typeof updateAdminUser>[1]) => {
    setIsSaving(true);
    try {
      const updated = await updateAdminUser(user.id, patch);
      setUsers((prev) => prev.map((item) => (item.id === user.id ? updated : item)));
      showNotice('用户已更新', 'success');
      setAuditLogs(await getAuditLogs(100));
      return true;
    } catch (err: any) {
      showNotice(err?.response?.data?.detail || '更新用户失败', 'error');
      return false;
    } finally {
      setIsSaving(false);
    }
  };

  const handleChangePassword = (user: AdminUser) => {
    setPasswordTarget(user);
    setNextPassword('');
  };

  const submitPasswordChange = async () => {
    if (!passwordTarget) return;
    if (nextPassword.length < 6) {
      showNotice('新密码至少需要 6 位', 'error');
      return;
    }
    const updated = await handlePatchUser(passwordTarget, { password: nextPassword });
    if (updated) {
      setPasswordTarget(null);
      setNextPassword('');
    }
  };

  const handleDeleteUser = async () => {
    const user = deleteUserTarget;
    if (!user) return;
    setIsSaving(true);
    try {
      await deleteAdminUser(user.id);
      setUsers((prev) => prev.filter((item) => item.id !== user.id));
      setDeleteUserTarget(null);
      showNotice('用户已删除', 'success');
      setAuditLogs(await getAuditLogs(100));
    } catch (err: any) {
      showNotice(err?.response?.data?.detail || '删除用户失败', 'error');
    } finally {
      setIsSaving(false);
    }
  };

  const handleFactoryReset = async () => {
    if (factoryResetText !== 'RESET_DEMO_FACTORY') {
      showNotice('确认文本不匹配，未执行恢复出厂设置', 'error');
      return;
    }
    setIsResetting(true);
    try {
      const result = await resetDemoFactory(factoryResetText);
      setUsers([result.admin_user]);
      setProjects(result.projects?.length ? result.projects : [result.project]);
      setCurrentProject(null);
      setFrames([]);
      setCurrentFrame(0);
      setMasks([]);
      setSelectedMaskIds([]);
      setAuditLogs(await getAuditLogs(100));
      setShowFactoryResetConfirm(false);
      setFactoryResetText('');
      showNotice(result.message || '演示环境已恢复出厂设置', 'success');
    } catch (err: any) {
      showNotice(err?.response?.data?.detail || '恢复演示出厂设置失败', 'error');
    } finally {
      setIsResetting(false);
    }
  };

  return (
    <div className="flex h-full flex-col overflow-hidden bg-[#0a0a0a] text-gray-200">
      <TransientNotice notice={notice} onDismiss={() => setNotice(null)} />
      <header className="border-b border-white/10 bg-[#0d0d0d] px-6 py-4">
        <div className="flex items-center justify-between gap-4">
          <div>
            <h1 className="text-xl font-semibold text-white">用户管理后台</h1>
            <p className="mt-1 text-xs text-gray-500">账号、角色、状态和安全审计</p>
          </div>
          <div className="flex items-center gap-3 text-xs text-gray-400">
            <span className="rounded border border-cyan-400/20 bg-cyan-400/10 px-3 py-1 text-cyan-100">
              当前管理员：{currentUser?.username || 'admin'}
            </span>
            <span className="rounded border border-white/10 bg-white/5 px-3 py-1">启用用户 {activeCount}</span>
          </div>
        </div>
      </header>

      <main className="grid min-h-0 flex-1 grid-cols-[minmax(0,1.15fr)_minmax(360px,0.85fr)] gap-4 overflow-hidden p-4">
        <section className="flex min-h-0 flex-col overflow-hidden rounded-lg border border-white/10 bg-[#111]">
          <div className="flex items-center justify-between border-b border-white/10 px-4 py-3">
            <div className="flex items-center gap-2 text-sm font-medium text-white">
              <UserCog size={18} className="text-cyan-300" />
              用户与权限
            </div>
            {isLoading && <Loader2 size={16} className="animate-spin text-cyan-300" />}
          </div>

          <form onSubmit={handleCreateUser} className="grid grid-cols-[1fr_1fr_150px_auto] gap-2 border-b border-white/10 p-4">
            <input
              value={newUsername}
              onChange={(event) => setNewUsername(event.target.value)}
              placeholder="用户名"
              autoComplete="off"
              className="rounded border border-white/10 bg-[#181818] px-3 py-2 text-sm text-white outline-none focus:border-cyan-400/50"
            />
            <input
              value={newPassword}
              type="password"
              onChange={(event) => setNewPassword(event.target.value)}
              placeholder="初始密码"
              autoComplete="new-password"
              className="rounded border border-white/10 bg-[#181818] px-3 py-2 text-sm text-white outline-none focus:border-cyan-400/50"
            />
            <select
              value={newRole}
              onChange={(event) => setNewRole(event.target.value)}
              className="rounded border border-white/10 bg-[#181818] px-3 py-2 text-sm text-white outline-none focus:border-cyan-400/50"
            >
              <option value="annotator">标注员</option>
              <option value="viewer">观察员</option>
              <option value="admin">管理员</option>
            </select>
            <button
              type="submit"
              disabled={isSaving}
              className="inline-flex items-center gap-2 rounded bg-cyan-500 px-4 py-2 text-sm font-semibold text-black transition-colors hover:bg-cyan-400 disabled:opacity-50"
            >
              <Plus size={16} />
              新增用户
            </button>
          </form>

          <div className="min-h-0 flex-1 overflow-auto">
            <table className="w-full text-left text-sm">
              <thead className="sticky top-0 bg-[#151515] text-xs uppercase text-gray-500">
                <tr>
                  <th className="px-4 py-3">用户</th>
                  <th className="px-4 py-3">角色</th>
                  <th className="px-4 py-3">状态</th>
                  <th className="px-4 py-3 text-right">操作</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-white/5">
                {users.map((user) => (
                  <tr key={user.id} className="hover:bg-white/[0.03]">
                    <td className="px-4 py-3">
                      <div className="font-medium text-white">{user.username}</div>
                      <div className="text-xs text-gray-500">ID {user.id}</div>
                    </td>
                    <td className="px-4 py-3">
                      <select
                        value={user.role}
                        onChange={(event) => void handlePatchUser(user, { role: event.target.value })}
                        disabled={isSaving}
                        className="rounded border border-white/10 bg-[#181818] px-2 py-1 text-xs text-cyan-100"
                      >
                        <option value="admin">管理员</option>
                        <option value="annotator">标注员</option>
                        <option value="viewer">观察员</option>
                      </select>
                    </td>
                    <td className="px-4 py-3">
                      <button
                        type="button"
                        onClick={() => void handlePatchUser(user, { is_active: !user.is_active })}
                        disabled={isSaving}
                        className={cn(
                          'rounded-full border px-3 py-1 text-xs',
                          user.is_active
                            ? 'border-emerald-400/30 bg-emerald-400/10 text-emerald-200'
                            : 'border-gray-500/30 bg-gray-500/10 text-gray-300',
                        )}
                      >
                        {user.is_active ? '启用' : '停用'}
                      </button>
                    </td>
                    <td className="px-4 py-3">
                      <div className="flex justify-end gap-2">
                        <button
                          type="button"
                          onClick={() => handleChangePassword(user)}
                          className="rounded border border-white/10 p-2 text-gray-300 hover:border-cyan-400/40 hover:text-cyan-200"
                          title="修改密码"
                        >
                          <KeyRound size={15} />
                        </button>
                        <button
                          type="button"
                          onClick={() => setDeleteUserTarget(user)}
                          disabled={user.id === currentUser?.id}
                          className="rounded border border-white/10 p-2 text-gray-300 hover:border-red-400/40 hover:text-red-200 disabled:cursor-not-allowed disabled:opacity-40"
                          title="删除用户"
                        >
                          <Trash2 size={15} />
                        </button>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </section>

        <section className="flex min-h-0 flex-col overflow-hidden rounded-lg border border-white/10 bg-[#111]">
          <div className="flex items-center gap-2 border-b border-white/10 px-4 py-3 text-sm font-medium text-white">
            <ShieldCheck size={18} className="text-emerald-300" />
            审计日志
          </div>
          <div className="min-h-0 flex-1 overflow-auto p-3">
            <div className="space-y-2">
              {auditLogs.map((log) => (
                <div key={log.id} className="rounded border border-white/10 bg-black/20 p-3">
                  <div className="flex items-center justify-between gap-2">
                    <span className="text-xs font-medium text-cyan-100">{log.action}</span>
                    <span className="text-[10px] text-gray-500">{formatTime(log.created_at)}</span>
                  </div>
                  <div className="mt-1 text-[11px] text-gray-400">
                    actor #{log.actor_user_id ?? 'system'} {'->'} {log.target_type || 'target'} #{log.target_id || '-'}
                  </div>
                  {log.detail && Object.keys(log.detail).length > 0 && (
                    <pre className="mt-2 max-h-24 overflow-auto rounded bg-black/30 p-2 text-[10px] leading-relaxed text-gray-500">
                      {JSON.stringify(log.detail, null, 2)}
                    </pre>
                  )}
                </div>
              ))}
              {!auditLogs.length && !isLoading && (
                <div className="py-10 text-center text-sm text-gray-500">暂无审计记录</div>
              )}
            </div>
          </div>
          <div className="border-t border-red-400/20 bg-red-950/10 p-4">
            <div className="flex items-start justify-between gap-3">
              <div>
                <div className="text-sm font-semibold text-red-100">演示环境出厂设置</div>
                <p className="mt-1 text-xs leading-relaxed text-red-200/70">
                  清空演示过程产生的用户、项目帧、标注、任务和私有模板，只保留默认 admin、演示视频项目和一个已按文件名顺序生成帧的演示 DICOM 项目。
                </p>
              </div>
              <button
                type="button"
                onClick={() => {
                  setFactoryResetText('');
                  setShowFactoryResetConfirm(true);
                }}
                disabled={isResetting || isSaving}
                className="shrink-0 rounded border border-red-400/40 bg-red-500/15 px-3 py-2 text-xs font-semibold text-red-100 transition-colors hover:bg-red-500/25 disabled:cursor-wait disabled:opacity-50"
              >
                {isResetting ? '恢复中...' : '恢复演示出厂设置'}
              </button>
            </div>
          </div>
        </section>
      </main>

      {passwordTarget && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 px-4">
          <div className="w-full max-w-sm rounded-lg border border-white/10 bg-[#151515] p-5 shadow-2xl">
            <h2 className="text-lg font-semibold text-white">修改密码</h2>
            <p className="mt-2 text-sm leading-relaxed text-gray-400">
              为用户“<span className="text-gray-100">{passwordTarget.username}</span>”设置新密码。
            </p>
            <input
              type="password"
              value={nextPassword}
              onChange={(event) => setNextPassword(event.target.value)}
              autoComplete="new-password"
              placeholder="至少 6 位"
              className="mt-4 w-full rounded border border-white/10 bg-black/30 px-3 py-2 text-sm text-white outline-none focus:border-cyan-400/50"
            />
            <div className="mt-5 flex justify-end gap-2">
              <button
                type="button"
                onClick={() => {
                  setPasswordTarget(null);
                  setNextPassword('');
                }}
                disabled={isSaving}
                className="rounded border border-white/10 px-3 py-2 text-xs text-gray-300 hover:bg-white/5 disabled:opacity-50"
              >
                取消
              </button>
              <button
                type="button"
                onClick={() => void submitPasswordChange()}
                disabled={isSaving || nextPassword.length < 6}
                className="inline-flex items-center gap-2 rounded bg-cyan-500 px-3 py-2 text-xs font-semibold text-black hover:bg-cyan-400 disabled:cursor-not-allowed disabled:opacity-50"
              >
                {isSaving && <Loader2 size={14} className="animate-spin" />}
                确认修改
              </button>
            </div>
          </div>
        </div>
      )}

      {deleteUserTarget && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 px-4">
          <div className="w-full max-w-sm rounded-lg border border-red-400/20 bg-[#151515] p-5 shadow-2xl">
            <h2 className="text-lg font-semibold text-white">删除用户</h2>
            <p className="mt-2 text-sm leading-relaxed text-gray-400">
              确认删除用户“<span className="text-gray-100">{deleteUserTarget.username}</span>”？已有项目的用户建议先停用。
            </p>
            <div className="mt-5 flex justify-end gap-2">
              <button
                type="button"
                onClick={() => setDeleteUserTarget(null)}
                disabled={isSaving}
                className="rounded border border-white/10 px-3 py-2 text-xs text-gray-300 hover:bg-white/5 disabled:opacity-50"
              >
                取消
              </button>
              <button
                type="button"
                onClick={() => void handleDeleteUser()}
                disabled={isSaving}
                className="inline-flex items-center gap-2 rounded bg-red-500 px-3 py-2 text-xs font-semibold text-white hover:bg-red-400 disabled:cursor-wait disabled:opacity-50"
              >
                {isSaving && <Loader2 size={14} className="animate-spin" />}
                确认删除
              </button>
            </div>
          </div>
        </div>
      )}

      {showFactoryResetConfirm && (
        <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/75 px-4">
          <div className="w-full max-w-lg rounded-lg border border-red-400/25 bg-[#151515] p-5 shadow-2xl">
            <h2 className="text-lg font-semibold text-white">恢复演示出厂设置</h2>
            <p className="mt-2 text-sm leading-relaxed text-red-100/80">
              该操作会删除除默认 admin 外的所有用户、项目帧、标注、任务和私有模板，只保留演示视频项目和已按文件名顺序生成帧的演示 DICOM 项目。
            </p>
            <label className="mt-4 block text-xs text-gray-400" htmlFor="factory-reset-confirm">
              输入 RESET_DEMO_FACTORY 确认
            </label>
            <input
              id="factory-reset-confirm"
              value={factoryResetText}
              onChange={(event) => setFactoryResetText(event.target.value)}
              className="mt-2 w-full rounded border border-white/10 bg-black/30 px-3 py-2 text-sm text-white outline-none focus:border-red-400/50"
            />
            <div className="mt-5 flex justify-end gap-2">
              <button
                type="button"
                onClick={() => {
                  setShowFactoryResetConfirm(false);
                  setFactoryResetText('');
                }}
                disabled={isResetting}
                className="rounded border border-white/10 px-3 py-2 text-xs text-gray-300 hover:bg-white/5 disabled:opacity-50"
              >
                取消
              </button>
              <button
                type="button"
                onClick={() => void handleFactoryReset()}
                disabled={isResetting || factoryResetText !== 'RESET_DEMO_FACTORY'}
                className="inline-flex items-center gap-2 rounded bg-red-500 px-3 py-2 text-xs font-semibold text-white hover:bg-red-400 disabled:cursor-not-allowed disabled:opacity-50"
              >
                {isResetting && <Loader2 size={14} className="animate-spin" />}
                确认恢复
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}
