import React, { createContext, useContext, useReducer, useCallback, useEffect } from 'react';
import { ApiMangaRepository } from '../../infrastructure/api/apiMangaRepository';
import { GetMangaCollection } from '../../application/useCases/getMangaCollection';
import { GetMangaDetail } from '../../application/useCases/getMangaDetail';

const mangaRepository = new ApiMangaRepository();
const getMangaCollection = new GetMangaCollection(mangaRepository);
const getMangaDetail = new GetMangaDetail(mangaRepository);

const MangaContext = createContext(null);

const initialState = {
  collection: null,
  detailedMangas: {},
  loading: false,
  error: null,
  lastCollectionUpdate: null,
  isBackgroundLoading: false
};

function mangaReducer(state, action) {
  switch (action.type) {
    case 'SET_LOADING':
      return { ...state, loading: action.payload };
    case 'SET_BACKGROUND_LOADING':
      return { ...state, isBackgroundLoading: action.payload };
    case 'SET_ERROR':
      return { ...state, error: action.payload, loading: false };
    case 'SET_COLLECTION':
      return { 
        ...state, 
        collection: action.payload, 
        loading: false, 
        error: null,
        lastCollectionUpdate: Date.now()
      };
    case 'UPDATE_COLLECTION':
      return {
        ...state,
        collection: action.payload,
        isBackgroundLoading: false,
        lastCollectionUpdate: Date.now()
      };
    case 'SET_MANGA_DETAIL':
      // Mettre à jour également le manga dans la collection si présent
      const updatedCollection = state.collection ? {
        ...state.collection,
        items: state.collection.items.map(manga => 
          manga.slug === action.payload.slug 
            ? { 
                ...manga, 
                ...action.payload,
                createdAt: manga.createdAt || action.payload.createdAt 
              }
            : manga
        )
      } : state.collection;

      return {
        ...state,
        collection: updatedCollection,
        detailedMangas: {
          ...state.detailedMangas,
          [action.payload.slug]: {
            ...action.payload,
            createdAt: state.collection?.items.find(m => m.slug === action.payload.slug)?.createdAt || action.payload.createdAt
          }
        },
        loading: false,
        error: null
      };
    default:
      return state;
  }
}

export function MangaProvider({ children }) {
  const [state, dispatch] = useReducer(mangaReducer, initialState);

  // Fonction pour charger la collection en arrière-plan
  const refreshCollectionInBackground = useCallback(async () => {
    if (state.isBackgroundLoading) return;
    
    dispatch({ type: 'SET_BACKGROUND_LOADING', payload: true });
    try {
      const collection = await getMangaCollection.execute(1);
      dispatch({ type: 'UPDATE_COLLECTION', payload: collection });
    } catch (error) {
      console.error('Background collection refresh failed:', error);
      dispatch({ type: 'SET_BACKGROUND_LOADING', payload: false });
    }
  }, [state.isBackgroundLoading]);

  // Rafraîchir la collection toutes les 5 minutes si elle est chargée
  useEffect(() => {
    if (!state.collection) return;

    const interval = setInterval(() => {
      refreshCollectionInBackground();
    }, 5 * 60 * 1000);

    return () => clearInterval(interval);
  }, [state.collection, refreshCollectionInBackground]);

  const loadCollection = useCallback(async () => {
    // Si nous avons déjà des données, les afficher immédiatement
    if (state.collection) {
      // Rafraîchir en arrière-plan si les données sont vieilles de plus de 30 secondes
      const isStale = state.lastCollectionUpdate && 
        (Date.now() - state.lastCollectionUpdate) > 30 * 1000;
      
      if (isStale && !state.isBackgroundLoading) {
        refreshCollectionInBackground();
      }
      return;
    }

    dispatch({ type: 'SET_LOADING', payload: true });
    try {
      const collection = await getMangaCollection.execute(1);
      dispatch({ type: 'SET_COLLECTION', payload: collection });
    } catch (error) {
      dispatch({ type: 'SET_ERROR', payload: 'Failed to load manga collection' });
      console.error(error);
    }
  }, [state.collection, state.lastCollectionUpdate, state.isBackgroundLoading, refreshCollectionInBackground]);

  const loadMangaDetail = useCallback(async (slug) => {
    // Retourner les données en cache si disponibles
    if (state.detailedMangas[slug]) {
      // Rafraîchir en arrière-plan si les données sont vieilles de plus de 5 minutes
      const cachedManga = state.detailedMangas[slug];
      const isStale = cachedManga.lastUpdate && 
        (Date.now() - cachedManga.lastUpdate) > 5 * 60 * 1000;
      
      if (isStale) {
        // Charger les nouvelles données en arrière-plan
        getMangaDetail.execute(slug).then(manga => {
          dispatch({ type: 'SET_MANGA_DETAIL', payload: { ...manga, lastUpdate: Date.now() } });
        }).catch(console.error);
      }
      
      return state.detailedMangas[slug];
    }

    // Si le manga est dans la collection, l'utiliser comme données temporaires
    const collectionManga = getMangaFromCollection(slug);
    if (collectionManga) {
      dispatch({ 
        type: 'SET_MANGA_DETAIL', 
        payload: { ...collectionManga, isPartial: true, lastUpdate: Date.now() } 
      });
    }

    // Charger les détails complets
    dispatch({ type: 'SET_LOADING', payload: true });
    try {
      const manga = await getMangaDetail.execute(slug);
      dispatch({ type: 'SET_MANGA_DETAIL', payload: { ...manga, lastUpdate: Date.now() } });
      return manga;
    } catch (error) {
      dispatch({ type: 'SET_ERROR', payload: 'Failed to load manga details' });
      console.error(error);
      return null;
    }
  }, [state.detailedMangas]);

  const getMangaFromCollection = useCallback((slug) => {
    if (!state.collection) return null;
    return state.collection.items.find(manga => manga.slug === slug);
  }, [state.collection]);

  const value = {
    ...state,
    loadCollection,
    loadMangaDetail,
    getMangaFromCollection,
    refreshCollectionInBackground
  };

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

export function useManga() {
  const context = useContext(MangaContext);
  if (!context) {
    throw new Error('useManga must be used within a MangaProvider');
  }
  return context;
}