"use client";

import { useEffect, useMemo, useCallback } from "react";
import { useRouter } from "next/navigation";

import { resolveNextScreenId, type UnleashChecker } from "@/lib/funnel/navigation";
import { resolveScreenVariant } from "@/lib/funnel/variants";
import { useFunnelRuntime } from "@/lib/funnel/FunnelProvider";
import { renderScreen } from "@/lib/funnel/screenRenderer";
import type {
  FunnelDefinition,
  FunnelAnswers,
  ListScreenDefinition,
  DateScreenDefinition,
} from "@/lib/funnel/types";
import { getZodiacSign } from "@/lib/funnel/zodiac";
import { useSession } from "@/hooks/session/useSession";
import { buildSessionDataFromScreen } from "@/lib/funnel/registrationHelpers";
import { useUnleashContext, sendUnleashImpression } from "@/lib/funnel/unleash";

// Функция для оценки длины пути пользователя на основе текущих ответов
function estimatePathLength(
  funnel: FunnelDefinition,
  answers: FunnelAnswers,
  unleashChecker?: UnleashChecker
): number {
  const visited = new Set<string>();
  let currentScreenId = funnel.meta.firstScreenId || funnel.screens[0]?.id;

  // Симулируем прохождение воронки с текущими ответами
  while (currentScreenId && !visited.has(currentScreenId)) {
    visited.add(currentScreenId);

    const currentScreen = funnel.screens.find((s) => s.id === currentScreenId);
    if (!currentScreen) break;

    const resolvedScreen = resolveScreenVariant(
      currentScreen,
      answers,
      funnel.screens,
      unleashChecker
    );
    const nextScreenId = resolveNextScreenId(
      resolvedScreen,
      answers,
      funnel.screens,
      unleashChecker
    );

    // Если достигли конца или зацикливание
    if (!nextScreenId || visited.has(nextScreenId)) {
      break;
    }

    currentScreenId = nextScreenId;
  }

  return visited.size;
}

interface FunnelRuntimeProps {
  funnel: FunnelDefinition;
  initialScreenId: string;
}

