import { useState, useRef, useCallback, useEffect } from 'react';
import { Play, Pause } from 'lucide-react';
import { useAuthedFileUrl } from '../../lib/authedFile';

interface Props {
  audioData: string; // base64 data URL (data:audio/webm;base64,...) OR an /api/files/* path
}

function formatDuration(s: number): string {
  if (!isFinite(s) || isNaN(s)) return '0:00';
  const mins = Math.floor(s / 60);
  const secs = Math.floor(s % 60);
  return `${mins}:${secs.toString().padStart(2, '0')}`;
}

export default function AudioBubble({ audioData }: Props) {
  const [playing, setPlaying] = useState(false);
  const [progress, setProgress] = useState(0);
  const [duration, setDuration] = useState(0);
  const audioRef = useRef<HTMLAudioElement | null>(null);
  const barRef = useRef<HTMLDivElement>(null);

  // Historical audio is stored as an /api/files/* path, which a native Audio element
  // can't fetch (the Bearer token can't ride on the request) — resolve it to a blob URL
  // fetched with auth. data: URLs (freshly-recorded clips) pass straight through.
  const resolvedAudioUrl = useAuthedFileUrl(audioData);

  // Create Audio element once the source URL is ready
  useEffect(() => {
    if (!resolvedAudioUrl) return;
    const audio = new Audio(resolvedAudioUrl);

    audio.addEventListener('durationchange', () => {
      // webm often reports Infinity initially — skip until real
      if (isFinite(audio.duration)) setDuration(audio.duration);
    });

    audio.addEventListener('timeupdate', () => {
      if (isFinite(audio.duration) && audio.duration > 0) {
        setProgress(audio.currentTime / audio.duration);
        // Update duration if we didn't get it from durationchange
        if (duration === 0) setDuration(audio.duration);
      }
    });

    audio.addEventListener('ended', () => {
      setPlaying(false);
      setProgress(0);
    });

    // Workaround for webm duration=Infinity: seek to large value to force browser to calculate duration
    audio.addEventListener('loadedmetadata', () => {
      if (!isFinite(audio.duration)) {
        audio.currentTime = 1e10;
        audio.addEventListener('timeupdate', function seekBack() {
          if (isFinite(audio.duration)) {
            setDuration(audio.duration);
            audio.currentTime = 0;
            audio.removeEventListener('timeupdate', seekBack);
          }
        });
      }
    });

    audioRef.current = audio;

    return () => {
      audio.pause();
      audio.src = '';
    };
  }, [resolvedAudioUrl]);

  const togglePlay = useCallback(() => {
    const audio = audioRef.current;
    if (!audio) return;
    if (playing) {
      audio.pause();
      setPlaying(false);
    } else {
      audio.play();
      setPlaying(true);
    }
  }, [playing]);

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

  return (
    <div className="flex items-center gap-2.5 min-w-[180px]">
      <button
        onClick={togglePlay}
        className="flex items-center justify-center h-8 w-8 shrink-0 rounded-full bg-white/20 hover:bg-white/30 transition-colors"
      >
        {playing ? (
          <Pause className="h-3.5 w-3.5 fill-current" />
        ) : (
          <Play className="h-3.5 w-3.5 fill-current ml-0.5" />
        )}
      </button>
      <div className="flex-1 flex flex-col gap-1">
        <div
          ref={barRef}
          onClick={handleSeek}
          className="h-1 bg-white/20 rounded-full cursor-pointer relative"
        >
          <div
            className="absolute inset-y-0 left-0 bg-white/70 rounded-full transition-[width] duration-100"
            style={{ width: `${progress * 100}%` }}
          />
        </div>
        <span className="text-[10px] opacity-60 tabular-nums">
          {formatDuration(playing ? progress * duration : duration)}
        </span>
      </div>
    </div>
  );
}
