/**
 * Regression tests for resource-registry nested-systems lookup (Wave 1 hotfix).
 *
 * Before the fix, `listResourcesForOrganization` built the systems map with
 * `Object.values(org.systems)`, which only surfaced top-level entries. Systems
 * declared as children under `system.subsystems` were invisible, so
 * `summarizeSystem` always returned `undefined` for nested paths.
 *
 * After the fix, the map is built via `listAllSystems` (DFS), which walks the
 * full tree and keys every entry by its dot-joined path.
 */
import { describe, it, expect } from 'vitest'
import { z } from 'zod'
import { ResourceRegistry } from '../resource-registry'
import type { SystemEntry } from '../../../organization-model/domains/systems'
import type { ResourceEntry } from '../../../organization-model/domains/resources'
import { OrganizationModelSchema } from '../../../organization-model/schema'
import type { OrganizationModel } from '../../../organization-model/types'
import type { WorkflowDefinition } from '../../../execution/engine/workflow/types'

// ---------------------------------------------------------------------------
// Minimal fixture helpers
// ---------------------------------------------------------------------------

function makeWorkflow(resourceId: string, resource?: ResourceEntry): WorkflowDefinition {
  return {
    config: {
      resourceId,
      name: `Workflow ${resourceId}`,
      description: `Test workflow ${resourceId}`,
      version: '1.0.0',
      type: 'workflow',
      status: 'prod',
      resource
    },
    contract: {
      inputSchema: z.object({ input: z.string() }),
      outputSchema: z.object({ output: z.string() })
    },
    steps: {
      step1: {
        id: 'step1',
        name: 'Step 1',
        description: 'Only step',
        handler: async () => ({ output: 'ok' }),
        inputSchema: z.object({ input: z.string() }),
        outputSchema: z.object({ output: z.string() }),
        next: null
      }
    },
    entryPoint: 'step1'
  }
}

function makeOrganizationModel(
  systems: Record<string, SystemEntry>,
  resources: Record<string, ResourceEntry>
): OrganizationModel {
  return OrganizationModelSchema.parse({
    systems,
    resources
  })
}

// ---------------------------------------------------------------------------
// Fixture: two-level system tree
//
//   systems
//   └── acquisition          (top-level, id: 'acquisition')
//       └── subsystems
//           └── outbound     (nested, id: 'outbound')  ← formerly invisible
// ---------------------------------------------------------------------------

const topLevelSystem: SystemEntry = {
  id: 'acquisition',
  label: 'Acquisition',
  description: 'Top-level acquisition system.',
  kind: 'operational',
  governedByKnowledge: [],
  drivesGoals: [],
  lifecycle: 'active',
  order: 10
}

const nestedSystem: SystemEntry = {
  id: 'outbound',
  label: 'Outbound',
  description: 'Outbound automation sub-system.',
  kind: 'operational',
  governedByKnowledge: [],
  drivesGoals: [],
  lifecycle: 'active',
  order: 10
}

/** Dot-joined path for the nested system as it appears in resource.systemPath */
const NESTED_SYSTEM_PATH = 'acquisition.outbound'

const topLevelSystemWithChildren: SystemEntry = {
  ...topLevelSystem,
  subsystems: {
    outbound: nestedSystem
  }
}

