import { describe, it, expect } from 'vitest'
import {
  SDK_STEPS,
  getStepById,
  getStepByUrl,
  getNextStep,
  getPreviousStep,
  getCompletionPercentage,
  getPhaseCompletionPercentage,
  type SDKState,
} from '../types'

describe('SDK_STEPS', () => {
  it('should have steps defined for both phases', () => {
    const phase1Steps = SDK_STEPS.filter(s => s.phase === 1)
    const phase2Steps = SDK_STEPS.filter(s => s.phase === 2)

    expect(phase1Steps.length).toBeGreaterThan(0)
    expect(phase2Steps.length).toBeGreaterThan(0)
  })

  it('should have unique IDs for all steps', () => {
    const ids = SDK_STEPS.map(s => s.id)
    const uniqueIds = new Set(ids)
    expect(uniqueIds.size).toBe(ids.length)
  })

  it('should have unique URLs for all steps', () => {
    const urls = SDK_STEPS.map(s => s.url)
    const uniqueUrls = new Set(urls)
    expect(uniqueUrls.size).toBe(urls.length)
  })

  it('should have checkpoint IDs for all steps', () => {
    SDK_STEPS.forEach(step => {
      expect(step.checkpointId).toBeDefined()
      expect(step.checkpointId.length).toBeGreaterThan(0)
    })
  })
})

describe('getStepById', () => {
  it('should return the correct step for a valid ID', () => {
    const step = getStepById('use-case-assessment')
    expect(step).toBeDefined()
    expect(step?.name).toBe('Anwendungsfall-Erfassung')
  })

  it('should return undefined for an invalid ID', () => {
    const step = getStepById('invalid-step-id')
    expect(step).toBeUndefined()
  })

  it('should find steps in Phase 2', () => {
    const step = getStepById('dsfa')
    expect(step).toBeDefined()
    expect(step?.phase).toBe(2)
  })
})

describe('getStepByUrl', () => {
  it('should return the correct step for a valid URL', () => {
    const step = getStepByUrl('/sdk/advisory-board')
    expect(step).toBeDefined()
    expect(step?.id).toBe('use-case-assessment')
  })

  it('should return undefined for an invalid URL', () => {
    const step = getStepByUrl('/invalid/url')
    expect(step).toBeUndefined()
  })

  it('should find Phase 2 steps by URL', () => {
    const step = getStepByUrl('/sdk/dsfa')
    expect(step).toBeDefined()
    expect(step?.id).toBe('dsfa')
  })
})

describe('getNextStep', () => {
  // getNextStep walks the steps ordered by `seq` (not array order), so the
  // expectations are derived from the seq-sorted sequence to stay correct when
  // steps are reordered or inserted (e.g. ai-act seq 350 sits before import 400).
  const bySeq = [...SDK_STEPS].sort((a, b) => a.seq - b.seq)

  it('should return the next step in sequence', () => {
    const idx = bySeq.findIndex(s => s.id === 'use-case-assessment')
    const nextStep = getNextStep('use-case-assessment')
    expect(nextStep).toBeDefined()
    expect(nextStep?.id).toBe(bySeq[idx + 1].id)
  })

  it('should return undefined for the last step', () => {
    const lastStep = bySeq[bySeq.length - 1]
    const nextStep = getNextStep(lastStep.id)
    expect(nextStep).toBeUndefined()
  })

  it('should handle transition between phases', () => {
    const lastPhase1Step = SDK_STEPS.filter(s => s.phase === 1).pop()
    expect(lastPhase1Step).toBeDefined()

    const nextStep = getNextStep(lastPhase1Step!.id)
    expect(nextStep?.phase).toBe(2)
  })
})

describe('getPreviousStep', () => {
  it('should return the previous step in sequence', () => {
    const prevStep = getPreviousStep('screening')
    expect(prevStep).toBeDefined()
    expect(prevStep?.id).toBe('import')
  })

  it('should return undefined for the first step', () => {
    const prevStep = getPreviousStep('company-profile')
    expect(prevStep).toBeUndefined()
  })
})

