"use client";

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

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

export function useVoiceRecorder() {
  const [recording, setRecording] = useState(false);
  const [seconds, setSeconds] = useState(0);
  const [error, setError] = useState<string | null>(null);
  const mediaRecorderRef = useRef<MediaRecorder | null>(null);
  const streamRef = useRef<MediaStream | null>(null);
  const chunksRef = useRef<Blob[]>([]);
  const timerRef = useRef<number | null>(null);

  const cleanupStream = useCallback(() => {
    streamRef.current?.getTracks().forEach((t) => t.stop());
    streamRef.current = null;
    if (timerRef.current) {
      window.clearInterval(timerRef.current);
      timerRef.current = null;
    }
  }, []);

  useEffect(() => () => cleanupStream(), [cleanupStream]);

  const start = useCallback(async () => {
    setError(null);
    chunksRef.current = [];
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      streamRef.current = stream;
      const mimeType = MediaRecorder.isTypeSupported("audio/webm;codecs=opus")
        ? "audio/webm;codecs=opus"
        : MediaRecorder.isTypeSupported("audio/webm")
          ? "audio/webm"
          : "";
      const recorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream);
      mediaRecorderRef.current = recorder;
      recorder.ondataavailable = (e) => {
        if (e.data.size > 0) chunksRef.current.push(e.data);
      };
      recorder.start(200);
      setRecording(true);
      setSeconds(0);
      timerRef.current = window.setInterval(() => setSeconds((s) => s + 1), 1000);
    } catch {
      setError("دسترسی به میکروفون ممکن نیست");
      cleanupStream();
    }
  }, [cleanupStream]);

  const cancel = useCallback(() => {
    mediaRecorderRef.current?.stop();
    mediaRecorderRef.current = null;
    chunksRef.current = [];
    cleanupStream();
    setRecording(false);
    setSeconds(0);
  }, [cleanupStream]);

  const stop = useCallback((): Promise<{ file: File; durationSeconds: number } | null> => {
    return new Promise((resolve) => {
      const recorder = mediaRecorderRef.current;
      if (!recorder || recorder.state === "inactive") {
        cancel();
        resolve(null);
        return;
      }

      recorder.onstop = () => {
        const blob = new Blob(chunksRef.current, { type: recorder.mimeType || "audio/webm" });
        const ext = blob.type.includes("ogg") ? "ogg" : "webm";
        const file = new File([blob], `voice-${Date.now()}.${ext}`, { type: blob.type || "audio/webm" });
        const duration = seconds || 1;
        cleanupStream();
        mediaRecorderRef.current = null;
        chunksRef.current = [];
        setRecording(false);
        setSeconds(0);
        resolve({ file, durationSeconds: duration });
      };

      recorder.stop();
    });
  }, [cancel, cleanupStream, seconds]);

  return { recording, seconds, error, start, stop, cancel };
}

export function VoiceRecordingBar({
  seconds,
  onCancel,
  onSend,
  sending,
}: {
  seconds: number;
  onCancel: () => void;
  onSend: () => void;
  sending?: boolean;
}) {
  return (
    <div className="mb-2 flex items-center gap-2 rounded-2xl bg-rose-50 px-3 py-2">
      <span className="relative flex h-3 w-3 shrink-0">
        <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-rose-400 opacity-75" />
        <span className="relative inline-flex h-3 w-3 rounded-full bg-rose-600" />
      </span>
      <span className="flex-1 text-sm font-medium text-rose-800">در حال ضبط… {formatDuration(seconds)}</span>
      <button type="button" className="rounded-full px-2 py-1 text-xs text-slate-600 hover:bg-white" onClick={onCancel}>
        لغو
      </button>
      <button
        type="button"
        disabled={sending || seconds < 1}
        className="rounded-full bg-teal-600 px-3 py-1 text-xs font-semibold text-white disabled:opacity-40"
        onClick={onSend}
      >
        ارسال
      </button>
    </div>
  );
}

export function VoiceMessagePlayer({
  url,
  durationSeconds,
}: {
  url: string;
  durationSeconds?: number | null;
}) {
  const audioRef = useRef<HTMLAudioElement>(null);
  const [playing, setPlaying] = useState(false);
  const [progress, setProgress] = useState(0);
  const [duration, setDuration] = useState(durationSeconds ?? 0);

  useEffect(() => {
    const audio = audioRef.current;
    if (!audio) return;
    const onTime = () => {
      if (audio.duration) setProgress(audio.currentTime / audio.duration);
    };
    const onMeta = () => {
      if (audio.duration && !Number.isNaN(audio.duration)) setDuration(Math.round(audio.duration));
    };
    const onEnd = () => {
      setPlaying(false);
      setProgress(0);
    };
    audio.addEventListener("timeupdate", onTime);
    audio.addEventListener("loadedmetadata", onMeta);
    audio.addEventListener("ended", onEnd);
    return () => {
      audio.removeEventListener("timeupdate", onTime);
      audio.removeEventListener("loadedmetadata", onMeta);
      audio.removeEventListener("ended", onEnd);
    };
  }, [url]);

  const toggle = () => {
    const audio = audioRef.current;
    if (!audio) return;
    if (playing) {
      audio.pause();
      setPlaying(false);
    } else {
      void audio.play();
      setPlaying(true);
    }
  };

  return (
    <div className="flex min-w-[220px] items-center gap-3 rounded-2xl bg-teal-50/80 px-3 py-2">
      <button
        type="button"
        onClick={toggle}
        className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-teal-600 text-white shadow-sm"
        aria-label={playing ? "توقف" : "پخش"}
      >
        {playing ? "❚❚" : "▶"}
      </button>
      <div className="min-w-0 flex-1">
        <div className="h-1.5 overflow-hidden rounded-full bg-teal-200/80">
          <div className="h-full rounded-full bg-teal-600 transition-all" style={{ width: `${progress * 100}%` }} />
        </div>
        <div className="mt-1 text-[10px] tabular-nums text-teal-800/70">{formatDuration(duration || 0)}</div>
      </div>
      <span className="text-lg">🎤</span>
      <audio ref={audioRef} src={url} preload="metadata" className="hidden" />
    </div>
  );
}
