import { describe, expect, it } from 'vitest'
import {
  AccessKeys,
  DIAGNOSTIC_VIEW_ACCESS_KEYS,
  PLATFORM_ADMIN_ACCESS_KEY,
  deriveAccessKeyCatalog,
  findAccessCatalogEntry,
  listAccessKeys,
  normalizeAccessKey
} from '../access-keys'
import type { OrganizationModel } from '../../organization-model/types'

const model = {
  systems: {
    sales: {
      id: 'sales',
      label: 'Sales',
      lifecycle: 'active',
      order: 10,
      systems: {
        crm: {
          id: 'crm',
          label: 'CRM',
          lifecycle: 'active',
          order: 10
        },
        'lead-gen': {
          id: 'lead-gen',
          label: 'Lead Gen',
          lifecycle: 'active',
          order: 20
        }
      }
    },
    operations: {
      id: 'operations',
      label: 'Operations',
      lifecycle: 'active',
      order: 20
    }
  }
} as OrganizationModel

describe('access keys', () => {
  it('normalizes string shorthand to view access keys', () => {
    expect(normalizeAccessKey('sales.crm')).toEqual({ systemPath: 'sales.crm', action: 'view' })
    expect(normalizeAccessKey({ systemPath: 'sales.crm' })).toEqual({ systemPath: 'sales.crm', action: 'view' })
  })

  it('normalizes platformAdmin string shorthand to the platform special-case key', () => {
    expect(normalizeAccessKey('platformAdmin')).toEqual(AccessKeys.platformAdmin)
    expect(normalizeAccessKey('platformAdmin').systemPath).toBe(PLATFORM_ADMIN_ACCESS_KEY)
  })

  it('derives view and manage access keys from nested Organization Model systems', () => {
    const catalog = deriveAccessKeyCatalog(model)
    const keys = listAccessKeys(catalog)

    expect(keys).toContainEqual({ systemPath: 'sales', action: 'view' })
    expect(keys).toContainEqual({ systemPath: 'sales.crm', action: 'view' })
    expect(keys).toContainEqual({ systemPath: 'sales.crm', action: 'manage' })
    expect(keys).toContainEqual(AccessKeys.leadGenManage)
    expect(keys).toContainEqual({ systemPath: 'operations', action: 'manage' })
  })

  it('includes diagnostic allowlist keys and platformAdmin in the catalog', () => {
    const catalog = deriveAccessKeyCatalog(model)

    for (const systemPath of DIAGNOSTIC_VIEW_ACCESS_KEYS) {
      expect(findAccessCatalogEntry(catalog, { systemPath, action: 'view' })?.source).toBe('diagnostic')
    }

    expect(findAccessCatalogEntry(catalog, AccessKeys.platformAdmin)?.source).toBe('platform')
  })

  it('includes permission-only access keys with their legacy role-permission mapping', () => {
    const catalog = deriveAccessKeyCatalog(model)

    expect(findAccessCatalogEntry(catalog, AccessKeys.organizationManage)).toMatchObject({
      source: 'permission',
      rolePermission: 'org.manage'
    })
    expect(findAccessCatalogEntry(catalog, AccessKeys.membersManage)).toMatchObject({
      source: 'permission',
      rolePermission: 'members.manage'
    })
  })

  it('maps the Lead Gen manage AccessKey to the OM System permission', () => {
    const catalog = deriveAccessKeyCatalog(model)

    expect(findAccessCatalogEntry(catalog, AccessKeys.leadGenManage)).toMatchObject({
      source: 'om-system',
      rolePermission: 'sales.lead-gen.manage'
    })
  })
})
