import { describe, expect, it } from 'vitest'
import { DEFAULT_ORGANIZATION_MODEL_BRANDING } from '../domains/branding'
import { getSystem, listAllSystems } from '../helpers'
import { defineOrganizationModel, resolveOrganizationModel, resolveOrganizationModelWithResources } from '../resolve'

describe('organization-model resolve', () => {
  it('resolves the system defaults', () => {
    const model = resolveOrganizationModel()

    expect(model.version).toBe(1)
    expect('surfaces' in model).toBe(false)
    expect('navigationGroups' in model).toBe(false)
    expect(model.systems).toEqual({})
    expect(model.navigation.sidebar.primary).toEqual({})
    expect(model.navigation.sidebar.bottom).toEqual({})
  })

  it('resolves authored sidebar navigation with explicit tenant systems', () => {
    const model = resolveOrganizationModel({
      navigation: {
        sidebar: {
          primary: {
            dashboard: {
              type: 'surface',
              label: 'Dashboard',
              path: '/',
              surfaceType: 'dashboard',
              order: 10,
              targets: { systems: ['dashboard'] }
            },
            business: {
              type: 'group',
              label: 'Business',
              order: 20,
              children: {
                clients: {
                  type: 'surface',
                  label: 'Clients',
                  path: '/clients',
                  surfaceType: 'list',
                  icon: 'clients',
                  order: 10,
                  targets: { systems: ['clients'] }
                }
              }
            }
          },
          bottom: {}
        }
      },
      systems: {
        dashboard: {
          id: 'dashboard',
          order: 10,
          label: 'Dashboard',
          lifecycle: 'active'
        },
        clients: {
          id: 'clients',
          order: 20,
          label: 'Clients',
          lifecycle: 'active',
          icon: 'clients'
        }
      }
    })
    const primaryEntries = Object.entries(model.navigation.sidebar.primary).sort(
      ([leftId, left], [rightId, right]) =>
        (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER) ||
        leftId.localeCompare(rightId)
    )

    expect(primaryEntries[0]?.[0]).toBe('dashboard')
    expect(primaryEntries[1]?.[0]).toBe('business')

    const business = model.navigation.sidebar.primary.business
    expect(business?.type).toBe('group')
    if (business?.type === 'group') {
      expect(business.children.clients).toMatchObject({
        type: 'surface',
        path: '/clients',
        icon: 'clients',
        targets: { systems: ['clients'] }
      })
    }
    expect(model.systems.clients?.icon).toBe('clients')
  })

  it('adds tenant systems additively to the merged record', () => {
    const baseSize = Object.keys(resolveOrganizationModel().systems).length

    const model = resolveOrganizationModel({
      systems: {
        custom: {
          id: 'custom',
          order: 10,
          label: 'Custom',
          enabled: true,
          path: '/custom'
        }
      }
    })

    expect(Object.keys(model.systems)).toHaveLength(baseSize + 1)
    expect(model.systems['custom']?.id).toBe('custom')
  })

  it('prunes flat default descendants when an override authors the same System as a nested child', () => {
    const model = resolveOrganizationModel({
      systems: {
        sales: {
          id: 'sales',
          order: 60,
          label: 'Sales',
          enabled: true,
          lifecycle: 'active',
          systems: {
            crm: {
              id: 'sales.crm',
              order: 70,
              label: 'CRM',
              enabled: true,
              lifecycle: 'active',
              path: '/crm-nested'
            }
          }
        }
      }
    })

    expect(model.systems['sales.crm']).toBeUndefined()
    expect(getSystem(model, 'sales.crm')?.path).toBe('/crm-nested')
    expect(listAllSystems(model).map(({ path }) => path)).toContain('sales.crm')
  })

  it('can resolve a full canonical model without inheriting the default fixture systems', () => {
    const model = resolveOrganizationModel(
      {
        version: 1,
        branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
        navigation: { sidebar: { primary: {}, bottom: {} } },
        systems: {
          custom: {
            id: 'custom',
            order: 10,
            label: 'Custom',
            enabled: true,
            lifecycle: 'active'
          }
        },
        resources: {},
        actions: {},
        entities: {},
        policies: {},
        knowledge: {}
      },
      { mergeDefaults: false }
    )

    expect(Object.keys(model.systems)).toEqual(['custom'])
    expect(model.systems.dashboard).toBeUndefined()
  })

  it('preserves sibling fields when overriding a nested property', () => {
    const model = resolveOrganizationModel({
      branding: {
        organizationName: 'OverriddenOrg'
      }
    })

    expect(model.branding.organizationName).toBe('OverriddenOrg')
    expect(model.branding.productName).toBe('Organization OS')
    expect(model.systems).toEqual({})
  })

  it('overrides an existing system by id when the same key is supplied', () => {
    const model = resolveOrganizationModel({
      systems: {
        dashboard: {
          id: 'dashboard',
          order: 10,
          label: 'Renamed Dashboard',
          enabled: true,
          path: '/dashboard-overridden'
        }
      }
    })

    expect(model.systems['dashboard']?.label).toBe('Renamed Dashboard')
    expect(model.systems['dashboard']?.path).toBe('/dashboard-overridden')
  })

  it('returns defineOrganizationModel input unchanged', () => {
    const input = { branding: { organizationName: 'Test', productName: 'TestOS', shortName: 'T' } }
    expect(defineOrganizationModel(input)).toBe(input)
  })
})

