using System.Collections.Generic;
using System.Linq;
using common;
using Eagle0.Tutorial;
using Net.Eagle0.Eagle.Views;
using UnityEngine;
using UnityEngine.UI;

namespace eagle {
    public class HeroesAndBattalionsPanelController : MonoBehaviour {
        public GameObject panel;
        public GameObject popupPanel;
        public HeroDetailsController popupPanelDetailsController;
        public GeneratedTextUpdater popupPanelBackstory;

        public GameObject battalionPopupPanel;
        public GeneratedTextUpdater battalionPopupPanelBackstory;

        [Header("Battalion Popup Header")]
        public GeneratedTextUpdater battalionPopupPanelName;
        public RawImage battalionPopupPanelTypeIcon;

        [Header("Popup Column Positioning")]
        public LayoutElement popupColumnSpacer;

        private ProvinceView _currentProvince;
        public ProvinceView CurrentProvince {
            get => _currentProvince;
            set {
                if (_currentProvince != value) {
                    _currentProvince = value;
                    UpdateTables();
                }
            }
        }

        private IGameModel _model;
        public IGameModel Model { private
            get => _model;
            set {
                _model = value;
                UpdateTables();
                panel.SetActive(value != null);
            }
        }

        public GameObject heroesAndBattalionsViews;
        public EventBasedTable heroesTable;
        public EventBasedTable battalionsTable;

        public CommandPanelController commandPanelController;

        private CommandSelector CommandSelector =>
                commandPanelController == null ? null : commandPanelController.Selector;

        public void UpdateTables() {
            if (Model == null) {
                panel.SetActive(false);
                return;
            }
            panel.SetActive(true);
            SetUpHeroesTable();
            SetUpBattalionsTable();
        }

        private void SetHeroRowSelections(HeroRowController row, HeroView hero) {
            if (CommandSelector == null) {
                row.Selected = false;
                row.Selectable = false;
                row.RightSelectable = false;
            } else {
                row.Selected = CommandSelector.TargetedHeroIds.Contains(hero.Id);
                row.Selectable = CommandSelector.HeroIsTargetable(hero.Id);
                row.RightSelectable = CommandSelector.TargetedHeroIds.Contains(hero.Id);
            }
        }

        private void SetBattalionRowSelections(BattalionRowController row, BattalionView batt) {
            if (CommandSelector == null) {
                row.Selected = false;
                row.Selectable = false;
                row.RightSelectable = false;
            } else {
                row.Selected = CommandSelector.TargetedBattalionIds.Contains(batt.Id);
                row.Selectable = CommandSelector.BattalionIsTargetable(batt.Id);
                row.RightSelectable = CommandSelector.TargetedBattalionIds.Contains(batt.Id);
            }
        }

        public void UpdateHeroSelections() {
            Heroes.Each(
                    (hero, i) => SetHeroRowSelections(
                            heroesTable.ComponentAt<HeroRowController>(i),
                            hero));
        }

        public void UpdateBattalionSelections() {
            Battalions.Each(
                    (batt, i) => SetBattalionRowSelections(
                            battalionsTable.ComponentAt<BattalionRowController>(i),
                            batt));
        }

        public void HeroRowClicked(int index) {
            var heroId = Heroes.ElementAt(index).Id;
            if (CommandSelector != null && CommandSelector.HeroIsTargetable(heroId)) {
                CommandSelector.AddTargetedHero(heroId);
            }
            UpdateHeroSelections();
        }

        public void HeroRowRightClicked(int index) {
            var heroId = Heroes.ElementAt(index).Id;
            if (CommandSelector != null) { CommandSelector.RemoveTargetedHero(heroId); }
            UpdateHeroSelections();
        }

        public void LongHoverRowChanged(int? newIndex) {
            if (newIndex is {} index) {
                var heroId = Heroes.ElementAt(index).Id;
                popupPanelDetailsController.SetHero(Model.Heroes[heroId], Model);
                popupPanelBackstory.TextId = Model.Heroes[heroId].BackstoryTextId;
                popupPanel.SetActive(true);
            } else {
                popupPanel.SetActive(false);
            }
        }

