using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class SongCreatorManager : MonoBehaviour
{
    [Header("음원 선택")]
    [SerializeField] private TMP_Dropdown audioDropdown;
    [SerializeField] private Button       refreshBtn;
    [SerializeField] private TMP_Text     inputPathHint; // 파일 넣는 경로 안내

    [Header("메타데이터")]
    [SerializeField] private TMP_InputField titleInput;
    [SerializeField] private TMP_InputField artistInput;
    [SerializeField] private TMP_InputField bpmInput;

    [Header("난이도")]
    [SerializeField] private Toggle toggleNormal;
    [SerializeField] private Toggle toggleHard;
    [SerializeField] private Toggle toggleExpert;
    [SerializeField] private Toggle toggleExpertPlus;

    [Header("액션")]
    [SerializeField] private Button generateButton;
    [SerializeField] private Button manualEditorButton; // 작은 버튼
    [SerializeField] private Button backButton;
    [SerializeField] private string introSceneName = "Intro";

    [Header("진행 상태")]
    [SerializeField] private GameObject progressGroup;
    [SerializeField] private TMP_Text   statusText;
    [SerializeField] private Slider     progressSlider;

    [Header("연결")]
    [SerializeField] private BeatSageUploader beatSageUploader;
    [SerializeField] private NasPublisher     nasPublisher;

    [Header("씬")]
    [SerializeField] private string mapEditorScene = "MapEditorScene";

    // Quest: /sdcard/Android/data/{packageName}/files/input/ 로 ADB 복사
    private static string InputPath =>
        Path.Combine(Application.persistentDataPath, "input");

    private readonly List<string> audioFiles = new();

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

    private void Start()
    {
        Directory.CreateDirectory(InputPath);

        if (inputPathHint != null)
            inputPathHint.text = $"음원 경로: {InputPath}";

        refreshBtn.onClick.AddListener(RefreshAudioList);
        generateButton.onClick.AddListener(OnGenerateClicked);
        manualEditorButton.onClick.AddListener(() => SceneManager.LoadScene(mapEditorScene));
        backButton?.onClick.AddListener(() => SceneManager.LoadScene(introSceneName));

        progressGroup.SetActive(false);
        RefreshAudioList();
    }

    // ── 음원 목록 갱신 ───────────────────────────────────────

    private void RefreshAudioList()
    {
        audioFiles.Clear();
        audioDropdown.ClearOptions();

        string[] files = Directory.GetFiles(InputPath, "*.mp3");
        var options = new List<string>();

        foreach (string f in files)
        {
            audioFiles.Add(f);
            options.Add(Path.GetFileNameWithoutExtension(f));
        }

        if (options.Count == 0)
            options.Add("-- .mp3 파일 없음 --");

        audioDropdown.AddOptions(options);
    }

    // ── 생성 버튼 ────────────────────────────────────────────

    private void OnGenerateClicked()
    {
        if (audioFiles.Count == 0)           { SetStatus("음원 파일이 없습니다."); return; }
        if (string.IsNullOrEmpty(titleInput.text)) { SetStatus("곡 제목을 입력해주세요."); return; }
        if (!float.TryParse(bpmInput.text, out float bpm) || bpm <= 0)
                                              { SetStatus("BPM을 올바르게 입력해주세요."); return; }

        var diffs = new List<string>();
        if (toggleNormal.isOn)    diffs.Add("normal");
        if (toggleHard.isOn)      diffs.Add("hard");
        if (toggleExpert.isOn)    diffs.Add("expert");
        if (toggleExpertPlus.isOn) diffs.Add("expertplus");

        if (diffs.Count == 0) { SetStatus("난이도를 하나 이상 선택해주세요."); return; }

        string audioPath = audioFiles[audioDropdown.value];
        Debug.Log($"[SongCreator] 생성 시작 — 파일: {audioPath}, BPM: {bpm}, 난이도: {string.Join(",", diffs)}");
        Debug.Log($"[SongCreator] beatSageUploader={beatSageUploader}, nasPublisher={nasPublisher}");

        StartCoroutine(GenerateFlow(audioPath, bpm, diffs));
    }

    // ── 생성 플로우 ───────────────────────────────────────────

    private IEnumerator GenerateFlow(string audioPath, float bpm, List<string> diffs)
    {
        SetInteractable(false);
        progressGroup.SetActive(true);
        Debug.Log("[SongCreator] GenerateFlow 시작");

        // 1단계: Beat Sage 전송 → 변환
        Dictionary<string, List<NoteData>> maps = null;
        bool failed = false;

        Debug.Log("[SongCreator] BeatSage Upload 호출");
        yield return beatSageUploader.Upload(
            audioPath, diffs, bpm,
            onProgress: p =>
            {
                progressSlider.value = p * 0.8f;
                SetStatus($"{beatSageUploader.CurrentStatus}  ({(int)(p * 80)}%)");
            },
            onComplete: result =>
            {
                maps = result;
                Debug.Log($"[SongCreator] BeatSage 완료 — 난이도 수: {result?.Count}");
            },
            onError: err =>
            {
                Debug.LogError($"[SongCreator] BeatSage 오류: {err}");
                SetStatus($"오류: {err}");
                failed = true;
            });

        Debug.Log($"[SongCreator] BeatSage 단계 끝 — failed={failed}, maps={maps?.Count}");
        if (failed) { SetInteractable(true); yield break; }

        // 2단계: NAS 업로드
        SongInfo song = BuildSongInfo(audioPath, bpm, maps);

        Debug.Log($"[SongCreator] NAS Publish 호출 — song.id={song.id}");
        yield return nasPublisher.Publish(
            song, audioPath, maps,
            onProgress: p =>
            {
                progressSlider.value = 0.8f + p * 0.2f;
                SetStatus($"[4/4] NAS 업로드 중...  ({(int)((0.8f + p * 0.2f) * 100)}%)");
            },
            onComplete: () =>
            {
                progressSlider.value = 1f;
                SetStatus($"완료! '{song.title}' 생성 성공 (100%)");
                Debug.Log($"[SongCreator] NAS 업로드 완료");
            },
            onError: err =>
            {
                Debug.LogError($"[SongCreator] NAS 오류: {err}");
                SetStatus($"NAS 업로드 실패: {err}");
                failed = true;
            });

        SetInteractable(true);
    }

    // ── 유틸 ─────────────────────────────────────────────────

    private SongInfo BuildSongInfo(string audioPath, float bpm,
        Dictionary<string, List<NoteData>> maps)
    {
        string id = titleInput.text.ToLower().Replace(" ", "_");

        var diffMap = new DifficultyMap();
        foreach (var kv in maps)
        {
            var info = new DifficultyInfo { noteCount = kv.Value.Count };
            switch (kv.Key)
            {
                case "normal":     diffMap.normal     = info; break;
                case "hard":       diffMap.hard       = info; break;
                case "expert":     diffMap.expert     = info; break;
                case "expertplus": diffMap.expertplus = info; break;
            }
        }

        return new SongInfo
        {
            id           = id,
            title        = titleInput.text,
            artist       = artistInput.text,
            bpm          = bpm,
            audioFile    = $"music/{id}.mp3",
            difficulties = diffMap,
            addedAt      = DateTime.Now.ToString("yyyy-MM-dd")
        };
    }

    private void SetStatus(string msg)
    {
        if (statusText != null) statusText.text = msg;
    }

    private void SetInteractable(bool value)
    {
        generateButton.interactable     = value;
        manualEditorButton.interactable = value;
        audioDropdown.interactable      = value;
        refreshBtn.interactable         = value;
    }
}
