import { useState, useEffect, useCallback, useRef } from 'react';
import {
  fetchUsers,
  fetchRoles,
  fetchOrgs,
  createUserApi,
  updateUserApi,
  changePasswordApi,
  approveUserApi,
  rejectUserApi,
  assignRolesApi,
  type UserListItem,
  type RoleWithPermissions,
  type OrgItem,
} from '@common/services/authApi';
import { getRoleColor, statusLabels } from './adminConstants';

const PAGE_SIZE = 15;

// ─── 포맷 헬퍼 ─────────────────────────────────────────────────
function formatDate(dateStr: string | null) {
  if (!dateStr) return '-';
  return new Date(dateStr).toLocaleString('ko-KR', {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
  });
}

// ─── 사용자 등록 모달 ───────────────────────────────────────────
interface RegisterModalProps {
  allRoles: RoleWithPermissions[];
  allOrgs: OrgItem[];
  onClose: () => void;
  onSuccess: () => void;
}

function RegisterModal({ allRoles, allOrgs, onClose, onSuccess }: RegisterModalProps) {
  const [account, setAccount] = useState('');
  const [password, setPassword] = useState('');
  const [name, setName] = useState('');
  const [rank, setRank] = useState('');
  const [orgSn, setOrgSn] = useState<number | ''>(() => {
    const defaultOrg = allOrgs.find((o) => o.orgNm === '기동방제과');
    return defaultOrg ? defaultOrg.orgSn : '';
  });
  const [email, setEmail] = useState('');
  const [roleSns, setRoleSns] = useState<number[]>([]);
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const toggleRole = (sn: number) => {
    setRoleSns((prev) => (prev.includes(sn) ? prev.filter((s) => s !== sn) : [...prev, sn]));
  };

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!account.trim() || !password.trim() || !name.trim()) {
      setError('계정, 비밀번호, 사용자명은 필수 항목입니다.');
      return;
    }
    setSubmitting(true);
    setError(null);
    try {
      await createUserApi({
        account: account.trim(),
        password,
        name: name.trim(),
        rank: rank.trim() || undefined,
        orgSn: orgSn !== '' ? orgSn : undefined,
        roleSns: roleSns.length > 0 ? roleSns : undefined,
      });
      onSuccess();
      onClose();
    } catch (err) {
      setError('사용자 등록에 실패했습니다.');
      console.error('사용자 등록 실패:', err);
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm">
      <div className="bg-bg-surface border border-stroke rounded-lg shadow-lg w-[480px] max-h-[90vh] flex flex-col">
        {/* 헤더 */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-stroke">
          <h2 className="text-body-2 font-bold text-fg font-korean">사용자 등록</h2>
          <button onClick={onClose} className="text-fg-disabled hover:text-fg transition-colors">
            <svg
              width="16"
              height="16"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              strokeWidth="2.5"
            >
              <path d="M18 6L6 18M6 6l12 12" />
            </svg>
          </button>
        </div>

        {/* 폼 */}
        <form onSubmit={handleSubmit} className="flex-1 overflow-y-auto">
          <div className="px-6 py-4 space-y-4">
            {/* 계정 */}
            <div>
              <label className="block text-label-2 font-semibold text-fg-sub font-korean mb-1.5">
                계정 <span className="text-red-400">*</span>
              </label>
              <input
                type="text"
                value={account}
                onChange={(e) => setAccount(e.target.value)}
                placeholder="로그인 계정 ID"
                className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono"
              />
            </div>

            {/* 비밀번호 */}
            <div>
              <label className="block text-label-2 font-semibold text-fg-sub font-korean mb-1.5">
                비밀번호 <span className="text-red-400">*</span>
              </label>
              <input
                type="password"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                placeholder="초기 비밀번호"
                className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono"
              />
            </div>

            {/* 사용자명 */}
            <div>
              <label className="block text-label-2 font-semibold text-fg-sub font-korean mb-1.5">
                사용자명 <span className="text-red-400">*</span>
              </label>
              <input
                type="text"
                value={name}
                onChange={(e) => setName(e.target.value)}
                placeholder="실명"
                className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-korean"
              />
            </div>

            {/* 직급 */}
            <div>
              <label className="block text-label-2 font-semibold text-fg-sub font-korean mb-1.5">
                직급
              </label>
              <input
                type="text"
                value={rank}
                onChange={(e) => setRank(e.target.value)}
                placeholder="예: 팀장, 주임 등"
                className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-korean"
              />
            </div>

            {/* 소속 */}
            <div>
              <label className="block text-label-2 font-semibold text-fg-sub font-korean mb-1.5">
                소속
              </label>
              <select
                value={orgSn}
                onChange={(e) => setOrgSn(e.target.value !== '' ? Number(e.target.value) : '')}
                className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg focus:border-color-accent focus:outline-none font-korean"
              >
                <option value="">소속 없음</option>
                {allOrgs.map((org) => (
                  <option key={org.orgSn} value={org.orgSn}>
                    {org.orgNm}
                    {org.orgAbbrNm ? ` (${org.orgAbbrNm})` : ''}
                  </option>
                ))}
              </select>
            </div>

            {/* 이메일 */}
            <div>
              <label className="block text-label-2 font-semibold text-fg-sub font-korean mb-1.5">
                이메일
              </label>
              <input
                type="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                placeholder="이메일 주소"
                className="w-full px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono"
              />
            </div>

            {/* 역할 */}
            <div>
              <label className="block text-label-2 font-semibold text-fg-sub font-korean mb-1.5">
                역할
              </label>
              <div className="bg-bg-elevated border border-stroke rounded-md p-2 space-y-1 max-h-[120px] overflow-y-auto">
                {allRoles.length === 0 ? (
                  <p className="text-caption text-fg-disabled font-korean px-1 py-1">역할 없음</p>
                ) : (
                  allRoles.map((role, idx) => {
                    const color = getRoleColor(role.code, idx);
                    return (
                      <label
                        key={role.sn}
                        className="flex items-center gap-2 px-2 py-1.5 hover:bg-[rgba(255,255,255,0.04)] rounded cursor-pointer"
                      >
                        <input
                          type="checkbox"
                          checked={roleSns.includes(role.sn)}
                          onChange={() => toggleRole(role.sn)}
                          style={{ accentColor: color }}
                        />
                        <span className="text-caption font-korean" style={{ color }}>
                          {role.name}
                        </span>
                        <span className="text-caption text-fg-disabled font-mono">{role.code}</span>
                      </label>
                    );
                  })
                )}
              </div>
            </div>

            {/* 에러 메시지 */}
            {error && <p className="text-label-2 text-red-400 font-korean">{error}</p>}
          </div>

          {/* 푸터 */}
          <div className="flex items-center justify-end gap-2 px-6 py-4 border-t border-stroke">
            <button
              type="button"
              onClick={onClose}
              className="px-4 py-2 text-caption border border-stroke text-fg-sub rounded-md hover:bg-[rgba(255,255,255,0.04)] transition-all font-korean"
            >
              취소
            </button>
            <button
              type="submit"
              disabled={submitting}
              className="px-4 py-2 text-caption font-semibold rounded-md bg-color-accent text-bg-0 hover:shadow-[0_0_12px_rgba(6,182,212,0.3)] transition-all disabled:opacity-50 font-korean"
            >
              {submitting ? '등록 중...' : '등록'}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}

// ─── 사용자 상세/수정 모달 ────────────────────────────────────
interface UserDetailModalProps {
  user: UserListItem;
  allRoles: RoleWithPermissions[];
  allOrgs: OrgItem[];
  onClose: () => void;
  onUpdated: () => void;
}

function UserDetailModal({ user, allOrgs, onClose, onUpdated }: UserDetailModalProps) {
  const [name, setName] = useState(user.name);
  const [rank, setRank] = useState(user.rank || '');
  const [orgSn, setOrgSn] = useState<number | ''>(user.orgSn ?? '');
  const [saving, setSaving] = useState(false);
  const [newPassword, setNewPassword] = useState('');
  const [resetPwLoading, setResetPwLoading] = useState(false);
  const [resetPwDone, setResetPwDone] = useState(false);
  const [unlockLoading, setUnlockLoading] = useState(false);
  const [message, setMessage] = useState<{ text: string; type: 'success' | 'error' } | null>(null);

  const handleSaveInfo = async () => {
    setSaving(true);
    setMessage(null);
    try {
      await updateUserApi(user.id, {
        name: name.trim(),
        rank: rank.trim() || undefined,
        orgSn: orgSn !== '' ? orgSn : null,
      });
      setMessage({ text: '사용자 정보가 수정되었습니다.', type: 'success' });
      onUpdated();
    } catch {
      setMessage({ text: '사용자 정보 수정에 실패했습니다.', type: 'error' });
    } finally {
      setSaving(false);
    }
  };

  const handleResetPassword = async () => {
    if (!newPassword.trim()) {
      setMessage({ text: '새 비밀번호를 입력하세요.', type: 'error' });
      return;
    }
    setResetPwLoading(true);
    setMessage(null);
    try {
      await changePasswordApi(user.id, newPassword);
      setMessage({ text: '비밀번호가 초기화되었습니다.', type: 'success' });
      setResetPwDone(true);
      setNewPassword('');
    } catch {
      setMessage({ text: '비밀번호 초기화에 실패했습니다.', type: 'error' });
    } finally {
      setResetPwLoading(false);
    }
  };

  const handleUnlock = async () => {
    setUnlockLoading(true);
    setMessage(null);
    try {
      await updateUserApi(user.id, { status: 'ACTIVE' });
      setMessage({ text: '계정 잠금이 해제되었습니다.', type: 'success' });
      onUpdated();
    } catch {
      setMessage({ text: '잠금 해제에 실패했습니다.', type: 'error' });
    } finally {
      setUnlockLoading(false);
    }
  };

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm">
      <div className="bg-bg-surface border border-stroke rounded-lg shadow-lg w-[480px] max-h-[90vh] flex flex-col">
        {/* 헤더 */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-stroke">
          <div>
            <h2 className="text-body-2 font-bold text-fg font-korean">사용자 정보</h2>
            <p className="text-caption text-fg-disabled font-mono mt-0.5">{user.account}</p>
          </div>
          <button onClick={onClose} className="text-fg-disabled hover:text-fg transition-colors">
            <svg
              width="16"
              height="16"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              strokeWidth="2.5"
            >
              <path d="M18 6L6 18M6 6l12 12" />
            </svg>
          </button>
        </div>

        <div className="flex-1 overflow-y-auto px-6 py-4 space-y-5">
          {/* 기본 정보 수정 */}
          <div>
            <h3 className="text-label-2 font-semibold text-fg-sub font-korean mb-3">
              기본 정보 수정
            </h3>
            <div className="space-y-3">
              <div>
                <label className="block text-caption text-fg-disabled font-korean mb-1">
                  사용자명
                </label>
                <input
                  type="text"
                  value={name}
                  onChange={(e) => setName(e.target.value)}
                  className="w-full px-3 py-1.5 text-caption bg-bg-elevated border border-stroke rounded-md text-fg focus:border-color-accent focus:outline-none font-korean"
                />
              </div>
              <div className="grid grid-cols-2 gap-3">
                <div>
                  <label className="block text-caption text-fg-disabled font-korean mb-1">
                    직급
                  </label>
                  <input
                    type="text"
                    value={rank}
                    onChange={(e) => setRank(e.target.value)}
                    placeholder="예: 팀장"
                    className="w-full px-3 py-1.5 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-korean"
                  />
                </div>
                <div>
                  <label className="block text-caption text-fg-disabled font-korean mb-1">
                    소속
                  </label>
                  <select
                    value={orgSn}
                    onChange={(e) => setOrgSn(e.target.value !== '' ? Number(e.target.value) : '')}
                    className="w-full px-3 py-1.5 text-caption bg-bg-elevated border border-stroke rounded-md text-fg focus:border-color-accent focus:outline-none font-korean"
                  >
                    <option value="">소속 없음</option>
                    {allOrgs.map((org) => (
                      <option key={org.orgSn} value={org.orgSn}>
                        {org.orgNm}
                        {org.orgAbbrNm ? ` (${org.orgAbbrNm})` : ''}
                      </option>
                    ))}
                  </select>
                </div>
              </div>
              <button
                onClick={handleSaveInfo}
                disabled={saving || !name.trim()}
                className="px-4 py-1.5 text-label-2 font-semibold rounded-md bg-color-accent text-bg-0 hover:shadow-[0_0_12px_rgba(6,182,212,0.3)] transition-all disabled:opacity-50 font-korean"
              >
                {saving ? '저장 중...' : '정보 저장'}
              </button>
            </div>
          </div>

          {/* 구분선 */}
          <div className="border-t border-stroke" />

          {/* 비밀번호 초기화 */}
          <div>
            <h3 className="text-label-2 font-semibold text-fg-sub font-korean mb-3">
              비밀번호 초기화
            </h3>
            <div className="flex items-end gap-2">
              <div className="flex-1">
                <label className="block text-caption text-fg-disabled font-korean mb-1">
                  새 비밀번호
                </label>
                <input
                  type="password"
                  value={newPassword}
                  onChange={(e) => setNewPassword(e.target.value)}
                  placeholder="새 비밀번호 입력"
                  className="w-full px-3 py-1.5 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-mono"
                />
              </div>
              <button
                onClick={handleResetPassword}
                disabled={resetPwLoading || !newPassword.trim()}
                className="px-4 py-1.5 text-label-2 font-semibold rounded-md border border-yellow-400 text-yellow-400 hover:bg-[rgba(250,204,21,0.1)] transition-all disabled:opacity-50 font-korean flex-shrink-0"
              >
                {resetPwLoading ? '초기화 중...' : resetPwDone ? '초기화 완료' : '비밀번호 초기화'}
              </button>
              <button
                onClick={handleUnlock}
                disabled={unlockLoading || user.status !== 'LOCKED'}
                className="px-4 py-1.5 text-label-2 font-semibold rounded-md border border-green-400 text-green-400 hover:bg-[rgba(74,222,128,0.1)] transition-all disabled:opacity-50 font-korean flex-shrink-0"
                title={user.status !== 'LOCKED' ? '잠금 상태가 아닙니다' : ''}
              >
                {unlockLoading ? '해제 중...' : '패스워드잠금해제'}
              </button>
            </div>
            <p className="text-caption text-fg-disabled font-korean mt-1.5">
              초기화 후 사용자에게 새 비밀번호를 전달하세요.
            </p>
          </div>

          {/* 구분선 */}
          <div className="border-t border-stroke" />

          {/* 계정 잠금 해제 */}
          <div>
            <h3 className="text-label-2 font-semibold text-fg-sub font-korean mb-2">계정 상태</h3>
            <div className="flex items-center justify-between bg-bg-elevated border border-stroke rounded-md px-4 py-3">
              <div>
                <div className="flex items-center gap-2">
                  <span
                    className={`inline-flex items-center gap-1.5 text-label-2 font-semibold font-korean ${(statusLabels[user.status] || statusLabels.INACTIVE).color}`}
                  >
                    <span
                      className={`w-1.5 h-1.5 rounded-full ${(statusLabels[user.status] || statusLabels.INACTIVE).dot}`}
                    />
                    {(statusLabels[user.status] || statusLabels.INACTIVE).label}
                  </span>
                  {user.failCount > 0 && (
                    <span className="text-caption text-red-400 font-korean">
                      (로그인 실패 {user.failCount}회)
                    </span>
                  )}
                </div>
                {user.status === 'LOCKED' && (
                  <p className="text-caption text-fg-disabled font-korean mt-1">
                    비밀번호 5회 이상 오류로 잠금 처리됨
                  </p>
                )}
              </div>
              {user.status === 'LOCKED' && (
                <button
                  onClick={handleUnlock}
                  disabled={unlockLoading}
                  className="px-4 py-1.5 text-label-2 font-semibold rounded-md border border-green-400 text-green-400 hover:bg-[rgba(74,222,128,0.1)] transition-all disabled:opacity-50 font-korean flex-shrink-0"
                >
                  {unlockLoading ? '해제 중...' : '잠금 해제'}
                </button>
              )}
            </div>
          </div>

          {/* 기타 정보 (읽기 전용) */}
          <div>
            <h3 className="text-label-2 font-semibold text-fg-sub font-korean mb-2">기타 정보</h3>
            <div className="grid grid-cols-2 gap-2 text-caption font-korean">
              <div className="bg-bg-elevated border border-stroke rounded px-3 py-2">
                <span className="text-fg-disabled">이메일: </span>
                <span className="text-fg-sub font-mono">{user.email || '-'}</span>
              </div>
              <div className="bg-bg-elevated border border-stroke rounded px-3 py-2">
                <span className="text-fg-disabled">OAuth: </span>
                <span className="text-fg-sub">{user.oauthProvider || '-'}</span>
              </div>
              <div className="bg-bg-elevated border border-stroke rounded px-3 py-2">
                <span className="text-fg-disabled">최종 로그인: </span>
                <span className="text-fg-sub">
                  {user.lastLogin ? formatDate(user.lastLogin) : '-'}
                </span>
              </div>
              <div className="bg-bg-elevated border border-stroke rounded px-3 py-2">
                <span className="text-fg-disabled">등록일: </span>
                <span className="text-fg-sub">{formatDate(user.regDtm)}</span>
              </div>
            </div>
          </div>

          {/* 메시지 */}
          {message && (
            <div
              className={`px-3 py-2 text-label-2 rounded-md font-korean ${
                message.type === 'success'
                  ? 'text-green-400 bg-[rgba(74,222,128,0.08)] border border-[rgba(74,222,128,0.2)]'
                  : 'text-red-400 bg-[rgba(239,68,68,0.08)] border border-[rgba(239,68,68,0.2)]'
              }`}
            >
              {message.text}
            </div>
          )}
        </div>

        {/* 푸터 */}
        <div className="flex items-center justify-end px-6 py-3 border-t border-stroke">
          <button
            onClick={onClose}
            className="px-4 py-2 text-caption border border-stroke text-fg-sub rounded-md hover:bg-[rgba(255,255,255,0.04)] transition-all font-korean"
          >
            닫기
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── 사용자 관리 패널 ─────────────────────────────────────────
function UsersPanel() {
  const [searchTerm, setSearchTerm] = useState('');
  const [statusFilter, setStatusFilter] = useState<string>('');
  const [orgFilter, setOrgFilter] = useState<string>('');
  const [users, setUsers] = useState<UserListItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [allRoles, setAllRoles] = useState<RoleWithPermissions[]>([]);
  const [allOrgs, setAllOrgs] = useState<OrgItem[]>([]);
  const [roleEditUserId, setRoleEditUserId] = useState<string | null>(null);
  const [selectedRoleSns, setSelectedRoleSns] = useState<number[]>([]);
  const [showRegisterModal, setShowRegisterModal] = useState(false);
  const [detailUser, setDetailUser] = useState<UserListItem | null>(null);
  const [currentPage, setCurrentPage] = useState(1);
  const roleDropdownRef = useRef<HTMLDivElement>(null);

  const loadUsers = useCallback(async () => {
    setLoading(true);
    try {
      const data = await fetchUsers(searchTerm || undefined, statusFilter || undefined);
      setUsers(data);
      setCurrentPage(1);
    } catch (err) {
      console.error('사용자 목록 조회 실패:', err);
    } finally {
      setLoading(false);
    }
  }, [searchTerm, statusFilter]);

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

  useEffect(() => {
    fetchRoles().then(setAllRoles).catch(console.error);
    fetchOrgs().then(setAllOrgs).catch(console.error);
  }, []);

  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (roleDropdownRef.current && !roleDropdownRef.current.contains(e.target as Node)) {
        setRoleEditUserId(null);
      }
    };
    if (roleEditUserId) {
      document.addEventListener('mousedown', handleClickOutside);
    }
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, [roleEditUserId]);

  // ─── 필터링 (org 클라이언트 사이드) ───────────────────────────
  const filteredUsers = orgFilter ? users.filter((u) => String(u.orgSn) === orgFilter) : users;

  // ─── 페이지네이션 ──────────────────────────────────────────────
  const totalCount = filteredUsers.length;
  const totalPages = Math.max(1, Math.ceil(totalCount / PAGE_SIZE));
  const pagedUsers = filteredUsers.slice((currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE);

  // ─── 액션 핸들러 ──────────────────────────────────────────────
  const handleUnlock = async (userId: string) => {
    try {
      await updateUserApi(userId, { status: 'ACTIVE' });
      await loadUsers();
    } catch (err) {
      console.error('계정 잠금 해제 실패:', err);
    }
  };

  const handleApprove = async (userId: string) => {
    try {
      await approveUserApi(userId);
      await loadUsers();
    } catch (err) {
      console.error('사용자 승인 실패:', err);
    }
  };

  const handleReject = async (userId: string) => {
    try {
      await rejectUserApi(userId);
      await loadUsers();
    } catch (err) {
      console.error('사용자 거절 실패:', err);
    }
  };

  const handleDeactivate = async (userId: string) => {
    try {
      await updateUserApi(userId, { status: 'INACTIVE' });
      await loadUsers();
    } catch (err) {
      console.error('사용자 비활성화 실패:', err);
    }
  };

  const handleActivate = async (userId: string) => {
    try {
      await updateUserApi(userId, { status: 'ACTIVE' });
      await loadUsers();
    } catch (err) {
      console.error('사용자 활성화 실패:', err);
    }
  };

  const handleOpenRoleEdit = (user: UserListItem) => {
    setRoleEditUserId(user.id);
    setSelectedRoleSns(user.roleSns || []);
  };

  const toggleRoleSelection = (roleSn: number) => {
    setSelectedRoleSns((prev) =>
      prev.includes(roleSn) ? prev.filter((s) => s !== roleSn) : [...prev, roleSn],
    );
  };

  const handleSaveRoles = async (userId: string) => {
    try {
      await assignRolesApi(userId, selectedRoleSns);
      await loadUsers();
      setRoleEditUserId(null);
    } catch (err) {
      console.error('역할 할당 실패:', err);
    }
  };

  const pendingCount = users.filter((u) => u.status === 'PENDING').length;

  return (
    <>
      <div className="flex flex-col h-full">
        {/* 헤더 */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-stroke">
          <div className="flex items-center gap-3">
            <div>
              <h1 className="text-lg font-bold text-fg font-korean">사용자 관리</h1>
              <p className="text-caption text-fg-disabled mt-1 font-korean">
                총 {filteredUsers.length}명
              </p>
            </div>
            {pendingCount > 0 && (
              <span className="px-2.5 py-1 text-caption font-bold rounded-full bg-[rgba(250,204,21,0.15)] text-yellow-400 border border-[rgba(250,204,21,0.3)] animate-pulse font-korean">
                승인대기 {pendingCount}명
              </span>
            )}
          </div>
          <div className="flex items-center gap-3">
            {/* 소속 필터 */}
            <select
              value={orgFilter}
              onChange={(e) => {
                setOrgFilter(e.target.value);
                setCurrentPage(1);
              }}
              className="px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg focus:border-color-accent focus:outline-none font-korean"
            >
              <option value="">전체 소속</option>
              {allOrgs.map((org) => (
                <option key={org.orgSn} value={String(org.orgSn)}>
                  {org.orgAbbrNm || org.orgNm}
                </option>
              ))}
            </select>
            {/* 상태 필터 */}
            <select
              value={statusFilter}
              onChange={(e) => setStatusFilter(e.target.value)}
              className="px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg focus:border-color-accent focus:outline-none font-korean"
            >
              <option value="">전체 상태</option>
              <option value="PENDING">승인대기</option>
              <option value="ACTIVE">활성</option>
              <option value="LOCKED">잠김</option>
              <option value="INACTIVE">비활성</option>
              <option value="REJECTED">거절됨</option>
            </select>
            {/* 텍스트 검색 */}
            <input
              type="text"
              placeholder="이름, 계정 검색..."
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              className="w-56 px-3 py-2 text-caption bg-bg-elevated border border-stroke rounded-md text-fg placeholder-fg-disabled focus:border-color-accent focus:outline-none font-korean"
            />
            <button
              onClick={() => setShowRegisterModal(true)}
              className="px-4 py-2 text-caption font-semibold rounded-md bg-color-accent text-bg-0 hover:shadow-[0_0_12px_rgba(6,182,212,0.3)] transition-all font-korean"
            >
              + 사용자 등록
            </button>
          </div>
        </div>

        {/* 테이블 */}
        <div className="flex-1 overflow-auto">
          {loading ? (
            <div className="flex items-center justify-center h-32 text-fg-disabled text-body-2 font-korean">
              불러오는 중...
            </div>
          ) : (
            <table className="w-full">
              <thead>
                <tr className="border-b border-stroke bg-bg-surface">
                  <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean w-10">
                    번호
                  </th>
                  <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-mono">
                    ID
                  </th>
                  <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean">
                    사용자명
                  </th>
                  <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean">
                    직급
                  </th>
                  <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean">
                    소속
                  </th>
                  <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean">
                    이메일
                  </th>
                  <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean">
                    역할
                  </th>
                  <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean">
                    승인상태
                  </th>
                  <th className="px-4 py-3 text-right text-label-2 font-semibold text-fg-disabled font-korean">
                    관리
                  </th>
                </tr>
              </thead>
              <tbody>
                {pagedUsers.length === 0 ? (
                  <tr>
                    <td
                      colSpan={9}
                      className="px-6 py-10 text-center text-caption text-fg-disabled font-korean"
                    >
                      조회된 사용자가 없습니다.
                    </td>
                  </tr>
                ) : (
                  pagedUsers.map((user, idx) => {
                    const statusInfo = statusLabels[user.status] || statusLabels.INACTIVE;
                    const rowNum = (currentPage - 1) * PAGE_SIZE + idx + 1;
                    return (
                      <tr
                        key={user.id}
                        className="border-b border-stroke hover:bg-[rgba(255,255,255,0.02)] transition-colors"
                      >
                        {/* 번호 */}
                        <td className="px-4 py-3 text-label-2 text-fg-disabled font-mono text-center">
                          {rowNum}
                        </td>

                        {/* ID(account) */}
                        <td className="px-4 py-3 text-label-1 text-fg-sub font-mono">
                          {user.account}
                        </td>

                        {/* 사용자명 */}
                        <td className="px-4 py-3">
                          <button
                            onClick={() => setDetailUser(user)}
                            className="text-label-1 text-color-accent font-semibold font-korean hover:underline"
                          >
                            {user.name}
                          </button>
                        </td>

                        {/* 직급 */}
                        <td className="px-4 py-3 text-label-1 text-fg-sub font-korean">
                          {user.rank || '-'}
                        </td>

                        {/* 소속 */}
                        <td className="px-4 py-3 text-label-1 text-fg-sub font-korean">
                          {user.orgAbbr || user.orgName || '-'}
                        </td>

                        {/* 이메일 */}
                        <td className="px-4 py-3 text-label-2 text-fg-disabled font-mono">
                          {user.email || '-'}
                        </td>

                        {/* 역할 (인라인 편집) */}
                        <td className="px-4 py-3">
                          <div className="relative">
                            <div
                              className="flex flex-wrap gap-1 cursor-pointer"
                              onClick={() => handleOpenRoleEdit(user)}
                              title="클릭하여 역할 변경"
                            >
                              {user.roles.length > 0 ? (
                                user.roles.map((roleCode, roleIdx) => {
                                  const color = getRoleColor(roleCode, roleIdx);
                                  const roleName =
                                    allRoles.find((r) => r.code === roleCode)?.name || roleCode;
                                  return (
                                    <span
                                      key={roleCode}
                                      className="px-2 py-0.5 text-caption font-semibold rounded-md font-korean"
                                      style={{
                                        background: `${color}20`,
                                        color: color,
                                        border: `1px solid ${color}40`,
                                      }}
                                    >
                                      {roleName}
                                    </span>
                                  );
                                })
                              ) : (
                                <span className="text-caption text-fg-disabled font-korean">
                                  역할 없음
                                </span>
                              )}
                              <span className="text-caption text-fg-disabled ml-0.5">
                                <svg
                                  width="10"
                                  height="10"
                                  viewBox="0 0 24 24"
                                  fill="none"
                                  stroke="currentColor"
                                  strokeWidth="2.5"
                                >
                                  <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
                                  <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
                                </svg>
                              </span>
                            </div>
                            {roleEditUserId === user.id && (
                              <div
                                ref={roleDropdownRef}
                                className="absolute z-20 top-full left-0 mt-1 p-2 bg-bg-surface border border-stroke rounded-lg shadow-lg min-w-[200px]"
                              >
                                <div className="text-caption text-fg-disabled font-korean font-semibold mb-1.5 px-1">
                                  역할 선택
                                </div>
                                {allRoles.map((role, roleIdx) => {
                                  const color = getRoleColor(role.code, roleIdx);
                                  return (
                                    <label
                                      key={role.sn}
                                      className="flex items-center gap-2 px-2 py-1.5 hover:bg-[rgba(255,255,255,0.04)] rounded cursor-pointer"
                                    >
                                      <input
                                        type="checkbox"
                                        checked={selectedRoleSns.includes(role.sn)}
                                        onChange={() => toggleRoleSelection(role.sn)}
                                        style={{ accentColor: color }}
                                      />
                                      <span className="text-caption font-korean" style={{ color }}>
                                        {role.name}
                                      </span>
                                      <span className="text-caption text-fg-disabled font-mono">
                                        {role.code}
                                      </span>
                                    </label>
                                  );
                                })}
                                <div className="flex justify-end gap-2 mt-2 pt-2 border-t border-stroke">
                                  <button
                                    onClick={() => setRoleEditUserId(null)}
                                    className="px-3 py-1 text-caption text-fg-disabled border border-stroke rounded hover:bg-bg-surface-hover font-korean"
                                  >
                                    취소
                                  </button>
                                  <button
                                    onClick={() => handleSaveRoles(user.id)}
                                    disabled={selectedRoleSns.length === 0}
                                    className="px-3 py-1 text-caption font-semibold rounded bg-color-accent text-bg-0 hover:shadow-[0_0_8px_rgba(6,182,212,0.3)] disabled:opacity-50 font-korean"
                                  >
                                    저장
                                  </button>
                                </div>
                              </div>
                            )}
                          </div>
                        </td>

                        {/* 승인상태 */}
                        <td className="px-4 py-3">
                          <span
                            className={`inline-flex items-center gap-1.5 text-caption font-semibold font-korean ${statusInfo.color}`}
                          >
                            <span className={`w-1.5 h-1.5 rounded-full ${statusInfo.dot}`} />
                            {statusInfo.label}
                          </span>
                        </td>

                        {/* 관리 */}
                        <td className="px-4 py-3 text-right">
                          <div className="flex items-center justify-end gap-2">
                            {user.status === 'PENDING' && (
                              <>
                                <button
                                  onClick={() => handleApprove(user.id)}
                                  className="px-2 py-1 text-caption font-semibold text-green-400 border border-green-400 rounded hover:bg-[rgba(74,222,128,0.1)] transition-all font-korean"
                                >
                                  승인
                                </button>
                                <button
                                  onClick={() => handleReject(user.id)}
                                  className="px-2 py-1 text-caption font-semibold text-red-400 border border-red-400 rounded hover:bg-[rgba(248,113,113,0.1)] transition-all font-korean"
                                >
                                  거절
                                </button>
                              </>
                            )}
                            {user.status === 'LOCKED' && (
                              <button
                                onClick={() => handleUnlock(user.id)}
                                className="px-2 py-1 text-caption font-semibold text-yellow-400 border border-yellow-400 rounded hover:bg-[rgba(250,204,21,0.1)] transition-all font-korean"
                              >
                                잠금해제
                              </button>
                            )}
                            {user.status === 'ACTIVE' && (
                              <button
                                onClick={() => handleDeactivate(user.id)}
                                className="px-2 py-1 text-caption font-semibold text-fg-disabled border border-stroke rounded hover:bg-[rgba(255,255,255,0.04)] transition-all font-korean"
                              >
                                비활성화
                              </button>
                            )}
                            {(user.status === 'INACTIVE' || user.status === 'REJECTED') && (
                              <button
                                onClick={() => handleActivate(user.id)}
                                className="px-2 py-1 text-caption font-semibold text-green-400 border border-green-400 rounded hover:bg-[rgba(74,222,128,0.1)] transition-all font-korean"
                              >
                                활성화
                              </button>
                            )}
                          </div>
                        </td>
                      </tr>
                    );
                  })
                )}
              </tbody>
            </table>
          )}
        </div>

        {/* 페이지네이션 */}
        {!loading && totalPages > 1 && (
          <div className="flex items-center justify-between px-6 py-3 border-t border-stroke bg-bg-surface">
            <span className="text-label-2 text-fg-disabled font-korean">
              {(currentPage - 1) * PAGE_SIZE + 1}–{Math.min(currentPage * PAGE_SIZE, totalCount)} /{' '}
              {totalCount}명
            </span>
            <div className="flex items-center gap-1">
              <button
                onClick={() => setCurrentPage((p) => Math.max(1, p - 1))}
                disabled={currentPage === 1}
                className="px-2.5 py-1 text-label-2 border border-stroke text-fg-disabled rounded hover:bg-[rgba(255,255,255,0.04)] disabled:opacity-40 transition-all font-korean"
              >
                이전
              </button>
              {Array.from({ length: totalPages }, (_, i) => i + 1)
                .filter((p) => p === 1 || p === totalPages || Math.abs(p - currentPage) <= 2)
                .reduce<(number | '...')[]>((acc, p, i, arr) => {
                  if (
                    i > 0 &&
                    typeof arr[i - 1] === 'number' &&
                    (p as number) - (arr[i - 1] as number) > 1
                  ) {
                    acc.push('...');
                  }
                  acc.push(p);
                  return acc;
                }, [])
                .map((item, i) =>
                  item === '...' ? (
                    <span key={`ellipsis-${i}`} className="px-2 text-label-2 text-fg-disabled">
                      …
                    </span>
                  ) : (
                    <button
                      key={item}
                      onClick={() => setCurrentPage(item as number)}
                      className="px-2.5 py-1 text-label-2 border rounded transition-all font-mono"
                      style={
                        currentPage === item
                          ? {
                              borderColor: 'var(--color-accent)',
                              color: 'var(--color-accent)',
                              background: 'rgba(6,182,212,0.1)',
                            }
                          : { borderColor: 'var(--border)', color: 'var(--fg-disabled)' }
                      }
                    >
                      {item}
                    </button>
                  ),
                )}
              <button
                onClick={() => setCurrentPage((p) => Math.min(totalPages, p + 1))}
                disabled={currentPage === totalPages}
                className="px-2.5 py-1 text-label-2 border border-stroke text-fg-disabled rounded hover:bg-[rgba(255,255,255,0.04)] disabled:opacity-40 transition-all font-korean"
              >
                다음
              </button>
            </div>
          </div>
        )}
      </div>

      {/* 사용자 등록 모달 */}
      {showRegisterModal && (
        <RegisterModal
          allRoles={allRoles}
          allOrgs={allOrgs}
          onClose={() => setShowRegisterModal(false)}
          onSuccess={loadUsers}
        />
      )}

      {/* 사용자 상세/수정 모달 */}
      {detailUser && (
        <UserDetailModal
          user={detailUser}
          allRoles={allRoles}
          allOrgs={allOrgs}
          onClose={() => setDetailUser(null)}
          onUpdated={() => {
            loadUsers();
            // 최신 정보로 모달 갱신을 위해 닫지 않음
          }}
        />
      )}
    </>
  );
}

export default UsersPanel;
