using System.Collections.Generic;
using Jovian.PopupSystem;
using Nox.UI;
using UnityEngine;
using Object = UnityEngine.Object;

namespace Nox.Game.UI {
    public class PartyGuiView {
        private const int PoolSize = 4;

        private readonly Transform portraitsContainer;
        private readonly PartyMemberSlot slotPrefab;
        private readonly PortraitsHolder portraitsHolder;
        private readonly IPopupSystem popupSystem;
        private readonly PartyMemberSlot[] slotPool = new PartyMemberSlot[PoolSize];

        private PartyDefinition trackedParty;
        private int activeCount;

        public PartyGuiView(Transform portraitsContainer, PartyMemberSlot slotPrefab, PortraitsHolder portraitsHolder, IPopupSystem popupSystem = null) {
            this.portraitsContainer = portraitsContainer;
            this.slotPrefab = slotPrefab;
            this.portraitsHolder = portraitsHolder;
            this.popupSystem = popupSystem;
        }

        public void Initialize(PartyDefinition party) {
            trackedParty = party;
            activeCount = 0;

            // Pre-create all slots (deactivated)
            for(int i = 0; i < PoolSize; i++) {
                if(slotPool[i] == null) {
                    slotPool[i] = Object.Instantiate(slotPrefab, portraitsContainer);
                }
                slotPool[i].gameObject.SetActive(false);
            }

            PopulateSlots();
        }

        public void Tick() {
            if(trackedParty == null) {
                return;
            }

            // Rebuild if member count changed
            if(trackedParty.members.Count != activeCount) {
                PopulateSlots();
            }

            // Update dynamic values
            var memberCount = Mathf.Min(activeCount, trackedParty.members.Count);
            for(int i = 0; i < memberCount; i++) {
                UpdateSlotStats(slotPool[i], trackedParty.members[i]);
            }
        }

        private void PopulateSlots() {
            var memberCount = trackedParty?.members != null
                ? Mathf.Min(trackedParty.members.Count, PoolSize)
                : 0;

            // Activate slots for current members, deactivate the rest
            for(var i = 0; i < PoolSize; i++) {
                var slot = slotPool[i];
                if(i < memberCount && trackedParty?.members != null) {
                    var member = trackedParty.members[i];
                    if(member == null) {
                        continue;
                    }
                    slot.gameObject.SetActive(true);

                    // Portrait
                    if(portraitsHolder != null && portraitsHolder.portraits.Length > 0) {
                        var idx = Mathf.Clamp(member.PortraitIndex, 0, portraitsHolder.portraits.Length - 1);
                        slot.portrait.sprite = portraitsHolder.portraits[idx];
                    }

                    UpdateSlotStats(slot, member);
                }
                else {
                    slot.gameObject.SetActive(false);
                }
            }

            activeCount = memberCount;

            // Initialize popup triggers
            popupSystem?.InitializeTriggersInChildren(portraitsContainer, (trigger, view) => {
                var slot = trigger.GetComponentInParent<PartyMemberSlot>();
                if(!slot) {
                    return;
                }
                var slotIndex = System.Array.IndexOf(slotPool, slot);
                if(slotIndex < 0 || slotIndex >= activeCount) {
                    return;
                }
                var member = trackedParty.members[slotIndex];
                view.SetContent(builder => BuildCharacterPopup(builder, member));
            });
        }

        private void BuildCharacterPopup(PopupContentBuilder builder, CharacterDefinition member) {
            // Header
            builder
                .AddText(member.Name, PopupElementType.Header)
                .AddText($"{member.Race} {member.Class}", "#CCCCCC", PopupElementType.Text)
                .AddText($"Role: {member.Role}", PopupElementType.Text)
                .AddSeparator(PopupElementType.Separator);

            // Stats
            if(member.Stats?.stats != null) {
                var level = member.Stats.GetValue(StatType.Level);
                var xp = member.Stats.GetValue(StatType.Experience);
                var health = member.Stats.GetValue(StatType.Health);
                var mana = member.Stats.GetValue(StatType.Mana);
                builder
                    .AddNameValue("Level", level, PopupElementType.LabelValueText)
                    .AddNameValue("XP", xp, PopupElementType.LabelValueText)
                    .AddSeparator(PopupElementType.Separator)
                    .AddNameValue("Health", health, PopupElementType.LabelValueText)
                    .AddNameValue("Mana", mana, PopupElementType.LabelValueText)
                    .AddSeparator(PopupElementType.Separator);
            }

            // Attributes
            if(member.Attributes?.attributes != null) {
                foreach(var attr in member.Attributes.attributes) {
                    if(attr.attribute == AttributeType.None) {
                        continue;
                    }
                    builder.AddNameValue(attr.attribute.ToString(), attr.value, PopupElementType.LabelValueText);
                }
            }
            builder.AddSeparator(PopupElementType.Separator);

            // Perks
            if(member.Perks?.perks is { Count: > 0 }) {
                builder.AddText("Perks", "#FFD700", PopupElementType.Text);
                foreach(var perk in member.Perks.perks) {
                    builder.AddText($"  {perk.Name}", PopupElementType.Text);
                }
                builder.AddSeparator(PopupElementType.Separator);
            }

            // Modifiers
            if(member.Modifiers?.modifiers is { Count: > 0 }) {
                builder.AddText("Modifiers", "#87CEEB", PopupElementType.Text);
                foreach(var mod in member.Modifiers.modifiers) {
                    var target = mod.Target != null ? mod.Target.ToString() : "";
                    builder.AddText($"  {mod.Name} ({mod.Operation} {mod.Value} {target})", PopupElementType.Text);
                }
            }
        }

        private static void UpdateSlotStats(PartyMemberSlot slot, CharacterDefinition member) {
            var health = member.Stats.GetValue(StatType.Health);
            var mana = member.Stats.GetValue(StatType.Mana);

            if(slot.healthBar != null) {
                slot.healthBar.fillAmount = Mathf.Clamp01(health / 100f);
            }

            if(slot.manaBar != null) {
                slot.manaBar.fillAmount = Mathf.Clamp01(mana / 100f);
            }
        }

        public void Dispose() {
            for(int i = 0; i < PoolSize; i++) {
                if(slotPool[i] != null) {
                    Object.Destroy(slotPool[i].gameObject);
                    slotPool[i] = null;
                }
            }
            activeCount = 0;
        }
    }
}
