using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.EventSystems;
using System.Collections.Generic;

public class BuildManager : MonoBehaviour
{
    public static BuildManager Instance;

    [System.Serializable]
    public struct TurretData // 타워별 정보를 담는 구조체
    {
        public string turretName;
        public GameObject finalPrefab;     // 완공 후 실제 타워
        public GameObject ghostPrefab;     // 건설 모드 시 미리보기
        public float buildTime;            // 건설 소요 시간
        public Vector2Int size;            // 점유 칸수
    }

    [Header("Settings")]
    [SerializeField] private float cellSize = 1f;
    [SerializeField] private LayerMask groundLayer;
    [SerializeField] private GameObject constructionSitePrefab; // 공용 토대 프리팹

    [Header("Current Selection")]
    [SerializeField] private TurretData selectedTurret; // 현재 선택된 타워 데이터
    [SerializeField] private bool isBuildMode = false;

    [SerializeField] private LayerMask playerLayer; // 플레이어의 레이어를 지정하세요.

    [Header("Turret Library")]
    [SerializeField] private List<TurretData> turretLibrary; // 인스펙터에서 여러 타워 등록

    private GameObject _ghostInstance;
    private Material _ghostMaterial;
    private HashSet<Vector2Int> _occupiedNodes = new HashSet<Vector2Int>();
    private PlayerInputActions _inputActions;

    void Awake()
    {
        Instance = this;
        _inputActions = new PlayerInputActions();
    }

    void OnEnable()
    {
        _inputActions.Player.Build.performed += OnBuildPerformed;
        _inputActions.Player.Cancel.performed += OnCancelPerformed;
        _inputActions.Player.ToggleBuild.performed += OnTogglePerformed;
        _inputActions.Enable();
    }

    void OnDisable()
    {
        _inputActions.Disable();
    }

