/**
 * lookup-helpers.test.ts
 *
 * Tests for recursive system-tree helpers:
 *   getSystem, getSystemAncestors, listAllSystems
 *
 * Fixtures author hierarchies through `subsystems` to verify the compatibility
 * alias still resolves into the canonical recursive `systems` tree.
 */
import { describe, expect, it } from 'vitest'
import { resolveOrganizationModel } from '../resolve'
import { getSystem, getSystemAncestors, listAllSystems } from '../helpers'
import type { OrganizationModel } from '../types'

function makeNestedModel(): OrganizationModel {
  return resolveOrganizationModel({
    systems: {
      root: {
        id: 'root',
        order: 10,
        label: 'Root',
        enabled: true,
        path: '/root',
        subsystems: {
          mid: {
            id: 'mid',
            order: 20,
            label: 'Mid',
            enabled: true,
            path: '/root/mid',
            config: { timeoutMs: 5000 },
            subsystems: {
              leaf: {
                id: 'leaf',
                order: 30,
                label: 'Leaf',
                enabled: true,
                path: '/root/mid/leaf'
              }
            }
          }
        }
      }
    }
  })
}

describe('getSystem', () => {
  it('returns a root-level system by single-segment path', () => {
    const sys = getSystem(makeNestedModel(), 'root')
    expect(sys).toBeDefined()
    expect(sys?.label).toBe('Root')
  })

  it('returns a 2-level nested system by dot-separated path', () => {
    const sys = getSystem(makeNestedModel(), 'root.mid')
    expect(sys).toBeDefined()
    expect(sys?.label).toBe('Mid')
  })

  it('returns a 3-level nested system by dot-separated path', () => {
    const sys = getSystem(makeNestedModel(), 'root.mid.leaf')
    expect(sys).toBeDefined()
    expect(sys?.label).toBe('Leaf')
  })

  it('returns a flat system whose id contains dots', () => {
    const model = resolveOrganizationModel({
      systems: {
        sales: { id: 'sales', order: 10, label: 'Sales', enabled: true, path: '/sales' },
        'sales.lead-gen': {
          id: 'sales.lead-gen',
          order: 20,
          label: 'Lead Gen',
          enabled: true,
          path: '/lead-gen'
        }
      }
    })

    expect(getSystem(model, 'sales.lead-gen')?.label).toBe('Lead Gen')
  })

  it('returns undefined for unresolved paths', () => {
    const model = makeNestedModel()
    expect(getSystem(model, 'nonexistent')).toBeUndefined()
    expect(getSystem(model, 'root.missing.leaf')).toBeUndefined()
    expect(getSystem(model, 'root.mid.leaf.deeper')).toBeUndefined()
  })

  it('returns the first-class config for a system that has config', () => {
    const sys = getSystem(makeNestedModel(), 'root.mid')
    expect(sys?.config).toEqual({ timeoutMs: 5000 })
  })
})

describe('getSystemAncestors', () => {
  it('returns root-first ancestors for resolved paths', () => {
    const model = makeNestedModel()

    expect(getSystemAncestors(model, 'root').map((system) => system.label)).toEqual(['Root'])
    expect(getSystemAncestors(model, 'root.mid').map((system) => system.label)).toEqual(['Root', 'Mid'])
    expect(getSystemAncestors(model, 'root.mid.leaf').map((system) => system.label)).toEqual([
      'Root',
      'Mid',
      'Leaf'
    ])
  })

  it('returns available ancestors for flat dotted system ids', () => {
    const model = resolveOrganizationModel({
      systems: {
        sales: { id: 'sales', order: 10, label: 'Sales', enabled: true, path: '/sales' },
        'sales.lead-gen': {
          id: 'sales.lead-gen',
          order: 20,
          label: 'Lead Gen',
          enabled: true,
          path: '/lead-gen'
        }
      }
    })

    expect(getSystemAncestors(model, 'sales.lead-gen').map((system) => system.label)).toEqual(['Sales', 'Lead Gen'])
  })

  it('returns empty arrays for unresolved paths', () => {
    const model = makeNestedModel()
    expect(getSystemAncestors(model, 'does.not.exist')).toEqual([])
    expect(getSystemAncestors(model, 'unknown.mid')).toEqual([])
  })
})

describe('listAllSystems', () => {
  it('returns an empty list for the generic default model', () => {
    expect(listAllSystems(resolveOrganizationModel())).toEqual([])
  })

  it('enumerates nested systems via subsystems in pre-order DFS order', () => {
    const paths = listAllSystems(makeNestedModel()).map((entry) => entry.path)

    expect(paths).toEqual(['root', 'root.mid', 'root.mid.leaf'])
  })

  it('each entry has a non-empty path and system object', () => {
    for (const entry of listAllSystems(makeNestedModel())) {
      expect(entry.path.length).toBeGreaterThan(0)
      expect(typeof entry.system).toBe('object')
      expect(entry.system).not.toBeNull()
    }
  })

  it('flat model returns only top-level systems', () => {
    const model = resolveOrganizationModel({
      systems: {
        lone: { id: 'lone', order: 10, label: 'Lone', enabled: true, path: '/lone' }
      }
    })

    expect(listAllSystems(model).map((entry) => entry.path)).toEqual(['lone'])
  })
})
