using System;
using System.Collections.Generic;
using System.Linq;
using EagleGUIUtils;
using Net.Eagle0.Eagle.Api;
using Net.Eagle0.Eagle.Common;
using Net.Eagle0.Eagle.Views;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

namespace eagle {
    using ProvinceId = Int32;
    using HeroId = Int32;

    public class ImproveCommandSelector : CommandSelector {
        public HeroDropdownController heroDropdownController;
        public Toggle lockToggle;

        // Toggle buttons for each improvement type (assign to same ToggleGroup in Unity)
        public Toggle economyToggle;
        public Toggle agricultureToggle;
        public Toggle infrastructureToggle;
        public Toggle devastationToggle;
        public ToggleGroup improvementToggleGroup;

        // Labels showing type name and value
        public TMP_Text economyLabel;
        public TMP_Text agricultureLabel;
        public TMP_Text infrastructureLabel;
        public TMP_Text devastationLabel;

        List<HeroView> orderedHeroes;

        private ImproveAvailableCommand ImproveAvailableCommand => _availableCommand.ImproveCommand;
        private ProvinceId ActingProvinceId => ImproveAvailableCommand.ActingProvinceId;

        private ImprovementType SelectedType {
            get {
                if (economyToggle != null && economyToggle.isOn && economyToggle.interactable)
                    return ImprovementType.Economy;
                if (agricultureToggle != null && agricultureToggle.isOn &&
                    agricultureToggle.interactable)
                    return ImprovementType.Agriculture;
                if (infrastructureToggle != null && infrastructureToggle.isOn &&
                    infrastructureToggle.interactable)
                    return ImprovementType.Infrastructure;
                if (devastationToggle != null && devastationToggle.isOn &&
                    devastationToggle.interactable)
                    return ImprovementType.Devastation;

                // Fallback: return first available type
                return ImproveAvailableCommand.AvailableTypes.FirstOrDefault();
            }
        }

        private float OriginalImprovementValueForType(ImprovementType type) {
            var province = _model.Provinces[ActingProvinceId];
            switch (type) {
                case ImprovementType.Agriculture: return province.FullInfo.Agriculture;
                case ImprovementType.Economy: return province.FullInfo.Economy;
                case ImprovementType.Infrastructure: return province.FullInfo.Infrastructure;
                case ImprovementType.Devastation:
                    return province.FullInfo.EconomyDevastation +
                           province.FullInfo.AgricultureDevastation +
                           province.FullInfo.InfrastructureDevastation;
                default: throw new InvalidOperationException($"unknown type {type}");
            }
        }

        private float EffectiveImprovementValueForType(ImprovementType type) {
            var province = _model.Provinces[ActingProvinceId];
            switch (type) {
                case ImprovementType.Agriculture:
                    return province.FullInfo.Agriculture - province.FullInfo.AgricultureDevastation;
                case ImprovementType.Economy:
                    return province.FullInfo.Economy - province.FullInfo.EconomyDevastation;
                case ImprovementType.Infrastructure:
                    return province.FullInfo.Infrastructure -
                           province.FullInfo.InfrastructureDevastation;
                case ImprovementType.Devastation:
                    return province.FullInfo.EconomyDevastation +
                           province.FullInfo.AgricultureDevastation +
                           province.FullInfo.InfrastructureDevastation;
                default: throw new InvalidOperationException($"unknown type {type}");
            }
        }

        private ImprovementType GetMinimumImprovementType() {
            ImprovementType minType = ImproveAvailableCommand.AvailableTypes[0];
            float minValue = OriginalImprovementValueForType(minType);
            for (int i = 1; i < ImproveAvailableCommand.AvailableTypes.Count; i++) {
                var thisType = ImproveAvailableCommand.AvailableTypes[i];
                float thisVal = OriginalImprovementValueForType(thisType);
                if (thisVal < minValue) {
                    minType = thisType;
                    minValue = thisVal;
                }
            }
            return minType;
        }

        private ImprovementType GetDefaultImprovementType() {
            // Prefer devastation if available
            if (ImproveAvailableCommand.AvailableTypes.Contains(ImprovementType.Devastation)) {
                return ImprovementType.Devastation;
            }

            // Otherwise pick the lowest stat
            return GetMinimumImprovementType();
        }

        private Toggle GetToggleForType(ImprovementType type) {
            switch (type) {
                case ImprovementType.Economy: return economyToggle;
                case ImprovementType.Agriculture: return agricultureToggle;
                case ImprovementType.Infrastructure: return infrastructureToggle;
                case ImprovementType.Devastation: return devastationToggle;
                default: return null;
            }
        }

