/**
 * Security composable for SBOM and security scanning
 */

import { computed, type ComputedRef, type Ref, ref } from 'vue'
import { useComplianceStore } from '../plugin'
import type {
  SBOM,
  SBOMComponent,
  SecurityIssue,
  Vulnerability,
  SecurityScanResult,
} from '@breakpilot/compliance-sdk-types'

export interface UseSecurityReturn {
  // SBOM
  sbom: ComputedRef<SBOM | null>
  components: ComputedRef<SBOMComponent[]>
  componentsByCategory: ComputedRef<Record<string, SBOMComponent[]>>
  vulnerableComponents: ComputedRef<SBOMComponent[]>
  generateSBOM: (source?: string) => Promise<SBOM>
  exportSBOM: (format: 'cyclonedx' | 'spdx') => Promise<Blob>

  // Security Issues
  securityIssues: ComputedRef<SecurityIssue[]>
  criticalIssues: ComputedRef<SecurityIssue[]>
  openIssues: ComputedRef<SecurityIssue[]>
  issuesBySeverity: ComputedRef<Record<string, SecurityIssue[]>>

  // Scanning
  scan: (options?: ScanOptions) => Promise<SecurityScanResult>
  lastScanResult: Ref<SecurityScanResult | null>
  isScanning: Ref<boolean>

  // Vulnerabilities
  vulnerabilities: ComputedRef<Vulnerability[]>
  getVulnerabilitiesForComponent: (componentId: string) => Vulnerability[]

  // Loading state
  isLoading: Ref<boolean>
  error: Ref<Error | null>
}

export interface ScanOptions {
  tools?: string[]
  targetPath?: string
  excludePaths?: string[]
}

export function useSecurity(): UseSecurityReturn {
  const store = useComplianceStore()
  const { state, security } = store

  const isLoading = ref(false)
  const isScanning = ref(false)
  const error = ref<Error | null>(null)
  const lastScanResult = ref<SecurityScanResult | null>(null)

  // SBOM
  const sbom = computed(() => state.sbom)

  const components = computed(() => state.sbom?.components || [])

  const componentsByCategory = computed(() => {
    const comps = state.sbom?.components || []
    return comps.reduce(
      (acc, comp) => {
        const cat = comp.category || 'other'
        if (!acc[cat]) acc[cat] = []
        acc[cat].push(comp)
        return acc
      },
      {} as Record<string, SBOMComponent[]>
    )
  })

  const vulnerableComponents = computed(() => {
    return components.value.filter(c => c.vulnerabilities && c.vulnerabilities.length > 0)
  })

  const generateSBOM = async (source?: string): Promise<SBOM> => {
    isLoading.value = true
    error.value = null

    try {
      return await security.generateSBOM(source)
    } catch (err) {
      error.value = err instanceof Error ? err : new Error(String(err))
      throw err
    } finally {
      isLoading.value = false
    }
  }

  const exportSBOM = async (format: 'cyclonedx' | 'spdx'): Promise<Blob> => {
    isLoading.value = true
    error.value = null

    try {
      return await security.exportSBOM(format)
    } catch (err) {
      error.value = err instanceof Error ? err : new Error(String(err))
      throw err
    } finally {
      isLoading.value = false
    }
  }

  // Security Issues
  const securityIssues = computed(() => state.securityIssues)

  const criticalIssues = computed(() =>
    state.securityIssues.filter(i => i.severity === 'CRITICAL' || i.severity === 'HIGH')
  )

  const openIssues = computed(() =>
    state.securityIssues.filter(i => i.status === 'OPEN' || i.status === 'IN_PROGRESS')
  )

  const issuesBySeverity = computed(() => {
    return state.securityIssues.reduce(
      (acc, issue) => {
        if (!acc[issue.severity]) acc[issue.severity] = []
        acc[issue.severity].push(issue)
        return acc
      },
      {} as Record<string, SecurityIssue[]>
    )
  })

  // Scanning
  const scan = async (options?: ScanOptions): Promise<SecurityScanResult> => {
    isScanning.value = true
    isLoading.value = true
    error.value = null

    try {
      const result = await security.scan(options)
      lastScanResult.value = result
      return result
    } catch (err) {
      error.value = err instanceof Error ? err : new Error(String(err))
      throw err
    } finally {
      isScanning.value = false
      isLoading.value = false
    }
  }

  // Vulnerabilities
  const vulnerabilities = computed(() => {
    const vulns: Vulnerability[] = []
    components.value.forEach(comp => {
      if (comp.vulnerabilities) {
        vulns.push(...comp.vulnerabilities)
      }
    })
    return vulns
  })

  const getVulnerabilitiesForComponent = (componentId: string): Vulnerability[] => {
    const comp = components.value.find(c => c.name === componentId)
    return comp?.vulnerabilities || []
  }

  return {
    sbom,
    components,
    componentsByCategory,
    vulnerableComponents,
    generateSBOM,
    exportSBOM,
    securityIssues,
    criticalIssues,
    openIssues,
    issuesBySeverity,
    scan,
    lastScanResult,
    isScanning,
    vulnerabilities,
    getVulnerabilitiesForComponent,
    isLoading,
    error,
  }
}
