'use client'

/**
 * Einwilligungen Context & Reducer
 *
 * Zentrale State-Verwaltung fuer das Datenpunktkatalog & DSI-Generator Modul.
 * Verwendet React Context + useReducer fuer vorhersehbare State-Updates.
 */

import {
  createContext,
  useContext,
  useReducer,
  useCallback,
  useMemo,
  ReactNode,
  Dispatch,
} from 'react'
import {
  EinwilligungenState,
  EinwilligungenAction,
  EinwilligungenTab,
  DataPoint,
  DataPointCatalog,
  GeneratedPrivacyPolicy,
  CookieBannerConfig,
  CompanyInfo,
  ConsentStatistics,
  PrivacyPolicySection,
  SupportedLanguage,
  ExportFormat,
  DataPointCategory,
  LegalBasis,
  RiskLevel,
} from './types'
import {
  PREDEFINED_DATA_POINTS,
  RETENTION_MATRIX,
  DEFAULT_COOKIE_CATEGORIES,
  createDefaultCatalog,
  getDataPointById,
  getDataPointsByCategory,
  countDataPointsByCategory,
  countDataPointsByRiskLevel,
} from './catalog/loader'

// =============================================================================
// INITIAL STATE
// =============================================================================

const initialState: EinwilligungenState = {
  // Data
  catalog: null,
  selectedDataPoints: [],
  privacyPolicy: null,
  cookieBannerConfig: null,
  companyInfo: null,
  consentStatistics: null,

  // UI State
  activeTab: 'catalog',
  isLoading: false,
  isSaving: false,
  error: null,

  // Editor State
  editingDataPoint: null,
  editingSection: null,

  // Preview
  previewLanguage: 'de',
  previewFormat: 'HTML',
}

// =============================================================================
// REDUCER
// =============================================================================