        private TMP_Text GetLabelForType(ImprovementType type) {
            switch (type) {
                case ImprovementType.Economy: return economyLabel;
                case ImprovementType.Agriculture: return agricultureLabel;
                case ImprovementType.Infrastructure: return infrastructureLabel;
                case ImprovementType.Devastation: return devastationLabel;
                default: return null;
            }
        }

        private void SelectType(ImprovementType type) {
            // Turn on the selected toggle - ToggleGroup handles turning off others
            var toggle = GetToggleForType(type);
            if (toggle != null && toggle.interactable) { toggle.isOn = true; }
        }

        private const float DisabledAlpha = 0.35f;

        private void ConfigureToggle(ImprovementType type, bool available) {
            var toggle = GetToggleForType(type);
            var label = GetLabelForType(type);

            if (toggle == null) return;

            // Always show the toggle, but disable if not available
            toggle.gameObject.SetActive(true);
            toggle.interactable = available;

            // Turn off unavailable toggles so they don't appear selected
            if (!available) { toggle.isOn = false; }

            // Only add to toggle group if available
            toggle.group = available ? improvementToggleGroup : null;

            // Gray out unavailable toggles using CanvasGroup
            var canvasGroup = toggle.GetComponent<CanvasGroup>();
            if (canvasGroup == null) {
                canvasGroup = toggle.gameObject.AddComponent<CanvasGroup>();
            }
            canvasGroup.alpha = available ? 1f : DisabledAlpha;

            // Always show label with current value
            if (label != null) { label.text = LabelStringForType(type); }
        }

        private string LabelStringForType(ImprovementType type) {
            var originalStat =
                    type == ImprovementType.Devastation
                            ? ProvinceStatUtils.RoundedDevastation(
                                      OriginalImprovementValueForType(type))
                            : ProvinceStatUtils.RoundedStat(OriginalImprovementValueForType(type));
            if (type == ImprovementType.Devastation) {
                return GUIUtils.ColoredString(Color.red, originalStat.ToString());
            }
            var devastatedStat =
                    ProvinceStatUtils.RoundedStat(EffectiveImprovementValueForType(type));
            if (devastatedStat == originalStat) {
                return $"{devastatedStat}";
            } else {
                return $"{GUIUtils.ColoredString(Color.red, devastatedStat.ToString())} / {originalStat}";
            }
        }

        protected override void SetUpUI() {
            var improveCommand = ImproveAvailableCommand;

            orderedHeroes = ImproveAvailableCommand.AvailableHeroIds.Select(id => _model.Heroes[id])
                                    .ToList();
            heroDropdownController.AvailableHeroes = orderedHeroes;
            heroDropdownController.SelectedHeroId = improveCommand.RecommendedHeroId;

            // Configure each toggle based on available types
            ConfigureToggle(
                    ImprovementType.Economy,
                    improveCommand.AvailableTypes.Contains(ImprovementType.Economy));
            ConfigureToggle(
                    ImprovementType.Agriculture,
                    improveCommand.AvailableTypes.Contains(ImprovementType.Agriculture));
            ConfigureToggle(
                    ImprovementType.Infrastructure,
                    improveCommand.AvailableTypes.Contains(ImprovementType.Infrastructure));
            ConfigureToggle(
                    ImprovementType.Devastation,
                    improveCommand.AvailableTypes.Contains(ImprovementType.Devastation));

            // Determine which type to select
            ImprovementType selectedType;
            if (improveCommand.LockedType != ImprovementType.None) {
                var lockedType = improveCommand.LockedType;
                if (improveCommand.AvailableTypes.Contains(lockedType)) {
                    selectedType = lockedType;
                    lockToggle.isOn = true;
                } else {
                    selectedType = GetDefaultImprovementType();
                    lockToggle.isOn = false;
                }
            } else {
                selectedType = GetDefaultImprovementType();
                lockToggle.isOn = false;
            }

            SelectType(selectedType);
        }

        public override AvailableCommand.SealedValueOneofCase CommandType =>
                AvailableCommand.SealedValueOneofCase.ImproveCommand;
        public override string HeaderString => "Improve Province";
        public override string CommitButtonString => "Commit Improvement";

        public override List<HeroId> TargetedHeroIds =>
                new() { heroDropdownController.SelectedHeroId };
        public override bool HeroIsTargetable(HeroId heroId) {
            var index = orderedHeroes.FindIndex(h => h.Id == heroId);
            return index != -1;
        }

        public override void AddTargetedHero(int heroId) {
            heroDropdownController.SelectedHeroId = heroId;
        }

        public override SelectedCommand Command => new SelectedCommand {
            ImproveCommand =
                    new ImproveSelectedCommand {
                        ImprovementType = SelectedType,
                        ActingHeroId = heroDropdownController.SelectedHeroId,
                        LockType = lockToggle.isOn
                    }
        };
    }
}