    void Update()
    {
        if (!isBuildMode || _ghostInstance == null) return;

        Vector2 mousePos = Mouse.current.position.ReadValue();
        Ray ray = Camera.main.ScreenPointToRay(mousePos);

        if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, groundLayer))
        {
            Vector2Int gridPos = WorldToGrid(hit.point);
            _ghostInstance.transform.position = GridToWorld(gridPos, selectedTurret.size);

            // 건설 가능 여부 실시간 체크
            bool canPlace = CanBuild(gridPos, selectedTurret.size);

            // 고스트 색상 변경 (Material의 _Color 속성이 있다고 가정)
            if (_ghostMaterial != null)
            {
                _ghostMaterial.color = canPlace ? new Color(0, 1, 0, 0.5f) : new Color(1, 0, 0, 0.5f);
            }
        }
    }

    // --- Input Callbacks ---
    private void OnTogglePerformed(InputAction.CallbackContext context) => ToggleBuildMode();
    private void OnCancelPerformed(InputAction.CallbackContext context)
    {
        if (isBuildMode) ToggleBuildMode();
    }

    private void OnBuildPerformed(InputAction.CallbackContext context)
    {
        if (!isBuildMode || EventSystem.current.IsPointerOverGameObject()) return;

        Vector2 mousePos = Mouse.current.position.ReadValue();
        Ray ray = Camera.main.ScreenPointToRay(mousePos);

        if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, groundLayer))
        {
            Vector2Int gridPos = WorldToGrid(hit.point);
            if (CanBuild(gridPos, selectedTurret.size))
            {
                Build(gridPos, selectedTurret);
            }
        }
    }

    // --- Core Logic ---
    private void ToggleBuildMode()
    {
        isBuildMode = !isBuildMode;

        if (isBuildMode) CreateGhost();
        else DestroyGhost();
    }

    private void CreateGhost()
    {
        if (selectedTurret.ghostPrefab == null) return;

        if (_ghostInstance != null) Destroy(_ghostInstance);

        _ghostInstance = Instantiate(selectedTurret.ghostPrefab);

        // [추가] 고스트의 크기도 데이터에 맞게 조정
        _ghostInstance.transform.localScale = new Vector3(selectedTurret.size.x, 5f, selectedTurret.size.y);
    }

    private void DestroyGhost()
    {
        if (_ghostInstance != null) Destroy(_ghostInstance);
    }

    private void UpdateGhost()
    {
        if (_ghostInstance == null) return;

        Vector2 mousePos = Mouse.current.position.ReadValue();
        Ray ray = Camera.main.ScreenPointToRay(mousePos);

        if (Physics.Raycast(ray, out RaycastHit hit, Mathf.Infinity, groundLayer))
        {
            _ghostInstance.SetActive(true);
            Vector2Int gridPos = WorldToGrid(hit.point);
            _ghostInstance.transform.position = GridToWorld(gridPos, selectedTurret.size);

            bool canBuild = CanBuild(gridPos, selectedTurret.size);
            _ghostMaterial.color = canBuild ? new Color(0, 1, 0, 0.5f) : new Color(1, 0, 0, 0.5f);
        }
        else
        {
            _ghostInstance.SetActive(false);
        }
    }

    private void Build(Vector2Int gridPos, TurretData data)
    {
        // 1. 프리팹 할당 여부 체크
        if (constructionSitePrefab == null)
        {
            Debug.LogError("BuildManager: Construction Site Prefab이 할당되지 않았습니다!");
            return;
        }

        if (data.finalPrefab == null)
        {
            Debug.LogError($"BuildManager: {data.turretName}의 Final Prefab이 할당되지 않았습니다!");
            return;
        }

        // 2. 점유 노드 등록
        for (int x = 0; x < data.size.x; x++)
            for (int y = 0; y < data.size.y; y++)
                _occupiedNodes.Add(new Vector2Int(gridPos.x + x, gridPos.y + y));

        // 3. 토대 생성
        GameObject siteObj = Instantiate(constructionSitePrefab, GridToWorld(gridPos, data.size), Quaternion.identity);

        // [추가] 토대의 비주얼 크기를 타워 사이즈에 맞게 조정
        // x와 z는 타워의 가로/세로 사이즈를 따르고, y(높이)는 1로 유지합니다.
        siteObj.transform.localScale = new Vector3(data.size.x, 5f, data.size.y);

        // 4. 컴포넌트 존재 여부 체크
        ConstructionSite siteScript = siteObj.GetComponent<ConstructionSite>();
        if (siteScript != null)
        {
            siteScript.Initialize(data.finalPrefab, data.buildTime, data.size);
        }
        else
        {
            Debug.LogError("BuildManager: 생성된 토대 프리팹에 ConstructionSite 스크립트가 없습니다!");
        }

        ToggleBuildMode();
    }

    // --- Utilities ---
    private bool CanBuild(Vector2Int startPos, Vector2Int size)
    {
        for (int x = 0; x < size.x; x++)
            for (int y = 0; y < size.y; y++)
                if (_occupiedNodes.Contains(new Vector2Int(startPos.x + x, startPos.y + y))) 
                    return false;

        // 2. 플레이어와 겹치는지 물리적 박스 검사
        Vector3 center = GridToWorld(startPos, size);
        // 타워 높이의 절반 정도 위에서 검사 (y축 위치 보정)
        center.y = 1f;

        // 타워 사이즈보다 아주 살짝 작게 설정하여 여유 공간 부여 (0.45f)
        Vector3 halfExtents = new Vector3(size.x * 0.45f, 0.5f, size.y * 0.45f);

        // 해당 영역에 playerLayer를 가진 콜라이더가 있는지 확인
        bool isPlayerOverlapping = Physics.CheckBox(center, halfExtents, Quaternion.identity, playerLayer);

        return !isPlayerOverlapping;
    }

    private Vector2Int WorldToGrid(Vector3 worldPos) => new Vector2Int(Mathf.FloorToInt(worldPos.x / cellSize), Mathf.FloorToInt(worldPos.z / cellSize));

    private Vector3 GridToWorld(Vector2Int gridPos, Vector2Int size)
    {
        return new Vector3(gridPos.x * cellSize + (size.x - 1) * cellSize * 0.5f, 0.05f, gridPos.y * cellSize + (size.y - 1) * cellSize * 0.5f);
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = new Color(1, 1, 1, 0.1f);
        for (int x = -10; x <= 10; x++)
            for (int z = -10; z <= 10; z++)
                Gizmos.DrawWireCube(new Vector3(x * cellSize, 0, z * cellSize), new Vector3(cellSize, 0.01f, cellSize));
    }

    // 현재 선택된 타워를 변경하는 공용 메서드
    public void SelectTurret(int index)
    {
        if (index >= 0 && index < turretLibrary.Count)
        {
            selectedTurret = turretLibrary[index];
            Debug.Log($"{selectedTurret.turretName} 선택됨!");

            // 만약 건설 모드 중이라면 고스트도 즉시 교체
            if (isBuildMode)
            {
                CreateGhost();
            }
        }
    }
}