using Minesweeper.Config;
using Minesweeper.Core;
using Minesweeper.Presentation.Views;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

namespace Minesweeper.Presentation.Factories
{
    public sealed class CellViewFactory : ICellViewFactory
    {
        private const string ContentImagePath = "Content/Image";
        private const string ContentLabelPath = "Content/Text (TMP)";

        private readonly MinesweeperUiConfig uiConfig;

        public CellViewFactory(MinesweeperUiConfig uiConfig)
        {
            this.uiConfig = uiConfig;
        }

        public CellView CreateCell(BoardCellData cell, Transform parent)
        {
            var prefab = uiConfig.CellButtonPrefab;
            var go = prefab != null ? Object.Instantiate(prefab, parent) : CreateFallbackCell(parent);
            go.name = BuildCellName(cell.X, cell.Y, cell.DisplayValue);

            var view = go.GetComponent<CellView>();
            if (view == null)
            {
                view = go.AddComponent<CellView>();
            }

            var button = go.GetComponent<Button>();
            var backgroundImage = go.GetComponent<Image>();
            var contentImage = FindComponent<Image>(go.transform, ContentImagePath);
            var label = FindComponent<TMP_Text>(go.transform, ContentLabelPath);
            view.Bind(button, backgroundImage, contentImage, label);
            view.AutoBind();
            view.Initialize(cell.X, cell.Y);
            return view;
        }

        public string BuildCellName(int x, int y, int value, bool isMine)
        {
            return $"bt_{x}_{y}_{(isMine ? "M" : value.ToString())}";
        }

        public string BuildCellName(int x, int y, string displayValue)
        {
            return $"bt_{x}_{y}_{displayValue}";
        }

        private static T FindComponent<T>(Transform root, string path) where T : Component
        {
            var child = root.Find(path);
            return child != null ? child.GetComponent<T>() : null;
        }

        private static GameObject CreateFallbackCell(Transform parent)
        {
            var go = new GameObject("Cell", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button));
            go.transform.SetParent(parent, false);

            var content = new GameObject("Content", typeof(RectTransform));
            content.transform.SetParent(go.transform, false);
            Stretch(content.GetComponent<RectTransform>());

            var image = new GameObject("Image", typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
            image.transform.SetParent(content.transform, false);
            Stretch(image.GetComponent<RectTransform>());

            var text = new GameObject("Text (TMP)", typeof(RectTransform), typeof(CanvasRenderer), typeof(TextMeshProUGUI));
            text.transform.SetParent(content.transform, false);
            Stretch(text.GetComponent<RectTransform>());

            var label = text.GetComponent<TextMeshProUGUI>();
            label.alignment = TextAlignmentOptions.Center;
            label.enableAutoSizing = true;
            return go;
        }

        private static void Stretch(RectTransform rectTransform)
        {
            rectTransform.anchorMin = Vector2.zero;
            rectTransform.anchorMax = Vector2.one;
            rectTransform.offsetMin = Vector2.zero;
            rectTransform.offsetMax = Vector2.zero;
        }
    }
}
