import { describe, expect, it, vi } from 'vitest'
import {
  DEFAULT_ORGANIZATION_MODEL_SYSTEMS,
  SYSTEM_INTERFACE_PROFILES,
  SystemEntrySchema,
  SystemApiInterfaceSchema,
  SystemInterfaceReadinessProfileSchema,
  SystemInterfaceRefSchema,
  SystemKindSchema,
  SystemStatusSchema,
  SystemsDomainSchema
} from '../../domains/systems'
import { resolveOrganizationModel } from '../../resolve'
import type {
  OrganizationModelSystemApiInterface,
  OrganizationModelSystemInterfaceReadinessProfile
} from '../../types'

const VALID_SYSTEM = {
  id: 'sys.lead-gen',
  order: 10,
  title: 'Lead Generation Pipeline',
  description: 'Coordinates prospecting, enrichment, qualification, and outreach preparation.',
  kind: 'operational' as const
}

describe('SystemEntrySchema - positive parse', () => {
  it('accepts a minimal tenant-defined system', () => {
    const result = SystemEntrySchema.safeParse(VALID_SYSTEM)

    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.governedByKnowledge).toEqual([])
      expect(result.data.drivesGoals).toEqual([])
    }
  })

  it('accepts all optional governance references when present', () => {
    const result = SystemEntrySchema.safeParse({
      ...VALID_SYSTEM,
      responsibleRoleId: 'role.sales-ops',
      governedByKnowledge: ['knowledge.lead-gen-playbook'],
      drivesGoals: ['goal.pipeline-coverage']
    })

    expect(result.success).toBe(true)
  })

  it('accepts a thin API System Interface marker with scoped resources', () => {
    const result = SystemEntrySchema.safeParse({
      ...VALID_SYSTEM,
      apiInterface: {
        lifecycle: 'active',
        readinessProfile: 'sales.lead-gen.api',
        resourceIds: ['lead-gen-list-builder']
      }
    })

    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.apiInterface).toEqual({
        lifecycle: 'active',
        readinessProfile: 'sales.lead-gen.api',
        resourceIds: ['lead-gen-list-builder']
      })
    }
  })

  it('accepts only registry-backed readiness profiles', () => {
    const profileValues = SYSTEM_INTERFACE_PROFILES.map((profile) => profile.readinessProfile)

    for (const readinessProfile of profileValues) {
      expect(SystemInterfaceReadinessProfileSchema.safeParse(readinessProfile).success).toBe(true)
    }

    expect(SystemInterfaceReadinessProfileSchema.safeParse('sales.lead-gen.unknown').success).toBe(false)
    expect(SystemApiInterfaceSchema.safeParse({ readinessProfile: 'sales.lead-gen.unknown' }).success).toBe(false)
  })

  it('publishes a narrowed System Interface readiness profile type', () => {
    const acceptedReadinessProfile: OrganizationModelSystemInterfaceReadinessProfile = 'sales.lead-gen.api'
    const acceptedInterface: OrganizationModelSystemApiInterface = {
      lifecycle: 'active',
      readinessProfile: acceptedReadinessProfile,
      resourceIds: []
    }

    // @ts-expect-error unsupported profiles are not part of the published readiness profile union.
    const unsupportedReadinessProfile: OrganizationModelSystemInterfaceReadinessProfile = 'sales.lead-gen.unknown'

    expect(acceptedInterface.readinessProfile).toBe('sales.lead-gen.api')
    expect(unsupportedReadinessProfile).toBe('sales.lead-gen.unknown')
  })

  it('represents missing and disabled System Interfaces distinctly', () => {
    const missing = SystemEntrySchema.parse(VALID_SYSTEM)
    const disabled = SystemEntrySchema.parse({
      ...VALID_SYSTEM,
      apiInterface: {
        lifecycle: 'disabled',
        readinessProfile: 'sales.lead-gen.api'
      }
    })

    expect(missing.apiInterface).toBeUndefined()
    expect(disabled.apiInterface?.lifecycle).toBe('disabled')
    expect(disabled.apiInterface?.resourceIds).toEqual([])
  })

  it('trims id, title, and description', () => {
    const result = SystemEntrySchema.safeParse({
      ...VALID_SYSTEM,
      id: '  sys.crm  ',
      title: '  CRM  ',
      description: '  Owns relationship and deal pipeline operations.  '
    })

    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.id).toBe('sys.crm')
      expect(result.data.title).toBe('CRM')
      expect(result.data.description).toBe('Owns relationship and deal pipeline operations.')
    }
  })

  it('accepts deprecated status and maps it to lifecycle for one-cycle compatibility', () => {
    const warn = vi.spyOn(console, 'warn').mockImplementation(() => undefined)

    const result = SystemEntrySchema.safeParse({
      ...VALID_SYSTEM,
      status: 'deprecated'
    })

    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.status).toBe('deprecated')
      expect(result.data.lifecycle).toBe('deprecated')
    }
    expect(warn).toHaveBeenCalledWith('[organization-model] System.status is deprecated; use System.lifecycle instead.')

    warn.mockRestore()
  })

  it('keeps non-color compatibility fields readable', () => {
    const result = SystemEntrySchema.safeParse({
      ...VALID_SYSTEM,
      path: '/lead-gen',
      icon: 'settings',
      uiPosition: 'sidebar-primary',
      enabled: true,
      devOnly: false
    })

    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data).toMatchObject({
        path: '/lead-gen',
        icon: 'settings',
        uiPosition: 'sidebar-primary',
        enabled: true,
        devOnly: false
      })
    }
  })
})

