import {Dispatch, SetStateAction, useEffect, useRef} from 'react';
import { getCartUpdates } from '../api/promoApi';
import { normalizeProductImage } from '../utils/product';
import type { Product } from '../types/cart';
import {useGlobalZustandState} from "./useGlobalZustandState";
import {reachGoal} from "./useYM";


interface UseCartPollingParams {
    enabled: boolean;
    onProductsChange: Dispatch<SetStateAction<Product[]>>;
    onComplete: () => void;
    onMistake: () => void;
    onLoadingChange: (isLoading: boolean) => void;
    setDisplayText: Dispatch<SetStateAction<string>>;
}

let missing_scenarios = [
    [
        [10_000, 'Ищем Брока...'],
        [10_000, 'Мы всё ещё пытаемся его найти...'],
        [10_000, 'Может быть он в колбасном отделе?'],
        [10_000, 'Или в своём любимом?'],
        [10_000, 'Какой у Брока любимый отдел?'],
        [10_000, 'Если это прятки, то я проиграл, выходи'],
        [10_000, 'Я сдаюсь, перезагрузите страницу?'],
    ],
    [
        [10_000, 'Брок у полки с соком...'],
        [10_000, 'Он выбирает апельсиновый...'],
        [10_000, 'Вспомнил, что любит яблочный...'],
        [10_000, 'Теперь сравнивает состав...'],
        [10_000, 'Сока нет, есть нектар...'],
        [10_000, 'Брок возмущён...'],
        [10_000, 'Он уходит с водой...'],
        [10_000, 'Классика. Перезагрузите страницу?']
    ],
    [
        [10_000, 'Брок в молочном отделе...'],
        [10_000, 'Ищет кефир 1%...'],
        [10_000, 'Нашёл, но срок годности...'],
        [10_000, 'Завтра. Брок не рискует...'],
        [10_000, 'Берёт 2,5%...'],
        [10_000, 'Потом ставит обратно...'],
        [10_000, 'Пробует на ощупь ряженку...'],
        [10_000, 'Это надолго. Перезагрузите страницу?']
    ],
    [
        [10_000, 'Брок в отделе замороженных продуктов...'],
        [15_000, 'Брок застрял в отделе заморозки. Буквально...'],
        [10_000, 'Брок пытается открыть морозилку изнутри...'],
        [10_000, 'Кажется, два пломбира ему мешают...'],
        [10_000, 'Вызвали спасателей и сотрудника с ломом...'],
        [10_000, 'Брок заявил, что без пломбира не выйдет...'],
        [10_000, 'Переговоры вступили в финальную стадию...'],
        [10_000, 'У Брока коробка пломбира'],
        [10_000, 'Перезагрузите страницу?'],
    ],
    [
        [10_000, 'Брок увидел акцию 1+1 и теперь не может выбрать...'],
        [10_000, 'Брок сказал, что ему нужно ещё пять минуточек...'],
        [10_000, 'Брок увлёкся бесплатными образцами...'],
        [10_000, 'Кажется, Брок уже на КСО'],
        [10_000, 'Брок забыл, что он собирает корзину?'],
        [10_000, 'Брок двигается к выходу с арбузом...'],
        [10_000, 'Брок отвлёкся на робот-пылесос...'],
        [10_000, 'Перезагрузите страницу?'],
    ],
    // [
        // [10_000, 'Брок встал в очередь на кассу...'],
        // [10_000, 'У Брока в корзине один огурец и лотерейный билет...'],
        // [10_000, 'Брок завис на вопросе: «Пакет нужен?»'],
        // [10_000, 'Брок спрашивает: «А у вас есть пакет с динозаврами?»'],
        // [10_000, 'Брок утверждает, что видел такие пакеты в рекламе 2007 года...'],
        // [10_000, 'Менеджер ищет пакеты с динозаврами на складе...'],
        // [10_000, 'Это надолго, нужна перезагрузка'],
    // ],
    [
        [10_000, 'Брок обнаружил тележку с крутящимся колесом...'],
        [10_000, 'Теперь он использует её как скейтборд...'],
        [10_000, 'Брок проехал мимо отдела напитков...'],
        [10_000, 'Сотрудник делает замечание...'],
        [10_000, 'Брок не слышит — он в наушниках...'],
        [10_000, 'Брок врезался в пирамиду из консервов...'],
        [10_000, 'Консервы разлетелись'],
        [10_000, 'Брок помогает собирать, напевая оперу...'],
        [10_000, 'Импровизированный концерт у полки с томатами.'],
        [10_000, 'Перезагрузите страницу?'],
    ],
    [
        [10_000, 'Брок идёт к выходу, его останавливает охранник...'],
        [10_000, 'Охранник просит показать чек...'],
        [10_000, 'Брок показывает купон на скидку...'],
        [10_000, 'Охранник терпеливо объясняет разницу...'],
        [10_000, 'Брок делает вид, что не понимает по-русски...'],
        [10_000, 'Охранник переходит на английский, французский...'],
        [10_000, 'Брок отвечает на клингонском'],
        [10_000, 'Охранник оказывается фанатом «Звёздного пути»'],
        [10_000, 'Они уже пьют кофе и обсуждают спин-оффы.']
    ],
    [
        [10_000, 'Брок свернул не туда и оказался в отделе игрушек...'],
        [10_000, 'Брок застыл перед полкой с резиновыми уточками...'],
        [10_000, 'Брок нажимает на всех уточек по очереди...'],
        [10_000, 'Магазин наполняется хором пищащих уток...'],
        [10_000, 'Сотрудник пытается остановить, но Брок уже дирижирует...'],
        [10_000, 'Покупатели подхватывают, достают уточек из корзин...'],
        [10_000, 'Флешмоб пищащих уток выходит из-под контроля...'],
        [10_000, 'Брок покидает отдел под овации, оставив уточку в кармане.'],
        [10_000, 'Брока вернёт лишь перезагрузка страницы'],
    ]
] as const;

