'use client';

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

/**
 * bitFlyer Lightning 스타일 효과음
 * sound-parlor.mp3 오디오 스프라이트 사용
 *
 * 스프라이트 구간 [startMs, durationMs]:
 *   electricalMagicPoof [0, 761]      → 호가 제거
 *   dropHeavyPlastic    [761, 574]    → 호가 추가
 *   MagicDing           [1330, 1221]  → 소형 매도 체결
 *   DescendingMagic     [2550, 1183]  → 대형 매도 체결
 *   coinGameWinPack1    [3740, 1140]  → 소형 매수 체결
 *   coinGameWinPack2    [4882, 1017]  → 대형 매수 체결
 */

// [startMs, durationMs]
const SPRITES = {
	orderbookRemove: [0, 761],
	orderbookAdd: [761, 574],
	sellSmall: [1330, 1221],
	sellBig: [2550, 1183],
	buySmall: [3740, 1140],
	buyBig: [4882, 1017],
} as const;

// 대형 체결 기준 (이 수량 이상이면 Big 사운드)
const BIG_TRADE_THRESHOLD = 1;

// 호가 사운드 쓰로틀 간격 (ms) — 짧게 설정하여 bitFlyer처럼 연속 재생
const OB_THROTTLE_ADD = 60;
const OB_THROTTLE_REMOVE = 150;

export default function useTradeSound() {
	const audioCtxRef = useRef<AudioContext | null>(null);
	const audioBufferRef = useRef<AudioBuffer | null>(null);
	const [muted, setMuted] = useState(true);
	const loadedRef = useRef(false);
	const loadingRef = useRef(false);
	const obThrottleRef = useRef<{ add: number; remove: number }>({ add: 0, remove: 0 });

	// AudioContext 초기화
	const ensureContext = useCallback(() => {
		if (!audioCtxRef.current) {
			audioCtxRef.current = new AudioContext();
		}
		if (audioCtxRef.current.state === 'suspended') {
			audioCtxRef.current.resume();
		}
		return audioCtxRef.current;
	}, []);

	// MP3 스프라이트 파일 로드
	const loadSound = useCallback(async () => {
		if (loadedRef.current || loadingRef.current) return;
		loadingRef.current = true;

		try {
			const ctx = ensureContext();
			const response = await fetch('/sounds/sound-parlor.mp3');
			const arrayBuffer = await response.arrayBuffer();
			const decoded = await ctx.decodeAudioData(arrayBuffer);
			audioBufferRef.current = decoded;
			loadedRef.current = true;
		} catch (err) {
			console.error('Failed to load trade sound:', err);
		} finally {
			loadingRef.current = false;
		}
	}, [ensureContext]);

	// 스프라이트 구간 재생
	const playSprite = useCallback((startMs: number, durationMs: number, volume: number) => {
		if (!audioBufferRef.current || !audioCtxRef.current) return;

		const ctx = audioCtxRef.current;
		if (ctx.state === 'suspended') {
			ctx.resume();
		}

		const source = ctx.createBufferSource();
		const gainNode = ctx.createGain();

		source.buffer = audioBufferRef.current;
		gainNode.gain.value = Math.min(Math.max(volume, 0.1), 1.0);

		source.connect(gainNode);
		gainNode.connect(ctx.destination);

		const startSec = startMs / 1000;
		const durationSec = durationMs / 1000;
		source.start(0, startSec, durationSec);
	}, []);

	// 체결 사운드 재생
	const playTradeSound = useCallback((side: 'BID' | 'ASK', tradeVolume: number = 0.5) => {
		if (muted || !loadedRef.current) return;

		const isBig = tradeVolume >= BIG_TRADE_THRESHOLD;
		let sprite: readonly [number, number];

		if (side === 'BID') {
			sprite = isBig ? SPRITES.buyBig : SPRITES.buySmall;
		} else {
			sprite = isBig ? SPRITES.sellBig : SPRITES.sellSmall;
		}

		// 거래량 기반 볼륨 (0.3 ~ 0.8)
		const vol = Math.min(0.3 + tradeVolume * 0.3, 0.8);
		playSprite(sprite[0], sprite[1], vol);
	}, [muted, playSprite]);

	// 호가 사운드 재생 (짧은 쓰로틀 → bitFlyer 스타일 연속 딸깍)
	const playOrderbookSound = useCallback((type: 'add' | 'remove') => {
		if (muted || !loadedRef.current) return;

		const now = Date.now();
		const throttle = type === 'add' ? OB_THROTTLE_ADD : OB_THROTTLE_REMOVE;
		if (now - obThrottleRef.current[type] < throttle) return;
		obThrottleRef.current[type] = now;

		// electricalMagicPoof (remove) 는 일단 비활성화
		if (type === 'remove') return;

		const sprite = SPRITES.orderbookAdd;
		playSprite(sprite[0], sprite[1], 0.15);
	}, [muted, playSprite]);

	// 토글 함수
	const toggleMute = useCallback(() => {
		setMuted((prev) => {
			if (prev) {
				// 음소거 해제 시 사운드 로드
				ensureContext();
				loadSound();
			}
			return !prev;
		});
	}, [ensureContext, loadSound]);

	// cleanup
	useEffect(() => {
		return () => {
			if (audioCtxRef.current) {
				audioCtxRef.current.close();
				audioCtxRef.current = null;
			}
		};
	}, []);

	return { playTradeSound, playOrderbookSound, muted, toggleMute };
}