using System;
using System.Collections;
using System.Collections.Generic;
using Net.Eagle0.Eagle.Common;
using Net.Eagle0.Eagle.Views;
using UnityEngine;
using ProvinceId = System.Int32;

namespace eagle {
    /// <summary>
    /// Manages festival firework effects for provinces.
    /// Spawns particle systems at province centers when FestivalEvent is active.
    /// </summary>
    public class ProvinceFestivalController : MonoBehaviour {
        [Header("References")]
        public RectTransform mapContainer;
        public GameObject fireworksPrefab;
        public ProvinceIDLoader provinceIDLoader;

        private Dictionary<ProvinceId, Vector2> _provinceCentroids = new();
        private Dictionary<ProvinceId, GameObject> _activeFireworks = new();

        void Awake() { provinceIDLoader.OnMapLoaded += LoadCentroids; }

        private void LoadCentroids() {
            var data = JsonUtility.FromJson<CentroidsData>(provinceIDLoader.CentroidsJsonText);
            if (data?.provinces == null) {
                Debug.LogWarning("ProvinceFestivalController: Failed to parse centroids.json");
                return;
            }

            foreach (var province in data.provinces) {
                _provinceCentroids[province.id] =
                        new Vector2(province.centroid_x, province.centroid_y);
            }
        }

        public void UpdateFestivalEffects(IGameModel model) {
            if (_provinceCentroids.Count == 0 && provinceIDLoader.CentroidsJsonText != null) {
                LoadCentroids();
            }
            if (model?.Provinces == null) { return; }

            var provincesWithFestivals = new HashSet<ProvinceId>();
            foreach (var province in model.Provinces.Values) {
                if (HasFestivalEvent(province)) { provincesWithFestivals.Add(province.Id); }
            }

            var toRemove = new List<ProvinceId>();
            foreach (var kvp in _activeFireworks) {
                if (!provincesWithFestivals.Contains(kvp.Key)) {
                    Destroy(kvp.Value);
                    toRemove.Add(kvp.Key);
                }
            }
            foreach (var id in toRemove) { _activeFireworks.Remove(id); }

            foreach (var provinceId in provincesWithFestivals) {
                if (!_activeFireworks.ContainsKey(provinceId)) { SpawnFireworks(provinceId); }
            }
        }

        private bool HasFestivalEvent(ProvinceView province) {
            foreach (var evt in province.KnownEvents) {
                if (evt.SealedValueCase == ProvinceEvent.SealedValueOneofCase.FestivalEvent) {
                    return true;
                }
            }
            return false;
        }

        private void SpawnFireworks(ProvinceId provinceId) {
            if (fireworksPrefab == null || mapContainer == null) { return; }
            if (!_provinceCentroids.TryGetValue(provinceId, out Vector2 centroid)) { return; }

            var fireworks = Instantiate(fireworksPrefab, mapContainer);
            fireworks.name = $"Fireworks_Province{provinceId}";

            var rectTransform = fireworks.GetComponent<RectTransform>();
            if (rectTransform != null) {
                var normalizedX = centroid.x / provinceIDLoader.mapWidth;
                var normalizedY = centroid.y / provinceIDLoader.mapHeight;

                Canvas.ForceUpdateCanvases();
                var containerSize = mapContainer.rect.size;

                if (containerSize.x < 1f || containerSize.y < 1f) {
                    containerSize =
                            new Vector2(provinceIDLoader.mapWidth, provinceIDLoader.mapHeight);
                }

                rectTransform.anchorMin = Vector2.zero;
                rectTransform.anchorMax = Vector2.zero;
                rectTransform.pivot = new Vector2(0.5f, 0.5f);
                rectTransform.anchoredPosition =
                        new Vector2(normalizedX * containerSize.x, normalizedY * containerSize.y);
            }

            _activeFireworks[provinceId] = fireworks;
        }

        void OnDestroy() {
            foreach (var fireworks in _activeFireworks.Values) {
                if (fireworks != null) { Destroy(fireworks); }
            }
            _activeFireworks.Clear();
        }

        [Serializable]
        private class CentroidsData {
            public ProvinceCentroid[] provinces;
        }

        [Serializable]
        private class ProvinceCentroid {
            public int id;
            public string name;
            public float centroid_x;
            public float centroid_y;
        }
    }
}
