import { describe, expect, it } from 'vitest'
import { DEFAULT_ORGANIZATION_MODEL, scaffoldOrganizationModel, type OrganizationModel } from '..'

const BASE_MODEL: OrganizationModel = {
  ...DEFAULT_ORGANIZATION_MODEL,
  systems: {
    sales: {
      id: 'sales',
      order: 10,
      label: 'Sales',
      lifecycle: 'active',
      systems: {
        crm: {
          id: 'sales.crm',
          order: 20,
          label: 'CRM',
          lifecycle: 'active'
        }
      }
    }
  },
  resources: {},
  knowledge: {}
}

describe('organization-model scaffolders', () => {
  it('plans the minimal system scaffold without route files', () => {
    const plan = scaffoldOrganizationModel(BASE_MODEL, {
      intent: 'system',
      id: 'sales.partners',
      label: 'Partners',
      description: 'Partner operations.',
      noProject: true
    })

    expect(plan.intent).toBe('system')
    expect(plan.id).toBe('sales.partners')
    expect(plan.edits.map((edit) => edit.path)).toEqual(
      expect.arrayContaining([
        'packages/elevasis-core/src/organization-model/systems.ts',
        'packages/elevasis-core/src/organization-model/navigation.ts',
        'packages/elevasis-core/src/organization-model/roles.ts',
        'packages/elevasis-core/src/organization-model/assembly.ts',
        'packages/elevasis-core/src/organization-model/knowledge.ts'
      ])
    )
    const manifestStub = plan.writes.find((write) => write.path.endsWith('manifest.stub.ts'))
    expect(manifestStub?.content).toContain('key: "sales-partners"')
    expect(manifestStub?.content).toContain('systemId: "sales.partners"')
    expect(manifestStub?.content).not.toContain('label:')
    expect(manifestStub?.content).not.toContain('routes:')
    expect(plan.writes.some((write) => write.path.includes('/routes/'))).toBe(false)
    expect(plan.projectCommand).toBeUndefined()
  })

  it('defaults system scaffolds to a project chain unless skipped', () => {
    const plan = scaffoldOrganizationModel(BASE_MODEL, {
      intent: 'system',
      id: 'sales.enablement',
      label: 'Enablement'
    })

    expect(plan.projectCommand).toContain('project:create --link-om sales.enablement')
  })

  it('keeps ontology/resource/knowledge project chains opt-in', () => {
    const ontology = scaffoldOrganizationModel(BASE_MODEL, {
      intent: 'ontology',
      id: 'deal-score',
      systemPath: 'sales.crm',
      kind: 'object'
    })
    const resource = scaffoldOrganizationModel(BASE_MODEL, {
      intent: 'resource',
      id: 'crm-score-workflow',
      systemPath: 'sales.crm'
    })
    const knowledge = scaffoldOrganizationModel(BASE_MODEL, {
      intent: 'knowledge',
      id: 'knowledge.crm-scoring',
      systemPath: 'sales.crm'
    })

    expect(ontology.projectCommand).toBeUndefined()
    expect(resource.projectCommand).toBeUndefined()
    expect(knowledge.projectCommand).toBeUndefined()
  })

  it('emits required link ontology stubs', () => {
    const plan = scaffoldOrganizationModel(BASE_MODEL, {
      intent: 'ontology',
      id: 'deal-owner',
      systemPath: 'sales.crm',
      kind: 'link'
    })

    expect(plan.edits[0]?.snippet).toContain('"sales.crm:link/deal-owner": {')
    expect(plan.edits[0]?.snippet).toContain('"from": "sales.crm:object/source-object"')
    expect(plan.edits[0]?.snippet).toContain('"to": "sales.crm:object/target-object"')
  })

  it('emits action ontology actsOn stubs', () => {
    const plan = scaffoldOrganizationModel(BASE_MODEL, {
      intent: 'ontology',
      id: 'update-deal',
      systemPath: 'sales.crm',
      kind: 'action'
    })

    expect(plan.edits[0]?.snippet).toContain('"sales.crm:action/update-deal": {')
    expect(plan.edits[0]?.snippet).toContain('"actsOn": []')
  })

  it('rejects duplicate system paths during planning', () => {
    expect(() =>
      scaffoldOrganizationModel(BASE_MODEL, {
        intent: 'system',
        id: 'sales.crm'
      })
    ).toThrow('system already exists: sales.crm')
  })
})
