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

namespace eagle.Notifications {
    using ProvinceId = Int32;

    public class DynamicTextNotification : Notification, IDisposable {
        private List<GeneratedTextListener> textListeners = new();
        private string textTemplate;
        private Dictionary<string, string> placeholderValues = new();

        public DynamicTextNotification(
                string title,
                string textTemplate,
                Dictionary<string, (string nameTextId, string fallback)> heroPlaceholders,
                List<ProvinceId> provinceIds,
                List<HeroView> displayedHeroes,
                bool shouldAppend = true,
                string llmId = null)
            : base(title,
                   BuildInitialText(textTemplate, heroPlaceholders),
                   provinceIds,
                   displayedHeroes,
                   shouldAppend,
                   llmId) {
            this.textTemplate = textTemplate;
            SetupTextListeners(heroPlaceholders);
        }

        public DynamicTextNotification(
                string title,
                string textTemplate,
                Dictionary<string, (string nameTextId, string fallback)> heroPlaceholders,
                ProvinceId singleProvinceId,
                List<HeroView> displayedHeroes,
                bool shouldAppend = true)
            : this(title,
                   textTemplate,
                   heroPlaceholders,
                   new List<ProvinceId> { singleProvinceId },
                   displayedHeroes,
                   shouldAppend) {}

        private static string BuildInitialText(
                string template,
                Dictionary<string, (string nameTextId, string fallback)> heroPlaceholders) {
            string result = template;
            foreach (var kvp in heroPlaceholders) {
                string placeholder = kvp.Key;
                string fallback = kvp.Value.fallback;

                // Try to get text immediately, fall back if not available
                string currentText = fallback;
                if (!string.IsNullOrEmpty(kvp.Value.nameTextId)) {
                    var textEntry = ClientTextProvider.Provider.GetTextEntry(kvp.Value.nameTextId);
                    if (textEntry != null && !string.IsNullOrEmpty(textEntry.Text)) {
                        currentText = textEntry.Text;
                    }
                }

                result = result.Replace($"{{{placeholder}}}", currentText);
            }
            return result;
        }

        private void SetupTextListeners(
                Dictionary<string, (string nameTextId, string fallback)> heroPlaceholders) {
            int index = 0;
            foreach (var kvp in heroPlaceholders) {
                string placeholder = kvp.Key;
                string nameTextId = kvp.Value.nameTextId;
                string fallback = kvp.Value.fallback;

                if (!string.IsNullOrEmpty(nameTextId)) {
                    var listener = new GeneratedTextListener(
                            nameTextId,
                            "",
                            "",
                            index,
                            (listenerIndex, text) => UpdatePlaceholder(placeholder, text));

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

                index++;
            }
        }

        private void UpdatePlaceholder(string placeholder, string newText) {
            placeholderValues[placeholder] = newText;
            UpdateText();
        }

        private void UpdateText() {
            string result = textTemplate;
            foreach (var kvp in placeholderValues) {
                result = result.Replace($"{{{kvp.Key}}}", kvp.Value);
            }

            // Use reflection to update the private setter
            var textProperty = typeof(Notification).GetProperty("Text");
            textProperty?.SetValue(this, result);
        }

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

        public static DynamicTextNotification StreamingDynamicNotification(
                string title,
                string textTemplate,
                Dictionary<string, (string nameTextId, string fallback)> heroPlaceholders,
                string llmId,
                List<ProvinceId> provinceIds,
                List<HeroView> displayedHeroes) {
            return new DynamicTextNotification(
                    title: title,
                    textTemplate: textTemplate,
                    heroPlaceholders: heroPlaceholders,
                    provinceIds: provinceIds,
                    displayedHeroes: displayedHeroes,
                    shouldAppend: false,
                    llmId: llmId);
        }
    }
}