using System;
using Minesweeper.Core;
using Minesweeper.Config;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace Minesweeper.Presentation.Views
{
    public sealed class CellView : MonoBehaviour, IPointerClickHandler, IPointerDownHandler, IPointerUpHandler
    {
        private const string ContentImagePath = "Content/Image";
        private const string ContentLabelPath = "Content/Text (TMP)";

        [SerializeField] private Button button;
        [SerializeField] private Image backgroundImage;
        [SerializeField] private Image contentImage;
        [SerializeField] private TMP_Text label;

        private int x;
        private int y;
        private bool inputEnabled = true;
        private bool isOpened;

        public event Action<int, int> OpenRequested;
        public event Action<int, int> FlagRequested;
        public event Action PressStarted;
        public event Action PressEnded;

        public void Bind(Button button, Image backgroundImage, Image contentImage, TMP_Text label)
        {
            this.button = button;
            this.backgroundImage = backgroundImage;
            this.contentImage = contentImage;
            this.label = label;
        }

        public void AutoBind()
        {
            if (button == null)
            {
                button = GetComponent<Button>();
            }

            if (backgroundImage == null)
            {
                backgroundImage = GetComponent<Image>();
            }

            if (contentImage == null)
            {
                var contentImageTransform = transform.Find(ContentImagePath);
                if (contentImageTransform != null)
                {
                    contentImage = contentImageTransform.GetComponent<Image>();
                }
            }

            if (label == null)
            {
                var labelTransform = transform.Find(ContentLabelPath);
                if (labelTransform != null)
                {
                    label = labelTransform.GetComponent<TMP_Text>();
                }
            }
        }

        public void Initialize(int x, int y)
        {
            this.x = x;
            this.y = y;
        }

        public void SetInputEnabled(bool enabled)
        {
            inputEnabled = enabled;
            if (button != null)
            {
                button.interactable = enabled && !isOpened;
            }
        }

        public void Render(BoardCellData cell, MinesweeperUiConfig config, float pixelsPerUnitMultiplier)
        {
            gameObject.name = $"bt_{cell.X}_{cell.Y}_{cell.DisplayValue}";
            isOpened = cell.IsOpened;

            if (backgroundImage != null)
            {
                backgroundImage.pixelsPerUnitMultiplier = pixelsPerUnitMultiplier;
                backgroundImage.color = cell.IsOpened ? config.OpenedCellColor : config.ClosedCellColor;
            }

            if (contentImage != null)
            {
                contentImage.pixelsPerUnitMultiplier = pixelsPerUnitMultiplier;
            }

            RenderContent(cell, config);

            if (button != null)
            {
                button.interactable = inputEnabled && !cell.IsOpened;
            }
        }

        private void RenderContent(BoardCellData cell, MinesweeperUiConfig config)
        {
            var showFlag = cell.IsFlagged && !cell.IsOpened;
            var showMine = cell.IsOpened && cell.IsMine;
            var showNumber = cell.IsOpened && !cell.IsMine && cell.NeighborMines > 0;

            if (contentImage != null)
            {
                contentImage.gameObject.SetActive(showFlag || showMine);
                if (showFlag)
                {
                    contentImage.sprite = config.FlagSprite;
                }
                else if (showMine)
                {
                    contentImage.sprite = config.MineSprite;
                }

                contentImage.color = Color.white;
            }

            if (label != null)
            {
                label.gameObject.SetActive(showNumber);
                label.text = showNumber ? cell.NeighborMines.ToString() : string.Empty;
                label.color = config.GetNumberTextColor(cell.NeighborMines);
            }
        }

        public void OnPointerClick(PointerEventData eventData)
        {
            if (!inputEnabled)
            {
                return;
            }

            if (eventData.button == PointerEventData.InputButton.Left)
            {
                OpenRequested?.Invoke(x, y);
            }
            else if (eventData.button == PointerEventData.InputButton.Right)
            {
                FlagRequested?.Invoke(x, y);
            }
        }

        public void OnPointerDown(PointerEventData eventData)
        {
            if (inputEnabled && eventData.button == PointerEventData.InputButton.Left)
            {
                PressStarted?.Invoke();
            }
        }

        public void OnPointerUp(PointerEventData eventData)
        {
            if (eventData.button == PointerEventData.InputButton.Left)
            {
                PressEnded?.Invoke();
            }
        }
    }
}
