import 'dart:collection';

import 'package:flutter/foundation.dart' show debugPrint;
import 'package:just_audio/just_audio.dart';

/// SFX 채널 풀 - 사운드 완료 보장
///
/// 대기열 기반으로 모든 사운드의 완전 재생을 보장합니다.
/// 사용 가능한 플레이어가 없으면 대기열에 추가하고,
/// 재생 완료 시 대기열의 다음 사운드를 자동 재생합니다.
class SfxChannelPool {
  SfxChannelPool({
    required this.name,
    this.poolSize = 4,
    double volume = 0.8,
  }) : _volume = volume;

  /// 채널명 (디버그용)
  final String name;

  /// 풀 크기
  final int poolSize;

  /// 채널 볼륨
  double _volume;

  /// AudioPlayer 풀
  final List<AudioPlayer> _players = [];

  /// 각 플레이어의 재생 중 여부 추적
  final List<bool> _playerBusy = [];

  /// 대기열 (재생 대기 중인 에셋 경로)
  final Queue<String> _pendingQueue = Queue();

  /// 초기화 여부
  bool _initialized = false;

  /// 초기화 실패 여부
  bool _initFailed = false;

  /// 현재 볼륨
  double get volume => _volume;

  /// 초기화
  Future<void> init() async {
    if (_initialized || _initFailed) return;

    try {
      for (var i = 0; i < poolSize; i++) {
        final player = AudioPlayer();
        await player.setVolume(_volume);

        // 재생 완료 리스너 등록
        player.playerStateStream.listen((state) {
          if (state.processingState == ProcessingState.completed) {
            _onPlayerComplete(_players.indexOf(player));
          }
        });

        _players.add(player);
        _playerBusy.add(false);
      }

      _initialized = true;
      debugPrint('[SfxChannelPool:$name] Initialized with $poolSize players');
    } catch (e) {
      _initFailed = true;
      debugPrint('[SfxChannelPool:$name] Init failed: $e');
    }
  }

  /// 사운드 재생 (완료 보장)
  ///
  /// 사용 가능한 플레이어가 있으면 즉시 재생하고,
  /// 모든 플레이어가 사용 중이면 대기열에 추가합니다.
  Future<void> play(String assetPath) async {
    if (_initFailed) return;
    if (!_initialized) await init();
    if (_initFailed || !_initialized) return;
    if (_volume == 0) return; // 볼륨이 0이면 재생 안함

    // 사용 가능한 플레이어 찾기
    final availableIndex = _findAvailablePlayer();

    if (availableIndex != -1) {
      // 즉시 재생
      await _playOnPlayer(availableIndex, assetPath);
    } else {
      // 대기열에 추가
      _pendingQueue.add(assetPath);
      debugPrint('[SfxChannelPool:$name] Queued: $assetPath '
          '(queue size: ${_pendingQueue.length})');
    }
  }

  /// 볼륨 설정 (0.0 ~ 1.0)
  Future<void> setVolume(double volume) async {
    _volume = volume.clamp(0.0, 1.0);
    if (_initialized) {
      for (final player in _players) {
        await player.setVolume(_volume);
      }
    }
  }

  /// 리소스 해제
  Future<void> dispose() async {
    for (final player in _players) {
      await player.dispose();
    }
    _players.clear();
    _playerBusy.clear();
    _pendingQueue.clear();
    _initialized = false;
  }

  /// 사용 가능한 플레이어 인덱스 반환 (-1: 없음)
  int _findAvailablePlayer() {
    for (var i = 0; i < _playerBusy.length; i++) {
      if (!_playerBusy[i]) {
        return i;
      }
    }
    return -1;
  }

  /// 특정 플레이어에서 사운드 재생
  Future<void> _playOnPlayer(int index, String assetPath) async {
    if (index < 0 || index >= _players.length) return;

    final player = _players[index];
    _playerBusy[index] = true;

    try {
      await player.setAsset(assetPath);
      await player.seek(Duration.zero);
      await player.play();
    } catch (e) {
      // 파일이 없거나 오류 시 busy 상태 해제
      _playerBusy[index] = false;
      debugPrint('[SfxChannelPool:$name] Play failed: $assetPath - $e');
    }
  }

  /// 플레이어 재생 완료 시 호출
  void _onPlayerComplete(int index) {
    if (index < 0 || index >= _playerBusy.length) return;

    _playerBusy[index] = false;

    // 대기열에 항목이 있으면 다음 사운드 재생
    if (_pendingQueue.isNotEmpty) {
      final nextAsset = _pendingQueue.removeFirst();
      _playOnPlayer(index, nextAsset);
    }
  }
}
