import { useReducer, useCallback, useMemo } from 'react';
import {
  Flyer,
  FlyerItem,
  MasterGroceryItem,
  AnalysisType,
  AiAnalysisState,
  AiAnalysisAction,
} from '../types';
import { AiAnalysisService } from '../services/aiAnalysisService';
import { logger } from '../services/logger.client';

/**
 * The initial state for the AI analysis reducer.
 */
const initialState: AiAnalysisState = {
  loadingAnalysis: null,
  error: null,
  results: {},
  sources: {},
  generatedImageUrl: null,
};

/**
 * A reducer function to manage the complex state of the AI analysis panel.
 * It handles loading, success, and error states for multiple types of analysis.
 * @param state - The current state.
 * @param action - The action to perform.
 * @returns The new state.
 */
export function aiAnalysisReducer(
  state: AiAnalysisState,
  action: AiAnalysisAction,
): AiAnalysisState {
  // Safely log the payload only if it exists on the action.
  const payload = 'payload' in action ? action.payload : {};
  logger.info(`[aiAnalysisReducer] Dispatched action: ${action.type}`, { payload });
  switch (action.type) {
    case 'FETCH_START':
      return {
        ...state,
        loadingAnalysis: action.payload.analysisType,
        error: null, // Clear previous errors on a new request
      };
    case 'FETCH_SUCCESS_TEXT':
      return {
        ...state,
        loadingAnalysis: null,
        results: {
          ...state.results,
          [action.payload.analysisType]: action.payload.data,
        },
      };
    case 'FETCH_SUCCESS_GROUNDED':
      return {
        ...state,
        loadingAnalysis: null,
        results: {
          ...state.results,
          [action.payload.analysisType]: action.payload.data.text,
        },
        sources: {
          ...state.sources,
          [action.payload.analysisType]: action.payload.data.sources,
        },
      };
    case 'FETCH_SUCCESS_IMAGE':
      return {
        ...state,
        loadingAnalysis: null,
        generatedImageUrl: `data:image/png;base64,${action.payload.data}`,
      };
    case 'FETCH_ERROR':
      return {
        ...state,
        loadingAnalysis: null,
        error: action.payload.error,
      };
    case 'CLEAR_ERROR':
      return { ...state, error: null };
    case 'RESET_STATE':
      return initialState;
    default:
      return state;
  }
}

interface UseAiAnalysisParams {
  flyerItems: FlyerItem[];
  selectedFlyer: Flyer | null;
  watchedItems: MasterGroceryItem[];
  // The service is now a required dependency.
  service: AiAnalysisService;
}

export const useAiAnalysis = ({
  flyerItems,
  selectedFlyer,
  watchedItems,
  service,
}: UseAiAnalysisParams) => {
  const [state, dispatch] = useReducer(aiAnalysisReducer, initialState);

  const runAnalysis = useCallback(
    async (analysisType: AnalysisType) => {
      dispatch({ type: 'FETCH_START', payload: { analysisType } });
      try {
        // Delegate the call to the injected service.
        switch (analysisType) {
          case AnalysisType.QUICK_INSIGHTS: {
            const data = await service.getQuickInsights(flyerItems);
            dispatch({ type: 'FETCH_SUCCESS_TEXT', payload: { analysisType, data } });
            break;
          }
          case AnalysisType.DEEP_DIVE: {
            const data = await service.getDeepDiveAnalysis(flyerItems);
            dispatch({ type: 'FETCH_SUCCESS_TEXT', payload: { analysisType, data } });
            break;
          }
          case AnalysisType.WEB_SEARCH: {
            const data = await service.searchWeb(flyerItems);
            dispatch({ type: 'FETCH_SUCCESS_GROUNDED', payload: { analysisType, data } });
            break;
          }
          case AnalysisType.PLAN_TRIP: {
            if (!selectedFlyer?.store)
              throw new Error('Store information is not available for trip planning.');
            const data = await service.planTripWithMaps(flyerItems, selectedFlyer.store);
            dispatch({ type: 'FETCH_SUCCESS_GROUNDED', payload: { analysisType, data } });
            break;
          }
          case AnalysisType.COMPARE_PRICES: {
            const data = await service.compareWatchedItemPrices(watchedItems);
            dispatch({ type: 'FETCH_SUCCESS_GROUNDED', payload: { analysisType, data } });
            break;
          }
        }
      } catch (err: unknown) {
        logger.error(`runAnalysis failed for type ${analysisType}`, { error: err });
        const message = err instanceof Error ? err.message : 'An unexpected error occurred.';
        dispatch({ type: 'FETCH_ERROR', payload: { error: message } });
      }
    },
    [service, flyerItems, watchedItems, selectedFlyer],
  );

  const generateImage = useCallback(async () => {
    const mealPlanText = state.results[AnalysisType.DEEP_DIVE];
    if (!mealPlanText) {
      logger.warn('generateImage called but no meal plan text available.');
      return;
    }
    dispatch({ type: 'FETCH_START', payload: { analysisType: AnalysisType.GENERATE_IMAGE } });
    try {
      const data = await service.generateImageFromText(mealPlanText);
      dispatch({ type: 'FETCH_SUCCESS_IMAGE', payload: { data } });
    } catch (err: unknown) {
      logger.error('generateImage failed', { error: err });
      const message =
        err instanceof Error
          ? err.message
          : 'An unexpected error occurred during image generation.';
      dispatch({ type: 'FETCH_ERROR', payload: { error: message } });
    }
  }, [service, state.results]);

  const clearError = useCallback(() => {
    dispatch({ type: 'CLEAR_ERROR' });
  }, []);

  const resetAnalysis = useCallback(() => {
    dispatch({ type: 'RESET_STATE' });
  }, []);

  return useMemo(
    () => ({
      ...state,
      runAnalysis,
      generateImage,
      clearError,
      resetAnalysis,
    }),
    [state, runAnalysis, generateImage, clearError, resetAnalysis],
  );
};