const nestedSystemResource: ResourceEntry = {
  id: 'cold-outreach-workflow',
  kind: 'workflow',
  systemPath: NESTED_SYSTEM_PATH,
  status: 'active',
  order: 10
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

describe('ResourceRegistry — nested-systems lookup regression', () => {
  it('resolves system metadata for a TOP-LEVEL system path', () => {
    const topResource: ResourceEntry = {
      id: 'top-workflow',
      kind: 'workflow',
      systemPath: 'acquisition',
      status: 'active',
      order: 10
    }
    const workflow = makeWorkflow('top-workflow', topResource)

    const registry = new ResourceRegistry({
      'test-org': {
        version: '1.0.0',
        organizationModel: makeOrganizationModel(
          { acquisition: topLevelSystemWithChildren },
          { 'top-workflow': topResource }
        ),
        workflows: [workflow]
      }
    })

    const result = registry.listResourcesForOrganization('test-org')

    expect(result.workflows).toHaveLength(1)
    expect(result.workflows[0].system).toBeDefined()
    expect(result.workflows[0].system).toMatchObject({
      id: 'acquisition',
      title: 'Acquisition',
      kind: 'operational',
      lifecycle: 'active'
    })
    expect(result.workflows[0].systemPath).toBe('acquisition')
  })

  it('resolves system metadata for a NESTED system path (the regression case)', () => {
    const workflow = makeWorkflow('cold-outreach-workflow', nestedSystemResource)

    const registry = new ResourceRegistry({
      'test-org': {
        version: '1.0.0',
        organizationModel: makeOrganizationModel(
          // The nested system lives under acquisition.subsystems, NOT as a top-level key.
          // Before the fix, Object.values(systems) missed this entirely.
          { acquisition: topLevelSystemWithChildren },
          { 'cold-outreach-workflow': nestedSystemResource }
        ),
        workflows: [workflow]
      }
    })

    const result = registry.listResourcesForOrganization('test-org')

    expect(result.workflows).toHaveLength(1)
    // Before the fix this was undefined; it must now be defined.
    expect(result.workflows[0].system).toBeDefined()
    expect(result.workflows[0].system).toMatchObject({
      id: 'outbound',
      title: 'Outbound',
      kind: 'operational',
      lifecycle: 'active'
    })
    expect(result.workflows[0].systemPath).toBe(NESTED_SYSTEM_PATH)
    expect(result.workflows[0].governanceStatus).toBe('active')
  })

  it('resolves system metadata for a THREE-level nested path', () => {
    const deepSystem: SystemEntry = {
      id: 'sequences',
      label: 'Sequences',
      description: 'Email sequence sub-sub-system.',
      kind: 'operational',
      governedByKnowledge: [],
      drivesGoals: [],
      lifecycle: 'active',
      order: 10
    }

    const outboundWithChildren: SystemEntry = {
      ...nestedSystem,
      subsystems: { sequences: deepSystem }
    }

    const topWithDeepNesting: SystemEntry = {
      ...topLevelSystem,
      subsystems: { outbound: outboundWithChildren }
    }

    const deepResource: ResourceEntry = {
      id: 'sequence-enroller',
      kind: 'workflow',
      systemPath: 'acquisition.outbound.sequences',
      status: 'active',
      order: 10
    }

    const workflow = makeWorkflow('sequence-enroller', deepResource)

    const registry = new ResourceRegistry({
      'test-org': {
        version: '1.0.0',
        organizationModel: makeOrganizationModel(
          { acquisition: topWithDeepNesting },
          { 'sequence-enroller': deepResource }
        ),
        workflows: [workflow]
      }
    })

    const result = registry.listResourcesForOrganization('test-org')

    expect(result.workflows).toHaveLength(1)
    expect(result.workflows[0].system).toBeDefined()
    expect(result.workflows[0].system).toMatchObject({
      id: 'sequences',
      title: 'Sequences',
      lifecycle: 'active'
    })
    expect(result.workflows[0].systemPath).toBe('acquisition.outbound.sequences')
  })

  it('returns undefined system when the workflow has no resource descriptor and no OM entry', () => {
    // A workflow with no OM resource descriptor and no organizationModel at all
    // should leave system undefined (no governance metadata attached).
    const workflow = makeWorkflow('bare-workflow')

    const registry = new ResourceRegistry({
      'test-org': {
        version: '1.0.0',
        workflows: [workflow]
      }
    })

    const result = registry.listResourcesForOrganization('test-org')

    expect(result.workflows).toHaveLength(1)
    expect(result.workflows[0].system).toBeUndefined()
    expect(result.workflows[0].systemPath).toBeUndefined()
  })
})
