/**
 * Controls composable for compliance controls management
 */

import { computed, type ComputedRef, type Ref, ref } from 'vue'
import { useComplianceStore } from '../plugin'
import type {
  Control,
  Evidence,
  Risk,
  ControlDomain,
  ImplementationStatus,
  EvidenceType,
  RiskLikelihood,
  RiskImpact,
} from '@breakpilot/compliance-sdk-types'

export interface UseControlsReturn {
  // Controls
  controls: ComputedRef<Control[]>
  controlsByDomain: ComputedRef<Record<ControlDomain, Control[]>>
  implementedControls: ComputedRef<Control[]>
  pendingControls: ComputedRef<Control[]>
  getControl: (id: string) => Control | undefined
  addControl: (control: Omit<Control, 'id' | 'createdAt' | 'updatedAt'>) => void
  updateControl: (id: string, updates: Partial<Control>) => void
  deleteControl: (id: string) => void
  setControlStatus: (id: string, status: ImplementationStatus) => void

  // Evidence
  evidence: ComputedRef<Evidence[]>
  validEvidence: ComputedRef<Evidence[]>
  expiredEvidence: ComputedRef<Evidence[]>
  getEvidenceForControl: (controlId: string) => Evidence[]
  addEvidence: (evidence: Omit<Evidence, 'id' | 'uploadedAt'>) => void
  updateEvidence: (id: string, updates: Partial<Evidence>) => void
  deleteEvidence: (id: string) => void

  // Risks
  risks: ComputedRef<Risk[]>
  criticalRisks: ComputedRef<Risk[]>
  unmitigatedRisks: ComputedRef<Risk[]>
  getRisksForControl: (controlId: string) => Risk[]
  addRisk: (risk: Omit<Risk, 'id' | 'createdAt' | 'updatedAt'>) => void
  updateRisk: (id: string, updates: Partial<Risk>) => void
  deleteRisk: (id: string) => void
  assessRisk: (id: string, likelihood: RiskLikelihood, impact: RiskImpact) => void

  // Compliance Score
  complianceScore: ComputedRef<number>
  scoreByDomain: ComputedRef<Record<ControlDomain, number>>
}