export function useCartPolling({
                                   enabled,
                                   onProductsChange,
                                   onComplete,
                                   onLoadingChange,
                                   setDisplayText,
                                   onMistake,
                               }: UseCartPollingParams) {
    const timeoutRef = useRef<number | null>(null);
    const {updateFromResponse, markAsComplete, markAsIncomplete} = useGlobalZustandState((state) => state);

    useEffect(() => {
        if (!enabled) return;

        setDisplayText('Брок бегает по супермаркету...')

        let cancelled = false;

        let missing_timeout: ReturnType<typeof setTimeout> | null = null;
        let missing_scenario_index = Math.round(Math.random() * (missing_scenarios.length - 1));
        let missing_scenario_element = -1;

        const timeoutFunction = () => {
            missing_scenario_element++;
            if (missing_scenario_element < missing_scenarios[missing_scenario_index].length) {
                setDisplayText(missing_scenarios[missing_scenario_index][missing_scenario_element][1])
                missing_timeout = setTimeout(timeoutFunction, missing_scenarios[missing_scenario_index][missing_scenario_element][0]);
            }
        };

        async function tick() {
            try {
                onLoadingChange(true);

                const update = await getCartUpdates();

                if (cancelled) return;

                if (update.status === 'waiting') {
                    if (!missing_timeout) {
                        missing_timeout = setTimeout(() => {
                            setDisplayText('Ищем Брока...')
                            timeoutFunction();
                        }, 10_000);
                    }
                    timeoutRef.current = window.setTimeout(tick, 2000);
                    return;
                } else if (missing_timeout) {
                    clearTimeout(missing_timeout);
                }
                missing_scenario_element = -1;

                if (update.status === 'complete') {
                    reachGoal('ac_cart_complete');
                    onLoadingChange(false);
                    onComplete();
                    updateFromResponse(true, update.payload?.excess || 0, update.payload?.precision || 0);
                    return;
                }

                if (update.status === 'clear') {
                    const nextProducts = update.payload?.chunk?.map(product => normalizeProductImage(product)) ?? [];
                    timeoutRef.current = window.setTimeout(tick, 3000);
                    markAsIncomplete();
                    onProductsChange(nextProducts);
                }

                if (update.status === 'data') {
                    const chunk = update.payload?.chunk?.map(product => normalizeProductImage(product)) ?? [];
                    updateFromResponse(false, update.payload?.excess || 0, update.payload?.precision || 0);

                    onProductsChange((current: Product[]) => {
                        const next = [...current];

                        chunk.forEach(product => {
                            const index = next.findIndex(item => item.name === product.name);

                            if (index === -1) {
                                next.push(product);
                            } else {
                                next[index] = {
                                    ...next[index],
                                    n: next[index].n + product.n,
                                };
                            }
                        });

                        if (update.payload?.unique_sku_cnt && update.payload?.unique_sku_cnt !== next.length) {
                            onMistake();
                        }

                        return next;
                    });

                    setDisplayText('Брок закинул пару товаров...')
                }
                timeoutRef.current = window.setTimeout(tick, 5000);
            } catch (error) {
                setDisplayText('Нет связи с супермаркетом...')
                timeoutRef.current = window.setTimeout(tick, 3000);
            }
        }

        tick();

        return () => {
            cancelled = true;

            if (missing_timeout) {
                window.clearTimeout(missing_timeout);
            }
            if (timeoutRef.current) {
                window.clearTimeout(timeoutRef.current);
            }
        };
    }, [enabled, onComplete, onLoadingChange, onProductsChange, updateFromResponse, markAsComplete, markAsIncomplete]);
}