import { useCallback, useEffect, useRef, useState } from "react";
import clsx from "clsx";

import Icon from "@/components/icon";
import Image from "@/components/image";
import { useRaf } from "@/hooks";
import type { AudioPlayerBlock } from "@/types";

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

const formatTime = (timeInMilliseconds: number) => {
  const totalSeconds = timeInMilliseconds / 1000;
  const minutes = Math.floor(totalSeconds / 60) || 0;
  const seconds = Math.floor(totalSeconds % 60) || 0;
  return `${minutes}:${seconds < 10 ? "0" : ""}${seconds}`;
};

type AudioPlayerProps = AudioPlayerBlock;

export default function AudioPlayer({
  title,
  coverImage,
  audioSource,
}: AudioPlayerProps) {
  const [isPlaying, setIsPlaying] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const howlInstance = useRef<Howl | null>(null);

  const playedPercentage = (currentTime / duration) * 100;

  useEffect(() => {
    howlInstance.current = new Howl({
      src: audioSource.map((source) => source.url),
      format: audioSource.map((source) => source.format),
      html5: true,
      onload: function () {
        if (this instanceof Howl && typeof this.duration === "function") {
          setDuration(this.duration() * 1000);
        }
      },
      onend: () => {
        setIsPlaying(false);
      },
    });

    return () => {
      howlInstance.current?.unload();
    };
  }, [audioSource]);

  const updateProgress = useCallback(() => {
    if (howlInstance.current) {
      setCurrentTime(howlInstance.current.seek() * 1000);
    }
  }, []);

  useRaf(updateProgress, [isPlaying, updateProgress]);

  const togglePlay = () => {
    if (howlInstance.current) {
      if (isPlaying) {
        howlInstance.current.pause();
      } else {
        howlInstance.current.play();
      }
      setIsPlaying(!isPlaying);
    }
  };

  const onSeek = (e: React.ChangeEvent<HTMLInputElement>) => {
    const time = Number(e.target.value);
    if (howlInstance.current) {
      howlInstance.current.seek(time / 1000);
    }
    setCurrentTime(time);
  };

  return (
    <div className={styles.audioPlayer}>
      <div className={styles.coverImageContainer}>
        <Image className={styles.coverImage} image={coverImage} />
      </div>
      <div className={styles.inner}>
        {title && <p className={styles.title}>{title}</p>}
        <div className={styles.timeStamps}>
          <span>{formatTime(currentTime)}</span>
          <span>{formatTime(duration)}</span>
        </div>
        <div className={styles.progressBarContainer}>
          <input
            className={styles.progressBar}
            type="range"
            min="0"
            max={duration}
            value={currentTime}
            onChange={onSeek}
            style={{
              background: `linear-gradient(to right, var(--color-black) 0%, var(--color-black) ${playedPercentage}%, var(--color-gray-400) ${playedPercentage}%, var(--color-gray-400) 100%)`,
            }}
          />
        </div>
      </div>
      <button
        className={styles.playPauseButton}
        onClick={togglePlay}
        aria-label={isPlaying ? "Pause audio" : "Play audio"}
      >
        <span className={styles.iconGroup}>
          <Icon
            id="pause-icon"
            className={clsx(styles.icon, {
              [styles.visible]: isPlaying,
            })}
            variant="pauseCircle"
          />
          <Icon
            id="play-icon"
            className={clsx(styles.icon, {
              [styles.visible]: !isPlaying,
            })}
            variant="playCircle"
          />
        </span>
      </button>
    </div>
  );
}
