import { useEffect, useRef, useState } from "react";
import { useVideoPlayer, VideoPlayer } from "react-datocms";
import MuxPlayer from "@mux/mux-player-react"; // '@mux/mux-player-react/lazy'
import clsx from "clsx";

import Icon from "@/components/icon";
import { APP_DOWNLOAD } from "@/config/constants";
import { downloadFile } from "@/helpers/download";
import { buildExternalVideoSrc, DEFAULT_VIDEO_OPTIONS } from "@/helpers/media";
import type { ExternalVideoField, FileField, VideoOption } from "@/types";

import "@mux/mux-player/themes/microvideo";

import styles from "./styles.module.scss";

interface FileVideoProps {
  video: FileField;
  type: "fileVideo";
  active?: boolean;
  carousel?: boolean;
  download?: boolean;
  index?: number;
  link?: string | null;
  options?: VideoOption[];
  style?: React.CSSProperties;
}

interface ExtVideoProps {
  video: ExternalVideoField;
  type: "extVideo";
  active?: boolean;
  carousel?: boolean;
  download?: boolean;
  link?: string | null;
  index?: number;
  options?: VideoOption[];
  style?: React.CSSProperties;
}

type VideoProps = FileVideoProps | ExtVideoProps;

export default function Video({
  video,
  type,
  active = true,
  carousel = false,
  download = false,
  link = null,
  index,
  options = DEFAULT_VIDEO_OPTIONS,
  style,
}: VideoProps) {
  const videoRef = useRef<any>(null);
  const [playing, setPlaying] = useState<boolean>(false);
  const [clickedPause, setClickedPause] = useState<boolean>(false);
  const [showUI, setShowUI] = useState<boolean>(false);
  const [downloading, setDownloading] = useState<boolean>(false);
  const [autoPlay, setAutoPlay] = useState<boolean>(false);
  const [showPoster, setShowPoster] = useState<boolean>(false);
  const [poster, setPoster] = useState<string>("");

  const propsVideo = useVideoPlayer({ data: (video as any).video });

  const toggleVideo = (
    event:
      | React.MouseEvent<HTMLButtonElement>
      | React.MouseEvent<HTMLVideoElement>
      | React.MouseEvent<HTMLDivElement>,
  ) => {
    event.stopPropagation();
    event.nativeEvent.stopImmediatePropagation();

    const videoEl = videoRef.current;
    if (!videoEl || !options.includes("controls")) return;

    if (videoEl.paused) {
      videoEl.play();
      setPlaying(true);
      setClickedPause(false);
    } else {
      videoEl.pause();
      setPlaying(false);
      setClickedPause(true);
    }
  };

  function onCanPlayThrough(e: any) {
    //console.log( e );
    const videoEl = videoRef.current;
    if (!videoEl) return;
    // -
    /*if (carousel && playing && index === 0 && active) {
      videoEl.pause();
      setPlaying(false);
    }*/
    //console.log( index, active, playing );
  }

  function onError(e: any) {
    console.log("Error: ", e.target.error.message);
  }

  async function downloadHandler(e: React.MouseEvent<HTMLButtonElement>) {
    setDownloading(true);
    // -
    await downloadFile(
      video.url,
      video.title || video.url.split("/").reverse()[0],
      false,
    );
    // -
    setDownloading(false);
  }

  // - INIT -----
  useEffect(() => {
    // - console.log( (video as any).video?.streamingUrl );
    // ?max_resolution=1080p

    const videoEl = videoRef.current;
    if (!videoEl) return;

    const handlePlay = () => setPlaying(true);
    const handlePause = () => setPlaying(false);

    //videoEl.addEventListener("play", handlePlay);
    //videoEl.addEventListener("pause", handlePause);

    // -
    setPoster((video as any).video.thumbnailUrl || "");
    /*
    const isIOS =
      /iPad|iPhone|iPod/.test(navigator.userAgent) &&
      !(window as any).MSStream;
    setShowPoster(isIOS);
    /*/
    setShowPoster(true);
    //*/
    // -

    return () => {
      //videoEl.removeEventListener("play", handlePlay);
      //videoEl.removeEventListener("pause", handlePause);
    };
  }, []);

  useEffect(() => {
    let timer: NodeJS.Timeout;
    if (active) {
      timer = setTimeout(() => {
        setShowUI(active);
      }, 700);
    } else {
      setShowUI(false);
    }
    return () => {
      clearTimeout(timer);
    };
  }, [active]);

  useEffect(() => {
    const videoEl = videoRef.current;
    if (!videoEl) return;

    if (showUI && options.includes("autoplay") && !clickedPause) {
      const promise = videoEl.play();

      if (promise !== undefined) {
        promise
          .then(() => {
            setPlaying(true);
          })
          .catch((error: Error) => {
            setPlaying(false);
          });
      }
    } else {
      videoEl.pause();
      setPlaying(false);
    }
  }, [showUI]);

  return (
    <div className={styles.videoContainer}>
      {type === "fileVideo" ? (
        <>
          {options.includes("controls") && (
            <div
              className={clsx(styles.controls, {
                [styles.active]: playing,
              })}
            >
              <button
                onClick={toggleVideo}
                aria-label={playing ? "Pause video" : "Play video"}
                className={clsx(styles.playIconsWrapper, {
                  [styles.show]: showUI,
                })}
              >
                <Icon
                  className={clsx(styles.icon, styles.iconPlay, {
                    [styles.active]: !playing,
                  })}
                  variant="play"
                />
                <Icon
                  className={clsx(styles.icon, styles.iconPause, {
                    [styles.active]: playing,
                  })}
                  variant="pause"
                />
              </button>

              {download && (
                <button
                  onClick={downloadHandler}
                  aria-label="Download video"
                  className={clsx(styles.download, {
                    [styles.show]: showUI,
                    [styles.downloading]: downloading,
                  })}
                >
                  <div className={styles.iconDownload}>
                    <Icon className={styles.arrow} variant="download" />
                    <div className={styles.spinner}>
                      <Icon className={styles.spinnerIcon} variant="spinner" />
                    </div>
                  </div>
                  <span aria-hidden={true}>{APP_DOWNLOAD}</span>
                </button>
              )}
            </div>
          )}

          {/*
          <VideoPlayer 
            data={video.video } 
            theme="minimal"

            ref={videoRef}
            className={clsx(styles.fileVideo, {
              [styles.show]: showUI,
            })}
            aria-label={video.title ?? video.alt ?? ""}
            playsInline
            controls={false}
            muted={options.includes("mute")}
            autoPlay={autoPlay}
            loop={options.includes("loop")}
            preload={showPoster ? "none" : "auto"}
            poster={showPoster ? poster : undefined}
            onClick={toggleVideo}
            onCanPlayThrough={onCanPlayThrough}
            onError={onError}
          />
          */}

          <MuxPlayer
            ref={videoRef}
            streamType="on-demand"
            theme="microvideo"
            //preload={showPoster ? "none" : "auto"}
            //loading="viewport"
            aria-label={video.title ?? video.alt ?? ""}
            className={clsx(styles.fileVideo, {
              [styles.show]: showUI,
            })}
            muted={options.includes("mute")}
            loop={options.includes("loop")}
            onCanPlayThrough={onCanPlayThrough}
            onError={onError}
            style={{
              aspectRatio: `${(video.width || 100) / (video.height || 100)}`,
              ...style,
            }}
            {...propsVideo}
          >
            {showPoster && <img slot="poster" src={poster} />}
          </MuxPlayer>
        </>
      ) : (
        <div
          className={styles.extVideo}
          style={{
            paddingBottom: `${(video.height / video.width) * 100}%`,
          }}
        >
          <iframe
            width={video.width}
            height={video.height}
            src={buildExternalVideoSrc(video, options)}
            frameBorder="0"
            allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
            allowFullScreen
            title={video.title}
            style={style}
          />
        </div>
      )}
    </div>
  );
}
