import { describe, expect, it } from 'vitest';
import { ProjectMemberRole, SystemRole } from '@prisma/client';
import { AuthUser, can } from './rbac';

function user(role: SystemRole, overrides: Partial<AuthUser> = {}): AuthUser {
  return {
    id: 'u1',
    code: 'EMP-001',
    name: 'Test',
    email: 't@example.com',
    role,
    active: true,
    ...overrides,
  };
}

describe('RBAC can()', () => {
  it('Super Admin can manage employees and leave', () => {
    const u = user(SystemRole.SuperAdmin);
    expect(can(u, 'manage_employees')).toBe(true);
    expect(can(u, 'manage_leave')).toBe(true);
    expect(can(u, 'view_reports_all')).toBe(true);
  });

  it('Developer cannot manage employees or leave', () => {
    const u = user(SystemRole.Developer);
    expect(can(u, 'manage_employees')).toBe(false);
    expect(can(u, 'manage_leave')).toBe(false);
    expect(can(u, 'log_time')).toBe(true);
    expect(can(u, 'apply_leave')).toBe(true);
  });

  it('Tester can create bug when project member', () => {
    const u = user(SystemRole.TesterQA);
    expect(can(u, 'create_bug', { isProjectMember: true })).toBe(true);
    expect(can(u, 'create_bug', { isProjectMember: false })).toBe(false);
  });

  it('Tester change_bug_status limited to Close/Reopen from Ready for Retest', () => {
    const u = user(SystemRole.TesterQA);
    expect(
      can(u, 'change_bug_status', {
        isProjectMember: true,
        bugStatus: 'Ready for Retest',
        toStatus: 'Closed',
      })
    ).toBe(true);
    expect(
      can(u, 'change_bug_status', {
        isProjectMember: true,
        bugStatus: 'Open',
        toStatus: 'Closed',
      })
    ).toBe(false);
    expect(
      can(u, 'change_bug_status', {
        isProjectMember: true,
        bugStatus: 'Ready for Retest',
        toStatus: 'In Progress',
      })
    ).toBe(false);
  });

  it('Bug assignee can change status freely', () => {
    const u = user(SystemRole.Developer);
    expect(
      can(u, 'change_bug_status', {
        isBugAssignee: true,
        bugStatus: 'Open',
        toStatus: 'Closed',
      })
    ).toBe(true);
  });

  it('edit_task blocked on Done for non-PA', () => {
    const u = user(SystemRole.Developer);
    expect(
      can(u, 'edit_task', { isProjectMember: true, taskStageDone: true })
    ).toBe(false);
    expect(
      can(u, 'edit_task', {
        isProjectMember: true,
        taskStageDone: true,
        projectRole: ProjectMemberRole.ProjectAdmin,
      })
    ).toBe(true);
  });

  it('inactive user denied', () => {
    const u = user(SystemRole.SuperAdmin, { active: false });
    expect(can(u, 'manage_employees')).toBe(false);
  });
});
