using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;
    public LevelGenerator levelGenerator;
    public UIManager uiManager; // UI 매니저 연결
    public bool isAnimating = false;

    // 현재 진행 중인 레벨 인덱스
    private int currentLevelIndex = 1; 
    private const int MAX_LEVEL = 100; // 최대 레벨

    // 드래그 관련 변수
    private TileController currentDraggedTile;
    private Vector3 dragStartPos; // 드래그 시작 전 원래 위치

    public LevelData testLevelData;
    public bool isGameOver = false;

    void Awake() { Instance = this; }

    void Start()
    {
        LoadLevel(currentLevelIndex);
    }

    public void LoadLevel(int index)
    {
        currentLevelIndex = index;
        
        // Resources 폴더에서 데이터 로드 (경로: Assets/Resources/Levels/Level_001...)
        string path = $"Levels/Level_{index:D3}";
        LevelData data = Resources.Load<LevelData>(path);

        if (data != null)
        {
            levelGenerator.SpawnLevel(data);
            // 약간의 딜레이 후 셔플 (연출 효과)
            StartCoroutine(ShuffleRoutine());
        }
        else
        {
            Debug.LogError($"레벨 데이터를 찾을 수 없습니다: {path}");
        }
    }

    public void LoadNextLevel()
    {
        currentLevelIndex++;
        if (currentLevelIndex > MAX_LEVEL) currentLevelIndex = 1; // 루프 혹은 엔딩
        LoadLevel(currentLevelIndex);
    }

    IEnumerator ShuffleRoutine()
    {
        yield return new WaitForSeconds(0.5f); // 타일 생성 감상 시간
        ShuffleGrid();
        isGameOver = false;
    }

    void ShuffleGrid()
    {
        // 간단하게 무작위로 N번 스왑
        int shuffleCount = 20; 
        int width = levelGenerator.tileGrid.GetLength(0);
        int height = levelGenerator.tileGrid.GetLength(1);

        for(int i=0; i<shuffleCount; i++)
        {
            int x1 = Random.Range(1, width-1); // 모서리(고정타일) 제외
            int y1 = Random.Range(0, height);  
            int x2 = Random.Range(1, width-1);
            int y2 = Random.Range(0, height);

            TileController t1 = levelGenerator.tileGrid[x1, y1];
            TileController t2 = levelGenerator.tileGrid[x2, y2];

            if(!t1.isFixed && !t2.isFixed)
            {
                // 셔플은 애니메이션 없이 즉시 데이터/위치 변경
                Vector3 tempPos = t1.transform.position;
                t1.transform.position = t2.transform.position;
                t2.transform.position = tempPos;

                Vector2Int tempCoord = t1.currentCoord;
                t1.currentCoord = t2.currentCoord;
                t2.currentCoord = tempCoord;
                
                levelGenerator.tileGrid[x1, y1] = t1;
                levelGenerator.tileGrid[x2, y2] = t2;
            }
        }
    }

    public void StartGame(LevelData data)
    {
        isGameOver = false;
        uiManager.HideWinUI();
        levelGenerator.SpawnLevel(data);
    }

    void Update()
    {
        if (isAnimating) return; // 애니메이션 중에는 조작 불가

        if (isGameOver || isAnimating) return;

        // 2. [중요] UI를 클릭 중이라면 게임 입력 무시 (PC/Mobile 통합)
        if (IsPointerOverUI()) return;

        HandleInput();
    }

    private bool IsPointerOverUI()
    {
        // PC or Unity Editor
        if (EventSystem.current.IsPointerOverGameObject()) return true;
        
        // Mobile (Touch)
        if (Input.touchCount > 0 && EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId)) return true;
        
        return false;
    }

    void HandleInput()
    {
        // 1. 터치/클릭 시작 (Pick Up)
        if (Input.GetMouseButtonDown(0))
        {
            TileController hitTile = GetTileUnderMouse();
            
            // 고정 타일이 아니고 유효한 타일이면 잡기
            if (hitTile != null && !hitTile.isFixed)
            {
                currentDraggedTile = hitTile;
                dragStartPos = currentDraggedTile.transform.position; // 원래 위치 기억
                currentDraggedTile.SetDraggingState(true); // 시각적 효과 ON & 콜라이더 OFF
            }
        }

        // 2. 드래그 중 (Dragging)
        if (Input.GetMouseButton(0) && currentDraggedTile != null)
        {
            Vector3 mousePos = GetWorldMousePosition();
            // 타일이 마우스 따라다니기 (Z값은 유지하거나 0으로)
            currentDraggedTile.transform.position = new Vector3(mousePos.x, mousePos.y, 0);
        }

        // 3. 터치/클릭 뗌 (Drop)
        if (Input.GetMouseButtonUp(0) && currentDraggedTile != null)
        {
            // 놓는 순간 마우스 밑에 뭐가 있는지 확인
            // (currentDraggedTile의 콜라이더가 꺼져 있으므로 밑에 있는 타일이 잡힘)
            TileController targetTile = GetTileUnderMouse();

            currentDraggedTile.SetDraggingState(false); // 상태 복구 (콜라이더 켜짐)

            if (targetTile != null && targetTile != currentDraggedTile && !targetTile.isFixed)
            {
                // 교체 대상이 있고, 고정 타일이 아니면 -> 스왑
                StartCoroutine(SwapTiles(currentDraggedTile, targetTile));
            }
            else
            {
                // 대상이 없거나 고정 타일이면 -> 원래 자리로 복귀
                StartCoroutine(currentDraggedTile.MoveToPosition(dragStartPos, 0.2f));
            }

            currentDraggedTile = null;
        }
    }

    // 마우스 위치의 타일 가져오는 헬퍼 함수
    TileController GetTileUnderMouse()
    {
        Vector2 mousePos = GetWorldMousePosition();
        RaycastHit2D hit = Physics2D.Raycast(mousePos, Vector2.zero);
        
        if (hit.collider != null)
        {
            return hit.collider.GetComponent<TileController>();
        }
        return null;
    }

    Vector3 GetWorldMousePosition()
    {
        Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        mousePos.z = 0;
        return mousePos;
    }

    // 기존 스왑 로직 (약간 수정: StartPos가 꼬이지 않게 위치 강제 할당)
    IEnumerator SwapTiles(TileController tileA, TileController tileB)
    {
        isAnimating = true;

        // 중요: 드래그 했던 타일(A)은 현재 마우스 위치에 있음.
        // 타일 B의 위치로 부드럽게 이동
        Vector3 posB = tileB.transform.position;
        
        // 타일 B는 타일 A의 원래 위치(dragStartPos)로 이동해야 함
        Vector3 posA = dragStartPos; // A의 현재 위치가 아니라 원래 위치!

        StartCoroutine(tileA.MoveToPosition(posB, 0.2f));
        yield return StartCoroutine(tileB.MoveToPosition(posA, 0.2f));

        // 데이터 교체
        Vector2Int tempCoord = tileA.currentCoord;
        tileA.currentCoord = tileB.currentCoord;
        tileB.currentCoord = tempCoord;

        levelGenerator.tileGrid[tileA.currentCoord.x, tileA.currentCoord.y] = tileA;
        levelGenerator.tileGrid[tileB.currentCoord.x, tileB.currentCoord.y] = tileB;

        isAnimating = false;
        CheckWinCondition();
    }

    // 승리 체크 로직은 그대로 유지
    void CheckWinCondition()
    {
        int width = levelGenerator.tileGrid.GetLength(0);
        int height = levelGenerator.tileGrid.GetLength(1);
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                TileController tile = levelGenerator.tileGrid[x, y];
                if (tile.currentCoord != tile.correctCoord) return;
            }
        }
        
        // 승리 확정!
        Debug.Log("Level Cleared!");
        isGameOver = true; // [중요] 이제부터 타일 클릭 금지!
        uiManager.ShowWinUI(); // UI 띄우기
    }
}