'use client';

import {
  createContext,
  useContext,
  ReactNode,
  useState,
  useCallback,
  useEffect,
  useTransition,
} from 'react';

// Types pour les timeouts de debounce
declare global {
  interface Window {
    kanbanFiltersSyncTimeout?: NodeJS.Timeout;
    viewPreferencesSyncTimeout?: NodeJS.Timeout;
    columnVisibilitySyncTimeout?: NodeJS.Timeout;
  }
}
import {
  UserPreferences,
  KanbanFilters,
  ViewPreferences,
  ColumnVisibility,
  TaskStatus,
} from '@/lib/types';
import {
  updateViewPreferences as updateViewPreferencesAction,
  updateKanbanFilters as updateKanbanFiltersAction,
  updateColumnVisibility as updateColumnVisibilityAction,
  toggleObjectivesVisibility as toggleObjectivesVisibilityAction,
  toggleObjectivesCollapse as toggleObjectivesCollapseAction,
  toggleFontSize as toggleFontSizeAction,
  toggleColumnVisibility as toggleColumnVisibilityAction,
} from '@/actions/preferences';
import { useTheme } from './ThemeContext';
import { useSession } from 'next-auth/react';

interface UserPreferencesContextType {
  preferences: UserPreferences;
  isPending: boolean;

  // Kanban Filters
  updateKanbanFilters: (updates: Partial<KanbanFilters>) => void;

  // View Preferences
  updateViewPreferences: (updates: Partial<ViewPreferences>) => void;
  toggleObjectivesVisibility: () => void;
  toggleObjectivesCollapse: () => void;
  toggleTheme: () => void;
  setTheme: (theme: 'light' | 'dark') => void;
  toggleFontSize: () => void;

  // Column Visibility
  updateColumnVisibility: (updates: Partial<ColumnVisibility>) => void;
  toggleColumnVisibility: (status: TaskStatus) => void;
  isColumnVisible: (status: TaskStatus) => boolean;
}

const UserPreferencesContext = createContext<UserPreferencesContextType | null>(
  null
);

interface UserPreferencesProviderProps {
  children: ReactNode;
  initialPreferences?: UserPreferences;
}

const defaultPreferences: UserPreferences = {
  kanbanFilters: {
    search: '',
    tags: [],
    priorities: [],
    showCompleted: false,
    sortBy: 'priority',
  },
  viewPreferences: {
    compactView: false,
    swimlanesByTags: false,
    showObjectives: true,
    showFilters: true,
    objectivesCollapsed: false,
    theme: 'light',
    fontSize: 'medium',
    backgroundImage: undefined,
    backgroundBlur: 0,
    backgroundOpacity: 100,
  },
  columnVisibility: {
    hiddenStatuses: [],
  },
  jiraConfig: {
    enabled: false,
  },
  jiraAutoSync: false,
  jiraSyncInterval: 'daily',
  tfsConfig: {
    enabled: false,
  },
  tfsAutoSync: false,
  tfsSyncInterval: 'daily',
};

