using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;

public class Spawner : MonoBehaviour
{
    [Header("오디오 및 파일 설정")]
    public AudioSource audioSource;

    [Header("노트 프리팹 & 위치")]
    public GameObject[] cubePrefabs;
    public Transform[]  spawnPoints;

    [Header("타이밍 설정")]
    public float noteSpeed     = 2.0f;
    public float distanceToHit = 10.0f;

    [Header("씬 설정")]
    public string songSelectSceneName = "SongSelect";

    private List<NoteData> mapNotes      = new List<NoteData>();
    private int            nextNoteIndex = 0;
    private float          travelTime;
    private bool           isReady       = false;

    // ── Unity ────────────────────────────────────────────────

    void Start()
    {
        travelTime = distanceToHit / noteSpeed;

        if (GameSession.SelectedSong == null)
        {
            Debug.LogWarning("[Spawner] 선택된 곡 없음 → 곡 선택 화면으로 이동");
            SceneManager.LoadScene(songSelectSceneName);
            return;
        }

        StartCoroutine(InitGame());
    }

    void Update()
    {
        if (!isReady || audioSource == null || !audioSource.isPlaying) return;

        float currentTime = audioSource.time;
        while (nextNoteIndex < mapNotes.Count &&
               currentTime + travelTime >= mapNotes[nextNoteIndex].time)
        {
            SpawnNote(mapNotes[nextNoteIndex]);
            nextNoteIndex++;
        }
    }

    // ── 초기화 ───────────────────────────────────────────────

    private IEnumerator InitGame()
    {
        SongInfo song       = GameSession.SelectedSong;
        string   difficulty = GameSession.SelectedDifficulty;

        // 맵 JSON 로드
        string mapPath = GetMapPath(song, difficulty);
        if (!File.Exists(mapPath))
        {
            Debug.LogError($"[Spawner] 맵 파일 없음: {mapPath}");
            yield break;
        }
        LoadMapJson(mapPath);

        // 오디오 로드 (로컬 파일 → AudioClip)
        string audioPath = GetAudioPath(song.id);
        yield return LoadAudioClip(audioPath);

        // LRU 갱신
        SongLibrary.Instance?.TouchSong(song.id);

        isReady = true;
        audioSource.Play();
        Debug.Log($"[Spawner] 시작: {song.title} ({difficulty})");
    }

    private void LoadMapJson(string path)
    {
        string  json = File.ReadAllText(path);
        MapData data = JsonUtility.FromJson<MapData>(json);
        mapNotes = data?.target ?? new List<NoteData>();
        mapNotes.Sort((a, b) => a.time.CompareTo(b.time));
        Debug.Log($"[Spawner] 노트 로드: {mapNotes.Count}개");
    }

    private IEnumerator LoadAudioClip(string path)
    {
        string uri = "file://" + path;
        using var req = UnityWebRequestMultimedia.GetAudioClip(uri, AudioType.MPEG);
        yield return req.SendWebRequest();

        if (req.result != UnityWebRequest.Result.Success)
        {
            Debug.LogError($"[Spawner] 오디오 로드 실패: {req.error}");
            yield break;
        }

        audioSource.clip = DownloadHandlerAudioClip.GetContent(req);
    }

    // ── 노트 스폰 ────────────────────────────────────────────

    private void SpawnNote(NoteData data)
    {
        if (data.colorType >= cubePrefabs.Length || data.position >= spawnPoints.Length) return;

        GameObject obj = Instantiate(
            cubePrefabs[data.colorType],
            spawnPoints[data.position].position,
            spawnPoints[data.position].rotation);
        obj.transform.Rotate(transform.forward, 90 * Random.Range(0, 4));
    }

    // ── 경로 헬퍼 ────────────────────────────────────────────

    private static string CacheRoot =>
        Path.Combine(Application.temporaryCachePath, "beatsaber");

    private static string GetAudioPath(string songId) =>
        Path.Combine(CacheRoot, songId, $"{songId}.mp3");

    private static string GetMapPath(SongInfo song, string difficulty)
    {
        DifficultyInfo info = song.difficulties.Get(difficulty);
        if (info == null) return string.Empty;
        return Path.Combine(CacheRoot, song.id, Path.GetFileName(info.mapFile));
    }
}