import React, { createContext, useContext, useReducer, useCallback } from 'react';
import { ApiReaderRepository } from '../../infrastructure/api/apiReaderRepository';
import { GetChapterContext } from '../../application/useCases/getChapterContext';
import { GetPage } from '../../application/useCases/getPage';
import { GetPages } from '../../application/useCases/getPages';

const readerRepository = new ApiReaderRepository();
const getChapterContext = new GetChapterContext(readerRepository);
const getPage = new GetPage(readerRepository);
const getPages = new GetPages(readerRepository);

const ReaderContext = createContext(null);

const initialState = {
  context: null,
  currentPage: 1,
  pages: [],
  loading: false,
  error: null,
  mode: 'classic', // 'classic' ou 'scrolling'
};

function readerReducer(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_CONTEXT':
      return { ...state, context: action.payload, loading: false };
    case 'SET_PAGES':
      return { ...state, pages: action.payload, loading: false };
    case 'SET_CURRENT_PAGE':
      return { ...state, currentPage: action.payload };
    case 'SET_MODE':
      return { ...state, mode: action.payload };
    case 'RESET_STATE':
      return initialState;
    default:
      return state;
  }
}

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

  const loadChapterContext = useCallback(async (chapterId) => {
    dispatch({ type: 'RESET_STATE' });
    dispatch({ type: 'SET_LOADING', payload: true });
    try {
      const context = await getChapterContext.execute(chapterId);
      dispatch({ type: 'SET_CONTEXT', payload: context });
      return true;
    } catch (error) {
      dispatch({ type: 'SET_ERROR', payload: error.response?.status === 404 ? 'Chapitre introuvable' : 'Erreur lors du chargement du chapitre' });
      console.error(error);
      return false;
    }
  }, []);

  const loadPage = useCallback(async (chapterId, pageNumber) => {
    dispatch({ type: 'SET_LOADING', payload: true });
    try {
      const page = await getPage.execute(chapterId, pageNumber);
      dispatch({ type: 'SET_LOADING', payload: false });
      return page;
    } catch (error) {
      const errorMessage = error.response?.status === 404 
        ? 'Page introuvable' 
        : 'Erreur lors du chargement de la page';
      dispatch({ type: 'SET_ERROR', payload: errorMessage });
      dispatch({ type: 'SET_LOADING', payload: false });
      return null;
    }
  }, []);

  const loadPages = useCallback(async (chapterId) => {
    dispatch({ type: 'SET_LOADING', payload: true });
    try {
      const { pages } = await getPages.execute(chapterId);
      if (!pages || pages.length === 0) {
        dispatch({ type: 'SET_ERROR', payload: 'Aucune page trouvée dans ce chapitre' });
        return false;
      }
      dispatch({ type: 'SET_PAGES', payload: pages });
      dispatch({ type: 'SET_CURRENT_PAGE', payload: 1 });
      dispatch({ type: 'SET_LOADING', payload: false });
      return true;
    } catch (error) {
      const errorMessage = error.response?.status === 404 
        ? 'Chapitre introuvable' 
        : 'Erreur lors du chargement des pages';
      dispatch({ type: 'SET_ERROR', payload: errorMessage });
      dispatch({ type: 'SET_LOADING', payload: false });
      return false;
    }
  }, []);

  const setCurrentPage = useCallback((pageNumber) => {
    dispatch({ type: 'SET_CURRENT_PAGE', payload: pageNumber });
  }, []);

  const setMode = useCallback((mode) => {
    dispatch({ type: 'SET_MODE', payload: mode });
  }, []);

  const value = {
    ...state,
    loadChapterContext,
    loadPage,
    loadPages,
    setCurrentPage,
    setMode,
  };

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

export function useReader() {
  const context = useContext(ReaderContext);
  if (!context) {
    throw new Error('useReader must be used within a ReaderProvider');
  }
  return context;
}