export function UserPreferencesProvider({
  children,
  initialPreferences,
}: UserPreferencesProviderProps) {
  const [preferences, setPreferences] = useState<UserPreferences>(
    initialPreferences || defaultPreferences
  );
  const [isPending] = useTransition();
  const { toggleTheme: themeToggleTheme, setTheme: themeSetTheme } = useTheme();
  const { status } = useSession();

  // Fonction pour charger les préférences côté client
  const loadUserPreferences = useCallback(async () => {
    if (status === 'loading') return; // Attendre que la session soit chargée

    try {
      const response = await fetch('/api/user-preferences');
      if (response.ok) {
        const result = await response.json();
        if (result.success) {
          setPreferences(result.data);
          // Ne plus synchroniser automatiquement le thème - ThemeContext est la source de vérité
        }
      }
    } catch (error) {
      console.error('Erreur lors du chargement des préférences:', error);
    }
  }, [status]);

  // Recharger les préférences quand la session change (login/logout)
  useEffect(() => {
    if (status === 'authenticated') {
      loadUserPreferences();
    } else if (status === 'unauthenticated') {
      // Reset aux préférences par défaut quand l'utilisateur se déconnecte
      setPreferences(defaultPreferences);
    }
  }, [status, loadUserPreferences]);

  // Ne plus synchroniser automatiquement - ThemeContext est la source de vérité

  // === KANBAN FILTERS ===

  const updateKanbanFilters = useCallback(
    (updates: Partial<KanbanFilters>) => {
      // Optimistic update immédiat
      setPreferences((prev) => ({
        ...prev,
        kanbanFilters: { ...prev.kanbanFilters, ...updates },
      }));

      // Sauvegarde locale immédiate pour éviter les pertes
      const newFilters = { ...preferences.kanbanFilters, ...updates };
      localStorage.setItem('kanbanFilters', JSON.stringify(newFilters));

      // Sync en arrière-plan avec debounce
      clearTimeout(window.kanbanFiltersSyncTimeout);
      window.kanbanFiltersSyncTimeout = setTimeout(() => {
        updateKanbanFiltersAction(updates).catch((error) => {
          console.error(
            'Erreur lors de la mise à jour des filtres Kanban:',
            error
          );
        });
      }, 1000); // debounce 1s
    },
    [preferences.kanbanFilters]
  );

  // === VIEW PREFERENCES ===

  const updateViewPreferences = useCallback(
    (updates: Partial<ViewPreferences>) => {
      // Optimistic update immédiat
      setPreferences((prev) => ({
        ...prev,
        viewPreferences: { ...prev.viewPreferences, ...updates },
      }));

      // Sauvegarde locale immédiate pour éviter les pertes
      const newViewPrefs = { ...preferences.viewPreferences, ...updates };
      localStorage.setItem('viewPreferences', JSON.stringify(newViewPrefs));

      // Sync en arrière-plan avec debounce
      clearTimeout(window.viewPreferencesSyncTimeout);
      window.viewPreferencesSyncTimeout = setTimeout(() => {
        updateViewPreferencesAction(updates).catch((error) => {
          console.error(
            'Erreur lors de la mise à jour des préférences de vue:',
            error
          );
        });
      }, 1000); // debounce 1s
    },
    [preferences.viewPreferences]
  );

  const toggleObjectivesVisibility = useCallback(() => {
    // Non-bloquant : utiliser setTimeout pour éviter de bloquer l'UI
    setTimeout(() => {
      toggleObjectivesVisibilityAction().catch((error) => {
        console.error(
          'Erreur lors du toggle de la visibilité des objectifs:',
          error
        );
      });
    }, 0);
  }, []);

  const toggleObjectivesCollapse = useCallback(() => {
    // Non-bloquant : utiliser setTimeout pour éviter de bloquer l'UI
    setTimeout(() => {
      toggleObjectivesCollapseAction().catch((error) => {
        console.error(
          'Erreur lors du toggle du collapse des objectifs:',
          error
        );
      });
    }, 0);
  }, []);

  const toggleTheme = useCallback(() => {
    themeToggleTheme();
  }, [themeToggleTheme]);

  const setTheme = useCallback(
    (theme: 'light' | 'dark') => {
      themeSetTheme(theme);
    },
    [themeSetTheme]
  );

  const toggleFontSize = useCallback(() => {
    // Optimistic update - cycle through font sizes
    const fontSizes: ('small' | 'medium' | 'large')[] = [
      'small',
      'medium',
      'large',
    ];
    const currentIndex = fontSizes.indexOf(
      preferences.viewPreferences.fontSize
    );
    const nextIndex = (currentIndex + 1) % fontSizes.length;
    const newFontSize = fontSizes[nextIndex];

    setPreferences((prev) => ({
      ...prev,
      viewPreferences: { ...prev.viewPreferences, fontSize: newFontSize },
    }));

    // Non-bloquant : utiliser setTimeout pour éviter de bloquer l'UI
    setTimeout(() => {
      toggleFontSizeAction().catch((error) => {
        console.error('Erreur lors du toggle de la taille de police:', error);
      });
    }, 0);
  }, [preferences.viewPreferences.fontSize]);

  // === COLUMN VISIBILITY ===

  const updateColumnVisibility = useCallback(
    (updates: Partial<ColumnVisibility>) => {
      // Optimistic update immédiat
      setPreferences((prev) => ({
        ...prev,
        columnVisibility: { ...prev.columnVisibility, ...updates },
      }));

      // Sauvegarde locale immédiate pour éviter les pertes
      const newColumnVisibility = {
        ...preferences.columnVisibility,
        ...updates,
      };
      localStorage.setItem(
        'columnVisibility',
        JSON.stringify(newColumnVisibility)
      );

      // Sync en arrière-plan avec debounce
      clearTimeout(window.columnVisibilitySyncTimeout);
      window.columnVisibilitySyncTimeout = setTimeout(() => {
        updateColumnVisibilityAction(updates).catch((error) => {
          console.error(
            'Erreur lors de la mise à jour de la visibilité des colonnes:',
            error
          );
        });
      }, 1000); // debounce 1s
    },
    [preferences.columnVisibility]
  );

  const toggleColumnVisibility = useCallback(
    (status: TaskStatus) => {
      const hiddenStatuses = [...preferences.columnVisibility.hiddenStatuses];

      // Optimistic update
      if (hiddenStatuses.includes(status)) {
        // Remove from hidden
        const index = hiddenStatuses.indexOf(status);
        hiddenStatuses.splice(index, 1);
      } else {
        // Add to hidden
        hiddenStatuses.push(status);
      }

      setPreferences((prev) => ({
        ...prev,
        columnVisibility: { ...prev.columnVisibility, hiddenStatuses },
      }));

      // Sauvegarde locale immédiate pour éviter les pertes
      localStorage.setItem(
        'columnVisibility',
        JSON.stringify({ hiddenStatuses })
      );

      // Sync en arrière-plan avec debounce
      clearTimeout(window.columnVisibilitySyncTimeout);
      window.columnVisibilitySyncTimeout = setTimeout(() => {
        toggleColumnVisibilityAction(status).catch((error) => {
          console.error(
            'Erreur lors du toggle de la visibilité des colonnes:',
            error
          );
        });
      }, 1000); // debounce 1s
    },
    [preferences.columnVisibility.hiddenStatuses]
  );

  const isColumnVisible = useCallback(
    (status: TaskStatus) => {
      return !preferences.columnVisibility.hiddenStatuses.includes(status);
    },
    [preferences.columnVisibility.hiddenStatuses]
  );

  const contextValue: UserPreferencesContextType = {
    preferences,
    isPending,
    updateKanbanFilters,
    updateViewPreferences,
    toggleObjectivesVisibility,
    toggleObjectivesCollapse,
    toggleTheme,
    setTheme,
    toggleFontSize,
    updateColumnVisibility,
    toggleColumnVisibility,
    isColumnVisible,
  };

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

export function useUserPreferences() {
  const context = useContext(UserPreferencesContext);
  if (!context) {
    throw new Error(
      'useUserPreferences must be used within a UserPreferencesProvider'
    );
  }
  return context;
}
