import { jsxs, jsx } from 'react/jsx-runtime';
import { useState, useRef, useCallback, useEffect } from 'react';
import { motion } from 'motion/react';
import { PlayIcon, PauseIcon, CheckIcon } from '@heroicons/react/24/outline';
import { cn } from '../../../utils/cn.js';
import { Button } from '../../core/Button/Button.js';

/**
 * Format seconds into MM:SS display
 */
const formatTime = (seconds) => {
    const mins = Math.floor(seconds / 60);
    const secs = seconds % 60;
    return `${mins.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
};
/**
 * Internal voice recorder sub-component.
 * Handles MediaRecorder lifecycle, timer display, and recording controls.
 *
 * Recording starts immediately on mount.
 * Not exported from the library's public API.
 */
const VoiceRecorder = ({ onComplete, onCancel, maxDuration, className, }) => {
    const [recordingState, setRecordingState] = useState("idle");
    const [elapsed, setElapsed] = useState(0);
    const mediaRecorderRef = useRef(null);
    const chunksRef = useRef([]);
    const timerRef = useRef(null);
    const streamRef = useRef(null);
    /**
     * Clean up timer
     */
    const clearTimer = useCallback(() => {
        if (timerRef.current) {
            clearInterval(timerRef.current);
            timerRef.current = null;
        }
    }, []);
    /**
     * Stop all media tracks and clean up
     */
    const cleanup = useCallback(() => {
        clearTimer();
        if (mediaRecorderRef.current &&
            mediaRecorderRef.current.state !== "inactive") {
            mediaRecorderRef.current.stop();
        }
        if (streamRef.current) {
            streamRef.current.getTracks().forEach((track) => track.stop());
            streamRef.current = null;
        }
        mediaRecorderRef.current = null;
    }, [clearTimer]);
    /**
     * Start the recording timer
     */
    const startTimer = useCallback(() => {
        clearTimer();
        timerRef.current = setInterval(() => {
            setElapsed((prev) => prev + 1);
        }, 1000);
    }, [clearTimer]);
    /**
     * Start recording immediately on mount
     */
    useEffect(() => {
        let cancelled = false;
        const startRecording = async () => {
            try {
                const stream = await navigator.mediaDevices.getUserMedia({
                    audio: true,
                });
                if (cancelled) {
                    stream.getTracks().forEach((t) => t.stop());
                    return;
                }
                streamRef.current = stream;
                // Choose supported MIME type
                const mimeType = MediaRecorder.isTypeSupported("audio/webm;codecs=opus")
                    ? "audio/webm;codecs=opus"
                    : MediaRecorder.isTypeSupported("audio/webm")
                        ? "audio/webm"
                        : "";
                const recorder = new MediaRecorder(stream, mimeType ? { mimeType } : undefined);
                mediaRecorderRef.current = recorder;
                chunksRef.current = [];
                recorder.ondataavailable = (e) => {
                    if (e.data.size > 0) {
                        chunksRef.current.push(e.data);
                    }
                };
                recorder.start(100); // collect data every 100ms
                setRecordingState("recording");
                startTimer();
            }
            catch (_a) {
                if (process.env.NODE_ENV !== "production") {
                    // eslint-disable-next-line no-console
                    console.warn("[VoiceRecorder] Microphone access denied or unavailable.");
                }
                onCancel();
            }
        };
        startRecording();
        return () => {
            cancelled = true;
            cleanup();
        };
        // Only run on mount/unmount
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);
    /**
     * Auto-stop at max duration
     */
    useEffect(() => {
        if (elapsed >= maxDuration && recordingState === "recording") {
            handleConfirm();
        }
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [elapsed, maxDuration, recordingState]);
    /**
     * Handle cancel — stop recording and discard
     */
    const handleCancel = useCallback(() => {
        cleanup();
        chunksRef.current = [];
        setRecordingState("idle");
        onCancel();
    }, [cleanup, onCancel]);
    /**
     * Handle confirm — stop recording and return blob
     */
    const handleConfirm = useCallback(() => {
        if (!mediaRecorderRef.current) {
            onCancel();
            return;
        }
        const recorder = mediaRecorderRef.current;
        recorder.onstop = () => {
            const mimeType = recorder.mimeType || "audio/webm";
            const blob = new Blob(chunksRef.current, { type: mimeType });
            chunksRef.current = [];
            if (streamRef.current) {
                streamRef.current.getTracks().forEach((t) => t.stop());
                streamRef.current = null;
            }
            onComplete(blob);
        };
        clearTimer();
        if (recorder.state !== "inactive") {
            recorder.stop();
        }
        setRecordingState("idle");
    }, [clearTimer, onComplete, onCancel]);
    /**
     * Toggle pause/resume
     */
    const handleTogglePause = useCallback(() => {
        const recorder = mediaRecorderRef.current;
        if (!recorder)
            return;
        if (recordingState === "recording") {
            recorder.pause();
            clearTimer();
            setRecordingState("paused");
        }
        else if (recordingState === "paused") {
            recorder.resume();
            startTimer();
            setRecordingState("recording");
        }
    }, [recordingState, clearTimer, startTimer]);
    return (jsxs("div", { className: cn("flex items-center justify-between w-full", className), children: [jsx(Button, { variant: "soft", color: "neutral", size: "sm", className: "rounded-full", onClick: handleCancel, "aria-label": "Cancel recording", children: "Cancel" }), jsxs("div", { className: "flex items-center gap-2.5", children: [jsx(motion.div, { className: "size-2.5 rounded-full bg-[var(--color-danger)]", animate: recordingState === "recording"
                            ? { opacity: [1, 0.3, 1] }
                            : { opacity: 0.5 }, transition: recordingState === "recording"
                            ? { duration: 1.2, repeat: Infinity, ease: "easeInOut" }
                            : undefined }), jsx("span", { className: "text-lg font-medium tabular-nums text-[var(--color-text-primary)] min-w-[3.5rem] text-center", children: formatTime(elapsed) })] }), jsxs("div", { className: "flex items-center gap-2", children: [jsx(Button, { iconOnly: true, variant: "outline", color: "neutral", size: "sm", className: "rounded-full", onClick: handleTogglePause, "aria-label": recordingState === "paused" ? "Resume recording" : "Pause recording", children: recordingState === "paused" ? (jsx(PlayIcon, { className: "size-4", strokeWidth: 2 })) : (jsx(PauseIcon, { className: "size-4", strokeWidth: 2 })) }), jsx(Button, { iconOnly: true, variant: "filled", color: "primary", size: "sm", className: "rounded-full", onClick: handleConfirm, "aria-label": "Confirm recording", children: jsx(CheckIcon, { className: "size-4", strokeWidth: 2.5 }) })] })] }));
};
VoiceRecorder.displayName = "VoiceRecorder";

export { VoiceRecorder };
