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

public class MapEditor : MonoBehaviour
{
    [Header("Components")]
    public AudioSource audioSource;
    public Slider timelineSlider;
    public TMP_Text timeText;

    [Header("Song Settings")]
    [Tooltip("확장자와 Map_을 제외한 저장할 노래 제목을 적으세요 (예: Life, Virus)")]
    public string songName = "Life";

    [Header("Note Guide (Large Background Numbers)")]
    public TMP_Text[] guideTexts; // 4, 5, 1, 2 순서로 배치된 큰 텍스트들

    [Header("Timeline (On Slider)")]
    public RectTransform[] timelineRows; // Slider 내부 NoteContainer 안의 4개 줄

    [Header("Prefabs")]
    public GameObject noteUIPrefab; // 텍스트가 없는 10x10 크기의 작은 사각형 프리팹

    private List<NoteData> recordedNotes = new List<NoteData>();
    private Dictionary<NoteData, GameObject> visualNoteMap = new Dictionary<NoteData, GameObject>();

    void Start()
    {
        // 슬라이더 클릭 시 해당 시간대로 이동하는 리스너
        timelineSlider.onValueChanged.AddListener(OnSliderValueChanged);
    }

    void Update()
    {
        var kb = Keyboard.current;
        if (kb == null) return;

        // 1. 재생/정지 제어 (Space)
        if (kb.spaceKey.wasPressedThisFrame)
        {
            if (audioSource.isPlaying) audioSource.Pause();
            else audioSource.Play();
        }

        // 2. 10초 되감기 (Left Arrow)
        if (kb.leftArrowKey.wasPressedThisFrame)
        {
            audioSource.time = Mathf.Max(0, audioSource.time - 10f);
        }

        // 3. 시간 및 UI 업데이트
        if (audioSource.isPlaying)
        {
            UpdateTimelineUI();
        }

        // 4. 입력 처리 (가이드 색상 변경 + 노트 기록)
        HandleEditorInput(kb);
    }

    void UpdateTimelineUI()
    {
        float currentTime = audioSource.time;
        float totalTime = audioSource.clip.length;
        timelineSlider.value = currentTime / totalTime;
        timeText.text = string.Format("{0:00}:{1:00} / {2:00}:{3:00}", 
            (int)currentTime / 60, (int)currentTime % 60, 
            (int)totalTime / 60, (int)totalTime % 60);
    }

    void HandleEditorInput(Keyboard kb)
    {
        // 1. 단일 노트 컬러 선택 (Q: 빨강, W: 파랑)
        int soloColor = kb.qKey.isPressed ? 0 : (kb.wKey.isPressed ? 1 : -1);
        
        // 가이드 비주얼 업데이트
        UpdateGuideVisuals(kb, soloColor);

        if (!audioSource.isPlaying) return;

        // 2. E 키를 누르고 있을 때 (더블 노트 모드: 1,4 빨강 / 2,5 파랑)
        if (kb.eKey.isPressed)
        {
            // E를 누른 상태에서 숫자패드를 누르는 순간 기록
            if (kb.numpad4Key.wasPressedThisFrame) ProcessNote(0, 0); // 4번 위치 빨강
            if (kb.numpad5Key.wasPressedThisFrame) ProcessNote(1, 1); // 5번 위치 파랑
            if (kb.numpad1Key.wasPressedThisFrame) ProcessNote(2, 0); // 1번 위치 빨강
            if (kb.numpad2Key.wasPressedThisFrame) ProcessNote(3, 1); // 2번 위치 파랑
        }
        // 3. E 키를 누르하지 않았을 때 (기존 Q/W 단일 노트 모드)
        else if (soloColor != -1)
        {
            if (kb.numpad4Key.wasPressedThisFrame) ProcessNote(0, soloColor);
            if (kb.numpad5Key.wasPressedThisFrame) ProcessNote(1, soloColor);
            if (kb.numpad1Key.wasPressedThisFrame) ProcessNote(2, soloColor);
            if (kb.numpad2Key.wasPressedThisFrame) ProcessNote(3, soloColor);
        }
    }