        public void BattalionRowClicked(int index) {
            var battalionId = Battalions.ElementAt(index).Id;
            if (CommandSelector != null && CommandSelector.BattalionIsTargetable(battalionId)) {
                CommandSelector.AddTargetedBattalion(battalionId);
            }
            UpdateBattalionSelections();
        }

        public void BattalionRowRightClicked(int index) {
            var battalionId = Battalions.ElementAt(index).Id;
            if (CommandSelector != null) { CommandSelector.RemoveTargetedBattalion(battalionId); }
            UpdateBattalionSelections();
        }

        public void BattalionLongHoverRowChanged(int? newIndex) {
            // Battalion backstory popups disabled - backstory updates are being eliminated
            // to reduce LLM request volume. See docs/eliminate-battalion-backstory-updates.md
            if (battalionPopupPanel != null) { battalionPopupPanel.SetActive(false); }
        }

        private void SetUpHeroesTable() {
            heroesTable.RowCount = HeroCount;

            Heroes.Each((hero, i) => {
                var row = heroesTable.ComponentAt<HeroRowController>(i);
                row.Hero = hero;
                SetHeroRowSelections(row, hero);

                // Check if this hero's profession should trigger a tutorial
                TutorialManager.Instance?.TriggerRegistry?.CheckProfessionTutorial(hero);
            });

            // Register hero rows with tutorial system for highlighting
            RegisterHeroRowsForTutorial();
        }

        private void RegisterHeroRowsForTutorial() {
            var registry = TutorialManager.Instance?.TargetRegistry;
            if (registry == null) return;

            // Register first row as WarlordRow (index 0)
            var warlordRow = heroesTable.GetRowRectTransform(0);
            if (warlordRow != null) { registry.RegisterTarget("WarlordRow", warlordRow); }

            // Register rows 1 and 2 as VassalRows
            var vassalRow1 = heroesTable.GetRowRectTransform(1);
            if (vassalRow1 != null) { registry.RegisterTarget("VassalRow1", vassalRow1); }

            var vassalRow2 = heroesTable.GetRowRectTransform(2);
            if (vassalRow2 != null) { registry.RegisterTarget("VassalRow2", vassalRow2); }

            // Register first vassal's loyalty label for tutorial highlighting
            if (heroesTable.RowCount > 1) {
                var firstVassalRow = heroesTable.ComponentAt<HeroRowController>(1);
                if (firstVassalRow?.loyaltyLabel != null) {
                    registry.RegisterTarget(
                            "LoyaltyLabel",
                            firstVassalRow.loyaltyLabel.GetComponent<RectTransform>());
                }
            }
        }

        private void SetUpBattalionsTable() {
            battalionsTable.RowCount = BattalionCount;

            Battalions.Each((battalion, i) => {
                var newRow = battalionsTable.ComponentAt<BattalionRowController>(i);
                newRow.Battalion = battalion;
                SetBattalionRowSelections(newRow, battalion);
            });
        }

        void Start() {
            panel.SetActive(Model != null);
            PopupClipper.Ensure(popupPanel);
            popupPanel.SetActive(false);
            if (battalionPopupPanel != null) { battalionPopupPanel.SetActive(false); }
        }

        private bool HasProvinceInfo => CurrentProvince is { FullInfo : not null };

        private int HeroCount =>
                HasProvinceInfo ? CurrentProvince.FullInfo.RulingFactionHeroIds.Count : 0;
        private IEnumerable<HeroView> Heroes =>
                HasProvinceInfo ? CurrentProvince.FullInfo.RulingFactionHeroIds
                                          .Select(id => Model.Heroes[id])
                                          .OrderByDescending(h => h, HeroComparer.Shared)
                                : new List<HeroView>();

        private int BattalionCount =>
                HasProvinceInfo ? CurrentProvince.FullInfo.Battalions.Count : 0;
        private IEnumerable<BattalionView> Battalions =>
                HasProvinceInfo ? ProvinceUtils.OrderedBattalions(CurrentProvince)
                                : new List<BattalionView>();
    }
}