import { useState, useEffect, useCallback, useRef } from 'react';
import type { UserListItem, PermTreeNode, RoleWithPermissions } from '@common/services/authApi';
import { fetchUsers, assignRolesApi } from '@common/services/authApi';
import { getRoleColor } from '../adminConstants';
import type { OperCode, PermState } from '../PermissionsPanel';
import { OPER_CODES, OPER_FULL_LABELS, OPER_LABELS, flattenTree, buildEffectiveStates } from '../PermissionsPanel';
import { TreeRow } from './TreeRow';
import { PermLegend } from './PermLegend';

interface UserPermTabProps {
  roles: RoleWithPermissions[];
  permTree: PermTreeNode[];
  rolePerms: Map<number, Map<string, boolean>>;
}

export function UserPermTab({ roles, permTree, rolePerms }: UserPermTabProps) {
  const [users, setUsers] = useState<UserListItem[]>([]);
  const [loadingUsers, setLoadingUsers] = useState(true);
  const [searchQuery, setSearchQuery] = useState('');
  const [showDropdown, setShowDropdown] = useState(false);
  const [selectedUser, setSelectedUser] = useState<UserListItem | null>(null);
  const [assignedRoleSns, setAssignedRoleSns] = useState<number[]>([]);
  const [savingRoles, setSavingRoles] = useState(false);
  const [rolesDirty, setRolesDirty] = useState(false);
  const [expanded, setExpanded] = useState<Set<string>>(new Set());
  const dropdownRef = useRef<HTMLDivElement>(null);

  const flatNodes = flattenTree(permTree);

  useEffect(() => {
    const loadUsers = async () => {
      setLoadingUsers(true);
      try {
        const data = await fetchUsers();
        setUsers(data);
      } catch (err) {
        console.error('사용자 목록 조회 실패:', err);
      } finally {
        setLoadingUsers(false);
      }
    };
    loadUsers();
  }, []);

  // 최상위 노드 기본 펼침
  useEffect(() => {
    if (permTree.length > 0) {
      setExpanded(new Set(permTree.map((n) => n.code)));
    }
  }, [permTree]);

  // 드롭다운 외부 클릭 시 닫기
  useEffect(() => {
    const handleClickOutside = (e: MouseEvent) => {
      if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) {
        setShowDropdown(false);
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

  const filteredUsers = users.filter((u) => {
    if (!searchQuery) return true;
    const q = searchQuery.toLowerCase();
    return (
      u.name.toLowerCase().includes(q) ||
      u.account.toLowerCase().includes(q) ||
      (u.orgName?.toLowerCase().includes(q) ?? false)
    );
  });

  const handleSelectUser = (user: UserListItem) => {
    setSelectedUser(user);
    setSearchQuery(user.name);
    setShowDropdown(false);
    setAssignedRoleSns(user.roleSns ?? []);
    setRolesDirty(false);
  };

  const handleToggleRole = (roleSn: number) => {
    setAssignedRoleSns((prev) => {
      const next = prev.includes(roleSn) ? prev.filter((sn) => sn !== roleSn) : [...prev, roleSn];
      return next;
    });
    setRolesDirty(true);
  };

  const handleSaveRoles = async () => {
    if (!selectedUser) return;
    setSavingRoles(true);
    try {
      await assignRolesApi(selectedUser.id, assignedRoleSns);
      setRolesDirty(false);
      // 로컬 users 상태 갱신
      setUsers((prev) =>
        prev.map((u) =>
          u.id === selectedUser.id
            ? {
                ...u,
                roleSns: assignedRoleSns,
                roles: roles.filter((r) => assignedRoleSns.includes(r.sn)).map((r) => r.name),
              }
            : u,
        ),
      );
      setSelectedUser((prev) =>
        prev
          ? {
              ...prev,
              roleSns: assignedRoleSns,
              roles: roles.filter((r) => assignedRoleSns.includes(r.sn)).map((r) => r.name),
            }
          : null,
      );
    } catch (err) {
      console.error('역할 저장 실패:', err);
    } finally {
      setSavingRoles(false);
    }
  };

  const handleToggleExpand = useCallback((code: string) => {
    setExpanded((prev) => {
      const next = new Set(prev);
      if (next.has(code)) next.delete(code);
      else next.add(code);
      return next;
    });
  }, []);

  // 사용자의 유효 권한: 할당된 역할들의 권한 병합 (OR 결합)
  const effectiveStateMap = (() => {
    if (!selectedUser || assignedRoleSns.length === 0) {
      return new Map<string, PermState>();
    }

    // 각 역할의 명시적 권한 병합: 어느 역할이든 granted=true면 허용
    const mergedPerms = new Map<string, boolean>();
    for (const roleSn of assignedRoleSns) {
      const perms = rolePerms.get(roleSn);
      if (!perms) continue;
      for (const [key, granted] of perms) {
        if (granted) {
          mergedPerms.set(key, true);
        } else if (!mergedPerms.has(key)) {
          mergedPerms.set(key, false);
        }
      }
    }

    return buildEffectiveStates(flatNodes, mergedPerms);
  })();

  const noOpToggle = useCallback((_code: string, _oper: OperCode, _state: PermState): void => {
    void _code;
    void _oper;
    void _state;
    // 읽기 전용 — 토글 없음
  }, []);

  return (
    <div className="flex flex-col flex-1 min-h-0">
      {/* 사용자 검색/선택 */}
      <div className="px-4 py-2.5 border-b border-stroke" style={{ flexShrink: 0 }}>
        <label className="text-caption text-fg-disabled font-korean block mb-1.5">
          사용자 선택
        </label>
        <div className="relative" ref={dropdownRef}>
          <input
            type="text"
            value={searchQuery}
            onChange={(e) => {
              setSearchQuery(e.target.value);
              setShowDropdown(true);
              if (selectedUser && e.target.value !== selectedUser.name) {
                setSelectedUser(null);
                setAssignedRoleSns([]);
                setRolesDirty(false);
              }
            }}
            onFocus={() => setShowDropdown(true)}
            placeholder={loadingUsers ? '불러오는 중...' : '이름, 계정, 조직으로 검색...'}
            disabled={loadingUsers}
            className="w-full max-w-sm 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 disabled:opacity-50"
          />
          {showDropdown && filteredUsers.length > 0 && (
            <div className="absolute left-0 top-full mt-1 w-full max-w-sm bg-bg-surface border border-stroke rounded-md shadow-xl z-20 overflow-auto max-h-52">
              {filteredUsers.map((user) => (
                <button
                  key={user.id}
                  onClick={() => handleSelectUser(user)}
                  className="w-full px-3 py-2 text-left hover:bg-bg-surface-hover transition-colors flex items-center gap-2"
                >
                  <div className="min-w-0 flex-1">
                    <div className="text-caption font-semibold text-fg font-korean truncate">
                      {user.name}
                      {user.rank && (
                        <span className="ml-1 text-caption text-fg-disabled font-korean">
                          {user.rank}
                        </span>
                      )}
                    </div>
                    <div className="text-caption text-fg-disabled font-mono truncate">
                      {user.account}
                    </div>
                  </div>
                  {user.orgName && (
                    <span className="text-caption text-fg-disabled font-korean flex-shrink-0 truncate max-w-[100px]">
                      {user.orgName}
                    </span>
                  )}
                </button>
              ))}
            </div>
          )}
          {showDropdown && !loadingUsers && filteredUsers.length === 0 && searchQuery && (
            <div className="absolute left-0 top-full mt-1 w-full max-w-sm bg-bg-surface border border-stroke rounded-md shadow-xl z-20 px-3 py-2 text-caption text-fg-disabled font-korean">
              검색 결과 없음
            </div>
          )}
        </div>
      </div>

      {selectedUser ? (
        <>
          {/* 역할 할당 섹션 */}
          <div
            className="px-4 py-2.5 border-b border-stroke bg-bg-surface"
            style={{ flexShrink: 0 }}
          >
            <div className="flex items-center justify-between mb-2">
              <span className="text-caption font-semibold text-fg-sub font-korean">역할 할당</span>
              <button
                onClick={handleSaveRoles}
                disabled={!rolesDirty || savingRoles}
                className={`px-3 py-1.5 text-label-2 font-semibold rounded-md transition-all font-korean ${
                  rolesDirty
                    ? 'bg-color-accent text-bg-0 hover:shadow-[0_0_12px_rgba(6,182,212,0.3)]'
                    : 'bg-bg-card text-fg-disabled cursor-not-allowed'
                }`}
              >
                {savingRoles ? '저장 중...' : '역할 저장'}
              </button>
            </div>
            <div className="flex flex-wrap gap-1.5">
              {roles.map((role, idx) => {
                const color = getRoleColor(role.code, idx);
                const isChecked = assignedRoleSns.includes(role.sn);
                return (
                  <label
                    key={role.sn}
                    className={[
                      'flex items-center gap-1 px-2 py-1 rounded-md border cursor-pointer transition-all font-korean text-label-2 select-none',
                      isChecked ? '' : 'border-stroke text-fg-disabled hover:border-text-2',
                    ].join(' ')}
                    style={
                      isChecked
                        ? { borderColor: color, color, backgroundColor: `${color}18` }
                        : undefined
                    }
                  >
                    <input
                      type="checkbox"
                      checked={isChecked}
                      onChange={() => handleToggleRole(role.sn)}
                      className="w-3 h-3 accent-primary-cyan"
                    />
                    <span>{role.name}</span>
                    <span className="text-caption font-mono opacity-60">{role.code}</span>
                  </label>
                );
              })}
            </div>
          </div>

          {/* 유효 권한 매트릭스 (읽기 전용) */}
          <div
            className="px-4 py-1.5 border-b border-stroke bg-bg-surface text-caption text-fg-disabled font-korean"
            style={{ flexShrink: 0 }}
          >
            <span className="font-semibold text-fg-sub">유효 권한 (읽기 전용)</span>
            <span className="ml-2">— 할당된 역할의 권한 합산 결과</span>
          </div>

          <PermLegend />

          {assignedRoleSns.length > 0 ? (
            <div className="flex-1 overflow-auto">
              <table className="w-full">
                <thead>
                  <tr className="border-b border-stroke bg-bg-surface sticky top-0 z-10">
                    <th className="px-4 py-3 text-left text-label-2 font-semibold text-fg-disabled font-korean min-w-[240px]">
                      기능
                    </th>
                    {OPER_CODES.map((oper) => (
                      <th key={oper} className="px-2 py-3 text-center w-16">
                        <div className="text-label-2 font-semibold text-fg-sub">
                          {OPER_LABELS[oper]}
                        </div>
                        <div className="text-caption text-fg-disabled font-korean">
                          {OPER_FULL_LABELS[oper]}
                        </div>
                      </th>
                    ))}
                  </tr>
                </thead>
                <tbody>
                  {permTree.map((rootNode) => (
                    <TreeRow
                      key={rootNode.code}
                      node={rootNode}
                      stateMap={effectiveStateMap}
                      expanded={expanded}
                      onToggleExpand={handleToggleExpand}
                      onTogglePerm={noOpToggle}
                      readOnly={true}
                    />
                  ))}
                </tbody>
              </table>
            </div>
          ) : (
            <div className="flex-1 flex items-center justify-center text-fg-disabled text-body-2 font-korean">
              역할을 하나 이상 할당하면 유효 권한이 표시됩니다
            </div>
          )}
        </>
      ) : (
        <div className="flex-1 flex items-center justify-center text-fg-disabled text-body-2 font-korean">
          사용자를 선택하세요
        </div>
      )}
    </div>
  );
}