export function FunnelRuntime({ funnel, initialScreenId }: FunnelRuntimeProps) {
  const router = useRouter();
  const { createSession, updateSession } = useSession({
    funnelId: funnel.meta.id,
  });
  const { answers, registerScreen, setAnswers, history } = useFunnelRuntime(
    funnel.meta.id
  );
  const { checkVariant, activeVariants } = useUnleashContext();

  // Создаем unleashChecker функцию для передачи в navigation/variants
  const unleashChecker: UnleashChecker = useCallback(
    (flag, expectedVariants, operator) => {
      return checkVariant(flag, expectedVariants, operator);
    },
    [checkVariant]
  );

  // ✅ Screen Map для O(1) поиска вместо O(n)
  const screenMap = useMemo(() => {
    return new Map(funnel.screens.map((screen) => [screen.id, screen]));
  }, [funnel.screens]);

  const baseScreen = useMemo(() => {
    const screen = screenMap.get(initialScreenId) ?? funnel.screens[0];
    if (!screen) {
      throw new Error("Funnel definition does not contain any screens");
    }
    return screen;
  }, [screenMap, initialScreenId, funnel.screens]);

  const currentScreen = useMemo(() => {
    return resolveScreenVariant(baseScreen, answers, funnel.screens, unleashChecker);
  }, [baseScreen, answers, funnel.screens, unleashChecker]);

  const selectedOptionIds = answers[currentScreen.id] ?? [];

  // Собираем флаги которые используются на текущем экране
  const currentScreenFlags = useMemo(() => {
    const flags = new Set<string>();

    // Флаги из вариантов текущего экрана
    currentScreen.variants?.forEach((variant) => {
      variant.conditions.forEach((condition) => {
        if (condition.conditionType === "unleash" && condition.unleashFlag) {
          flags.add(condition.unleashFlag);
        }
      });
    });

    // Флаги из правил навигации текущего экрана
    currentScreen.navigation?.rules?.forEach((rule) => {
      rule.conditions.forEach((condition) => {
        if (condition.conditionType === "unleash" && condition.unleashFlag) {
          flags.add(condition.unleashFlag);
        }
      });
    });

    return Array.from(flags);
  }, [currentScreen]);

  useEffect(() => {
    createSession();
  }, [createSession]);

  useEffect(() => {
    registerScreen(currentScreen.id);
  }, [currentScreen.id, registerScreen]);

  // Создаем стабильный ключ для текущих вариантов флагов
  const currentFlagsKey = useMemo(() => {
    if (currentScreenFlags.length === 0) {
      return "";
    }
    
    // Создаем строку вида "flag1:variant1,flag2:variant2"
    return currentScreenFlags
      .map(flag => `${flag}:${activeVariants[flag] || "loading"}`)
      .sort()
      .join(",");
  }, [currentScreenFlags, activeVariants]);

  // Отправляем impression события в GA когда пользователь видит экран с AB тестами
  useEffect(() => {
    if (currentScreenFlags.length === 0) {
      return; // Нет AB тестов на этом экране
    }

    // Проверяем что все флаги загружены
    const allFlagsLoaded = currentScreenFlags.every(flag => {
      const variant = activeVariants[flag];
      return variant !== undefined && variant !== "loading";
    });
    
    if (!allFlagsLoaded) {
      // Ждем пока все флаги загрузятся
      return;
    }

    // Отправляем impression для каждого флага на этом экране
    currentScreenFlags.forEach((flag) => {
      const variant = activeVariants[flag];
      sendUnleashImpression(flag, variant);
    });
    
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [currentScreen.id, currentFlagsKey]);

  const historyWithCurrent = useMemo(() => {
    if (history.length === 0) {
      return [currentScreen.id];
    }

    const last = history[history.length - 1];
    if (last === currentScreen.id) {
      return history;
    }

    const existingIndex = history.lastIndexOf(currentScreen.id);
    if (existingIndex >= 0) {
      return history.slice(0, existingIndex + 1);
    }

    return [...history, currentScreen.id];
  }, [history, currentScreen.id]);

  // Calculate automatic progress based on user's actual path
  const screenProgress = useMemo(() => {
    const total = estimatePathLength(funnel, answers, unleashChecker);
    const current = historyWithCurrent.length; // Номер текущего экрана = количество посещенных
    return { current, total };
  }, [historyWithCurrent.length, funnel, answers, unleashChecker]);

  const goToScreen = (screenId: string | undefined) => {
    if (!screenId) {
      return;
    }
    router.push(`/${funnel.meta.id}/${screenId}`);
  };

  const handleContinue = () => {
    if (answers[currentScreen.id] && currentScreen.template !== "email") {
      // Собираем данные для сессии
      const sessionData = buildSessionDataFromScreen(
        currentScreen,
        answers[currentScreen.id]
      );

      // Для date экранов с registrationFieldKey НЕ отправляем answers
      const shouldSkipAnswers =
        currentScreen.template === "date" &&
        "dateInput" in currentScreen &&
        currentScreen.dateInput?.registrationFieldKey;

      updateSession({
        ...(shouldSkipAnswers
          ? {}
          : {
              answers: {
                [currentScreen.id]: answers[currentScreen.id],
              },
            }),
        // Добавляем данные с registrationFieldKey
        ...sessionData,
      });
    }
    const nextScreenId = resolveNextScreenId(
      currentScreen,
      answers,
      funnel.screens,
      unleashChecker
    );
    goToScreen(nextScreenId);
  };

  const handleSelectionChange = (ids: string[], skipCheckChanges = false) => {
    const prevSelectedIds = selectedOptionIds;
    const hasChanged =
      skipCheckChanges ||
      prevSelectedIds.length !== ids.length ||
      prevSelectedIds.some((value, index) => value !== ids[index]);

    // Check if this is a single selection list without action button
    const shouldAutoAdvance =
      currentScreen.template === "list" &&
      (() => {
        const listScreen = currentScreen as ListScreenDefinition;
        const selectionType = listScreen.list.selectionType;

        // Простая логика: автопереход если single selection и кнопка отключена
        const bottomActionButton = listScreen.bottomActionButton;
        const isButtonExplicitlyDisabled = bottomActionButton?.show === false;

        return (
          selectionType === "single" &&
          isButtonExplicitlyDisabled &&
          ids.length > 0
        );
      })();

    // ПРАВИЛЬНОЕ РЕШЕНИЕ: Автопереход ТОЛЬКО при изменении значения
    // Это исключает автопереход при возврате назад, когда компоненты
    // восстанавливают состояние и вызывают callbacks без реального изменения
    const shouldProceed = hasChanged;

    if (!shouldProceed) {
      return; // Блокируем программные вызовы useEffect без изменений
    }

    const nextAnswers = {
      ...answers,
      [currentScreen.id]: ids,
    } as typeof answers;

    if (ids.length === 0) {
      delete nextAnswers[currentScreen.id];
    }

    // Only save answers if they actually changed
    if (hasChanged) {
      setAnswers(currentScreen.id, ids);
    }

    if (currentScreen.template === "date") {
      const dateScreen = currentScreen as DateScreenDefinition;
      const zodiacSettings = dateScreen.dateInput?.zodiac;
      const storageKey = zodiacSettings?.storageKey?.trim();

      if (storageKey) {
        if (zodiacSettings?.enabled) {
          const [monthValue, dayValue] = ids;
          const month = parseInt(monthValue ?? "", 10);
          const day = parseInt(dayValue ?? "", 10);
          const zodiac =
            Number.isNaN(month) || Number.isNaN(day)
              ? null
              : getZodiacSign(month, day);

          if (zodiac) {
            setAnswers(storageKey, [zodiac]);
          } else {
            setAnswers(storageKey, []);
          }
        } else {
          setAnswers(storageKey, []);
        }
      }
    }

    // Auto-advance for single selection without action button
    if (shouldAutoAdvance) {
      // Собираем данные для сессии
      const sessionData = buildSessionDataFromScreen(currentScreen, ids);

      updateSession({
        answers: {
          [currentScreen.id]: ids,
        },
        // Добавляем данные с registrationFieldKey если они есть
        ...sessionData,
      });
      const nextScreenId = resolveNextScreenId(
        currentScreen,
        nextAnswers,
        funnel.screens,
        unleashChecker
      );
      goToScreen(nextScreenId);
    }
  };

  const onBack = () => {
    const backTarget: string | undefined = currentScreen.navigation?.onBackScreenId;

    if (backTarget) {
      // Переназначаем назад на конкретный экран без роста истории
      router.replace(`/${funnel.meta.id}/${backTarget}`);
      return;
    }

    const currentIndex = historyWithCurrent.lastIndexOf(currentScreen.id);

    if (currentIndex > 0) {
      goToScreen(historyWithCurrent[currentIndex - 1]);
      return;
    }

    if (historyWithCurrent.length > 1) {
      goToScreen(historyWithCurrent[historyWithCurrent.length - 2]);
      return;
    }

    router.back();
  };

  // Перехват аппаратной/браузерной кнопки Назад, когда настроен onBackScreenId
  useEffect(() => {
    const backTarget: string | undefined = currentScreen.navigation?.onBackScreenId;
    if (!backTarget) return;

    // Флаг для предотвращения множественных срабатываний
    let isRedirecting = false;

    const pushTrap = () => {
      try {
        window.history.pushState(
          { __trap: true, __screenId: currentScreen.id },
          "",
          window.location.href
        );
      } catch {}
    };

    // Добавляем trap state в историю
    pushTrap();

    const handlePopState = () => {
      // Проверяем наличие backTarget на момент события
      const currentBackTarget = currentScreen.navigation?.onBackScreenId;
      if (!currentBackTarget || isRedirecting) return;

      isRedirecting = true;

      // Перемещаемся вперед на 1 шаг чтобы отменить переход назад
      window.history.go(1);

      // Небольшая задержка для завершения history.go
      setTimeout(() => {
        try {
          // Выполняем редирект на целевой экран
          router.replace(`/${funnel.meta.id}/${currentBackTarget}`);
          
          // Сбрасываем флаг
          setTimeout(() => {
            isRedirecting = false;
          }, 100);
        } catch (error) {
          // Fallback: если router.replace не сработал, используем нативную навигацию
          console.error('Router replace failed, using fallback navigation:', error);
          window.location.href = `/${funnel.meta.id}/${currentBackTarget}`;
        }
      }, 10);
    };

    window.addEventListener("popstate", handlePopState);
    return () => {
      window.removeEventListener("popstate", handlePopState);
    };
  }, [currentScreen.id, currentScreen.navigation?.onBackScreenId, funnel.meta.id, router]);

  const canGoBack = historyWithCurrent.lastIndexOf(currentScreen.id) > 0;

  return renderScreen({
    funnel,
    screen: currentScreen,
    selectedOptionIds,
    onSelectionChange: handleSelectionChange,
    onContinue: handleContinue,
    canGoBack,
    onBack,
    screenProgress,
    defaultTexts: funnel.defaultTexts,
    answers,
  });
}
