import React, {
  useEffect,
  useRef,
  useState,
} from 'react';

import {
  MdPauseCircle,
  MdPlayCircle,
} from 'react-icons/md';

interface AudioMessageProps {
  barColor: string;
  src: string;
  barsCount?: number;
  cacheKey?: string;
}

const barsCache = new Map<string, number[]>();

const generateBars = (barsCount: number) => {
  // Симметричная по центру форма волны: каждая «полоска» — высота от 6 до 24px.
  const bars: number[] = [];
  const baseHeight = 14;
  const variation = 7;

  let last = baseHeight;
  for (let i = 0; i < barsCount; i++) {
    const delta = (Math.random() - 0.5) * variation;
    const next = Math.max(5, Math.min(24, last + delta));
    bars.push(Math.round(next));
    last = next;
  }
  return bars;
};

const formatTime = (seconds: number) => {
  if (!seconds || !isFinite(seconds)) return '0:00';
  const m = Math.floor(seconds / 60);
  const s = Math.floor(seconds % 60);
  return `${m}:${s.toString().padStart(2, '0')}`;
};

const AudioMessage: React.FC<AudioMessageProps> = ({
  src,
  barsCount = 32,
  cacheKey,
  barColor,
}) => {
  const audioRef = useRef<HTMLAudioElement>(null);
  const trackRef = useRef<HTMLDivElement | null>(null);
  const [isPlaying, setIsPlaying] = useState(false);
  const [progress, setProgress] = useState(0);
  const [duration, setDuration] = useState(0);
  const [currentTime, setCurrentTime] = useState(0);
  const [barHeights, setBarHeights] = useState<number[]>([]);

  useEffect(() => {
    const resolvedCacheKey = cacheKey ?? src;
    const cachedBars = barsCache.get(resolvedCacheKey);

    if (cachedBars && cachedBars.length === barsCount) {
      setBarHeights(cachedBars);
      return;
    }

    const nextBars = generateBars(barsCount);
    barsCache.set(resolvedCacheKey, nextBars);
    setBarHeights(nextBars);
  }, [barsCount, cacheKey, src]);

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

    const updateProgress = () => {
      if (audio.duration) {
        setProgress((audio.currentTime / audio.duration) * 100);
        setCurrentTime(audio.currentTime);
      }
    };

    const setDur = () => {
      setDuration(audio.duration || 0);
    };

    const onEnded = () => {
      setIsPlaying(false);
      setProgress(0);
      setCurrentTime(0);
    };

    audio.addEventListener('timeupdate', updateProgress);
    audio.addEventListener('loadedmetadata', setDur);
    audio.addEventListener('ended', onEnded);

    return () => {
      audio.removeEventListener('timeupdate', updateProgress);
      audio.removeEventListener('loadedmetadata', setDur);
      audio.removeEventListener('ended', onEnded);
    };
  }, []);

  const togglePlay = () => {
    const audio = audioRef.current;
    if (!audio) return;

    if (isPlaying) {
      audio.pause();
    } else {
      audio.play().catch(() => {});
    }
    setIsPlaying(!isPlaying);
  };

  const handleSeekFromEvent = (clientX: number) => {
    const audio = audioRef.current;
    const track = trackRef.current;
    if (!audio || !track || !duration) return;
    const rect = track.getBoundingClientRect();
    const ratio = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
    audio.currentTime = ratio * duration;
  };

  const currentBarIdx = Math.floor((progress / 100) * barHeights.length);

  return (
    <div
      className="flex items-center gap-2 select-none"
      onClick={(e) => {
        e.preventDefault();
        e.stopPropagation();
      }}
    >
      <audio ref={audioRef} src={src} preload="metadata" />

      <button
        type="button"
        onClick={(e) => {
          e.preventDefault();
          e.stopPropagation();
          togglePlay();
        }}
        className="shrink-0 inline-flex items-center justify-center
          text-[var(--tg-accent)]"
        aria-label={isPlaying ? 'Пауза' : 'Играть'}
      >
        {isPlaying ? <MdPauseCircle size={36} /> : <MdPlayCircle size={36} />}
      </button>

      <div className="flex-1 min-w-0">
        <div
          ref={trackRef}
          className="flex items-center gap-[3px] h-7 cursor-pointer"
          onClick={(e) => {
            e.preventDefault();
            e.stopPropagation();
            handleSeekFromEvent(e.clientX);
          }}
        >
          {barHeights.map((height, i) => (
            <div
              key={i}
              className="w-[2px] rounded-full transition-opacity duration-150"
              style={{
                height,
                backgroundColor: barColor,
                opacity: i <= currentBarIdx ? 1 : 0.4,
              }}
            />
          ))}
        </div>
        <div className="mt-0.5 text-[11px] opacity-70 leading-none">
          {formatTime(isPlaying || currentTime > 0 ? currentTime : duration)}
        </div>
      </div>
    </div>
  );
};

export default AudioMessage;
