import { useCallback, useEffect, useRef, useState } from 'react';
import axios from 'axios';
import type { HistorialCupsResponse, TipoCupsHistorial } from '../types/historialCups';

interface CacheEntry {
    data: HistorialCupsResponse;
}

/** Caché compartida entre instancias del hook (misma sesión de pantalla). */
const historialCacheGlobal = new Map<string, CacheEntry>();

function claveCache(tipo: TipoCupsHistorial, codCups: number): string {
    return `${tipo}-${codCups}`;
}

export function invalidateHistorialCupsCache(tipo: TipoCupsHistorial, codCups: number): void {
    historialCacheGlobal.delete(claveCache(tipo, codCups));
}

export interface UseHistorialCupsResult {
    data: HistorialCupsResponse | null;
    loading: boolean;
    error: string | null;
    codCupsActivo: number | null;
    fetchHistorial: () => Promise<void>;
    refetchHistorial: () => Promise<void>;
    invalidate: () => void;
}

export function useHistorialCups(
    codCups: number | null,
    tipo: TipoCupsHistorial,
    tipoRuta: string
): UseHistorialCupsResult {
    const [data, setData] = useState<HistorialCupsResponse | null>(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [codCupsActivo, setCodCupsActivo] = useState<number | null>(null);
    const requestIdRef = useRef(0);
    const codCupsRef = useRef(codCups);

    codCupsRef.current = codCups;

    useEffect(() => {
        if (!codCups) {
            setData(null);
            setError(null);
            setLoading(false);
            setCodCupsActivo(null);
            return;
        }

        const key = claveCache(tipo, codCups);
        const cached = historialCacheGlobal.get(key);

        if (cached && cached.data.codCups === codCups) {
            setData(cached.data);
            setCodCupsActivo(codCups);
            setError(null);
            return;
        }

        setData(null);
        setCodCupsActivo(null);
        setError(null);
    }, [codCups, tipo]);

    const cargarHistorial = useCallback(async (force = false) => {
        const cupsId = codCupsRef.current;

        if (!cupsId) {
            setData(null);
            setError(null);
            setLoading(false);
            setCodCupsActivo(null);
            return;
        }

        const key = claveCache(tipo, cupsId);

        if (force) {
            historialCacheGlobal.delete(key);
        } else {
            const cached = historialCacheGlobal.get(key);
            if (cached && cached.data.codCups === cupsId) {
                setData(cached.data);
                setCodCupsActivo(cupsId);
                setError(null);
                setLoading(false);
                return;
            }
        }

        const requestId = ++requestIdRef.current;
        setLoading(true);
        setError(null);
        setData(null);
        setCodCupsActivo(null);

        try {
            const response = await axios.get(route('cups.historial', { id: cupsId, tipo: tipoRuta }));

            if (requestId !== requestIdRef.current || codCupsRef.current !== cupsId) {
                return;
            }

            if (response.data?.success) {
                const payload = response.data.data as HistorialCupsResponse;
                historialCacheGlobal.set(key, { data: payload });
                setData(payload);
                setCodCupsActivo(cupsId);
            } else {
                setError(response.data?.message ?? 'Error al cargar el historial');
            }
        } catch (err: unknown) {
            if (requestId !== requestIdRef.current || codCupsRef.current !== cupsId) {
                return;
            }

            const message = axios.isAxiosError(err)
                ? (err.response?.data?.message ?? 'Error de red al cargar el historial')
                : 'Error al cargar el historial';
            setError(message);
        } finally {
            if (requestId === requestIdRef.current && codCupsRef.current === cupsId) {
                setLoading(false);
            }
        }
    }, [tipo, tipoRuta]);

    useEffect(() => {
        void cargarHistorial(false);
    }, [codCups, cargarHistorial]);

    const fetchHistorial = useCallback(async () => {
        await cargarHistorial(false);
    }, [cargarHistorial]);

    const refetchHistorial = useCallback(async () => {
        await cargarHistorial(true);
    }, [cargarHistorial]);

    const invalidate = useCallback(() => {
        if (codCupsRef.current) {
            historialCacheGlobal.delete(claveCache(tipo, codCupsRef.current));
        }
        requestIdRef.current += 1;
        setData(null);
        setCodCupsActivo(null);
        setError(null);
    }, [tipo]);

    const datosCoinciden = codCupsActivo === codCups;

    return {
        data: datosCoinciden ? data : null,
        loading,
        error,
        codCupsActivo,
        fetchHistorial,
        refetchHistorial,
        invalidate,
    };
}
