import React, { createContext, useContext, useReducer, useCallback } 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
};

function mangaReducer(state, action) {
  switch (action.type) {
    case 'SET_LOADING':
      return { ...state, loading: action.payload };
    case 'SET_ERROR':
      return { ...state, error: action.payload, loading: false };
    case 'SET_COLLECTION':
      return { ...state, collection: action.payload, loading: false, error: null };
    case 'SET_MANGA_DETAIL':
      return {
        ...state,
        detailedMangas: {
          ...state.detailedMangas,
          [action.payload.slug]: action.payload
        },
        loading: false,
        error: null
      };
    default:
      return state;
  }
}

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

  const loadCollection = useCallback(async () => {
    if (state.collection) return; // Return if already loaded

    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);
    }
  }, []);

  const loadMangaDetail = useCallback(async (slug) => {
    // Return cached data if available
    if (state.detailedMangas[slug]) return state.detailedMangas[slug];

    dispatch({ type: 'SET_LOADING', payload: true });
    try {
      const manga = await getMangaDetail.execute(slug);
      dispatch({ type: 'SET_MANGA_DETAIL', payload: manga });
      return manga;
    } catch (error) {
      dispatch({ type: 'SET_ERROR', payload: 'Failed to load manga details' });
      console.error(error);
      return null;
    }
  }, []);

  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
  };

  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;
}