    void UpdateGuideVisuals(Keyboard kb, int color)
    {
        // 기본 흰색으로 초기화
        foreach (var txt in guideTexts) txt.color = Color.white;

        if (color == -1) return;

        Color activeColor = (color == 0) ? Color.red : Color.blue;

        // 키패드 누르고 있을 때 가이드 텍스트 색 변경
        if (kb.numpad4Key.isPressed) guideTexts[0].color = activeColor;
        if (kb.numpad5Key.isPressed) guideTexts[1].color = activeColor;
        if (kb.numpad1Key.isPressed) guideTexts[2].color = activeColor;
        if (kb.numpad2Key.isPressed) guideTexts[3].color = activeColor;
    }

    void ProcessNote(int pos, int color)
    {
        float currentTime = audioSource.time;
        
        // 수정 로직: 현재 시간 0.1초 내에 같은 줄에 이미 노트가 있다면 제거 (덮어쓰기 준비)
        NoteData existingNote = recordedNotes.Find(n => n.position == pos && Mathf.Abs(n.time - currentTime) < 0.1f);
        if (existingNote != null) RemoveNote(existingNote);

        RecordNote(pos, color);
    }

    void RecordNote(int pos, int color)
    {
        NoteData newNote = new NoteData { time = audioSource.time, position = pos, colorType = color };
        recordedNotes.Add(newNote);

        // 1. 생성 및 부모 설정
        GameObject obj = Instantiate(noteUIPrefab, timelineRows[pos]);
        RectTransform rt = obj.GetComponent<RectTransform>();

        // 2. 크기 및 앵커 강제 고정 (길어짐 방지)
        rt.anchorMin = new Vector2(0, 0.5f);
        rt.anchorMax = new Vector2(0, 0.5f);
        rt.pivot = new Vector2(0, 0.5f);
        rt.sizeDelta = new Vector2(1, 15);
        rt.localScale = Vector3.one;       // 스케일 1로 초기화

        // 3. 색상 강제 적용 (색상 사라짐 방지)
        Image noteImage = obj.GetComponent<Image>();
        if (noteImage != null)
        {
            // 0이면 빨강, 1이면 파랑 적용
            noteImage.color = (color == 0) ? Color.red : Color.blue;
        }

        // 4. 위치 계산
        float rowWidth = timelineRows[pos].rect.width;
        float xPos = (newNote.time / audioSource.clip.length) * rowWidth;
        rt.anchoredPosition = new Vector2(xPos, 0);

        // 5. 관리 리스트에 추가
        visualNoteMap.Add(newNote, obj);
        obj.GetComponent<Button>().onClick.AddListener(() => RemoveNote(newNote));
    }

    void RemoveNote(NoteData note)
    {
        if (visualNoteMap.ContainsKey(note))
        {
            Destroy(visualNoteMap[note]);
            visualNoteMap.Remove(note);
            recordedNotes.Remove(note);
        }
    }

    public void OnSliderValueChanged(float value)
    {
        // 정지 상태에서 슬라이더 조작 시 음악 시간 이동
        if (!audioSource.isPlaying)
        {
            audioSource.time = value * audioSource.clip.length;
        }
    }

public void SaveBeatMap()
    {
        // 오디오 소스나 클립이 없을 때 예외 처리
        if (audioSource == null || audioSource.clip == null)
        {
            Debug.LogError("[맵에디터] AudioSource에 음악 파일(Clip)이 등록되어 있지 않습니다!");
            return;
        }

        // 😎 인스펙터의 Song Name을 무시하고, 실제 오디오 클립의 이름(예: Bethoven_Virus__Piano_)을 가져옵니다.
        string actualSongName = audioSource.clip.name;
        string fileName = "Map_" + actualSongName + ".json";
        string filePath = Path.Combine(Application.streamingAssetsPath, fileName).Replace("\\", "/");

        // 데이터 직렬화 및 저장
        string json = JsonUtility.ToJson(new Serialization<NoteData>(recordedNotes));
        File.WriteAllText(filePath, json);
        
        Debug.Log($"[맵에디터] 오디오 이름으로 저장 완료! 파일명: {fileName} | 경로: {filePath}");

#if UNITY_EDITOR
        UnityEditor.AssetDatabase.Refresh();
#endif
    }
}

[System.Serializable]
public class Serialization<T>
{
    public List<T> target;
    public Serialization(List<T> target) { this.target = target; }
}