// Tests for ModuleCapabilityResolver (KAR-959/P2, Master-Prompt §32 gate
// replacement API).

import { describe, expect, it } from 'vitest'
import {
  moduleCapability,
  isModuleAvailable,
  isModuleUsable,
  availableModules,
  usableModules,
  shouldShowSection,
  summarizeCoverage,
} from '../module-capability-resolver'
import { detectWorkbookCapabilities } from '../capability-detector'
import type { WorkbookCapabilityMatrix } from '../types'

function matrixWith(overrides: Partial<Record<'MATERIAL' | 'SBM' | 'MANUFACTURING', 'AVAILABLE' | 'PARTIAL' | 'DERIVABLE' | 'MISSING' | 'PARSE_FAILED'>>): WorkbookCapabilityMatrix {
  const base = detectWorkbookCapabilities([], {})
  return {
    ...base,
    modules: base.modules.map((m) => (m.module in overrides ? { ...m, status: overrides[m.module as keyof typeof overrides]! } : m)),
  }
}

describe('moduleCapability / isModuleAvailable / isModuleUsable', () => {
  it('returns the finding for a covered module', () => {
    const matrix = matrixWith({ MATERIAL: 'AVAILABLE' })
    expect(moduleCapability(matrix, 'MATERIAL')?.status).toBe('AVAILABLE')
  })

  it('isModuleAvailable is true only for AVAILABLE', () => {
    const matrix = matrixWith({ MATERIAL: 'AVAILABLE', SBM: 'PARTIAL' })
    expect(isModuleAvailable(matrix, 'MATERIAL')).toBe(true)
    expect(isModuleAvailable(matrix, 'SBM')).toBe(false)
  })

  it('isModuleUsable is true for AVAILABLE, PARTIAL, and DERIVABLE, false for MISSING/PARSE_FAILED', () => {
    const matrix = matrixWith({ MATERIAL: 'AVAILABLE', SBM: 'PARTIAL', MANUFACTURING: 'DERIVABLE' })
    expect(isModuleUsable(matrix, 'MATERIAL')).toBe(true)
    expect(isModuleUsable(matrix, 'SBM')).toBe(true)
    expect(isModuleUsable(matrix, 'MANUFACTURING')).toBe(true)

    const missing = matrixWith({ MATERIAL: 'MISSING' })
    expect(isModuleUsable(missing, 'MATERIAL')).toBe(false)

    const failed = matrixWith({ MATERIAL: 'PARSE_FAILED' })
    expect(isModuleUsable(failed, 'MATERIAL')).toBe(false)
  })
})

describe('availableModules / usableModules', () => {
  it('lists only AVAILABLE modules', () => {
    const matrix = matrixWith({ MATERIAL: 'AVAILABLE', SBM: 'PARTIAL' })
    expect(availableModules(matrix)).toEqual(['MATERIAL'])
  })

  it('lists AVAILABLE + PARTIAL + DERIVABLE modules', () => {
    const matrix = matrixWith({ MATERIAL: 'AVAILABLE', SBM: 'PARTIAL', MANUFACTURING: 'DERIVABLE' })
    expect(usableModules(matrix).sort()).toEqual(['MANUFACTURING', 'MATERIAL', 'SBM'].sort())
  })
})

describe('shouldShowSection — B15/B16/B17 gate-replacement predicate', () => {
  it('is true when at least one of the given modules has usable data', () => {
    const matrix = matrixWith({ MANUFACTURING: 'PARTIAL' })
    expect(shouldShowSection(matrix, ['MANUFACTURING'])).toBe(true)
  })

  it('is false when none of the given modules has usable data (replaces an unconditional comparison_mode check)', () => {
    const matrix = matrixWith({ MANUFACTURING: 'MISSING' })
    expect(shouldShowSection(matrix, ['MANUFACTURING'])).toBe(false)
  })

  it('is true when ANY of several given modules is usable', () => {
    const matrix = matrixWith({ MANUFACTURING: 'MISSING', MATERIAL: 'AVAILABLE' })
    expect(shouldShowSection(matrix, ['MANUFACTURING', 'MATERIAL'])).toBe(true)
  })
})

describe('summarizeCoverage', () => {
  it('counts every status bucket across all 8 modules', () => {
    const matrix = matrixWith({ MATERIAL: 'AVAILABLE', SBM: 'PARTIAL', MANUFACTURING: 'DERIVABLE' })
    const summary = summarizeCoverage(matrix)
    expect(summary.totalModules).toBe(8)
    expect(summary.available).toBe(1)
    expect(summary.partial).toBe(1)
    expect(summary.derivable).toBe(1)
    expect(summary.missing + summary.parseFailed).toBe(5)
  })
})