describe('getCompletionPercentage', () => {
  const createMockState = (completedSteps: string[]) => ({
    version: '1.0.0',
    projectVersion: 1,
    lastModified: new Date(),
    tenantId: 'test',
    userId: 'test',
    subscription: 'PROFESSIONAL',
    projectId: 'test-project',
    projectInfo: null,
    customerType: null,
    companyProfile: null,
    complianceScope: null,
    sourcePolicy: null,
    currentPhase: 1,
    currentStep: 'use-case-assessment',
    completedSteps,
    checkpoints: {},
    importedDocuments: [],
    gapAnalysis: null,
    useCases: [],
    activeUseCase: null,
    screening: null,
    modules: [],
    requirements: [],
    controls: [],
    evidence: [],
    checklist: [],
    risks: [],
    aiActClassification: null,
    obligations: [],
    dsfa: null,
    toms: [],
    retentionPolicies: [],
    vvt: [],
    documents: [],
    cookieBanner: null,
    consents: [],
    dsrConfig: null,
    escalationWorkflows: [],
    iaceProjects: [],
    ragCorpusStatus: null,
    sbom: null,
    securityIssues: [],
    securityBacklog: [],
    customCatalogs: {},
    commandBarHistory: [],
    recentSearches: [],
    preferences: {
      language: 'de',
      theme: 'light',
      compactMode: false,
      showHints: true,
      autoSave: true,
      autoValidate: true,
      allowParallelWork: true,
    },
  }) as SDKState

  it('should return 0 for no completed steps', () => {
    const state = createMockState([])
    const percentage = getCompletionPercentage(state)
    expect(percentage).toBe(0)
  })

  it('should return 100 for all completed steps', () => {
    const allStepIds = SDK_STEPS.map(s => s.id)
    const state = createMockState(allStepIds)
    const percentage = getCompletionPercentage(state)
    expect(percentage).toBe(100)
  })

  it('should calculate correct percentage for partial completion', () => {
    const halfSteps = SDK_STEPS.slice(0, Math.floor(SDK_STEPS.length / 2)).map(s => s.id)
    const state = createMockState(halfSteps)
    const percentage = getCompletionPercentage(state)
    expect(percentage).toBeGreaterThan(40)
    expect(percentage).toBeLessThan(60)
  })
})

describe('getPhaseCompletionPercentage', () => {
  const createMockState = (completedSteps: string[]) => ({
    version: '1.0.0',
    projectVersion: 1,
    lastModified: new Date(),
    tenantId: 'test',
    userId: 'test',
    subscription: 'PROFESSIONAL',
    projectId: 'test-project',
    projectInfo: null,
    customerType: null,
    companyProfile: null,
    complianceScope: null,
    sourcePolicy: null,
    currentPhase: 1,
    currentStep: 'use-case-assessment',
    completedSteps,
    checkpoints: {},
    importedDocuments: [],
    gapAnalysis: null,
    useCases: [],
    activeUseCase: null,
    screening: null,
    modules: [],
    requirements: [],
    controls: [],
    evidence: [],
    checklist: [],
    risks: [],
    aiActClassification: null,
    obligations: [],
    dsfa: null,
    toms: [],
    retentionPolicies: [],
    vvt: [],
    documents: [],
    cookieBanner: null,
    consents: [],
    dsrConfig: null,
    escalationWorkflows: [],
    iaceProjects: [],
    ragCorpusStatus: null,
    sbom: null,
    securityIssues: [],
    securityBacklog: [],
    customCatalogs: {},
    commandBarHistory: [],
    recentSearches: [],
    preferences: {
      language: 'de',
      theme: 'light',
      compactMode: false,
      showHints: true,
      autoSave: true,
      autoValidate: true,
      allowParallelWork: true,
    },
  }) as SDKState

  it('should return 0 for Phase 1 with no completed steps', () => {
    const state = createMockState([])
    const percentage = getPhaseCompletionPercentage(state, 1)
    expect(percentage).toBe(0)
  })

  it('should return 100 for Phase 1 when all Phase 1 steps are complete', () => {
    const phase1Steps = SDK_STEPS.filter(s => s.phase === 1).map(s => s.id)
    const state = createMockState(phase1Steps)
    const percentage = getPhaseCompletionPercentage(state, 1)
    expect(percentage).toBe(100)
  })

  it('should not count Phase 2 steps in Phase 1 percentage', () => {
    const phase2Steps = SDK_STEPS.filter(s => s.phase === 2).map(s => s.id)
    const state = createMockState(phase2Steps)
    const percentage = getPhaseCompletionPercentage(state, 1)
    expect(percentage).toBe(0)
  })
})