describe('SystemEntrySchema - negative parse', () => {
  it('rejects missing required fields', () => {
    expect(SystemEntrySchema.safeParse({ id: 'sys.missing' }).success).toBe(false)
  })

  it('rejects an unknown system kind', () => {
    expect(SystemEntrySchema.safeParse({ ...VALID_SYSTEM, kind: 'sales' }).success).toBe(false)
  })

  it('rejects an unknown deprecated system status', () => {
    expect(SystemEntrySchema.safeParse({ ...VALID_SYSTEM, status: 'paused' }).success).toBe(false)
  })

  it('rejects IDs that do not match the OM model-id format', () => {
    expect(SystemEntrySchema.safeParse({ ...VALID_SYSTEM, id: 'Sys Lead Gen' }).success).toBe(false)
  })

  it('rejects the retired color compatibility field', () => {
    expect(SystemEntrySchema.safeParse({ ...VALID_SYSTEM, color: 'blue' }).success).toBe(false)
  })

  it('rejects malformed System Interface states', () => {
    expect(SystemApiInterfaceSchema.safeParse({ kind: 'api', lifecycle: 'active' }).success).toBe(false)
    expect(SystemApiInterfaceSchema.safeParse({ lifecycle: 'paused' }).success).toBe(false)
    expect(SystemApiInterfaceSchema.safeParse({ readinessProfile: 'Sales Lead Gen API' }).success).toBe(false)
    expect(SystemApiInterfaceSchema.safeParse({ readinessProfile: 'sales.lead-gen.unknown' }).success).toBe(false)
    expect(
      SystemInterfaceRefSchema.safeParse({ systemPath: 'sales.lead-gen', interfaceKey: 'api' }).success
    ).toBe(true)
  })
})

describe('SystemsDomainSchema', () => {
  it('accepts an empty systems record', () => {
    expect(SystemsDomainSchema.safeParse({}).success).toBe(true)
  })

  it('defaults systems to an empty record when omitted', () => {
    const result = SystemsDomainSchema.safeParse({})

    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data).toEqual(DEFAULT_ORGANIZATION_MODEL_SYSTEMS)
    }
  })
})

describe('SystemKindSchema', () => {
  it.each(['product', 'operational', 'platform', 'diagnostic'] as const)('accepts kind "%s"', (kind) => {
    expect(SystemKindSchema.safeParse(kind).success).toBe(true)
  })
})

describe('SystemStatusSchema', () => {
  it.each(['active', 'deprecated', 'archived'] as const)('accepts deprecated status "%s"', (status) => {
    expect(SystemStatusSchema.safeParse(status).success).toBe(true)
  })
})

describe('resolveOrganizationModel - systems domain integration', () => {
  it('omitting systems keeps the generic systems domain empty', () => {
    const model = resolveOrganizationModel({})

    expect(model.systems).toEqual(DEFAULT_ORGANIZATION_MODEL_SYSTEMS)
  })

  it('accepts valid responsible role, knowledge, and goal references', () => {
    expect(() =>
      resolveOrganizationModel({
        roles: {
          'role.sales-ops': { id: 'role.sales-ops', order: 10, title: 'Sales Ops' }
        },
        goals: {
          'goal.pipeline-coverage': {
            id: 'goal.pipeline-coverage',
            order: 10,
            description: 'Improve sales pipeline coverage',
            periodStart: '2026-01-01',
            periodEnd: '2026-12-31'
          }
        },
        knowledge: {
          'knowledge.lead-gen-playbook': {
            id: 'knowledge.lead-gen-playbook',
            kind: 'playbook',
            title: 'Lead Gen Playbook',
            summary: 'How lead generation is governed.',
            body: '## Lead Gen',
            updatedAt: '2026-05-08'
          }
        },
        systems: {
          'sys.lead-gen': {
            ...VALID_SYSTEM,
            responsibleRoleId: 'role.sales-ops',
            governedByKnowledge: ['knowledge.lead-gen-playbook'],
            drivesGoals: ['goal.pipeline-coverage']
          }
        }
      })
    ).not.toThrow()
  })

  it('throws when system IDs are duplicated', () => {
    expect(() =>
      resolveOrganizationModel({
        systems: {
          'sys.lead-gen': VALID_SYSTEM,
          'sys.lead-gen-dup': {
            ...VALID_SYSTEM,
            id: 'sys.lead-gen'
          }
        }
      })
    ).toThrow()
  })

  it('throws when responsibleRoleId references an unknown role', () => {
    expect(() =>
      resolveOrganizationModel({
        systems: {
          'sys.lead-gen': { ...VALID_SYSTEM, responsibleRoleId: 'role.missing' }
        }
      })
    ).toThrow(/unknown responsibleRoleId \\"role\.missing\\"/)
  })

  it('throws when governedByKnowledge references an unknown knowledge node', () => {
    expect(() =>
      resolveOrganizationModel({
        systems: {
          'sys.lead-gen': { ...VALID_SYSTEM, governedByKnowledge: ['knowledge.missing'] }
        }
      })
    ).toThrow(/unknown knowledge node \\"knowledge\.missing\\"/)
  })

  it('throws when drivesGoals references an unknown goal', () => {
    expect(() =>
      resolveOrganizationModel({
        systems: {
          'sys.lead-gen': { ...VALID_SYSTEM, drivesGoals: ['goal.missing'] }
        }
      })
    ).toThrow(/unknown goal \\"goal\.missing\\"/)
  })
})
