'use client'

/**
 * Einwilligungen Provider
 *
 * React Context Provider fuer das Einwilligungen-Modul.
 * Stellt State, computed values und Actions bereit.
 */

import {
  createContext,
  useReducer,
  useCallback,
  useMemo,
  ReactNode,
  Dispatch,
} from 'react'
import {
  EinwilligungenState,
  EinwilligungenAction,
  EinwilligungenTab,
  DataPoint,
  CookieBannerConfig,
  CompanyInfo,
  SupportedLanguage,
  ExportFormat,
  DataPointCategory,
  LegalBasis,
  RiskLevel,
} from './types'
import {
  PREDEFINED_DATA_POINTS,
  DEFAULT_COOKIE_CATEGORIES,
  createDefaultCatalog,
} from './catalog/loader'
import { einwilligungenReducer, initialState } from './reducer'

// =============================================================================
// CONTEXT
// =============================================================================

export interface EinwilligungenContextValue {
  state: EinwilligungenState
  dispatch: Dispatch<EinwilligungenAction>

  // Computed Values
  allDataPoints: DataPoint[]
  selectedDataPointsData: DataPoint[]
  dataPointsByCategory: Record<DataPointCategory, DataPoint[]>
  categoryStats: Record<DataPointCategory, number>
  riskStats: Record<RiskLevel, number>
  legalBasisStats: Record<LegalBasis, number>

  // Actions
  initializeCatalog: (tenantId: string) => void
  loadCatalog: (tenantId: string) => Promise<void>
  saveCatalog: () => Promise<void>
  toggleDataPoint: (id: string) => void
  addCustomDataPoint: (dataPoint: DataPoint) => void
  updateDataPoint: (id: string, data: Partial<DataPoint>) => void
  deleteCustomDataPoint: (id: string) => void
  setActiveTab: (tab: EinwilligungenTab) => void
  setPreviewLanguage: (language: SupportedLanguage) => void
  setPreviewFormat: (format: ExportFormat) => void
  setCompanyInfo: (info: CompanyInfo) => void
  generatePrivacyPolicy: () => Promise<void>
  generateCookieBannerConfig: () => void
}

export const EinwilligungenContext = createContext<EinwilligungenContextValue | null>(null)

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

interface EinwilligungenProviderProps {
  children: ReactNode
  tenantId?: string
}

