/**
 * FilterPipeline — Records every filter decision for auditability.
 *
 * Tracks which findings were dismissed, downgraded, aggregated, or deduplicated
 * at each stage of the scanning pipeline. This enables answering
 * "why was finding X suppressed?" without rerunning the scan.
 *
 * Zero overhead by default — only records when explicitly enabled.
 */

export type FilterStage =
  | 'file_context_adjustment'
  | 'localhost_aggregation'
  | 'noisy_aggregation'
  | 'auto_dismiss'
  | 'confidence_scoring'
  | 'ai_validation'
  | 'global_context'
  | 'contradiction_resolution'
  | 'deduplication'
  | 'user_suppression'

export type FilterAction =
  | 'kept'
  | 'dismissed'
  | 'downgraded'
  | 'aggregated'
  | 'deduplicated'
  | 'suppressed'

export interface FilterDecision {
  stage: FilterStage
  action: FilterAction
  reason: string
  originalSeverity?: string
  newSeverity?: string
  ruleName?: string
}

export interface AnnotatedFinding {
  findingId: string
  decisions: FilterDecision[]
  finalStatus: 'surfaced' | 'dismissed'
}

export interface FilterStageSummary {
  dismissed: number
  downgraded: number
  kept: number
  aggregated: number
  deduplicated: number
  suppressed: number
}

export class FilterPipeline {
  private decisions = new Map<string, FilterDecision[]>()
  private readonly enabled: boolean

  constructor(enabled: boolean = false) {
    this.enabled = enabled
  }

  /** Record a filter decision for a finding. No-op if pipeline is disabled. */
  record(findingId: string, decision: FilterDecision): void {
    if (!this.enabled) return

    const existing = this.decisions.get(findingId)
    if (existing) {
      existing.push(decision)
    } else {
      this.decisions.set(findingId, [decision])
    }
  }

  /** Get the full audit trail for all findings. */
  getAuditTrail(): AnnotatedFinding[] {
    const trail: AnnotatedFinding[] = []

    for (const [findingId, decisions] of this.decisions) {
      const finalStatus = decisions.some(d =>
        d.action === 'dismissed' || d.action === 'deduplicated' || d.action === 'suppressed'
      ) ? 'dismissed' as const : 'surfaced' as const

      trail.push({ findingId, decisions, finalStatus })
    }

    return trail
  }

  /** Get all decisions that led to a specific finding being filtered. */
  explainDismissal(findingId: string): FilterDecision[] {
    return this.decisions.get(findingId) ?? []
  }

  /** Get summary statistics per filter stage. */
  getSummaryStats(): Record<FilterStage, FilterStageSummary> {
    const stages: FilterStage[] = [
      'file_context_adjustment',
      'localhost_aggregation',
      'noisy_aggregation',
      'auto_dismiss',
      'confidence_scoring',
      'ai_validation',
      'global_context',
      'contradiction_resolution',
      'deduplication',
      'user_suppression',
    ]

    const stats = {} as Record<FilterStage, FilterStageSummary>
    for (const stage of stages) {
      stats[stage] = { dismissed: 0, downgraded: 0, kept: 0, aggregated: 0, deduplicated: 0, suppressed: 0 }
    }

    for (const decisions of this.decisions.values()) {
      for (const d of decisions) {
        if (stats[d.stage]) {
          stats[d.stage][d.action]++
        }
      }
    }

    return stats
  }

  /** Whether this pipeline is actively recording. */
  get isEnabled(): boolean {
    return this.enabled
  }
}
