import { describe, expect, it } from 'vitest'
import {
  getSortedSidebarEntries,
  OrganizationModelNavigationSchema,
  SidebarNodeSchema,
  SurfaceDefinitionSchema,
  SurfaceTypeSchema
} from '../../domains/navigation'
import { ResourceMappingSchema } from '../../domains/shared'
import { OrganizationModelSchema } from '../../schema'

function makeMinimalSystems() {
  return {
    dashboard: {
      id: 'dashboard',
      order: 10,
      label: 'Dashboard',
      enabled: true,
      lifecycle: 'active' as const,
      path: '/'
    },
    sales: {
      id: 'sales',
      order: 20,
      label: 'Sales',
      enabled: true,
      lifecycle: 'active' as const,
      path: '/sales'
    }
  }
}

function makeMinimalModel(overrides: Record<string, unknown> = {}) {
  return {
    version: 1,
    branding: { organizationName: 'Test', productName: 'Test OS', shortName: 'Test' },
    systems: makeMinimalSystems(),
    entities: {},
    actions: {},
    ...overrides
  }
}

function getIssueMessages(data: unknown): string[] {
  const result = OrganizationModelSchema.safeParse(data)
  if (result.success) return []
  return result.error.issues.map((issue) => issue.message)
}

describe('SurfaceTypeSchema - closed enum regression guard', () => {
  const validSurfaceTypes = ['page', 'dashboard', 'graph', 'detail', 'list', 'settings'] as const

  it.each(validSurfaceTypes)('"%s" is a valid surfaceType', (surfaceType) => {
    expect(SurfaceTypeSchema.safeParse(surfaceType).success).toBe(true)
  })

  it('rejects an unknown surfaceType value', () => {
    expect(SurfaceTypeSchema.safeParse('spotlight').success).toBe(false)
  })
})

describe('ResourceMappingSchema resourceType - closed enum regression guard', () => {
  it('rejects an unknown resourceType value', () => {
    const result = ResourceMappingSchema.safeParse({
      id: 'rm-ext',
      label: 'Extended Resource',
      resourceId: 'res-ext',
      resourceType: 'custom-handler',
      systemIds: [],
      entityIds: [],
      surfaceIds: [],
      actionIds: []
    })

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

describe('OrganizationModelNavigationSchema', () => {
  it('defaults sidebar sections to empty records', () => {
    const result = OrganizationModelNavigationSchema.parse({})

    expect(result.sidebar.primary).toEqual({})
    expect(result.sidebar.bottom).toEqual({})
  })

  it('accepts a nested sidebar group with routeable surface leaves', () => {
    const result = SidebarNodeSchema.safeParse({
      type: 'group',
      label: 'Business',
      order: 20,
      children: {
        sales: {
          type: 'surface',
          label: 'Sales',
          path: '/sales',
          surfaceType: 'page',
          order: 10,
          targets: { systems: ['sales'] }
        }
      }
    })

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

  it('sorts record-shaped sidebar entries by order, then id', () => {
    const entries = getSortedSidebarEntries({
      zed: { type: 'surface', label: 'Zed', path: '/zed', surfaceType: 'page', order: 20 },
      alpha: { type: 'surface', label: 'Alpha', path: '/alpha', surfaceType: 'page', order: 10 },
      beta: { type: 'surface', label: 'Beta', path: '/beta', surfaceType: 'page', order: 10 }
    })

    expect(entries.map(([id]) => id)).toEqual(['alpha', 'beta', 'zed'])
  })
})

describe('OrganizationModelSchema - navigation.sidebar contract', () => {
  it('accepts authored primary and bottom sidebar sections', () => {
    const result = OrganizationModelSchema.safeParse(
      makeMinimalModel({
        navigation: {
          sidebar: {
            primary: {
              dashboard: {
                type: 'surface',
                label: 'Dashboard',
                path: '/',
                surfaceType: 'dashboard',
                order: 10,
                targets: { systems: ['dashboard'] }
              },
              business: {
                type: 'group',
                label: 'Business',
                order: 20,
                children: {
                  sales: {
                    type: 'surface',
                    label: 'Sales',
                    path: '/sales',
                    surfaceType: 'page',
                    order: 10,
                    targets: { systems: ['sales'] }
                  }
                }
              }
            },
            bottom: {
              settings: {
                type: 'surface',
                label: 'Settings',
                path: '/settings/account',
                surfaceType: 'settings',
                order: 10
              }
            }
          }
        }
      })
    )

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

  it('navigation.sidebar defaults when omitted', () => {
    const result = OrganizationModelSchema.safeParse(makeMinimalModel())

    expect(result.success).toBe(true)
    if (result.success) {
      expect(result.data.navigation.sidebar.primary).toEqual({})
      expect(result.data.navigation.sidebar.bottom).toEqual({})
      expect('surfaces' in result.data).toBe(false)
      expect('navigationGroups' in result.data).toBe(false)
    }
  })

  it('rejects duplicate sidebar node ids across sections and children', () => {
    const messages = getIssueMessages(
      makeMinimalModel({
        navigation: {
          sidebar: {
            primary: {
              sales: {
                type: 'surface',
                label: 'Sales',
                path: '/sales',
                surfaceType: 'page'
              }
            },
            bottom: {
              sales: {
                type: 'surface',
                label: 'Sales Duplicate',
                path: '/settings/sales',
                surfaceType: 'settings'
              }
            }
          }
        }
      })
    )

    expect(messages.some((message) => message.includes('duplicates another sidebar node'))).toBe(true)
  })

  it('rejects duplicate routeable surface paths', () => {
    const messages = getIssueMessages(
      makeMinimalModel({
        navigation: {
          sidebar: {
            primary: {
              first: {
                type: 'surface',
                label: 'First',
                path: '/sales',
                surfaceType: 'page'
              },
              second: {
                type: 'surface',
                label: 'Second',
                path: '/sales/',
                surfaceType: 'page'
              }
            }
          }
        }
      })
    )

    expect(messages.some((message) => message.includes('duplicates surface "first"'))).toBe(true)
  })

  it('rejects surface leaves targeting unknown systems', () => {
    const messages = getIssueMessages(
      makeMinimalModel({
        navigation: {
          sidebar: {
            primary: {
              missing: {
                type: 'surface',
                label: 'Missing',
                path: '/missing',
                surfaceType: 'page',
                targets: { systems: ['missing-system'] }
              }
            }
          }
        }
      })
    )

    expect(messages.some((message) => message.includes('references unknown system "missing-system"'))).toBe(true)
  })
})

describe('SurfaceDefinitionSchema', () => {
  it('keeps derived surface DTO validation available for projections', () => {
    const result = SurfaceDefinitionSchema.safeParse({
      id: 'minimal-surface',
      label: 'Minimal',
      path: '/minimal',
      surfaceType: 'page'
    })

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