"use client";

import { useCallback, useEffect, useRef, useState } from "react";
import BoldIcon from "@/components/ui/BoldIcon";
import IOSSpinner from "@/components/ui/IOSSpinner";
import { cn } from "@/lib/utils";

interface VoiceMessagePlayerProps {
  src: string;
  isOutgoing?: boolean;
  autoPlay?: boolean;
  singlePlay?: boolean;
  onPlaybackComplete?: () => void;
}

function formatDuration(sec: number) {
  const m = Math.floor(sec / 60);
  const s = Math.floor(sec % 60);
  return `${m}:${s.toString().padStart(2, "0")}`;
}

/** Telegram-style voice: download → waveform player with seek */
export default function VoiceMessagePlayer({
  src,
  isOutgoing = false,
  autoPlay = false,
  singlePlay = false,
  onPlaybackComplete,
}: VoiceMessagePlayerProps) {
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const [downloaded, setDownloaded] = useState(false);
  const [downloadProgress, setDownloadProgress] = useState(0);
  const [isPlaying, setIsPlaying] = useState(false);
  const [duration, setDuration] = useState(0);
  const [currentTime, setCurrentTime] = useState(0);
  const [waveform, setWaveform] = useState<number[]>([]);
  const [playedOnce, setPlayedOnce] = useState(false);
  const isBlob = src.startsWith("blob:");

  useEffect(() => {
    setPlayedOnce(false);
  }, [src]);

  useEffect(() => {
    if (isBlob) {
      setDownloaded(true);
      return;
    }
    setDownloaded(false);
    setDownloadProgress(0);
  }, [src, isBlob]);

  const generateWaveform = useCallback((len = 32) => {
    const bars: number[] = [];
    for (let i = 0; i < len; i++) {
      bars.push(0.25 + Math.random() * 0.75);
    }
    setWaveform(bars);
  }, []);

  const handleDownload = async () => {
    if (downloaded || isBlob) return;
    try {
      const xhr = new XMLHttpRequest();
      xhr.open("GET", src, true);
      xhr.responseType = "blob";
      xhr.onprogress = (e) => {
        if (e.lengthComputable) {
          setDownloadProgress(Math.round((e.loaded / e.total) * 100));
        }
      };
      xhr.onload = () => {
        if (xhr.status === 200) {
          const blobUrl = URL.createObjectURL(xhr.response);
          if (audioRef.current) audioRef.current.src = blobUrl;
          setDownloaded(true);
          setDownloadProgress(100);
          generateWaveform();
        }
      };
      xhr.send();
    } catch {
      setDownloaded(true);
      generateWaveform();
    }
  };

  useEffect(() => {
    if (downloaded) generateWaveform();
  }, [downloaded, generateWaveform]);

  useEffect(() => {
    const audio = audioRef.current;
    if (!audio || !downloaded) return;

    const onMeta = () => setDuration(audio.duration || 0);
    const onTime = () => setCurrentTime(audio.currentTime);
    const onEnd = () => {
      setIsPlaying(false);
      setCurrentTime(0);
      setPlayedOnce(true);
      onPlaybackComplete?.();
    };

    audio.addEventListener("loadedmetadata", onMeta);
    audio.addEventListener("timeupdate", onTime);
    audio.addEventListener("ended", onEnd);
    return () => {
      audio.removeEventListener("loadedmetadata", onMeta);
      audio.removeEventListener("timeupdate", onTime);
      audio.removeEventListener("ended", onEnd);
    };
  }, [downloaded, onPlaybackComplete]);

  useEffect(() => {
    const audio = audioRef.current;
    if (!audio || !downloaded || !autoPlay || playedOnce) return;
    audio.play().then(() => setIsPlaying(true)).catch(() => {});
  }, [autoPlay, downloaded, playedOnce, src]);

  const togglePlay = () => {
    const audio = audioRef.current;
    if (!audio) return;
    if (singlePlay && playedOnce) return;
    if (isPlaying) {
      audio.pause();
      setIsPlaying(false);
    } else {
      audio.play();
      setIsPlaying(true);
    }
  };

  const handleSeek = (e: React.MouseEvent<HTMLDivElement>) => {
    const audio = audioRef.current;
    if (!audio || !duration) return;
    const rect = e.currentTarget.getBoundingClientRect();
    const ratio = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
    audio.currentTime = ratio * duration;
    setCurrentTime(audio.currentTime);
  };

  const progress = duration ? currentTime / duration : 0;

  const bubbleClass = isOutgoing
    ? "bg-[#2aabee]/15 dark:bg-[#2aabee]/20"
    : "bg-neutral-100 dark:bg-neutral-800";

  if (!downloaded && !isBlob) {
    return (
      <div
        className={cn(
          "flex min-w-[200px] items-center gap-3 rounded-2xl px-3 py-2.5",
          bubbleClass
        )}
      >
        <button
          type="button"
          onClick={handleDownload}
          className="gentle-transition flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-[#2aabee] text-white active:scale-95"
          aria-label="دانلود ویس"
        >
          {downloadProgress > 0 && downloadProgress < 100 ? (
            <IOSSpinner size={18} color="#fff" />
          ) : (
            <BoldIcon name="document-download" size={18} tinted className="text-current" />
          )}
        </button>
        <div className="flex-1">
          <div className="h-1.5 overflow-hidden rounded-full bg-neutral-200 dark:bg-neutral-700">
            <div
              className="gentle-transition h-full rounded-full bg-[#2aabee]"
              style={{ width: `${downloadProgress}%` }}
            />
          </div>
          <span className="mt-1 block text-[10px] text-neutral-500">
            {downloadProgress > 0 ? `${downloadProgress}%` : "برای پخش دانلود کنید"}
          </span>
        </div>
      </div>
    );
  }

  return (
    <div
      className={cn(
        "flex min-w-[220px] max-w-[280px] items-center gap-2 rounded-2xl px-2 py-2",
        bubbleClass
      )}
    >
      <audio ref={audioRef} src={src} preload="metadata" className="hidden" />
      <button
        type="button"
        onClick={togglePlay}
        disabled={singlePlay && playedOnce}
        className={cn(
          "gentle-transition flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-[#2aabee] text-white active:scale-95",
          singlePlay && playedOnce && "cursor-not-allowed opacity-50"
        )}
        aria-label={isPlaying ? "توقف" : "پخش"}
      >
        {isPlaying ? <BoldIcon name="pause" size={18} tinted className="text-current mr-[-2px]" /> : <BoldIcon name="play" size={18} tinted className="text-current mr-[-2px]" />}
      </button>
      <div className="flex min-w-0 flex-1 flex-col gap-0.5">
        <div
          className="flex h-7 cursor-pointer items-end gap-[2px] px-0.5"
          onClick={handleSeek}
          role="slider"
          aria-valuenow={Math.round(progress * 100)}
        >
          {waveform.map((h, i) => {
            const played = i / waveform.length <= progress;
            return (
              <div
                key={i}
                className={cn(
                  "w-[3px] rounded-full gentle-transition",
                  played ? "bg-[#2aabee]" : "bg-neutral-300 dark:bg-neutral-600"
                )}
                style={{ height: `${h * 100}%`, minHeight: 4 }}
              />
            );
          })}
        </div>
        <span className="text-[10px] tabular-nums text-neutral-500">
          {formatDuration(isPlaying || currentTime > 0 ? currentTime : duration)}
        </span>
      </div>
    </div>
  );
}
