import { StepType, TourContext, TourProvider } from "@reactour/tour";
import clsx from "clsx";
import { Dispatch, FC, HTMLAttributes, SetStateAction } from "react";

import QuestionIcon from "@dndbeyond/fontawesome-cache/svgs/solid/question.svg";

import { Button } from "../Button";
import styles from "./styles.module.css";

export interface GuidedTourProps extends HTMLAttributes<HTMLDivElement> {
  afterOpen?: (target: Element | null) => void;
  beforeClose?: (target: Element | null) => void;
  cookieName?: string;
  setStep?: SetStateAction<any>;
  showOnFirstLoad?: boolean;
  steps?: StepType[];
  step?: number;
}

export const GuidedTour: FC<GuidedTourProps> = ({
  afterOpen,
  beforeClose,
  children,
  className,
  cookieName = "ddbGuidedTour",
  setStep,
  showOnFirstLoad,
  step = 0,
  steps = [],
  ...props
}) => {
  const handleBeforeClose = () => {
    const html = document.querySelector("html");
    if (html) html.style.overflowY = "visible";
    if (beforeClose) beforeClose(null);
  };

  const handleAfterOpen = () => {
    const html = document.querySelector("html");
    if (html) html.style.overflowY = "hidden";
    if (afterOpen) afterOpen(null);
  };

  const handleLoad = (setIsOpen: Dispatch<SetStateAction<boolean>>) => {
    if (showOnFirstLoad) {
      const viewedTour = localStorage.getItem(cookieName);

      if (!viewedTour) {
        setIsOpen(true);
        localStorage.setItem(cookieName, "true");
      }
    }
  };

  const PrevButton = ({ Button, ...props }) => (
    <Button {...props} kind="prev" hideArrow={step === 0} />
  );

  const NextButton = ({ Button, ...props }) => (
    <Button
      {...props}
      kind="next"
      hideArrow={step === (steps?.length || 0) - 1}
    />
  );

  return (
    <div className={clsx([styles.guidedTour, className])} {...props}>
      <TourProvider
        steps={steps}
        currentStep={step}
        setCurrentStep={setStep}
        afterOpen={handleAfterOpen}
        beforeClose={handleBeforeClose}
        showDots={false}
        prevButton={PrevButton}
        nextButton={NextButton}
      >
        <TourContext.Consumer>
          {({ setIsOpen }) => (
            <div onLoad={() => handleLoad(setIsOpen)}>
              {children}
              <Button
                className={styles.tourButton}
                onClick={() => setIsOpen(true)}
                color="info"
                size="small"
                aria-label="Open guided tour"
              >
                <QuestionIcon />
              </Button>
            </div>
          )}
        </TourContext.Consumer>
      </TourProvider>
    </div>
  );
};