export function useControls(): UseControlsReturn {
  const store = useComplianceStore()
  const { state, dispatch, compliance } = store

  // Controls
  const controls = computed(() => state.controls)

  const controlsByDomain = computed(() => {
    const domains: ControlDomain[] = [
      'ACCESS_CONTROL',
      'DATA_PROTECTION',
      'NETWORK_SECURITY',
      'INCIDENT_RESPONSE',
      'BUSINESS_CONTINUITY',
      'COMPLIANCE',
      'RISK_MANAGEMENT',
      'ASSET_MANAGEMENT',
      'HUMAN_RESOURCES',
    ]

    return domains.reduce(
      (acc, domain) => {
        acc[domain] = state.controls.filter(c => c.domain === domain)
        return acc
      },
      {} as Record<ControlDomain, Control[]>
    )
  })

  const implementedControls = computed(() =>
    state.controls.filter(c => c.implementationStatus === 'IMPLEMENTED')
  )

  const pendingControls = computed(() =>
    state.controls.filter(c => c.implementationStatus === 'NOT_IMPLEMENTED')
  )

  const getControl = (id: string): Control | undefined => {
    return state.controls.find(c => c.id === id)
  }

  const addControl = (control: Omit<Control, 'id' | 'createdAt' | 'updatedAt'>): void => {
    dispatch({ type: 'ADD_CONTROL', payload: control })
  }

  const updateControl = (id: string, updates: Partial<Control>): void => {
    dispatch({ type: 'UPDATE_CONTROL', payload: { id, updates } })
  }

  const deleteControl = (id: string): void => {
    dispatch({ type: 'DELETE_CONTROL', payload: id })
  }

  const setControlStatus = (id: string, status: ImplementationStatus): void => {
    dispatch({
      type: 'UPDATE_CONTROL',
      payload: { id, updates: { implementationStatus: status } },
    })
  }

  // Evidence
  const evidence = computed(() => state.evidence)

  const validEvidence = computed(() => {
    const now = new Date()
    return state.evidence.filter(e => !e.validUntil || new Date(e.validUntil) > now)
  })

  const expiredEvidence = computed(() => {
    const now = new Date()
    return state.evidence.filter(e => e.validUntil && new Date(e.validUntil) <= now)
  })

  const getEvidenceForControl = (controlId: string): Evidence[] => {
    return state.evidence.filter(e => e.controlIds.includes(controlId))
  }

  const addEvidence = (ev: Omit<Evidence, 'id' | 'uploadedAt'>): void => {
    dispatch({ type: 'ADD_EVIDENCE', payload: ev })
  }

  const updateEvidence = (id: string, updates: Partial<Evidence>): void => {
    dispatch({ type: 'UPDATE_EVIDENCE', payload: { id, updates } })
  }

  const deleteEvidence = (id: string): void => {
    dispatch({ type: 'DELETE_EVIDENCE', payload: id })
  }

  // Risks
  const risks = computed(() => state.risks)

  const criticalRisks = computed(() => compliance.getCriticalRisks())

  const unmitigatedRisks = computed(() =>
    state.risks.filter(r => r.status === 'IDENTIFIED' || r.status === 'ANALYZED')
  )

  const getRisksForControl = (controlId: string): Risk[] => {
    return state.risks.filter(r => r.controlIds?.includes(controlId))
  }

  const addRisk = (risk: Omit<Risk, 'id' | 'createdAt' | 'updatedAt'>): void => {
    dispatch({ type: 'ADD_RISK', payload: risk })
  }

  const updateRisk = (id: string, updates: Partial<Risk>): void => {
    dispatch({ type: 'UPDATE_RISK', payload: { id, updates } })
  }

  const deleteRisk = (id: string): void => {
    dispatch({ type: 'DELETE_RISK', payload: id })
  }

  const assessRisk = (id: string, likelihood: RiskLikelihood, impact: RiskImpact): void => {
    const severity = likelihood * impact
    let severityLevel: Risk['severity']

    if (severity >= 20) severityLevel = 'CRITICAL'
    else if (severity >= 12) severityLevel = 'HIGH'
    else if (severity >= 6) severityLevel = 'MEDIUM'
    else severityLevel = 'LOW'

    dispatch({
      type: 'UPDATE_RISK',
      payload: {
        id,
        updates: {
          likelihood,
          impact,
          severity: severityLevel,
          status: 'ANALYZED',
        },
      },
    })
  }

  // Compliance Score
  const complianceScore = computed(() => {
    const score = compliance.calculateComplianceScore()
    return score.overall
  })

  const scoreByDomain = computed(() => {
    const domains: ControlDomain[] = [
      'ACCESS_CONTROL',
      'DATA_PROTECTION',
      'NETWORK_SECURITY',
      'INCIDENT_RESPONSE',
      'BUSINESS_CONTINUITY',
      'COMPLIANCE',
      'RISK_MANAGEMENT',
      'ASSET_MANAGEMENT',
      'HUMAN_RESOURCES',
    ]

    return domains.reduce(
      (acc, domain) => {
        const domainControls = state.controls.filter(c => c.domain === domain)
        if (domainControls.length === 0) {
          acc[domain] = 0
          return acc
        }

        const implemented = domainControls.filter(c => c.implementationStatus === 'IMPLEMENTED')
        const partial = domainControls.filter(c => c.implementationStatus === 'PARTIAL')

        acc[domain] = Math.round(
          ((implemented.length + partial.length * 0.5) / domainControls.length) * 100
        )
        return acc
      },
      {} as Record<ControlDomain, number>
    )
  })

  return {
    controls,
    controlsByDomain,
    implementedControls,
    pendingControls,
    getControl,
    addControl,
    updateControl,
    deleteControl,
    setControlStatus,
    evidence,
    validEvidence,
    expiredEvidence,
    getEvidenceForControl,
    addEvidence,
    updateEvidence,
    deleteEvidence,
    risks,
    criticalRisks,
    unmitigatedRisks,
    getRisksForControl,
    addRisk,
    updateRisk,
    deleteRisk,
    assessRisk,
    complianceScore,
    scoreByDomain,
  }
}
