'use client';

import { useState, useRef, useCallback, useEffect } from 'react';

export type RecordingState = 'idle' | 'recording' | 'paused' | 'stopped';

interface UseAudioRecorderReturn {
    /** 현재 녹음 상태 */
    state: RecordingState;
    /** 녹음 시작 */
    startRecording: () => Promise<void>;
    /** 일시정지 */
    pauseRecording: () => void;
    /** 이어서 녹음 */
    resumeRecording: () => void;
    /** 녹음 중지 → Blob 반환 */
    stopRecording: () => Promise<Blob | null>;
    /** 경과 시간 (초) */
    elapsedSeconds: number;
    /** 녹음 시작 시각 (HH:mm 형식) */
    startTime: string | null;
    /** 에러 메시지 */
    error: string | null;
}

/**
 * 브라우저 MediaRecorder API 래핑 훅
 * 
 * - audio/webm;codecs=opus 포맷 (고압축, 2h ≈ 30-40MB)
 * - 장시간 녹음 지원 (2시간+)
 * - 일시정지/이어서 녹음 지원
 * - 경과 시간 실시간 표시
 */
export function useAudioRecorder(): UseAudioRecorderReturn {
    const [state, setState] = useState<RecordingState>('idle');
    const [elapsedSeconds, setElapsedSeconds] = useState(0);
    const [startTime, setStartTime] = useState<string | null>(null);
    const [error, setError] = useState<string | null>(null);

    const mediaRecorderRef = useRef<MediaRecorder | null>(null);
    const chunksRef = useRef<Blob[]>([]);
    const timerRef = useRef<NodeJS.Timeout | null>(null);
    const streamRef = useRef<MediaStream | null>(null);
    const resolveStopRef = useRef<((blob: Blob | null) => void) | null>(null);

    // 타이머 관리
    const startTimer = useCallback(() => {
        timerRef.current = setInterval(() => {
            setElapsedSeconds(prev => prev + 1);
        }, 1000);
    }, []);

    const stopTimer = useCallback(() => {
        if (timerRef.current) {
            clearInterval(timerRef.current);
            timerRef.current = null;
        }
    }, []);

    // 클린업
    useEffect(() => {
        return () => {
            stopTimer();
            if (streamRef.current) {
                streamRef.current.getTracks().forEach(track => track.stop());
            }
        };
    }, [stopTimer]);

    const startRecording = useCallback(async () => {
        try {
            setError(null);
            chunksRef.current = [];

            const stream = await navigator.mediaDevices.getUserMedia({
                audio: {
                    echoCancellation: true,
                    noiseSuppression: true,
                    sampleRate: 44100,
                }
            });
            streamRef.current = stream;

            // MIME 타입 결정 (브라우저 호환성)
            const mimeType = MediaRecorder.isTypeSupported('audio/webm;codecs=opus')
                ? 'audio/webm;codecs=opus'
                : MediaRecorder.isTypeSupported('audio/webm')
                    ? 'audio/webm'
                    : 'audio/mp4';

            const recorder = new MediaRecorder(stream, {
                mimeType,
                audioBitsPerSecond: 64000, // 64kbps — 2h ≈ 55MB
            });

            recorder.ondataavailable = (e) => {
                if (e.data.size > 0) {
                    chunksRef.current.push(e.data);
                }
            };

            recorder.onstop = () => {
                const blob = new Blob(chunksRef.current, { type: mimeType });
                if (resolveStopRef.current) {
                    resolveStopRef.current(blob);
                    resolveStopRef.current = null;
                }
                // 스트림 정리
                if (streamRef.current) {
                    streamRef.current.getTracks().forEach(track => track.stop());
                    streamRef.current = null;
                }
            };

            recorder.onerror = () => {
                setError('녹음 중 오류가 발생했습니다.');
                setState('idle');
                stopTimer();
            };

            // 30초마다 데이터 수집 (메모리 안정성)
            recorder.start(30000);
            mediaRecorderRef.current = recorder;

            // 시작 시각 기록
            const now = new Date();
            const hh = String(now.getHours()).padStart(2, '0');
            const mm = String(now.getMinutes()).padStart(2, '0');
            setStartTime(`${hh}:${mm}`);

            setElapsedSeconds(0);
            setState('recording');
            startTimer();

        } catch (err: unknown) {
            if (err instanceof Error) {
                if (err.name === 'NotAllowedError') {
                    setError('마이크 권한이 필요합니다. 브라우저 설정에서 마이크를 허용해주세요.');
                } else if (err.name === 'NotFoundError') {
                    setError('마이크를 찾을 수 없습니다.');
                } else {
                    setError(`녹음 시작 실패: ${err.message}`);
                }
            } else {
                setError(`녹음 시작 실패: ${String(err)}`);
            }
        }
    }, [startTimer, stopTimer]);

    const pauseRecording = useCallback(() => {
        if (mediaRecorderRef.current?.state === 'recording') {
            mediaRecorderRef.current.pause();
            setState('paused');
            stopTimer();
        }
    }, [stopTimer]);

    const resumeRecording = useCallback(() => {
        if (mediaRecorderRef.current?.state === 'paused') {
            mediaRecorderRef.current.resume();
            setState('recording');
            startTimer();
        }
    }, [startTimer]);

    const stopRecording = useCallback((): Promise<Blob | null> => {
        return new Promise((resolve) => {
            if (!mediaRecorderRef.current || mediaRecorderRef.current.state === 'inactive') {
                resolve(null);
                return;
            }

            resolveStopRef.current = resolve;
            mediaRecorderRef.current.stop();
            setState('stopped');
            stopTimer();
        });
    }, [stopTimer]);

    return {
        state,
        startRecording,
        pauseRecording,
        resumeRecording,
        stopRecording,
        elapsedSeconds,
        startTime,
        error,
    };
}

/** 초를 "1h47m" 또는 "03:25" 형식으로 변환 */
export function formatDuration(totalSeconds: number): string {
    const h = Math.floor(totalSeconds / 3600);
    const m = Math.floor((totalSeconds % 3600) / 60);
    const s = totalSeconds % 60;

    if (h > 0) {
        return `${h}h${String(m).padStart(2, '0')}m`;
    }
    return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;
}

/** 초를 "1시간 47분" 형식으로 변환 (카드 표시용) */
export function formatDurationKorean(totalSeconds: number): string {
    const h = Math.floor(totalSeconds / 3600);
    const m = Math.floor((totalSeconds % 3600) / 60);

    if (h > 0 && m > 0) return `${h}시간 ${m}분`;
    if (h > 0) return `${h}시간`;
    if (m > 0) return `${m}분`;
    return `${totalSeconds}초`;
}
