using UnityEngine;
using UnityEngine.EventSystems;

public class CardMovingManager : MonoBehaviour
{
    [SerializeField] private GameObject buildingsParent;
    [SerializeField] private LayerMask overlapLayer;
    [SerializeField] private AudioClipGroup pickupSound;
    [SerializeField] private AudioClipGroup dropSound;

    private BuildingsInteractionManager buildingsInteractionManager;

    public bool IsMovingCard { get; private set; }
    
    private Card selectedCard;

    private CardHolderBuilding preview;
    private SpriteRenderer previewSprite;

    private Building selectedCardBuilding;
    private SpriteRenderer selectedCardBuildingSprite;

    private void Awake()
    {
        buildingsInteractionManager = GetComponent<BuildingsInteractionManager>();
        IsMovingCard = false;
        Events.OnCardForMovingSelected += OnCardForMovingSelected;
        Events.OnDayEnd += OnDayEnd;
    }

    private void OnDestroy()
    {
        Events.OnCardForMovingSelected -= OnCardForMovingSelected;
        Events.OnDayEnd -= OnDayEnd;
    }

    private void Update()
    {
        if (IsMovingCard)
        {
            if (selectedCard == null)
            {
                IsMovingCard = false;
                return;
            }
            UpdateCardPosition();
            UpdatePosition();
            previewSprite.enabled = IsAvailableForPlacing();
        }
    }

    private void DeselectCard()
    {
        preview.Demolish();
        selectedCard.transform.SetLocalPositionAndRotation(new Vector3(0,0,-1),Quaternion.identity);

        if (selectedCardBuilding is CardHolderBuilding)
        {
            selectedCardBuildingSprite.enabled = true;
            MapManager.Instance.ChangeBuildingTop(selectedCardBuilding.transform.position, 
                selectedCardBuilding.BuildingData, TileType.Available);

        }
    }

    private void OnDayEnd()
    {
        if (IsMovingCard) Place();
    }

    public void Place()
    {
        dropSound.Play();
        IsMovingCard = false;
        
        if (EventSystem.current.IsPointerOverGameObject())
            DeselectCard();
        else if (IsAvailableForPlacing())
        {
            selectedCard.PlaceCard(preview.GetComponentInChildren<CardHoldArea>());
            previewSprite.enabled = true;

            MapManager.Instance.NewBuildingPlaced(
                preview.transform.position,
                preview.BuildingData
                );
            MapManager.Instance.BuildingBuilt(
                preview.transform.position,
                preview.BuildingData);
        }
        else
        {
            CardHoldArea cardHoldArea = CanPlaceCard();
            if (cardHoldArea == null) 
                DeselectCard();
            else
            {
                preview.Demolish();
                selectedCard.PlaceCard(cardHoldArea);
            }
            
        }

        CardHoldArea CanPlaceCard()
        {
            Collider2D[] colliders = Physics2D.OverlapPointAll(
                Camera.main.ScreenToWorldPoint(Input.mousePosition),
                overlapLayer);

            foreach (Collider2D collider in colliders)
            {
                CardHoldArea[] cardHoldAreas = collider.GetComponentsInChildren<CardHoldArea>();
                foreach (CardHoldArea cardHoldArea in cardHoldAreas)
                    if (cardHoldArea.CanAddCard(selectedCard))
                        return cardHoldArea;
            }

            return null;
        }
    }

    private void UpdatePosition()
    {
        Vector3 mousePosition = Input.mousePosition;

        float clampedX = Mathf.Clamp(mousePosition.x, 0f, Screen.width);
        float clampedY = Mathf.Clamp(mousePosition.y, 0f, Screen.height);

        mousePosition = new(clampedX, clampedY, mousePosition.z);

        Vector3 pos = Camera.main.ScreenToWorldPoint(mousePosition);

        // Snap to grid based on building size
        float xOffset = 0.5f * preview.BuildingData.Size.x;
        float yOffset = 0.5f * preview.BuildingData.Size.y;
        pos.Set(Mathf.Round(pos.x - xOffset) + xOffset, Mathf.Round(pos.y - yOffset) + yOffset, 0);

        preview.transform.position = pos;
    }

    private void UpdateCardPosition()
    {
        Vector3 mousePosition = Input.mousePosition;

        float clampedX = Mathf.Clamp(mousePosition.x, 0f, Screen.width);
        float clampedY = Mathf.Clamp(mousePosition.y, 0f, Screen.height);

        mousePosition = new(clampedX, clampedY, mousePosition.z);

        Vector3 pos = Camera.main.ScreenToWorldPoint(mousePosition);
        selectedCard.transform.position = new Vector3(pos.x, pos.y, selectedCard.transform.position.z);
    }

    private void OnCardForMovingSelected(Building building, Card card)
    {
        if (!GameManager.Instance.GameIsOn) return;
        if (buildingsInteractionManager.CursorState != CursorState.Free &&
            buildingsInteractionManager.CursorState != CursorState.MovingCard) return;
        pickupSound.Play();
        selectedCard = card;

        preview = Instantiate(selectedCard.cardData.BuildingPrefab, buildingsParent.transform);
        previewSprite = preview.GetComponent<SpriteRenderer>();
        previewSprite.enabled = false;

        selectedCardBuilding = building;
        selectedCardBuildingSprite = selectedCardBuilding.GetComponent<SpriteRenderer>();

        if (selectedCardBuilding is CardHolderBuilding)
        {
            MapManager.Instance.ChangeBuildingTop(selectedCardBuilding.transform.position, selectedCardBuilding.BuildingData, TileType.Empty);
            selectedCardBuildingSprite.enabled = false;
        }

        UpdatePosition();
        IsMovingCard = true;
    }

    private bool IsAvailableForPlacing()
    {
        return MapManager.Instance.CheckIfAvailableForBuilding(
            preview.transform.position,
            preview.BuildingData);
    }

}
