// src/hooks/useAiAnalysis.ts
import { useState, useCallback, useMemo, useEffect } from 'react';
import { Flyer, FlyerItem, MasterGroceryItem, AnalysisType } from '../types';
import type { GroundingChunk } from '@google/genai';
import * as aiApiClient from '../services/aiApiClient';
import { logger } from '../services/logger.client';
import { useApi } from './useApi';

interface Source {
    uri: string;
    title: string;
}

interface GroundedResponse {
    text: string;
    sources: (GroundingChunk | Source)[];
}

interface UseAiAnalysisParams {
    flyerItems: FlyerItem[];
    selectedFlyer: Flyer | null;
    watchedItems: MasterGroceryItem[];
}

export const useAiAnalysis = ({ flyerItems, selectedFlyer, watchedItems }: UseAiAnalysisParams) => {
    // --- State for results ---
    const [results, setResults] = useState<{ [key in AnalysisType]?: string }>({});
    const [sources, setSources] = useState<{ [key in AnalysisType]?: Source[] }>({});
    const [internalError, setInternalError] = useState<string | null>(null);

    // --- API Hooks for each analysis type ---
    const { execute: getQuickInsights, data: quickInsightsData, loading: loadingQuickInsights, error: errorQuickInsights } = useApi<string, [FlyerItem[]]>(aiApiClient.getQuickInsights);
    const { execute: getDeepDive, data: deepDiveData, loading: loadingDeepDive, error: errorDeepDive } = useApi<string, [FlyerItem[]]>(aiApiClient.getDeepDiveAnalysis);
    const { execute: searchWeb, data: webSearchData, loading: loadingWebSearch, error: errorWebSearch } = useApi<GroundedResponse, [FlyerItem[]]>(aiApiClient.searchWeb);
    const { execute: planTrip, data: tripPlanData, loading: loadingTripPlan, error: errorTripPlan } = useApi<GroundedResponse, [FlyerItem[], Flyer['store'], GeolocationCoordinates]>(aiApiClient.planTripWithMaps);
    const { execute: comparePrices, data: priceComparisonData, loading: loadingComparePrices, error: errorComparePrices } = useApi<GroundedResponse, [typeof watchedItems]>(aiApiClient.compareWatchedItemPrices);
    const { execute: generateImageApi, data: generatedImageData, loading: isGeneratingImage, error: errorGenerateImage } = useApi<string, [string]>(aiApiClient.generateImageFromText);

    // --- Derived State (Loading and Error) ---
    const loadingStates = useMemo(() => ({
        [AnalysisType.QUICK_INSIGHTS]: loadingQuickInsights,
        [AnalysisType.DEEP_DIVE]: loadingDeepDive,
        [AnalysisType.WEB_SEARCH]: loadingWebSearch,
        [AnalysisType.PLAN_TRIP]: loadingTripPlan,
        [AnalysisType.COMPARE_PRICES]: loadingComparePrices,
    }), [loadingQuickInsights, loadingDeepDive, loadingWebSearch, loadingTripPlan, loadingComparePrices]);

    const error = useMemo(() => {
        if (internalError) return internalError;
        const firstError = errorQuickInsights || errorDeepDive || errorWebSearch || errorTripPlan || errorComparePrices || errorGenerateImage;
        return firstError ? firstError.message : null;
    }, [internalError, errorQuickInsights, errorDeepDive, errorWebSearch, errorTripPlan, errorComparePrices, errorGenerateImage]);

    // --- Effects to update state when API data changes ---
    useEffect(() => {
        if (quickInsightsData) {
            setResults(prev => ({ ...prev, [AnalysisType.QUICK_INSIGHTS]: quickInsightsData }));
        }
        if (deepDiveData) {
            setResults(prev => ({ ...prev, [AnalysisType.DEEP_DIVE]: deepDiveData }));
        }
        if (webSearchData) {
            setResults(prev => ({ ...prev, [AnalysisType.WEB_SEARCH]: webSearchData.text }));
            const mappedSources = (webSearchData.sources || []).map(s => ('web' in s ? { uri: s.web?.uri || '', title: s.web?.title || 'Untitled' } : s) as Source);
            setSources(prev => ({ ...prev, [AnalysisType.WEB_SEARCH]: mappedSources }));
        }
        if (tripPlanData) {
            setResults(prev => ({ ...prev, [AnalysisType.PLAN_TRIP]: tripPlanData.text }));
            setSources(prev => ({ ...prev, [AnalysisType.PLAN_TRIP]: tripPlanData.sources as Source[] }));
        }
        if (priceComparisonData) {
            setResults(prev => ({ ...prev, [AnalysisType.COMPARE_PRICES]: priceComparisonData.text }));
            const mappedSources = (priceComparisonData.sources || []).map(s => ('web' in s ? { uri: s.web?.uri || '', title: s.web?.title || 'Untitled' } : s) as Source);
            setSources(prev => ({ ...prev, [AnalysisType.COMPARE_PRICES]: mappedSources }));
        }
    }, [quickInsightsData, deepDiveData, webSearchData, tripPlanData, priceComparisonData]);

    const generatedImageUrl = useMemo(() => generatedImageData ? `data:image/png;base64,${generatedImageData}` : null, [generatedImageData]);

    const runAnalysis = useCallback(async (type: AnalysisType) => {
        setInternalError(null);
        try {
            if (type === AnalysisType.QUICK_INSIGHTS) {
                await getQuickInsights(flyerItems);
            } else if (type === AnalysisType.DEEP_DIVE) {
                await getDeepDive(flyerItems);
            } else if (type === AnalysisType.WEB_SEARCH) {
                await searchWeb(flyerItems);
            } else if (type === AnalysisType.PLAN_TRIP) {
                const userLocation = await new Promise<GeolocationCoordinates>((resolve, reject) => {
                    navigator.geolocation.getCurrentPosition(pos => resolve(pos.coords), err => reject(err));
                });
                await planTrip(flyerItems, selectedFlyer?.store, userLocation);
            } else if (type === AnalysisType.COMPARE_PRICES) {
                await comparePrices(watchedItems);
            }
        } catch (e) {
            // The useApi hook now handles setting the error state.
            // We can add specific logging here if needed.
            logger.error(`runAnalysis caught an error for type ${type}`, { error: e });
            let message = 'An unexpected error occurred';
            
            // Check for Geolocation error specifically or by code (1 = PERMISSION_DENIED)
            if (
                (typeof e === 'object' && e !== null && 'code' in e && (e as { code: unknown }).code === 1) || 
                (typeof GeolocationPositionError !== 'undefined' && e instanceof GeolocationPositionError && e.code === GeolocationPositionError.PERMISSION_DENIED)
            ) {
                message = "Geolocation permission denied.";
            } else if (e instanceof Error) {
                message = e.message;
            } else if (typeof e === 'object' && e !== null && 'message' in e) {
                message = String((e as { message: unknown }).message);
            } else if (typeof e === 'string') {
                message = e;
            }
            
            setInternalError(message);        }
    }, [
        flyerItems,
        selectedFlyer?.store,
        watchedItems,
        getQuickInsights,
        getDeepDive,
        searchWeb,
        planTrip,
        comparePrices
    ]);

    const generateImage = useCallback(async () => {
        const mealPlanText = results[AnalysisType.DEEP_DIVE];
        if (!mealPlanText) {
            logger.warn('generateImage called but no meal plan text available in results');
            return;
        }
        setInternalError(null);
        try {
            await generateImageApi(mealPlanText);
        } catch (e) {
            logger.error('generateImage failed', { error: e });
            let message = 'An unexpected error occurred';
             if (e instanceof Error) {
                message = e.message;
            } else if (typeof e === 'object' && e !== null && 'message' in e) {
                message = String((e as { message: unknown }).message);
            } else if (typeof e === 'string') {
                message = e;
            }
            setInternalError(message);
        }
    }, [results, generateImageApi]);

    return {
        results,
        sources,
        loadingStates,
        error,
        runAnalysis,
        generatedImageUrl,
        isGeneratingImage,
        generateImage,
    };
};