import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import Joyride, { ACTIONS, CallBackProps, EVENTS, STATUS } from 'react-joyride';
import { useLocation, useNavigate } from 'react-router-dom';
import { Colors } from '../../config/designTokens';
import {
  hasSeenWalkthrough,
  markWalkthroughSeen,
  walkthroughSteps,
} from '../../walkthrough/walkthroughConfig';

interface GuidedWalkthroughProps {
  isEnabled: boolean;
}

export const GuidedWalkthrough: React.FC<GuidedWalkthroughProps> = ({ isEnabled }) => {
  const navigate = useNavigate();
  const location = useLocation();
  const [isActive, setIsActive] = useState(false);
  const [isTargetReady, setIsTargetReady] = useState(false);
  const [stepIndex, setStepIndex] = useState(0);
  const hasInitialized = useRef(false);

  const steps = useMemo(
    () =>
      walkthroughSteps.map(({ route: _route, ...step }) => ({
        ...step,
      })),
    []
  );

  const navigateToStepRoute = useCallback(
    (index: number) => {
      const targetStep = walkthroughSteps[index];
      if (!targetStep) {
        return;
      }

      const targetRoute = targetStep.route;
      const currentRoute = `${location.pathname}${location.search}`;
      if (currentRoute !== targetRoute) {
        navigate(targetRoute);
      }
    },
    [location.pathname, location.search, navigate]
  );

  const isStepTargetAvailable = useCallback((index: number) => {
    if (typeof document === 'undefined') {
      return false;
    }

    const step = walkthroughSteps[index];
    if (!step) {
      return false;
    }

    return document.querySelector(step.target) !== null;
  }, []);

  const startTour = useCallback(() => {
    if (!isEnabled) {
      return;
    }

    setStepIndex(0);
    setIsTargetReady(false);
    setIsActive(true);
    navigateToStepRoute(0);
  }, [isEnabled, navigateToStepRoute]);

  useEffect(() => {
    if (!isEnabled) {
      setIsActive(false);
      setIsTargetReady(false);
      return;
    }

    if (!hasInitialized.current && !hasSeenWalkthrough()) {
      hasInitialized.current = true;
      startTour();
    }
  }, [isEnabled, startTour]);

  useEffect(() => {
    if (!isEnabled || !isActive) {
      setIsTargetReady(false);
      return;
    }

    let isCancelled = false;

    navigateToStepRoute(stepIndex);

    const syncTargetAvailability = () => {
      if (isCancelled) {
        return;
      }

      const ready = isStepTargetAvailable(stepIndex);
      setIsTargetReady(ready);

      if (!ready) {
        window.setTimeout(syncTargetAvailability, 150);
      }
    };

    syncTargetAvailability();

    return () => {
      isCancelled = true;
    };
  }, [isActive, isEnabled, isStepTargetAvailable, navigateToStepRoute, stepIndex, location.pathname, location.search]);

  const finishTour = useCallback(() => {
    setIsActive(false);
    setIsTargetReady(false);
    markWalkthroughSeen();
  }, []);

  const handleCallback = useCallback(
    (data: CallBackProps) => {
      const { action, index, status, type } = data;

      if (status === STATUS.FINISHED || status === STATUS.SKIPPED) {
        finishTour();
        return;
      }

      if (type === EVENTS.TARGET_NOT_FOUND) {
        setIsTargetReady(false);
        navigateToStepRoute(index);
        return;
      }

      if (type === EVENTS.STEP_AFTER) {
        const nextIndex = action === ACTIONS.PREV ? index - 1 : index + 1;

        if (nextIndex < 0 || nextIndex >= walkthroughSteps.length) {
          finishTour();
          return;
        }

        setIsTargetReady(false);
        setStepIndex(nextIndex);
        navigateToStepRoute(nextIndex);
      }
    },
    [finishTour, navigateToStepRoute]
  );

  if (!isEnabled) {
    return null;
  }

  return (
    <>
      <Joyride
        callback={handleCallback}
        continuous
        disableScrolling={false}
        hideBackButton={false}
        run={isActive && isTargetReady}
        scrollToFirstStep
        showProgress
        showSkipButton
        spotlightClicks={false}
        stepIndex={stepIndex}
        steps={steps}
        locale={{
          back: 'Back',
          close: 'Close',
          last: 'Finish',
          next: 'Next',
          skip: 'Skip tour',
        }}
        styles={{
          options: {
            arrowColor: Colors.parchment.light,
            backgroundColor: Colors.parchment.light,
            overlayColor: 'rgba(15, 17, 23, 0.7)',
            primaryColor: Colors.gold.default,
            textColor: Colors.text.primary,
            zIndex: 9999,
          },
          buttonBack: {
            color: Colors.forest.dark,
          },
          buttonSkip: {
            color: Colors.text.secondary,
          },
        }}
      />

      <button
        type="button"
        onClick={startTour}
        aria-label="Show walkthrough"
        title="Show walkthrough"
        className="fixed bottom-6 right-6 h-12 w-12 rounded-full bg-gold text-text-primary border-2 border-forest shadow-lg hover:bg-gold-light transition-all duration-300 z-40 font-epic text-xl"
      >
        ?
      </button>
    </>
  );
};

GuidedWalkthrough.displayName = 'GuidedWalkthrough';
