import React, { useEffect, useState, useCallback } from "react";
import { TourGuideButtons } from "./TourGuideButtons";
import { Highlight } from "./Highlight";
import './TourGuidePopup.css';
import { TourGuidePopupProps } from "../types/app.types";

type PopupPosition = {
  top: number;
  left: number;
  width: number;
  height: number;
  position: "top" | "bottom" | "left" | "right";
  arrowOffset: number;  // Add arrowOffset
};

type CustomRect = {
  top: number;
  left: number;
  width: number;
  height: number;
  x: number;
  y: number;
  bottom: number;
  right: number;
  toJSON: () => object;
};

export const TourGuidePopup: React.FC<TourGuidePopupProps> = ({ steps }) => {
  const [isVisible, setIsVisible] = useState(false);
  const [currentStep, setCurrentStep] = useState(0);
  const [popupPosition, setPopupPosition] = useState<PopupPosition | null>(null);

  useEffect(() => {
    if (steps.length > 0) {
      setIsVisible(true);
    }
  }, [steps]);

  const calculateValidPositions = useCallback(
    ({ top, left, bottom, right }: CustomRect) => {
      const viewportWidth = window.innerWidth;
      const viewportHeight = window.innerHeight;

      return [
        { position: "bottom", space: viewportHeight - bottom },
        { position: "top", space: top },
        { position: "right", space: viewportWidth - right },
        { position: "left", space: left },
      ].sort((a, b) => b.space - a.space); // Sort by available space
    },
    []
  );

  const getPopupPosition = useCallback(
    (
      position: "top" | "bottom" | "left" | "right",
      { top, left, width, height }: CustomRect
    ): PopupPosition => {
      const popupWidth = 300;
      const popupHeight = 150;

      let arrowOffset = 0;
      let popupTop = 0;
      let popupLeft = 0;

      switch (position) {
        case "bottom":
          popupTop = top + height + 15;
          popupLeft = left + width / 2 - popupWidth / 2;
          arrowOffset = left + width / 2 - popupLeft;
          break;
        case "top":
          popupTop = top - popupHeight - 15;
          popupLeft = left + width / 2 - popupWidth / 2;
          arrowOffset = left + width / 2 - popupLeft;
          break;
        case "right":
          popupTop = top + height / 2 - popupHeight / 2;
          popupLeft = left + width + 15;
          arrowOffset = top + height / 2 - popupTop;
          break;
        case "left":
          popupTop = top + height / 2 - popupHeight / 2;
          popupLeft = left - popupWidth - 15;
          arrowOffset = top + height / 2 - popupTop;
          break;
        default:
          break;
      }

      return {
        top: Math.max(popupTop + window.scrollY, 0),
        left: Math.max(popupLeft + window.scrollX, 0),
        width: popupWidth,
        height: popupHeight,
        position,
        arrowOffset, // Return the arrow offset
      };
    },
    []
  );

  useEffect(() => {
    if (isVisible && steps[currentStep]?.id) {
      const target = document.getElementById(steps[currentStep].id);
      if (target) {
        target.scrollIntoView({ behavior: "smooth", block: "center" });

        const { top, left, width, height } = target.getBoundingClientRect();

        const positionData: CustomRect = {
          top,
          left,
          width,
          height,
          x: left,
          y: top,
          bottom: top + height,
          right: left + width,
          toJSON: () => ({
            top,
            left,
            width,
            height,
            x: left,
            y: top,
            bottom: top + height,
            right: left + width,
          }),
        };

        const validPositions = calculateValidPositions(positionData);
        const chosenPosition =
          validPositions.find((pos) => pos.space >= 150)?.position || "bottom";

        const newPosition = getPopupPosition(chosenPosition as "top" | "bottom" | "left" | "right", positionData);
        setPopupPosition(newPosition);

        target.style.zIndex = "1001";
        target.style.position = "relative";
      }
    }

    return () => {
      const target = document.getElementById(steps[currentStep]?.id);
      if (target) {
        target.style.zIndex = "";
        target.style.position = "";
      }
    };
  }, [isVisible, currentStep, steps, calculateValidPositions, getPopupPosition]);

  const handlePrevious = () => setCurrentStep((prev) => Math.max(prev - 1, 0));
  const handleClose = () => setIsVisible(false);
  const handleNext = () => {
    if (currentStep === steps.length - 1) {
      handleClose();
    } else {
      setCurrentStep((prev) => prev + 1);
    }
  };
  const handleRestart = () => {
    setCurrentStep(0);
    setIsVisible(true);
  };

  // Handle keyboard navigation
  const handleKeyDown = useCallback((e: KeyboardEvent) => {
    if (e.key === "ArrowLeft") {
      handlePrevious();
    } else if (e.key === "ArrowRight") {
      handleNext();
    }
  }, [handlePrevious, handleNext]);

  useEffect(() => {
    // Add keydown event listener
    window.addEventListener("keydown", handleKeyDown);

    return () => {
      // Clean up the event listener
      window.removeEventListener("keydown", handleKeyDown);
    };
  }, [handleKeyDown]);

  if (!isVisible || !popupPosition)
    return (
      <button onClick={handleRestart} className="button-restart">
        Restart Tour
      </button>
    );

  const progress = ((currentStep + 1) / steps.length) * 100;

  return (
    <>
      <div className="progress-container">
        <div className="progress-bar" style={{ width: `${progress}%` }}></div>
      </div>

      <div className="tour-overlay" onClick={handleClose}></div>
      <Highlight targetId={steps[currentStep]?.id} />

      {/* Tooltip-like popup */}
      <div
        className={`tour-guide-popup ${popupPosition.position}`}
        style={{
          top: popupPosition.top,
          left: popupPosition.left,
        }}
      >
        <div
          className={`popup-arrow ${popupPosition.position}`}
          style={{
            "--arrow-offset": `${popupPosition.arrowOffset}px`,
          } as React.CSSProperties}
        />
        <button onClick={handleClose} className="button-close" aria-label="Close">
          &times;
        </button>
        <div className="popup-content">
          <p>{steps[currentStep]?.content}</p>
          <TourGuideButtons
            currentStep={currentStep}
            totalSteps={steps.length}
            onPrevious={handlePrevious}
            onNext={handleNext}
            onClose={handleClose}
          />
        </div>
      </div>
    </>
  );
};
