'use client' import { useState, useEffect } from 'react' import { useSDK, Risk, RiskLikelihood, RiskImpact, RiskSeverity, RiskStatus, RiskMitigation, calculateRiskScore, getRiskSeverityFromScore } from '@/lib/sdk' import { RiskFormData } from '../_components/RiskForm' export function useRisks() { const { state, dispatch, addRisk } = useSDK() const [showForm, setShowForm] = useState(false) const [editingRisk, setEditingRisk] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [matrixFilter, setMatrixFilter] = useState<{ likelihood: number; impact: number } | null>(null) useEffect(() => { const fetchRisks = async () => { try { setLoading(true) const res = await fetch('/api/sdk/v1/compliance/risks') if (res.ok) { const data = await res.json() const backendRisks = data.risks || data if (Array.isArray(backendRisks) && backendRisks.length > 0) { const mapped: Risk[] = backendRisks.map((r: Record) => ({ id: (r.risk_id || r.id || '') as string, title: (r.title || '') as string, description: (r.description || '') as string, category: (r.category || 'technical') as string, likelihood: (r.likelihood || 3) as RiskLikelihood, impact: (r.impact || 3) as RiskImpact, severity: ((r.inherent_risk || r.severity || 'MEDIUM') as string).toUpperCase() as RiskSeverity, inherentRiskScore: (r.likelihood as number || 3) * (r.impact as number || 3), residualRiskScore: (r.residual_likelihood as number || r.likelihood as number || 3) * (r.residual_impact as number || r.impact as number || 3), status: (r.status || 'IDENTIFIED') as RiskStatus, mitigation: (Array.isArray(r.mitigating_controls) ? (r.mitigating_controls as RiskMitigation[]) : []) as RiskMitigation[], owner: (r.owner || null) as string | null, relatedControls: [] as string[], relatedRequirements: [] as string[], })) dispatch({ type: 'SET_STATE', payload: { risks: mapped } }) setError(null) } } } catch { // Backend unavailable — use SDK state as-is } finally { setLoading(false) } } fetchRisks() }, []) // eslint-disable-line react-hooks/exhaustive-deps const handleSubmit = async (data: RiskFormData) => { const score = calculateRiskScore(data.likelihood, data.impact) const severity = getRiskSeverityFromScore(score) if (editingRisk) { dispatch({ type: 'UPDATE_RISK', payload: { id: editingRisk.id, data: { ...data, severity, inherentRiskScore: score, residualRiskScore: score }, }, }) try { await fetch(`/api/sdk/v1/compliance/risks/${editingRisk.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title: data.title, description: data.description, category: data.category, likelihood: data.likelihood, impact: data.impact, }), }) } catch { // Silently fail } } else { const riskId = `risk-${Date.now()}` const newRisk: Risk = { id: riskId, ...data, severity, inherentRiskScore: score, residualRiskScore: score, status: 'IDENTIFIED', mitigation: [], owner: null, relatedControls: [], relatedRequirements: [], } addRisk(newRisk) try { await fetch('/api/sdk/v1/compliance/risks', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ risk_id: riskId, title: data.title, description: data.description, category: data.category, likelihood: data.likelihood, impact: data.impact, }), }) } catch { // Silently fail } } setShowForm(false) setEditingRisk(null) } const handleDelete = async (id: string) => { if (!confirm('Moechten Sie dieses Risiko wirklich loeschen?')) return dispatch({ type: 'DELETE_RISK', payload: id }) try { await fetch(`/api/sdk/v1/compliance/risks/${id}`, { method: 'DELETE' }) } catch { // Silently fail } } const handleStatusChange = async (riskId: string, status: RiskStatus) => { dispatch({ type: 'UPDATE_RISK', payload: { id: riskId, data: { status } } }) try { await fetch(`/api/sdk/v1/compliance/risks/${riskId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ status }), }) } catch { // Silently fail } } const handleEdit = (risk: Risk) => { setEditingRisk(risk) setShowForm(true) } const handleMatrixCellClick = (l: number, i: number) => { if (matrixFilter && matrixFilter.likelihood === l && matrixFilter.impact === i) { setMatrixFilter(null) } else { setMatrixFilter({ likelihood: l, impact: i }) } } const stats = { totalRisks: state.risks.length, criticalRisks: state.risks.filter(r => r.severity === 'CRITICAL').length, highRisks: state.risks.filter(r => r.severity === 'HIGH').length, mitigatedRisks: state.risks.filter(r => r.mitigation.length > 0).length, } const filteredRisks = state.risks .filter(risk => !matrixFilter || (risk.likelihood === matrixFilter.likelihood && risk.impact === matrixFilter.impact)) .sort((a, b) => b.inherentRiskScore - a.inherentRiskScore) return { state, showForm, setShowForm, editingRisk, setEditingRisk, loading, error, setError, matrixFilter, setMatrixFilter, handleSubmit, handleDelete, handleStatusChange, handleEdit, handleMatrixCellClick, stats, filteredRisks, } }