'use client'

import React, {
  useReducer,
  useMemo,
  useEffect,
  useState,
} from 'react'

import {
  VendorComplianceContextValue,
  ProcessingActivity,
  VendorStatistics,
  ComplianceStatistics,
  RiskOverview,
  VendorStatus,
  VendorRole,
  RiskLevel,
  FindingType,
  FindingSeverity,
  getRiskLevelFromScore,
} from './types'

import { initialState, vendorComplianceReducer } from './reducer'
import { VendorComplianceContext } from './hooks'
import { useVendorComplianceActions } from './use-actions'

// Re-export hooks and selectors for barrel
export {
  useVendorCompliance,
  useVendor,
  useProcessingActivity,
  useVendorContracts,
  useVendorFindings,
  useContractFindings,
  useControlInstancesForEntity,
} from './hooks'

// ==========================================
// PROVIDER
// ==========================================

interface VendorComplianceProviderProps {
  children: React.ReactNode
  tenantId?: string
}

export function VendorComplianceProvider({
  children,
  tenantId,
}: VendorComplianceProviderProps) {
  const [state, dispatch] = useReducer(vendorComplianceReducer, initialState)
  const [isInitialized, setIsInitialized] = useState(false)

  const actions = useVendorComplianceActions(state, dispatch)

  // ==========================================
  // COMPUTED VALUES
  // ==========================================

  const vendorStats = useMemo<VendorStatistics>(() => {
    const vendors = state.vendors

    const byStatus = vendors.reduce(
      (acc, v) => {
        acc[v.status] = (acc[v.status] || 0) + 1
        return acc
      },
      {} as Record<VendorStatus, number>
    )

    const byRole = vendors.reduce(
      (acc, v) => {
        acc[v.role] = (acc[v.role] || 0) + 1
        return acc
      },
      {} as Record<VendorRole, number>
    )

    const byRiskLevel = vendors.reduce(
      (acc, v) => {
        const level = getRiskLevelFromScore(v.residualRiskScore / 4)
        acc[level] = (acc[level] || 0) + 1
        return acc
      },
      {} as Record<RiskLevel, number>
    )

    const now = new Date()
    const pendingReviews = vendors.filter(
      (v) => v.nextReviewDate && new Date(v.nextReviewDate) <= now
    ).length

    const withExpiredContracts = vendors.filter((v) =>
      state.contracts.some(
        (c) =>
          c.vendorId === v.id &&
          c.expirationDate &&
          new Date(c.expirationDate) <= now &&
          c.status === 'ACTIVE'
      )
    ).length

    return {
      total: vendors.length,
      byStatus,
      byRole,
      byRiskLevel,
      pendingReviews,
      withExpiredContracts,
    }
  }, [state.vendors, state.contracts])

  const complianceStats = useMemo<ComplianceStatistics>(() => {
    const findings = state.findings
    const contracts = state.contracts
    const controlInstances = state.controlInstances

    const averageComplianceScore =
      contracts.length > 0
        ? contracts.reduce((sum, c) => sum + (c.complianceScore || 0), 0) /
          contracts.filter((c) => c.complianceScore !== undefined).length || 0
        : 0

    const findingsByType = findings.reduce(
      (acc, f) => {
        acc[f.type] = (acc[f.type] || 0) + 1
        return acc
      },
      {} as Record<FindingType, number>
    )

    const findingsBySeverity = findings.reduce(
      (acc, f) => {
        acc[f.severity] = (acc[f.severity] || 0) + 1
        return acc
      },
      {} as Record<FindingSeverity, number>
    )

    const openFindings = findings.filter(
      (f) => f.status === 'OPEN' || f.status === 'IN_PROGRESS'
    ).length

    const resolvedFindings = findings.filter(
      (f) => f.status === 'RESOLVED' || f.status === 'FALSE_POSITIVE'
    ).length

    const passedControls = controlInstances.filter(
      (ci) => ci.status === 'PASS'
    ).length
    const applicableControls = controlInstances.filter(
      (ci) => ci.status !== 'NOT_APPLICABLE'
    ).length
    const controlPassRate =
      applicableControls > 0 ? (passedControls / applicableControls) * 100 : 0

    return {
      averageComplianceScore,
      findingsByType,
      findingsBySeverity,
      openFindings,
      resolvedFindings,
      controlPassRate,
    }
  }, [state.findings, state.contracts, state.controlInstances])

  const riskOverview = useMemo<RiskOverview>(() => {
    const vendors = state.vendors
    const findings = state.findings

    const averageInherentRisk =
      vendors.length > 0
        ? vendors.reduce((sum, v) => sum + v.inherentRiskScore, 0) / vendors.length
        : 0

    const averageResidualRisk =
      vendors.length > 0
        ? vendors.reduce((sum, v) => sum + v.residualRiskScore, 0) / vendors.length
        : 0

    const highRiskVendors = vendors.filter(
      (v) => v.residualRiskScore >= 60
    ).length

    const criticalFindings = findings.filter(
      (f) => f.severity === 'CRITICAL' && f.status === 'OPEN'
    ).length

    const transfersToThirdCountries = vendors.filter((v) =>
      v.processingLocations.some((pl) => !pl.isEU && !pl.isAdequate)
    ).length

    return {
      averageInherentRisk,
      averageResidualRisk,
      highRiskVendors,
      criticalFindings,
      transfersToThirdCountries,
    }
  }, [state.vendors, state.findings])

  // ==========================================
  // API CALLS
  // ==========================================

  const apiBase = '/api/sdk/v1/vendor-compliance'

  const loadData = useCallback(async () => {
    dispatch({ type: 'SET_LOADING', payload: true })
    dispatch({ type: 'SET_ERROR', payload: null })

    try {
      const [
        activitiesRes,
        vendorsRes,
        contractsRes,
        findingsRes,
        controlsRes,
        controlInstancesRes,
      ] = await Promise.all([
        fetch(`${apiBase}/processing-activities`),
        fetch(`${apiBase}/vendors`),
        fetch(`${apiBase}/contracts`),
        fetch(`${apiBase}/findings`),
        fetch(`${apiBase}/controls`),
        fetch(`${apiBase}/control-instances`),
      ])

      if (activitiesRes.ok) {
        const data = await activitiesRes.json()
        dispatch({ type: 'SET_PROCESSING_ACTIVITIES', payload: data.data || [] })
      }

      if (vendorsRes.ok) {
        const data = await vendorsRes.json()
        dispatch({ type: 'SET_VENDORS', payload: data.data || [] })
      }

      if (contractsRes.ok) {
        const data = await contractsRes.json()
        dispatch({ type: 'SET_CONTRACTS', payload: data.data || [] })
      }

      if (findingsRes.ok) {
        const data = await findingsRes.json()
        dispatch({ type: 'SET_FINDINGS', payload: data.data || [] })
      }

      if (controlsRes.ok) {
        const data = await controlsRes.json()
        dispatch({ type: 'SET_CONTROLS', payload: data.data || [] })
      }

      if (controlInstancesRes.ok) {
        const data = await controlInstancesRes.json()
        dispatch({ type: 'SET_CONTROL_INSTANCES', payload: data.data || [] })
      }
    } catch (error) {
      console.error('Failed to load vendor compliance data:', error)
      dispatch({
        type: 'SET_ERROR',
        payload: 'Fehler beim Laden der Daten',
      })
    } finally {
      dispatch({ type: 'SET_LOADING', payload: false })
    }
  }, [apiBase])

  const refresh = useCallback(async () => {
    await loadData()
  }, [loadData])

  // ==========================================
  // PROCESSING ACTIVITIES ACTIONS
  // ==========================================

  const createProcessingActivity = useCallback(
    async (
      data: Omit<ProcessingActivity, 'id' | 'tenantId' | 'createdAt' | 'updatedAt'>
    ): Promise<ProcessingActivity> => {
      const response = await fetch(`${apiBase}/processing-activities`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data),
      })

      if (!response.ok) {
        const error = await response.json()
        throw new Error(error.error || 'Fehler beim Erstellen der Verarbeitungstätigkeit')
      }

      const result = await response.json()
      const activity = result.data

      dispatch({ type: 'ADD_PROCESSING_ACTIVITY', payload: activity })

      return activity
    },
    [apiBase]
  )

  const deleteProcessingActivity = useCallback(
    async (id: string): Promise<void> => {
      const response = await fetch(`${apiBase}/processing-activities/${id}`, {
        method: 'DELETE',
      })

      if (!response.ok) {
        const error = await response.json()
        throw new Error(error.error || 'Fehler beim Löschen der Verarbeitungstätigkeit')
      }

      dispatch({ type: 'DELETE_PROCESSING_ACTIVITY', payload: id })
    },
    [apiBase]
  )

  const duplicateProcessingActivity = useCallback(
    async (id: string): Promise<ProcessingActivity> => {
      const original = state.processingActivities.find((a) => a.id === id)
      if (!original) {
        throw new Error('Verarbeitungstätigkeit nicht gefunden')
      }

      const { id: _id, vvtId: _vvtId, createdAt: _createdAt, updatedAt: _updatedAt, tenantId: _tenantId, ...rest } = original

      const newActivity = await createProcessingActivity({
        ...rest,
        vvtId: '', // Will be generated by backend
        name: {
          de: `${original.name.de} (Kopie)`,
          en: `${original.name.en} (Copy)`,
        },
        status: 'DRAFT',
      })

      return newActivity
    },
    [state.processingActivities, createProcessingActivity]
  )

  // ==========================================
  // VENDOR ACTIONS
  // ==========================================

  const deleteVendor = useCallback(
    async (id: string): Promise<void> => {
      const response = await fetch(`${apiBase}/vendors/${id}`, {
        method: 'DELETE',
      })

      if (!response.ok) {
        const error = await response.json()
        throw new Error(error.error || 'Fehler beim Löschen des Vendors')
      }

      dispatch({ type: 'DELETE_VENDOR', payload: id })
    },
    [apiBase]
  )

  // ==========================================
  // CONTRACT ACTIONS
  // ==========================================

  const deleteContract = useCallback(
    async (id: string): Promise<void> => {
      const contract = state.contracts.find((c) => c.id === id)

      const response = await fetch(`${apiBase}/contracts/${id}`, {
        method: 'DELETE',
      })

      if (!response.ok) {
        const error = await response.json()
        throw new Error(error.error || 'Fehler beim Löschen des Vertrags')
      }

      dispatch({ type: 'DELETE_CONTRACT', payload: id })

      // Update vendor's contracts list
      if (contract) {
        const vendor = state.vendors.find((v) => v.id === contract.vendorId)
        if (vendor) {
          dispatch({
            type: 'UPDATE_VENDOR',
            payload: {
              id: vendor.id,
              data: { contracts: vendor.contracts.filter((cId) => cId !== id) },
            },
          })
        }
      }
    },
    [apiBase, state.contracts, state.vendors]
  )

  const startContractReview = useCallback(
    async (contractId: string): Promise<void> => {
      dispatch({
        type: 'UPDATE_CONTRACT',
        payload: { id: contractId, data: { reviewStatus: 'IN_PROGRESS' } },
      })

      const response = await fetch(`${apiBase}/contracts/${contractId}/review`, {
        method: 'POST',
      })

      if (!response.ok) {
        dispatch({
          type: 'UPDATE_CONTRACT',
          payload: { id: contractId, data: { reviewStatus: 'FAILED' } },
        })
        const error = await response.json()
        throw new Error(error.error || 'Fehler beim Starten der Vertragsprüfung')
      }

      const result = await response.json()

      // Update contract with review results
      dispatch({
        type: 'UPDATE_CONTRACT',
        payload: {
          id: contractId,
          data: {
            reviewStatus: 'COMPLETED',
            reviewCompletedAt: new Date(),
            complianceScore: result.data.complianceScore,
          },
        },
      })

      // Add findings
      if (result.data.findings && result.data.findings.length > 0) {
        dispatch({ type: 'ADD_FINDINGS', payload: result.data.findings })
      }
    },
    [apiBase]
  )

  // ==========================================
  // INITIALIZATION
  // ==========================================

  useEffect(() => {
    if (!isInitialized) {
      actions.loadData()
      setIsInitialized(true)
    }
  }, [isInitialized, actions])

  // ==========================================
  // CONTEXT VALUE
  // ==========================================

  const contextValue = useMemo<VendorComplianceContextValue>(
    () => ({
      ...state,
      dispatch,
      vendorStats,
      complianceStats,
      riskOverview,
      deleteProcessingActivity,
      duplicateProcessingActivity,
      deleteVendor,
      deleteContract,
      startContractReview,
      loadData,
      refresh,
    }),
    [
      state,
      vendorStats,
      complianceStats,
      riskOverview,
      deleteProcessingActivity,
      duplicateProcessingActivity,
      deleteVendor,
      deleteContract,
      startContractReview,
      loadData,
      refresh,
    ]
  )

  return (
    <VendorComplianceContext.Provider value={contextValue}>
      {children}
    </VendorComplianceContext.Provider>
  )
}

// ==========================================
// HOOK
// ==========================================

export function useVendorCompliance(): VendorComplianceContextValue {
  const context = useContext(VendorComplianceContext)

  if (!context) {
    throw new Error(
      'useVendorCompliance must be used within a VendorComplianceProvider'
    )
  }

  return context
}