function einwilligungenReducer(
  state: EinwilligungenState,
  action: EinwilligungenAction
): EinwilligungenState {
  switch (action.type) {
    case 'SET_CATALOG':
      return {
        ...state,
        catalog: action.payload,
        // Automatisch alle aktiven Datenpunkte auswaehlen
        selectedDataPoints: [
          ...action.payload.dataPoints.filter((dp) => dp.isActive !== false).map((dp) => dp.id),
          ...action.payload.customDataPoints.filter((dp) => dp.isActive !== false).map((dp) => dp.id),
        ],
      }

    case 'SET_SELECTED_DATA_POINTS':
      return {
        ...state,
        selectedDataPoints: action.payload,
      }

    case 'TOGGLE_DATA_POINT': {
      const id = action.payload
      const isSelected = state.selectedDataPoints.includes(id)
      return {
        ...state,
        selectedDataPoints: isSelected
          ? state.selectedDataPoints.filter((dpId) => dpId !== id)
          : [...state.selectedDataPoints, id],
      }
    }

    case 'ADD_CUSTOM_DATA_POINT':
      if (!state.catalog) return state
      return {
        ...state,
        catalog: {
          ...state.catalog,
          customDataPoints: [...state.catalog.customDataPoints, action.payload],
          updatedAt: new Date(),
        },
        selectedDataPoints: [...state.selectedDataPoints, action.payload.id],
      }

    case 'UPDATE_DATA_POINT': {
      if (!state.catalog) return state
      const { id, data } = action.payload

      // Pruefe ob es ein vordefinierter oder kundenspezifischer Datenpunkt ist
      const isCustom = state.catalog.customDataPoints.some((dp) => dp.id === id)

      if (isCustom) {
        return {
          ...state,
          catalog: {
            ...state.catalog,
            customDataPoints: state.catalog.customDataPoints.map((dp) =>
              dp.id === id ? { ...dp, ...data } : dp
            ),
            updatedAt: new Date(),
          },
        }
      } else {
        // Vordefinierte Datenpunkte: nur isActive aendern
        return {
          ...state,
          catalog: {
            ...state.catalog,
            dataPoints: state.catalog.dataPoints.map((dp) =>
              dp.id === id ? { ...dp, ...data } : dp
            ),
            updatedAt: new Date(),
          },
        }
      }
    }

    case 'DELETE_CUSTOM_DATA_POINT':
      if (!state.catalog) return state
      return {
        ...state,
        catalog: {
          ...state.catalog,
          customDataPoints: state.catalog.customDataPoints.filter((dp) => dp.id !== action.payload),
          updatedAt: new Date(),
        },
        selectedDataPoints: state.selectedDataPoints.filter((id) => id !== action.payload),
      }

    case 'SET_PRIVACY_POLICY':
      return {
        ...state,
        privacyPolicy: action.payload,
      }

    case 'SET_COOKIE_BANNER_CONFIG':
      return {
        ...state,
        cookieBannerConfig: action.payload,
      }

    case 'UPDATE_COOKIE_BANNER_STYLING':
      if (!state.cookieBannerConfig) return state
      return {
        ...state,
        cookieBannerConfig: {
          ...state.cookieBannerConfig,
          styling: {
            ...state.cookieBannerConfig.styling,
            ...action.payload,
          },
          updatedAt: new Date(),
        },
      }

    case 'UPDATE_COOKIE_BANNER_TEXTS':
      if (!state.cookieBannerConfig) return state
      return {
        ...state,
        cookieBannerConfig: {
          ...state.cookieBannerConfig,
          texts: {
            ...state.cookieBannerConfig.texts,
            ...action.payload,
          },
          updatedAt: new Date(),
        },
      }

    case 'SET_COMPANY_INFO':
      return {
        ...state,
        companyInfo: action.payload,
      }

    case 'SET_CONSENT_STATISTICS':
      return {
        ...state,
        consentStatistics: action.payload,
      }

    case 'SET_ACTIVE_TAB':
      return {
        ...state,
        activeTab: action.payload,
      }

    case 'SET_LOADING':
      return {
        ...state,
        isLoading: action.payload,
      }

    case 'SET_SAVING':
      return {
        ...state,
        isSaving: action.payload,
      }

    case 'SET_ERROR':
      return {
        ...state,
        error: action.payload,
      }

    case 'SET_EDITING_DATA_POINT':
      return {
        ...state,
        editingDataPoint: action.payload,
      }

    case 'SET_EDITING_SECTION':
      return {
        ...state,
        editingSection: action.payload,
      }

    case 'SET_PREVIEW_LANGUAGE':
      return {
        ...state,
        previewLanguage: action.payload,
      }

    case 'SET_PREVIEW_FORMAT':
      return {
        ...state,
        previewFormat: action.payload,
      }

    case 'RESET_STATE':
      return initialState

    default:
      return state
  }
}

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

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
}

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[]>> = {}
    // 18 Kategorien (A-R)
    const categories: DataPointCategory[] = [
      'MASTER_DATA',       // A
      'CONTACT_DATA',      // B
      'AUTHENTICATION',    // C
      'CONSENT',           // D
      'COMMUNICATION',     // E
      'PAYMENT',           // F
      'USAGE_DATA',        // G
      'LOCATION',          // H
      'DEVICE_DATA',       // I
      'MARKETING',         // J
      'ANALYTICS',         // K
      'SOCIAL_MEDIA',      // L
      'HEALTH_DATA',       // M - Art. 9 DSGVO
      'EMPLOYEE_DATA',     // N - BDSG § 26
      'CONTRACT_DATA',     // O
      'LOG_DATA',          // P
      'AI_DATA',           // Q - AI Act
      'SECURITY',          // R
    ]
    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(() => {
    // Alle 7 Rechtsgrundlagen
    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) {
          // Katalog existiert noch nicht - erstelle Default
          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' })
        // Fallback zu Default
        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,
        // Filtere nur die ausgewaehlten Datenpunkte
        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,

    // Computed Values
    allDataPoints,
    selectedDataPointsData,
    dataPointsByCategory,
    categoryStats,
    riskStats,
    legalBasisStats,

    // Actions
    initializeCatalog,
    loadCatalog,
    saveCatalog,
    toggleDataPoint,
    addCustomDataPoint,
    updateDataPoint,
    deleteCustomDataPoint,
    setActiveTab,
    setPreviewLanguage,
    setPreviewFormat,
    setCompanyInfo,
    generatePrivacyPolicy,
    generateCookieBannerConfig,
  }

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

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

export function useEinwilligungen(): EinwilligungenContextValue {
  const context = useContext(EinwilligungenContext)
  if (!context) {
    throw new Error('useEinwilligungen must be used within EinwilligungenProvider')
  }
  return context
}

// =============================================================================
// EXPORTS
// =============================================================================

export { initialState, einwilligungenReducer }
