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

namespace eagle.Notifications.ARNNotifications {
    using ProvinceId = Int32;
    using HeroId = Int32;

    public static class ProfessionGainedDetailsNotificationGenerator {
        public static readonly ARNNotificationGenerator Generator = GenerateNotifications;

        private const int NoFactionId = 0;

        private static class Placeholders {
            public static readonly DynamicTextPlaceholderName Hero = new(nameof(Hero));
        }

        private static readonly Random Random = new();

        private static readonly Dictionary<Profession, string> ProfessionNames = new() {
            { Profession.Mage, "Mage" },
            { Profession.Necromancer, "Necromancer" },
            { Profession.Engineer, "Engineer" },
            { Profession.Paladin, "Paladin" },
            { Profession.Ranger, "Ranger" },
            { Profession.Champion, "Champion" },
            { Profession.Warden, "Warden" }
        };

        private static readonly Dictionary<Profession, List<string>> ProfessionTitles = new() {
            { Profession.Mage,
              new List<string> {
                  "Arcane Awakening",
                  "The Gift Revealed",
                  "Touched by Magic",
                  "Mystical Ascension",
                  "Power Unbound",
                  "The Arcane Path",
                  "Secrets of the Weave",
                  "Spellborn",
                  "Wielder of the Unseen",
                  "Flames of Knowledge"
              } },
            { Profession.Necromancer,
              new List<string> {
                  "Dark Pact Sealed",
                  "Beyond the Veil",
                  "Death's Apprentice",
                  "Whispers from Beyond",
                  "The Forbidden Art",
                  "Shadow Covenant",
                  "Secrets of the Grave",
                  "Communion with Darkness",
                  "The Deathless Path",
                  "Embrace of Shadow"
              } },
            { Profession.Engineer,
              new List<string> {
                  "Genius Unleashed",
                  "Master of Mechanisms",
                  "The Inventor's Spark",
                  "Gears of Progress",
                  "Mind of Innovation",
                  "Builder of Wonders",
                  "The Tinkerer's Art",
                  "Siege Mastery",
                  "Architect of War",
                  "Mechanical Brilliance"
              } },
            { Profession.Paladin,
              new List<string> {
                  "Divine Calling",
                  "Holy Vows Taken",
                  "Blessed Champion",
                  "The Righteous Path",
                  "Shield of the Faith",
                  "Anointed Warrior",
                  "Oath of Light",
                  "Heaven's Chosen",
                  "Sacred Duty",
                  "Defender of the Realm"
              } },
            { Profession.Ranger,
              new List<string> {
                  "One with the Wild",
                  "Voice of the Forest",
                  "The Untamed Path",
                  "Nature's Guardian",
                  "Shadow of the Woods",
                  "Hunter's Instinct",
                  "Wild Heart",
                  "The Wanderer's Way",
                  "Beast Companion",
                  "Eyes of the Hawk"
              } },
            { Profession.Champion,
              new List<string> {
                  "Born for Battle",
                  "Blade Mastery",
                  "The Warrior's Edge",
                  "Forged in Combat",
                  "Unmatched Prowess",
                  "Heart of Steel",
                  "The Victor's Path",
                  "Legend in the Making",
                  "Master of Arms",
                  "Glory Awaits"
              } },
            { Profession.Warden,
              new List<string> {
                  "Keeper of the Gate",
                  "Oath of Custody",
                  "The Watch Begins",
                  "Shield of the Line",
                  "Steadfast Calling",
                  "Warden's Vigil",
                  "Guardian of the Hold",
                  "Chains and Oaths",
                  "The Sentinel's Path",
                  "Duty Unbroken"
              } }
        };

        private static string GetProfessionName(Profession profession) {
            return ProfessionNames.TryGetValue(profession, out var name) ? name : "Unknown";
        }

        private static string GetProfessionTitle(Profession profession) {
            if (ProfessionTitles.TryGetValue(profession, out var titles) && titles.Count > 0) {
                return titles[Random.Next(titles.Count)];
            }
            return "Profession Gained";
        }

        private static ProvinceId? FindProvinceForHero(HeroId heroId, IGameModel model) {
            foreach (var province in model.Provinces.Values) {
                if (province.FullInfo?.RulingFactionHeroIds.Contains(heroId) == true) {
                    return province.Id;
                }
            }
            return null;
        }

        private static IEnumerable<Notification> GenerateNotifications(
                Net.Eagle0.Eagle.Common.Notification notification,
                IGameModel currentModel) {
            var details = notification.Details.ProfessionGainedDetails;
            var hero = currentModel.Heroes[details.HeroId];
            var professionName = GetProfessionName(details.NewProfession);
            var article = DisplayNames.IndefiniteArticle(professionName);

            DynamicTextTemplate textTemplate;
            List<ProvinceId> affectedProvinces;

            if (details.FactionId == NoFactionId && !hero.FactionId.HasValue) {
                var heroProvinceId = FindProvinceForHero(details.HeroId, currentModel);
                textTemplate = DynamicTextTemplate.Parsed(
                        $"{DynamicTextTemplate.Placeholder(Placeholders.Hero)} became {article} {professionName}.\n\n");
                affectedProvinces = heroProvinceId.HasValue
                                            ? new List<ProvinceId> { heroProvinceId.Value }
                                            : new List<ProvinceId>();
            } else {
                var factionId =
                        details.FactionId != NoFactionId ? details.FactionId : hero.FactionId.Value;

                if (factionId == currentModel.PlayerId) {
                    // Player's own hero - vary text based on faction leader status
                    string heroDescription;
                    if (hero.IsFactionLeader) {
                        heroDescription =
                                $"Your sworn {DisplayNames.SiblingDescription(hero.PronounGender)}";
                    } else {
                        heroDescription = "Your vassal";
                    }
                    var heroProvinceId = FindProvinceForHero(details.HeroId, currentModel);
                    if (heroProvinceId.HasValue) {
                        var provinceName = currentModel.Provinces[heroProvinceId.Value].Name;
                        textTemplate = DynamicTextTemplate.Parsed(
                                $"{heroDescription} {DynamicTextTemplate.Placeholder(Placeholders.Hero)} in {provinceName} became {article} {professionName}.\n\n");
                        affectedProvinces = new List<ProvinceId> { heroProvinceId.Value };
                    } else {
                        textTemplate = DynamicTextTemplate.Parsed(
                                $"{heroDescription} {DynamicTextTemplate.Placeholder(Placeholders.Hero)} became {article} {professionName}.\n\n");
                        affectedProvinces = currentModel.ProvincesForFaction(factionId);
                    }
                } else {
                    // Another faction's hero
                    var factionName = currentModel.FactionName(factionId);
                    textTemplate = DynamicTextTemplate.Parsed(
                            $"{DynamicTextTemplate.Placeholder(Placeholders.Hero)} of {factionName} became {article} {professionName}.\n\n");
                    affectedProvinces = currentModel.ProvincesForFaction(factionId);
                }
            }

            var heroPlaceholders = new List<DynamicPlaceholder> {
                DynamicPlaceholder.HeroName(Placeholders.Hero, hero, "A hero")
            };

            yield return DynamicTextNotification.StreamingDynamicNotification(
                    title: GetProfessionTitle(details.NewProfession),
                    textTemplate: textTemplate,
                    placeholders: heroPlaceholders,
                    llmId: notification.LlmId,
                    provinceIds: affectedProvinces,
                    displayedHeroes: new List<HeroView> { hero });
        }
    }
}
