using System;
using System.Collections.Generic;
using Net.Eagle0.Eagle.Views;
using TMPro;
using UnityEngine;

namespace eagle {
    public class DynamicFactionTextUpdater : IDisposable {
        private List<GeneratedTextListener> textListeners = new();
        private Dictionary<string, TMP_Text> textComponents = new();
        private Dictionary<string, FactionTextConfig> factionConfigs = new();

        private class FactionTextConfig {
            public FactionView Faction { get; }
            public IGameModel GameModel { get; }
            public string Template { get; }
            public string FallbackText { get; }

            public FactionTextConfig(
                    FactionView faction,
                    IGameModel gameModel,
                    string template,
                    string fallbackText) {
                Faction = faction;
                GameModel = gameModel;
                Template = template;
                FallbackText = fallbackText;
            }
        }

        public void SetFactionText(
                TMP_Text textComponent,
                FactionView faction,
                IGameModel gameModel,
                string template = null,
                string fallbackText = null) {
            if (!textComponent || faction == null || gameModel == null) return;

            string componentKey = textComponent.GetInstanceID().ToString();
            textComponents[componentKey] = textComponent;

            // Use the provided template or get the default faction string template
            string actualTemplate =
                    template ?? DisplayNames.FactionStringTemplate(faction, gameModel);
            string actualFallback = fallbackText ?? faction.Name;

            factionConfigs[componentKey] =
                    new FactionTextConfig(faction, gameModel, actualTemplate, actualFallback);

            // Set initial text
            UpdateFactionText(componentKey);

            // If the template contains {FactionLeaderName}, subscribe to leader name updates
            if (actualTemplate.Contains("{FactionLeaderName}")) {
                var leader = gameModel.Heroes[faction.FactionHeadId];
                if (!string.IsNullOrEmpty(leader.NameTextId)) {
                    var textEntry = ClientTextProvider.Provider.GetTextEntry(leader.NameTextId);
                    if (textEntry == null || string.IsNullOrEmpty(textEntry.Text)) {
                        // Create listener for dynamic updates
                        var listener = new GeneratedTextListener(
                                leader.NameTextId,
                                "",
                                "",
                                0,
                                (index, text) => UpdateFactionText(componentKey));

                        textListeners.Add(listener);
                        ClientTextProvider.Provider.AddListener(listener);
                    }
                }
            }
        }

        public void SetFactionTextWithCustomFormat(
                TMP_Text textComponent,
                FactionView faction,
                IGameModel gameModel,
                string customFormat,
                string fallbackText = null) {
            if (!textComponent || faction == null || gameModel == null ||
                string.IsNullOrEmpty(customFormat))
                return;

            string componentKey = textComponent.GetInstanceID().ToString();
            textComponents[componentKey] = textComponent;

            string actualFallback = fallbackText ?? faction.Name;
            factionConfigs[componentKey] =
                    new FactionTextConfig(faction, gameModel, customFormat, actualFallback);

            // Set initial text
            UpdateFactionTextWithCustomFormat(componentKey, customFormat);

            // If the custom format contains {FactionLeaderName}, subscribe to leader name updates
            if (customFormat.Contains("{FactionLeaderName}")) {
                var leader = gameModel.Heroes[faction.FactionHeadId];
                if (!string.IsNullOrEmpty(leader.NameTextId)) {
                    var textEntry = ClientTextProvider.Provider.GetTextEntry(leader.NameTextId);
                    if (textEntry == null || string.IsNullOrEmpty(textEntry.Text)) {
                        // Create listener for dynamic updates
                        var listener = new GeneratedTextListener(
                                leader.NameTextId,
                                "",
                                "",
                                0,
                                (index, text) => UpdateFactionTextWithCustomFormat(
                                        componentKey,
                                        customFormat));

                        textListeners.Add(listener);
                        ClientTextProvider.Provider.AddListener(listener);
                    }
                }
            }
        }

        private void UpdateFactionText(string componentKey) {
            if (!textComponents.TryGetValue(componentKey, out var component) ||
                !factionConfigs.TryGetValue(componentKey, out var config) || component == null) {
                return;
            }

            var template = config.Template;
            if (template.Contains("{FactionLeaderName}")) {
                var leader = config.GameModel.Heroes[config.Faction.FactionHeadId];
                var textEntry = ClientTextProvider.Provider.GetTextEntry(leader.NameTextId);
                if (textEntry != null && !string.IsNullOrEmpty(textEntry.Text)) {
                    component.text = template.Replace("{FactionLeaderName}", textEntry.Text);
                } else {
                    component.text = template.Replace("{FactionLeaderName}", "Leader");
                }
            } else {
                component.text = template;
            }
        }

        private void UpdateFactionTextWithCustomFormat(string componentKey, string customFormat) {
            if (!textComponents.TryGetValue(componentKey, out var component) ||
                !factionConfigs.TryGetValue(componentKey, out var config) || component == null) {
                return;
            }

            string resolvedText = customFormat;
            if (customFormat.Contains("{FactionLeaderName}")) {
                var leader = config.GameModel.Heroes[config.Faction.FactionHeadId];
                var textEntry = ClientTextProvider.Provider.GetTextEntry(leader.NameTextId);
                if (textEntry != null && !string.IsNullOrEmpty(textEntry.Text)) {
                    resolvedText = resolvedText.Replace("{FactionLeaderName}", textEntry.Text);
                } else {
                    resolvedText = resolvedText.Replace("{FactionLeaderName}", "Leader");
                }
            }

            if (customFormat.Contains("{FactionName}")) {
                resolvedText = resolvedText.Replace("{FactionName}", config.Faction.Name);
            }

            if (customFormat.Contains("{Prestige}")) {
                resolvedText =
                        resolvedText.Replace("{Prestige}", config.Faction.Prestige.ToString());
            }

            component.text = resolvedText;
        }

        public void Dispose() {
            foreach (var listener in textListeners) {
                ClientTextProvider.Provider.RemoveListener(listener);
            }
            textListeners.Clear();
            textComponents.Clear();
            factionConfigs.Clear();
        }
    }
}