import { describe, it, expect, vi, beforeEach } from 'vitest';

// useAuth mock
vi.mock('@/contexts/AuthContext', () => ({
  useAuth: vi.fn(),
}));

// React hook 환경 모킹 (node 환경에서 실행)
vi.mock('react', () => ({
  useState: vi.fn((init: unknown) => [init, vi.fn()]),
  useEffect: vi.fn(),
  useRef: vi.fn((init: unknown) => ({ current: init })),
  useCallback: vi.fn((fn: unknown) => fn),
  useMemo: vi.fn((fn: () => unknown) => fn()),
  createContext: vi.fn(),
  useContext: vi.fn(),
}));

import { useAuth } from '@/contexts/AuthContext';
import { useReviewPermission } from '@/hooks/useReviewPermission';

const mockUseAuth = vi.mocked(useAuth);

describe('useReviewPermission', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('admin 역할', () => {
    it('모든 권한이 true여야 한다', () => {
      mockUseAuth.mockReturnValue({
        user: null,
        userRole: 'admin',
        customName: null,
        loading: false,
        signInWithGoogle: vi.fn(),
        signOut: vi.fn(),
      });

      const permissions = useReviewPermission();

      expect(permissions.canReview).toBe(true);
      expect(permissions.canApprove).toBe(true);
      expect(permissions.canManageReviewers).toBe(true);
      expect(permissions.canViewReviewQueue).toBe(true);
      expect(permissions.canSubmitDocument).toBe(true);
      expect(permissions.role).toBe('admin');
    });
  });

  describe('reviewer 역할', () => {
    it('canReview와 canViewReviewQueue, canSubmitDocument는 true이고, canApprove와 canManageReviewers는 false여야 한다', () => {
      mockUseAuth.mockReturnValue({
        user: null,
        userRole: 'reviewer',
        customName: null,
        loading: false,
        signInWithGoogle: vi.fn(),
        signOut: vi.fn(),
      });

      const permissions = useReviewPermission();

      expect(permissions.canReview).toBe(true);
      expect(permissions.canApprove).toBe(false);
      expect(permissions.canManageReviewers).toBe(false);
      expect(permissions.canViewReviewQueue).toBe(true);
      expect(permissions.canSubmitDocument).toBe(true);
      expect(permissions.role).toBe('reviewer');
    });
  });

  describe('member 역할', () => {
    it('canSubmitDocument만 true이고 나머지는 false여야 한다', () => {
      mockUseAuth.mockReturnValue({
        user: null,
        userRole: 'member',
        customName: null,
        loading: false,
        signInWithGoogle: vi.fn(),
        signOut: vi.fn(),
      });

      const permissions = useReviewPermission();

      expect(permissions.canReview).toBe(false);
      expect(permissions.canApprove).toBe(false);
      expect(permissions.canManageReviewers).toBe(false);
      expect(permissions.canViewReviewQueue).toBe(false);
      expect(permissions.canSubmitDocument).toBe(true);
      expect(permissions.role).toBe('member');
    });
  });

  describe('guest 역할', () => {
    it('모든 권한이 false여야 한다', () => {
      mockUseAuth.mockReturnValue({
        user: null,
        userRole: 'guest',
        customName: null,
        loading: false,
        signInWithGoogle: vi.fn(),
        signOut: vi.fn(),
      });

      const permissions = useReviewPermission();

      expect(permissions.canReview).toBe(false);
      expect(permissions.canApprove).toBe(false);
      expect(permissions.canManageReviewers).toBe(false);
      expect(permissions.canViewReviewQueue).toBe(false);
      expect(permissions.canSubmitDocument).toBe(false);
      expect(permissions.role).toBe('guest');
    });
  });

  describe('null 역할 (로딩 중)', () => {
    it('모든 권한이 false이고 role이 null이어야 한다', () => {
      mockUseAuth.mockReturnValue({
        user: null,
        userRole: null,
        customName: null,
        loading: true,
        signInWithGoogle: vi.fn(),
        signOut: vi.fn(),
      });

      const permissions = useReviewPermission();

      expect(permissions.canReview).toBe(false);
      expect(permissions.canApprove).toBe(false);
      expect(permissions.canManageReviewers).toBe(false);
      expect(permissions.canViewReviewQueue).toBe(false);
      expect(permissions.canSubmitDocument).toBe(false);
      expect(permissions.role).toBe(null);
    });
  });

  describe('역할 변경 시 권한 업데이트', () => {
    it('역할이 member에서 reviewer로 변경되면 canReview가 true로 업데이트되어야 한다', () => {
      // member 상태
      mockUseAuth.mockReturnValue({
        user: null,
        userRole: 'member',
        customName: null,
        loading: false,
        signInWithGoogle: vi.fn(),
        signOut: vi.fn(),
      });

      const memberPermissions = useReviewPermission();
      expect(memberPermissions.canReview).toBe(false);
      expect(memberPermissions.canSubmitDocument).toBe(true);

      // reviewer로 변경
      mockUseAuth.mockReturnValue({
        user: null,
        userRole: 'reviewer',
        customName: null,
        loading: false,
        signInWithGoogle: vi.fn(),
        signOut: vi.fn(),
      });

      const reviewerPermissions = useReviewPermission();
      expect(reviewerPermissions.canReview).toBe(true);
      expect(reviewerPermissions.canViewReviewQueue).toBe(true);
      expect(reviewerPermissions.canSubmitDocument).toBe(true);
    });

    it('역할이 admin에서 guest로 변경되면 모든 권한이 false로 업데이트되어야 한다', () => {
      // admin 상태
      mockUseAuth.mockReturnValue({
        user: null,
        userRole: 'admin',
        customName: null,
        loading: false,
        signInWithGoogle: vi.fn(),
        signOut: vi.fn(),
      });

      const adminPermissions = useReviewPermission();
      expect(adminPermissions.canApprove).toBe(true);
      expect(adminPermissions.canManageReviewers).toBe(true);

      // guest로 변경
      mockUseAuth.mockReturnValue({
        user: null,
        userRole: 'guest',
        customName: null,
        loading: false,
        signInWithGoogle: vi.fn(),
        signOut: vi.fn(),
      });

      const guestPermissions = useReviewPermission();
      expect(guestPermissions.canReview).toBe(false);
      expect(guestPermissions.canApprove).toBe(false);
      expect(guestPermissions.canManageReviewers).toBe(false);
      expect(guestPermissions.canViewReviewQueue).toBe(false);
      expect(guestPermissions.canSubmitDocument).toBe(false);
    });
  });
});