export function EinwilligungenProvider({ children, tenantId }: EinwilligungenProviderProps) {
  const [state, dispatch] = useReducer(einwilligungenReducer, initialState)

  // ---------------------------------------------------------------------------
  // COMPUTED VALUES
  // ---------------------------------------------------------------------------

  const allDataPoints = useMemo(() => {
    if (!state.catalog) return PREDEFINED_DATA_POINTS
    return [...state.catalog.dataPoints, ...state.catalog.customDataPoints]
  }, [state.catalog])

  const selectedDataPointsData = useMemo(() => {
    return allDataPoints.filter((dp) => state.selectedDataPoints.includes(dp.id))
  }, [allDataPoints, state.selectedDataPoints])

  const dataPointsByCategory = useMemo(() => {
    const result: Partial<Record<DataPointCategory, DataPoint[]>> = {}
    const categories: DataPointCategory[] = [
      'MASTER_DATA', 'CONTACT_DATA', 'AUTHENTICATION', 'CONSENT',
      'COMMUNICATION', 'PAYMENT', 'USAGE_DATA', 'LOCATION',
      'DEVICE_DATA', 'MARKETING', 'ANALYTICS', 'SOCIAL_MEDIA',
      'HEALTH_DATA', 'EMPLOYEE_DATA', 'CONTRACT_DATA', 'LOG_DATA',
      'AI_DATA', 'SECURITY',
    ]
    for (const cat of categories) {
      result[cat] = selectedDataPointsData.filter((dp) => dp.category === cat)
    }
    return result as Record<DataPointCategory, DataPoint[]>
  }, [selectedDataPointsData])

  const categoryStats = useMemo(() => {
    const counts: Partial<Record<DataPointCategory, number>> = {}
    for (const dp of selectedDataPointsData) {
      counts[dp.category] = (counts[dp.category] || 0) + 1
    }
    return counts as Record<DataPointCategory, number>
  }, [selectedDataPointsData])

  const riskStats = useMemo(() => {
    const counts: Record<RiskLevel, number> = { LOW: 0, MEDIUM: 0, HIGH: 0 }
    for (const dp of selectedDataPointsData) {
      counts[dp.riskLevel]++
    }
    return counts
  }, [selectedDataPointsData])

  const legalBasisStats = useMemo(() => {
    const counts: Record<LegalBasis, number> = {
      CONTRACT: 0, CONSENT: 0, EXPLICIT_CONSENT: 0,
      LEGITIMATE_INTEREST: 0, LEGAL_OBLIGATION: 0,
      VITAL_INTERESTS: 0, PUBLIC_INTEREST: 0,
    }
    for (const dp of selectedDataPointsData) {
      counts[dp.legalBasis]++
    }
    return counts
  }, [selectedDataPointsData])

  // ---------------------------------------------------------------------------
  // ACTIONS
  // ---------------------------------------------------------------------------

  const initializeCatalog = useCallback(
    (tid: string) => {
      const catalog = createDefaultCatalog(tid)
      dispatch({ type: 'SET_CATALOG', payload: catalog })
    },
    [dispatch]
  )

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

      try {
        const response = await fetch(`/api/sdk/v1/einwilligungen/catalog`, {
          headers: { 'X-Tenant-ID': tid },
        })

        if (response.ok) {
          const data = await response.json()
          dispatch({ type: 'SET_CATALOG', payload: data.catalog })
          if (data.companyInfo) {
            dispatch({ type: 'SET_COMPANY_INFO', payload: data.companyInfo })
          }
          if (data.cookieBannerConfig) {
            dispatch({ type: 'SET_COOKIE_BANNER_CONFIG', payload: data.cookieBannerConfig })
          }
        } else if (response.status === 404) {
          initializeCatalog(tid)
        } else {
          throw new Error('Failed to load catalog')
        }
      } catch (error) {
        console.error('Error loading catalog:', error)
        dispatch({ type: 'SET_ERROR', payload: 'Fehler beim Laden des Katalogs' })
        initializeCatalog(tid)
      } finally {
        dispatch({ type: 'SET_LOADING', payload: false })
      }
    },
    [dispatch, initializeCatalog]
  )

  const saveCatalog = useCallback(async () => {
    if (!state.catalog) return

    dispatch({ type: 'SET_SAVING', payload: true })
    dispatch({ type: 'SET_ERROR', payload: null })

    try {
      const response = await fetch(`/api/sdk/v1/einwilligungen/catalog`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-Tenant-ID': state.catalog.tenantId,
        },
        body: JSON.stringify({
          catalog: state.catalog,
          companyInfo: state.companyInfo,
          cookieBannerConfig: state.cookieBannerConfig,
        }),
      })

      if (!response.ok) {
        throw new Error('Failed to save catalog')
      }
    } catch (error) {
      console.error('Error saving catalog:', error)
      dispatch({ type: 'SET_ERROR', payload: 'Fehler beim Speichern des Katalogs' })
    } finally {
      dispatch({ type: 'SET_SAVING', payload: false })
    }
  }, [state.catalog, state.companyInfo, state.cookieBannerConfig, dispatch])

  const toggleDataPoint = useCallback(
    (id: string) => {
      dispatch({ type: 'TOGGLE_DATA_POINT', payload: id })
    },
    [dispatch]
  )

  const addCustomDataPoint = useCallback(
    (dataPoint: DataPoint) => {
      dispatch({ type: 'ADD_CUSTOM_DATA_POINT', payload: { ...dataPoint, isCustom: true } })
    },
    [dispatch]
  )

  const updateDataPoint = useCallback(
    (id: string, data: Partial<DataPoint>) => {
      dispatch({ type: 'UPDATE_DATA_POINT', payload: { id, data } })
    },
    [dispatch]
  )

  const deleteCustomDataPoint = useCallback(
    (id: string) => {
      dispatch({ type: 'DELETE_CUSTOM_DATA_POINT', payload: id })
    },
    [dispatch]
  )

  const setActiveTab = useCallback(
    (tab: EinwilligungenTab) => {
      dispatch({ type: 'SET_ACTIVE_TAB', payload: tab })
    },
    [dispatch]
  )

  const setPreviewLanguage = useCallback(
    (language: SupportedLanguage) => {
      dispatch({ type: 'SET_PREVIEW_LANGUAGE', payload: language })
    },
    [dispatch]
  )

  const setPreviewFormat = useCallback(
    (format: ExportFormat) => {
      dispatch({ type: 'SET_PREVIEW_FORMAT', payload: format })
    },
    [dispatch]
  )

  const setCompanyInfo = useCallback(
    (info: CompanyInfo) => {
      dispatch({ type: 'SET_COMPANY_INFO', payload: info })
    },
    [dispatch]
  )

  const generatePrivacyPolicy = useCallback(async () => {
    if (!state.catalog || !state.companyInfo) {
      dispatch({ type: 'SET_ERROR', payload: 'Bitte zuerst Firmendaten eingeben' })
      return
    }

    dispatch({ type: 'SET_LOADING', payload: true })
    dispatch({ type: 'SET_ERROR', payload: null })

    try {
      const response = await fetch(`/api/sdk/v1/einwilligungen/privacy-policy/generate`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-Tenant-ID': state.catalog.tenantId,
        },
        body: JSON.stringify({
          dataPointIds: state.selectedDataPoints,
          companyInfo: state.companyInfo,
          language: state.previewLanguage,
          format: state.previewFormat,
        }),
      })

      if (response.ok) {
        const policy = await response.json()
        dispatch({ type: 'SET_PRIVACY_POLICY', payload: policy })
      } else {
        throw new Error('Failed to generate privacy policy')
      }
    } catch (error) {
      console.error('Error generating privacy policy:', error)
      dispatch({ type: 'SET_ERROR', payload: 'Fehler bei der Generierung der Datenschutzerklaerung' })
    } finally {
      dispatch({ type: 'SET_LOADING', payload: false })
    }
  }, [
    state.catalog,
    state.companyInfo,
    state.selectedDataPoints,
    state.previewLanguage,
    state.previewFormat,
    dispatch,
  ])

  const generateCookieBannerConfig = useCallback(() => {
    if (!state.catalog) return

    const config: CookieBannerConfig = {
      id: `cookie-banner-${state.catalog.tenantId}`,
      tenantId: state.catalog.tenantId,
      categories: DEFAULT_COOKIE_CATEGORIES.map((cat) => ({
        ...cat,
        dataPointIds: cat.dataPointIds.filter((id) => state.selectedDataPoints.includes(id)),
      })),
      styling: {
        position: 'BOTTOM',
        theme: 'LIGHT',
        primaryColor: '#6366f1',
        borderRadius: 12,
      },
      texts: {
        title: { de: 'Cookie-Einstellungen', en: 'Cookie Settings' },
        description: {
          de: 'Wir verwenden Cookies, um Ihnen die bestmoegliche Nutzung unserer Website zu ermoeglichen.',
          en: 'We use cookies to provide you with the best possible experience on our website.',
        },
        acceptAll: { de: 'Alle akzeptieren', en: 'Accept All' },
        rejectAll: { de: 'Alle ablehnen', en: 'Reject All' },
        customize: { de: 'Anpassen', en: 'Customize' },
        save: { de: 'Auswahl speichern', en: 'Save Selection' },
        privacyPolicyLink: { de: 'Datenschutzerklaerung', en: 'Privacy Policy' },
      },
      updatedAt: new Date(),
    }

    dispatch({ type: 'SET_COOKIE_BANNER_CONFIG', payload: config })
  }, [state.catalog, state.selectedDataPoints, dispatch])

  // ---------------------------------------------------------------------------
  // CONTEXT VALUE
  // ---------------------------------------------------------------------------

  const value: EinwilligungenContextValue = {
    state,
    dispatch,
    allDataPoints,
    selectedDataPointsData,
    dataPointsByCategory,
    categoryStats,
    riskStats,
    legalBasisStats,
    initializeCatalog,
    loadCatalog,
    saveCatalog,
    toggleDataPoint,
    addCustomDataPoint,
    updateDataPoint,
    deleteCustomDataPoint,
    setActiveTab,
    setPreviewLanguage,
    setPreviewFormat,
    setCompanyInfo,
    generatePrivacyPolicy,
    generateCookieBannerConfig,
  }

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