/**
 * Security Module
 *
 * Security scanning and SBOM management
 */

import type {
  SBOM,
  SecurityIssue,
  SecurityScanResult,
  BacklogItem,
  SecurityIssueSeverity,
  SecurityTool,
  FindingsSummary,
  SDKState,
} from '@breakpilot/compliance-sdk-types'
import { ComplianceClient } from '../client'

export class SecurityModule {
  private client: ComplianceClient
  private getState: () => SDKState

  constructor(client: ComplianceClient, getState: () => SDKState) {
    this.client = client
    this.getState = getState
  }

  // ---------------------------------------------------------------------------
  // Security Scanning
  // ---------------------------------------------------------------------------

  async startScan(options?: {
    tools?: SecurityTool[]
    targetPath?: string
    severityThreshold?: SecurityIssueSeverity
    generateSBOM?: boolean
  }): Promise<{ id: string; status: string }> {
    return this.client.startSecurityScan({
      tools: options?.tools,
      targetPath: options?.targetPath,
      severityThreshold: options?.severityThreshold,
      generateSBOM: options?.generateSBOM ?? true,
    })
  }

  async getScanResult(scanId: string): Promise<SecurityScanResult | null> {
    const result = await this.client.getSecurityScanResult(scanId)
    return result as SecurityScanResult | null
  }

  getLastScanResult(): SecurityScanResult | null {
    const screening = this.getState().screening
    return screening?.securityScan ?? null
  }

  // ---------------------------------------------------------------------------
  // SBOM
  // ---------------------------------------------------------------------------

  getSBOM(): SBOM | null {
    return this.getState().sbom
  }

  getComponents() {
    return this.getSBOM()?.components ?? []
  }

  getComponentsByLicense(license: string) {
    return this.getComponents().filter(c => c.licenses.includes(license as never))
  }

  getVulnerableComponents() {
    return this.getComponents().filter(c => c.vulnerabilities.length > 0)
  }

  getLicenseSummary(): Record<string, number> {
    const components = this.getComponents()
    const summary: Record<string, number> = {}

    components.forEach(c => {
      c.licenses.forEach(license => {
        summary[license] = (summary[license] || 0) + 1
      })
    })

    return summary
  }

  // ---------------------------------------------------------------------------
  // Security Issues
  // ---------------------------------------------------------------------------

  getSecurityIssues(): SecurityIssue[] {
    return this.getState().securityIssues
  }

  getIssueById(id: string): SecurityIssue | undefined {
    return this.getSecurityIssues().find(i => i.id === id)
  }

  getIssuesBySeverity(severity: SecurityIssueSeverity): SecurityIssue[] {
    return this.getSecurityIssues().filter(i => i.severity === severity)
  }

  getIssuesByStatus(status: string): SecurityIssue[] {
    return this.getSecurityIssues().filter(i => i.status === status)
  }

  getIssuesByTool(tool: SecurityTool): SecurityIssue[] {
    return this.getSecurityIssues().filter(i => i.tool === tool)
  }

  getOpenIssues(): SecurityIssue[] {
    return this.getSecurityIssues().filter(i => i.status === 'OPEN' || i.status === 'IN_PROGRESS')
  }

  getCriticalIssues(): SecurityIssue[] {
    return this.getSecurityIssues().filter(
      i => (i.severity === 'CRITICAL' || i.severity === 'HIGH') && i.status === 'OPEN'
    )
  }

  // ---------------------------------------------------------------------------
  // Backlog
  // ---------------------------------------------------------------------------

  getBacklog(): BacklogItem[] {
    return this.getState().securityBacklog
  }

  getBacklogByStatus(status: 'OPEN' | 'IN_PROGRESS' | 'DONE'): BacklogItem[] {
    return this.getBacklog().filter(i => i.status === status)
  }

  getOverdueBacklogItems(): BacklogItem[] {
    const now = new Date()
    return this.getBacklog().filter(i => {
      if (!i.dueDate || i.status === 'DONE') return false
      return new Date(i.dueDate) < now
    })
  }

  // ---------------------------------------------------------------------------
  // Summary & Statistics
  // ---------------------------------------------------------------------------

  getSecuritySummary(): FindingsSummary {
    const issues = this.getSecurityIssues()

    const bySeverity: Record<SecurityIssueSeverity, number> = {
      CRITICAL: 0,
      HIGH: 0,
      MEDIUM: 0,
      LOW: 0,
      INFO: 0,
    }

    const byStatus: Record<string, number> = {
      OPEN: 0,
      IN_PROGRESS: 0,
      RESOLVED: 0,
      ACCEPTED: 0,
      FALSE_POSITIVE: 0,
    }

    const byTool: Record<string, number> = {}

    issues.forEach(issue => {
      bySeverity[issue.severity]++
      byStatus[issue.status]++
      byTool[issue.tool] = (byTool[issue.tool] || 0) + 1
    })

    // Calculate average resolution time for resolved issues
    const resolvedIssues = issues.filter(i => i.status === 'RESOLVED' && i.resolvedAt)
    let averageResolutionDays = 0
    if (resolvedIssues.length > 0) {
      const totalDays = resolvedIssues.reduce((sum, issue) => {
        // Would need createdAt field to calculate properly
        return sum + 7 // Placeholder
      }, 0)
      averageResolutionDays = Math.round(totalDays / resolvedIssues.length)
    }

    // Find oldest unresolved issue
    const openIssues = issues.filter(i => i.status === 'OPEN')
    let oldestUnresolvedDays = 0
    // Would need createdAt field to calculate properly

    return {
      totalFindings: issues.length,
      bySeverity,
      byStatus: byStatus as Record<string, number>,
      byTool: byTool as Record<SecurityTool, number>,
      averageResolutionDays,
      oldestUnresolvedDays,
    }
  }

  getSecurityScore(): number {
    const issues = this.getSecurityIssues()
    const openIssues = issues.filter(i => i.status === 'OPEN' || i.status === 'IN_PROGRESS')

    if (issues.length === 0) return 100

    // Weight by severity
    const severityWeights = {
      CRITICAL: 10,
      HIGH: 5,
      MEDIUM: 2,
      LOW: 1,
      INFO: 0,
    }

    const totalWeight = issues.reduce((sum, i) => sum + severityWeights[i.severity], 0)
    const openWeight = openIssues.reduce((sum, i) => sum + severityWeights[i.severity], 0)

    if (totalWeight === 0) return 100

    return Math.round(((totalWeight - openWeight) / totalWeight) * 100)
  }

  // ---------------------------------------------------------------------------
  // Utilities
  // ---------------------------------------------------------------------------

  getAvailableTools(): SecurityTool[] {
    return ['gitleaks', 'semgrep', 'bandit', 'trivy', 'grype', 'syft']
  }

  async exportSBOM(format: 'CycloneDX' | 'SPDX'): Promise<Blob> {
    return this.client.exportState(format === 'CycloneDX' ? 'json' : 'json')
  }
}

export function createSecurityModule(
  client: ComplianceClient,
  getState: () => SDKState
): SecurityModule {
  return new SecurityModule(client, getState)
}