describe('resolveOrganizationModelWithResources', () => {
  it('populates resources on the matching system entry', () => {
    const resolved = resolveOrganizationModelWithResources({
      systems: {
        sys: {
          id: 'sys',
          order: 900,
          label: 'Sys',
          enabled: true
        },
        'sys.crm': {
          id: 'sys.crm',
          order: 910,
          label: 'CRM',
          enabled: true
        }
      },
      resources: {
        'crm-workflow': {
          id: 'crm-workflow',
          kind: 'workflow',
          systemPath: 'sys.crm',
          status: 'active',
          order: 10
        }
      }
    })

    const crmSystem = resolved.systems['sys.crm']
    expect(crmSystem?.resources).toHaveLength(1)
    expect(crmSystem?.resources?.[0]?.id).toBe('crm-workflow')
  })

  it('leaves systems without resources with no resources property', () => {
    const resolved = resolveOrganizationModelWithResources({
      systems: {
        sys: {
          id: 'sys',
          order: 900,
          label: 'Sys',
          enabled: true
        }
      }
    })

    // sys has no resources attached — property should be absent (undefined)
    expect(resolved.systems['sys']?.resources).toBeUndefined()
  })

  it('does not include descendant resources in the direct system entry', () => {
    const resolved = resolveOrganizationModelWithResources({
      systems: {
        sys: {
          id: 'sys',
          order: 900,
          label: 'Sys',
          enabled: true
        },
        'sys.crm': {
          id: 'sys.crm',
          order: 910,
          label: 'CRM',
          enabled: true
        }
      },
      resources: {
        'crm-workflow': {
          id: 'crm-workflow',
          kind: 'workflow',
          systemPath: 'sys.crm',
          status: 'active',
          order: 10
        }
      }
    })

    // 'sys' parent should NOT pick up the child's resource
    expect(resolved.systems['sys']?.resources).toBeUndefined()
  })

  it('groups multiple resources under the correct system', () => {
    const resolved = resolveOrganizationModelWithResources({
      systems: {
        sys: {
          id: 'sys',
          order: 900,
          label: 'Sys',
          enabled: true
        },
        'sys.crm': {
          id: 'sys.crm',
          order: 910,
          label: 'CRM',
          enabled: true
        }
      },
      resources: {
        'crm-workflow-a': {
          id: 'crm-workflow-a',
          kind: 'workflow',
          systemPath: 'sys.crm',
          status: 'active',
          order: 10
        },
        'crm-workflow-b': {
          id: 'crm-workflow-b',
          kind: 'workflow',
          systemPath: 'sys.crm',
          status: 'active',
          order: 20
        }
      }
    })

    expect(resolved.systems['sys.crm']?.resources).toHaveLength(2)
  })

  it('enriches nested systems with direct resources and effective local config', () => {
    const resolved = resolveOrganizationModelWithResources({
      systems: {
        sys: {
          id: 'sys',
          order: 900,
          label: 'Sys',
          enabled: true,
          config: { parentOnly: true },
          systems: {
            crm: {
              id: 'crm',
              order: 910,
              label: 'CRM',
              enabled: true,
              config: { retryCount: 3, fromConfig: true }
            }
          }
        }
      },
      resources: {
        'sys-workflow': {
          id: 'sys-workflow',
          kind: 'workflow',
          systemPath: 'sys',
          status: 'active',
          order: 10
        },
        'crm-workflow': {
          id: 'crm-workflow',
          kind: 'workflow',
          systemPath: 'sys.crm',
          status: 'active',
          order: 20
        }
      }
    })

    expect(resolved.systems.sys?.resources?.map((resource) => resource.id)).toEqual(['sys-workflow'])
    expect(resolved.systems['sys.crm']?.id).toBe('sys.crm')
    expect(resolved.systems['sys.crm']?.resources?.map((resource) => resource.id)).toEqual(['crm-workflow'])
    expect(resolved.systems['sys.crm']?.config).toEqual({ retryCount: 3, fromConfig: true })
  })
})
