import { FilterPipeline } from '../pipeline'
import type { FilterDecision } from '../pipeline'

describe('FilterPipeline', () => {
  describe('when disabled', () => {
    it('does not record decisions', () => {
      const pipeline = new FilterPipeline(false)
      pipeline.record('finding-1', {
        stage: 'auto_dismiss',
        action: 'dismissed',
        reason: 'test file',
      })
      expect(pipeline.getAuditTrail()).toEqual([])
    })

    it('reports isEnabled as false', () => {
      expect(new FilterPipeline(false).isEnabled).toBe(false)
      expect(new FilterPipeline().isEnabled).toBe(false)
    })
  })

  describe('when enabled', () => {
    let pipeline: FilterPipeline

    beforeEach(() => {
      pipeline = new FilterPipeline(true)
    })

    it('reports isEnabled as true', () => {
      expect(pipeline.isEnabled).toBe(true)
    })

    it('records and retrieves decisions', () => {
      const decision: FilterDecision = {
        stage: 'auto_dismiss',
        action: 'dismissed',
        reason: 'test file detected',
        ruleName: 'test_file_dismiss',
      }
      pipeline.record('finding-1', decision)

      const trail = pipeline.getAuditTrail()
      expect(trail).toHaveLength(1)
      expect(trail[0].findingId).toBe('finding-1')
      expect(trail[0].decisions).toEqual([decision])
      expect(trail[0].finalStatus).toBe('dismissed')
    })

    it('accumulates multiple decisions for the same finding', () => {
      pipeline.record('finding-1', {
        stage: 'file_context_adjustment',
        action: 'downgraded',
        reason: 'tooling directory',
        originalSeverity: 'medium',
        newSeverity: 'info',
      })
      pipeline.record('finding-1', {
        stage: 'ai_validation',
        action: 'kept',
        reason: 'AI confirmed the finding',
      })

      const decisions = pipeline.explainDismissal('finding-1')
      expect(decisions).toHaveLength(2)
      expect(decisions[0].stage).toBe('file_context_adjustment')
      expect(decisions[1].stage).toBe('ai_validation')
    })

    it('marks final status as surfaced when no dismissal', () => {
      pipeline.record('finding-1', {
        stage: 'ai_validation',
        action: 'kept',
        reason: 'confirmed',
      })

      const trail = pipeline.getAuditTrail()
      expect(trail[0].finalStatus).toBe('surfaced')
    })

    it('marks final status as dismissed for deduplicated findings', () => {
      pipeline.record('finding-1', {
        stage: 'deduplication',
        action: 'deduplicated',
        reason: 'duplicate of finding-2',
      })

      const trail = pipeline.getAuditTrail()
      expect(trail[0].finalStatus).toBe('dismissed')
    })

    it('marks final status as dismissed for suppressed findings', () => {
      pipeline.record('finding-1', {
        stage: 'user_suppression',
        action: 'suppressed',
        reason: 'inline oculum-ignore comment',
      })

      const trail = pipeline.getAuditTrail()
      expect(trail[0].finalStatus).toBe('dismissed')
    })

    it('returns empty array for unknown finding in explainDismissal', () => {
      expect(pipeline.explainDismissal('nonexistent')).toEqual([])
    })
  })

  describe('getSummaryStats', () => {
    it('aggregates counts per stage and action', () => {
      const pipeline = new FilterPipeline(true)

      pipeline.record('f1', { stage: 'auto_dismiss', action: 'dismissed', reason: 'test' })
      pipeline.record('f2', { stage: 'auto_dismiss', action: 'dismissed', reason: 'css' })
      pipeline.record('f3', { stage: 'auto_dismiss', action: 'kept', reason: 'real finding' })
      pipeline.record('f4', { stage: 'ai_validation', action: 'downgraded', reason: 'lower severity' })
      pipeline.record('f5', { stage: 'deduplication', action: 'deduplicated', reason: 'dup' })

      const stats = pipeline.getSummaryStats()

      expect(stats.auto_dismiss.dismissed).toBe(2)
      expect(stats.auto_dismiss.kept).toBe(1)
      expect(stats.ai_validation.downgraded).toBe(1)
      expect(stats.deduplication.deduplicated).toBe(1)
      expect(stats.localhost_aggregation.dismissed).toBe(0)
    })

    it('returns zero counts when no decisions recorded', () => {
      const pipeline = new FilterPipeline(true)
      const stats = pipeline.getSummaryStats()

      expect(stats.auto_dismiss.dismissed).toBe(0)
      expect(stats.confidence_scoring.kept).toBe(0)
    })
  })
})
