// Feature: divisi-metrics, Property 3: Role-based navigation visibility
// **Validates: Requirements 3.7, 14.8**

import { describe, it, expect } from 'vitest';
import * as fc from 'fast-check';
import { getNavItemsForRole } from '@/lib/constants/navigation';
import type { UserRole } from '@/lib/constants/navigation';

/**
 * Expected navigation labels per role, derived from the requirements:
 *  - Viewer:          Overview, Income, Costs, Statements
 *  - Publisher_Admin:  all items except Audit (10 items)
 *  - Super_Admin:      all 11 items
 */
const expectedNavByRole: Record<UserRole, string[]> = {
  Viewer: ['Overview', 'Income', 'Costs', 'Statements'],
  Publisher_Admin: [
    'Overview',
    'Works',
    'Composers',
    'Payees',
    'Contracts',
    'Income',
    'Transactions',
    'Costs',
    'Statements',
    'Suspense',
  ],
  Super_Admin: [
    'Overview',
    'Works',
    'Composers',
    'Payees',
    'Contracts',
    'Income',
    'Transactions',
    'Costs',
    'Statements',
    'Suspense',
    'Audit',
  ],
  Client_Portal: [
    'Inicio',
    'Overview',
    'Top Songs',
    'Income Groups',
    'Territories',
    'Exploitation Sources',
    'Canciones',
    'Documentos',
  ],
};

describe('Property 3: Role-based navigation visibility', () => {
  it('visible navigation items match exactly the authorized set for any role', () => {
    fc.assert(
      fc.property(
        fc.constantFrom<UserRole>('Super_Admin', 'Publisher_Admin', 'Viewer', 'Client_Portal'),
        (role) => {
          const visibleLabels = getNavItemsForRole(role).map((item) => item.label);
          const expectedLabels = expectedNavByRole[role];

          // Same count — no extra items, no missing items
          expect(visibleLabels).toHaveLength(expectedLabels.length);

          // Exact set match (order-independent)
          expect(visibleLabels.sort()).toEqual(expectedLabels.slice().sort());
        },
      ),
      { numRuns: 100 },
    );
  });

  it('no role sees items it is not authorized to access', () => {
    fc.assert(
      fc.property(
        fc.constantFrom<UserRole>('Super_Admin', 'Publisher_Admin', 'Viewer', 'Client_Portal'),
        (role) => {
          const visibleLabels = new Set(
            getNavItemsForRole(role).map((item) => item.label),
          );
          const expectedSet = new Set(expectedNavByRole[role]);

          // Every visible item must be in the expected set
          for (const label of visibleLabels) {
            expect(expectedSet.has(label)).toBe(true);
          }

          // Every expected item must be visible
          for (const label of expectedSet) {
            expect(visibleLabels.has(label)).toBe(true);
          }
        },
      ),
      { numRuns: 100 },
    );
  });
});
