/**
 * Cookie Consent Context
 *
 * Provides cookie consent state and methods to the application
 * Syncs with backend for authenticated users
 */

'use client';

import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import {
  getConsentPreferences,
  updateConsentPreferences,
  type CookiePreferences,
} from '../api/gdpr';
import { getAuthToken } from '../api/client';

const STORAGE_KEY = 'cookieConsent';
const STORAGE_DATE_KEY = 'cookieConsentDate';

interface CookieContextType {
  preferences: CookiePreferences;
  showBanner: boolean;
  showSettings: boolean;
  isLoading: boolean;
  setShowBanner: (show: boolean) => void;
  setShowSettings: (show: boolean) => void;
  acceptAll: () => Promise<void>;
  acceptEssentialOnly: () => Promise<void>;
  savePreferences: (prefs: CookiePreferences) => Promise<void>;
  openPreferences: () => void;
}

const defaultPreferences: CookiePreferences = {
  essential: true,
  functional: false,
  analytics: false,
  marketing: false,
};

const CookieContext = createContext<CookieContextType | undefined>(undefined);

export function CookieProvider({ children }: { children: React.ReactNode }) {
  const [preferences, setPreferences] = useState<CookiePreferences>(defaultPreferences);
  const [showBanner, setShowBanner] = useState(false);
  const [showSettings, setShowSettings] = useState(false);
  const [isLoading, setIsLoading] = useState(true);
  const [hasInitialized, setHasInitialized] = useState(false);

  // Check if user is authenticated
  const isAuthenticated = useCallback(() => {
    return !!getAuthToken();
  }, []);

  // Load preferences from localStorage
  const loadFromLocalStorage = useCallback((): CookiePreferences | null => {
    if (typeof window === 'undefined') return null;
    const stored = localStorage.getItem(STORAGE_KEY);
    if (stored) {
      try {
        return JSON.parse(stored);
      } catch {
        return null;
      }
    }
    return null;
  }, []);

  // Save preferences to localStorage
  const saveToLocalStorage = useCallback((prefs: CookiePreferences) => {
    if (typeof window === 'undefined') return;
    localStorage.setItem(STORAGE_KEY, JSON.stringify(prefs));
    localStorage.setItem(STORAGE_DATE_KEY, new Date().toISOString());
  }, []);

  // Apply preferences (gtag, etc.)
  const applyPreferences = useCallback((prefs: CookiePreferences) => {
    if (typeof window === 'undefined') return;

    // Google Analytics consent
    const gtag = (window as any).gtag;
    if (gtag) {
      gtag('consent', 'update', {
        analytics_storage: prefs.analytics ? 'granted' : 'denied',
        ad_storage: prefs.marketing ? 'granted' : 'denied',
        functionality_storage: prefs.functional ? 'granted' : 'denied',
      });
    }

    // Sentry (if analytics enabled)
    const Sentry = (window as any).Sentry;
    if (Sentry) {
      if (prefs.analytics) {
        Sentry.init && Sentry.getCurrentHub && Sentry.getCurrentHub().getClient()?.getOptions();
      }
    }
  }, []);

  // Initialize preferences
  useEffect(() => {
    const initializePreferences = async () => {
      setIsLoading(true);

      // First, check localStorage
      const localPrefs = loadFromLocalStorage();

      if (localPrefs) {
        setPreferences(localPrefs);
        applyPreferences(localPrefs);
        setShowBanner(false);
      } else {
        // No local consent - show banner
        setShowBanner(true);
      }

      // If authenticated, try to sync with backend
      if (isAuthenticated() && localPrefs) {
        try {
          const backendPrefs = await getConsentPreferences();
          if (backendPrefs) {
            // Backend has preferences - use them
            const prefs: CookiePreferences = {
              essential: backendPrefs.essential,
              functional: backendPrefs.functional,
              analytics: backendPrefs.analytics,
              marketing: backendPrefs.marketing,
            };
            setPreferences(prefs);
            saveToLocalStorage(prefs);
            applyPreferences(prefs);
          } else if (localPrefs) {
            // No backend preferences but we have local - sync to backend
            try {
              await updateConsentPreferences({
                ...localPrefs,
                userAgent: navigator.userAgent,
              });
            } catch (syncError) {
              console.warn('Failed to sync consent to backend:', syncError);
            }
          }
        } catch (error) {
          console.warn('Failed to fetch consent from backend:', error);
          // Continue with local preferences
        }
      }

      setIsLoading(false);
      setHasInitialized(true);
    };

    initializePreferences();
  }, [isAuthenticated, loadFromLocalStorage, saveToLocalStorage, applyPreferences]);

  // Save preferences (to localStorage and optionally backend)
  const savePreferences = useCallback(
    async (prefs: CookiePreferences) => {
      // Ensure essential is always true
      const safePrefs = { ...prefs, essential: true };

      setPreferences(safePrefs);
      saveToLocalStorage(safePrefs);
      applyPreferences(safePrefs);
      setShowBanner(false);
      setShowSettings(false);

      // Sync to backend if authenticated
      if (isAuthenticated()) {
        try {
          await updateConsentPreferences({
            ...safePrefs,
            userAgent: typeof navigator !== 'undefined' ? navigator.userAgent : undefined,
          });
        } catch (error) {
          console.warn('Failed to sync consent to backend:', error);
          // Local save succeeded, backend sync failed - that's okay
        }
      }
    },
    [isAuthenticated, saveToLocalStorage, applyPreferences]
  );

  const acceptAll = useCallback(async () => {
    await savePreferences({
      essential: true,
      functional: true,
      analytics: true,
      marketing: true,
    });
  }, [savePreferences]);

  const acceptEssentialOnly = useCallback(async () => {
    await savePreferences({
      essential: true,
      functional: false,
      analytics: false,
      marketing: false,
    });
  }, [savePreferences]);

  const openPreferences = useCallback(() => {
    setShowBanner(true);
    setShowSettings(true);
  }, []);

  const value: CookieContextType = {
    preferences,
    showBanner,
    showSettings,
    isLoading,
    setShowBanner,
    setShowSettings,
    acceptAll,
    acceptEssentialOnly,
    savePreferences,
    openPreferences,
  };

  return <CookieContext.Provider value={value}>{children}</CookieContext.Provider>;
}

export function useCookieConsent() {
  const context = useContext(CookieContext);
  if (context === undefined) {
    throw new Error('useCookieConsent must be used within a CookieProvider');
  }
  return context;
}
