/*
 * File: ShadowedRealms.Core/Models/Alliance/Alliance.cs
 * Created: 2025-10-19
 * Last Modified: 2025-10-19
 * Description: Core Alliance entity representing player organizations with territory, research, and coalition systems. Handles alliance hierarchy, progression, and KvK participation while preserving alliance independence.
 * Last Edit Notes: Added MemberCount property to resolve Repository compatibility
 */

using ShadowedRealms.Core.Interfaces;
using ShadowedRealms.Core.Models.Kingdom;
using ShadowedRealms.Core.Models.Player;
using System.ComponentModel.DataAnnotations;

namespace ShadowedRealms.Core.Models.Alliance
{
    public class Alliance : IKingdomScoped
    {
        public int Id { get; set; }

        [Required]
        [StringLength(50, MinimumLength = 3)]
        public string Name { get; set; } = string.Empty;

        [Required]
        [StringLength(5, MinimumLength = 2)]
        public string Tag { get; set; } = string.Empty;

        [Required]
        public int KingdomId { get; set; }

        [Required]
        public int LeaderId { get; set; }

        [Required]
        [Range(1, 25)]
        public int Level { get; set; } = 1;

        [Required]
        [Range(0, long.MaxValue)]
        public long Power { get; set; } = 0;

        [Required]
        [Range(0, long.MaxValue)]
        public long ExperiencePoints { get; set; } = 0;

        [Required]
        public DateTime CreatedAt { get; set; } = DateTime.UtcNow;

        [Required]
        public bool IsActive { get; set; } = true;

        [Required]
        [Range(10, 200)]
        public int MaxMembers { get; set; } = 50;

        // Alliance Description and Settings
        [StringLength(1000)]
        public string? Description { get; set; }

        [StringLength(200)]
        public string? WelcomeMessage { get; set; }

        public bool IsOpenToJoin { get; set; } = true;

        public bool RequireApproval { get; set; } = true;

        [Range(1, 30)]
        public int MinCastleLevelToJoin { get; set; } = 1;

        [Range(0, long.MaxValue)]
        public long MinPowerToJoin { get; set; } = 0;

        // Alliance Territory System
        [Range(-1000, 1000)]
        public int FortressX { get; set; } = 0;

        [Range(-1000, 1000)]
        public int FortressY { get; set; } = 0;

        [Range(1, 10)]
        public int FortressLevel { get; set; } = 1;

        [Range(0, 20)]
        public int TowerCount { get; set; } = 0;

        [Range(0, 15)]
        public int ResourceBuildingCount { get; set; } = 0;

        public bool HasTerritory { get; set; } = false;

        // Research Trees - Military Branch
        [Range(0, 50)]
        public int MilitaryAttackResearch { get; set; } = 0;

        [Range(0, 50)]
        public int MilitaryDefenseResearch { get; set; } = 0;

        [Range(0, 50)]
        public int MilitaryHealthResearch { get; set; } = 0;

        [Range(0, 50)]
        public int MilitarySpeedResearch { get; set; } = 0;

        [Range(0, 50)]
        public int MilitaryCapacityResearch { get; set; } = 0;

        // Research Trees - Economic Branch
        [Range(0, 50)]
        public int EconomicGatheringResearch { get; set; } = 0;

        [Range(0, 50)]
        public int EconomicStorageResearch { get; set; } = 0;

        [Range(0, 50)]
        public int EconomicTradeResearch { get; set; } = 0;

        [Range(0, 50)]
        public int EconomicProductionResearch { get; set; } = 0;

        [Range(0, 50)]
        public int EconomicTaxationResearch { get; set; } = 0;

        // Research Trees - Technology Branch
        [Range(0, 50)]
        public int TechnologyConstructionResearch { get; set; } = 0;

        [Range(0, 50)]
        public int TechnologyUpgradeResearch { get; set; } = 0;

        [Range(0, 50)]
        public int TechnologyTrainingResearch { get; set; } = 0;

        [Range(0, 50)]
        public int TechnologyResearchResearch { get; set; } = 0;

        [Range(0, 50)]
        public int TechnologyHealingResearch { get; set; } = 0;

        // Alliance Statistics
        [Range(0, long.MaxValue)]
        public long TotalKills { get; set; } = 0;

        [Range(0, long.MaxValue)]
        public long TotalDeaths { get; set; } = 0;

        [Range(0, long.MaxValue)]
        public long ResourcesGathered { get; set; } = 0;

        [Range(0, long.MaxValue)]
        public long ResourcesShared { get; set; } = 0;

        [Range(0, int.MaxValue)]
        public int KvKParticipations { get; set; } = 0;

        [Range(0, int.MaxValue)]
        public int KvKWins { get; set; } = 0;

        public DateTime? LastKvKParticipation { get; set; }

        // Coalition System for KvK
        public int? CurrentCoalitionId { get; set; }

        public bool IsEligibleForKvK { get; set; } = true;

        public bool AcceptsCoalitionInvites { get; set; } = true;

        [Range(0, 100)]
        public int CoalitionReputationScore { get; set; } = 50; // 0-100 scale

        // Alliance Treasury
        [Range(0, long.MaxValue)]
        public long TreasuryFood { get; set; } = 0;

        [Range(0, long.MaxValue)]
        public long TreasuryWood { get; set; } = 0;

        [Range(0, long.MaxValue)]
        public long TreasuryIron { get; set; } = 0;

        [Range(0, long.MaxValue)]
        public long TreasurySilver { get; set; } = 0;

        [Range(0, long.MaxValue)]
        public long TreasuryMithril { get; set; } = 0;

        // Navigation Properties
        public virtual Kingdom.Kingdom Kingdom { get; set; } = null!;

        public virtual Player.Player Leader { get; set; } = null!;

        public virtual ICollection<Player.Player> Members { get; set; } = new List<Player.Player>();

        public virtual ICollection<AllianceRole> Roles { get; set; } = new List<AllianceRole>();

        public virtual ICollection<AllianceInvitation> PendingInvitations { get; set; } = new List<AllianceInvitation>();

        // ADDED: Missing property that repository expects
        // This should be kept in sync with ActiveMemberCount
        public int MemberCount => ActiveMemberCount;

        // Computed Properties
        public int ActiveMemberCount => Members?.Count(m => m.IsActive) ?? 0;

        public int InactiveMemberCount => Members?.Count(m => !m.IsActive) ?? 0;

        public double AverageMemberPower => ActiveMemberCount > 0 ? (double)Power / ActiveMemberCount : 0;

        public int AverageCastleLevel => ActiveMemberCount > 0 ? (int)Members.Where(m => m.IsActive).Average(m => m.CastleLevel) : 0;

        public long ExperienceToNextLevel => CalculateExperienceForLevel(Level + 1) - ExperiencePoints;

        public bool CanLevelUp => Level < 25 && ExperiencePoints >= CalculateExperienceForLevel(Level + 1);

        public int MaxMembersForLevel => CalculateMaxMembersForLevel();

        public double KvKWinRate => KvKParticipations > 0 ? (double)KvKWins / KvKParticipations * 100 : 0;

        public AllianceHealthStatus HealthStatus => GetAllianceHealthStatus();

        public long TotalTreasuryValue => TreasuryFood + TreasuryWood + TreasuryIron + TreasurySilver + TreasuryMithril;

        public bool HasFullTerritoryControl => HasTerritory && FortressLevel >= 5 && TowerCount >= 8 && ResourceBuildingCount >= 10;

        // Research bonus calculations
        public double MilitaryAttackBonus => MilitaryAttackResearch * 0.5; // 0.5% per level

        public double MilitaryDefenseBonus => MilitaryDefenseResearch * 0.5;

        public double MilitaryHealthBonus => MilitaryHealthResearch * 0.5;

        public double MilitarySpeedBonus => MilitarySpeedResearch * 0.3;

        public double MilitaryCapacityBonus => MilitaryCapacityResearch * 1.0;

        public double EconomicGatheringBonus => EconomicGatheringResearch * 0.7;

        public double EconomicStorageBonus => EconomicStorageResearch * 1.0;

        public double EconomicTradeBonus => EconomicTradeResearch * 0.4;

        public double EconomicProductionBonus => EconomicProductionResearch * 0.6;

        public double TechnologyConstructionBonus => TechnologyConstructionResearch * 0.8;

        public double TechnologyUpgradeBonus => TechnologyUpgradeResearch * 0.6;

        public double TechnologyTrainingBonus => TechnologyTrainingResearch * 0.9;

        public double TechnologyHealingBonus => TechnologyHealingResearch * 1.2;

        // Business Logic Methods
        private long CalculateExperienceForLevel(int level)
        {
            // Exponential XP requirements: Level * Level * 1000
            return level * level * 1000L;
        }

        private int CalculateMaxMembersForLevel()
        {
            // Base 50 + 5 per level above 1
            return 50 + (Level - 1) * 5;
        }

        public bool CanAcceptNewMember()
        {
            return IsActive && IsOpenToJoin && ActiveMemberCount < Math.Min(MaxMembers, MaxMembersForLevel);
        }

        public bool MeetsMemberRequirements(Player.Player player)
        {
            if (player == null || !player.IsActive) return false;
            if (player.CastleLevel < MinCastleLevelToJoin) return false;
            if (player.Power < MinPowerToJoin) return false;
            if (player.KingdomId != KingdomId) return false;

            return true;
        }

        public void AddExperience(long xp)
        {
            ExperiencePoints += xp;

            // Auto-level up if possible
            while (CanLevelUp && Level < 25)
            {
                Level++;
                MaxMembers = MaxMembersForLevel;
            }
        }

        public void UpdatePower()
        {
            Power = Members?.Where(m => m.IsActive).Sum(m => m.Power) ?? 0;
        }

        public void UpdateStatistics()
        {
            if (Members?.Any() != true) return;

            var activeMembers = Members.Where(m => m.IsActive);

            TotalKills = activeMembers.Sum(m => m.TroopsKilled);
            TotalDeaths = activeMembers.Sum(m => m.TroopsLost);
            ResourcesGathered = activeMembers.Sum(m => m.ResourcesGathered);

            UpdatePower();
        }

        public AllianceHealthStatus GetAllianceHealthStatus()
        {
            if (!IsActive) return AllianceHealthStatus.Disbanded;

            var memberCount = ActiveMemberCount;
            var averagePower = AverageMemberPower;
            var activityRatio = memberCount > 0 ? (double)ActiveMemberCount / (ActiveMemberCount + InactiveMemberCount) : 0;

            if (memberCount < 5 || activityRatio < 0.3) return AllianceHealthStatus.Critical;
            if (memberCount < 15 || activityRatio < 0.5 || averagePower < 100000) return AllianceHealthStatus.Struggling;
            if (memberCount < 25 || activityRatio < 0.7 || averagePower < 500000) return AllianceHealthStatus.Stable;
            if (memberCount < 40 || activityRatio < 0.85 || averagePower < 1000000) return AllianceHealthStatus.Strong;

            return AllianceHealthStatus.Dominant;
        }

        public bool CanFormCoalition(Alliance otherAlliance)
        {
            if (otherAlliance == null || !otherAlliance.IsActive || !IsActive) return false;
            if (otherAlliance.KingdomId != KingdomId) return false;
            if (!IsEligibleForKvK || !otherAlliance.IsEligibleForKvK) return false;
            if (!AcceptsCoalitionInvites || !otherAlliance.AcceptsCoalitionInvites) return false;

            // Reputation threshold for coalition formation
            var combinedReputation = (CoalitionReputationScore + otherAlliance.CoalitionReputationScore) / 2;
            return combinedReputation >= 30; // Minimum 30% combined reputation
        }

        public double CalculateResearchBonus(ResearchType researchType, ResearchCategory category)
        {
            return (researchType, category) switch
            {
                (ResearchType.Military, ResearchCategory.Attack) => MilitaryAttackBonus,
                (ResearchType.Military, ResearchCategory.Defense) => MilitaryDefenseBonus,
                (ResearchType.Military, ResearchCategory.Health) => MilitaryHealthBonus,
                (ResearchType.Military, ResearchCategory.Speed) => MilitarySpeedBonus,
                (ResearchType.Military, ResearchCategory.Capacity) => MilitaryCapacityBonus,
                (ResearchType.Economic, ResearchCategory.Gathering) => EconomicGatheringBonus,
                (ResearchType.Economic, ResearchCategory.Storage) => EconomicStorageBonus,
                (ResearchType.Economic, ResearchCategory.Trade) => EconomicTradeBonus,
                (ResearchType.Economic, ResearchCategory.Production) => EconomicProductionBonus,
                (ResearchType.Technology, ResearchCategory.Construction) => TechnologyConstructionBonus,
                (ResearchType.Technology, ResearchCategory.Upgrade) => TechnologyUpgradeBonus,
                (ResearchType.Technology, ResearchCategory.Training) => TechnologyTrainingBonus,
                (ResearchType.Technology, ResearchCategory.Healing) => TechnologyHealingBonus,
                _ => 0
            };
        }

        public bool CanResearchTechnology(ResearchType type, ResearchCategory category, int currentLevel)
        {
            if (currentLevel >= 50) return false; // Max research level

            var requiredResources = CalculateResearchCost(type, category, currentLevel + 1);
            return CanAffordResources(requiredResources.Food, requiredResources.Wood,
                                    requiredResources.Iron, requiredResources.Silver, requiredResources.Mithril);
        }

        public (long Food, long Wood, long Iron, long Silver, long Mithril) CalculateResearchCost(ResearchType type, ResearchCategory category, int level)
        {
            var baseCost = level * level * 10000L; // Exponential cost scaling
            var multiplier = type switch
            {
                ResearchType.Military => 1.2,
                ResearchType.Economic => 1.0,
                ResearchType.Technology => 1.5,
                _ => 1.0
            };

            var totalCost = (long)(baseCost * multiplier);

            // Distribute cost across resources based on research type
            return type switch
            {
                ResearchType.Military => (totalCost / 2, totalCost / 4, totalCost, totalCost / 8, totalCost / 16),
                ResearchType.Economic => (totalCost, totalCost / 2, totalCost / 4, totalCost / 2, totalCost / 8),
                ResearchType.Technology => (totalCost / 4, totalCost / 2, totalCost / 2, totalCost, totalCost / 4),
                _ => (0, 0, 0, 0, 0)
            };
        }

        public bool CanAffordResources(long food, long wood, long iron, long silver, long mithril)
        {
            return TreasuryFood >= food && TreasuryWood >= wood && TreasuryIron >= iron &&
                   TreasurySilver >= silver && TreasuryMithril >= mithril;
        }

        public void ConsumeResources(long food, long wood, long iron, long silver, long mithril)
        {
            if (!CanAffordResources(food, wood, iron, silver, mithril))
                throw new InvalidOperationException("Alliance treasury has insufficient resources");

            TreasuryFood = Math.Max(0, TreasuryFood - food);
            TreasuryWood = Math.Max(0, TreasuryWood - wood);
            TreasuryIron = Math.Max(0, TreasuryIron - iron);
            TreasurySilver = Math.Max(0, TreasurySilver - silver);
            TreasuryMithril = Math.Max(0, TreasuryMithril - mithril);
        }

        public void AddToTreasury(long food, long wood, long iron, long silver, long mithril)
        {
            TreasuryFood += food;
            TreasuryWood += wood;
            TreasuryIron += iron;
            TreasurySilver += silver;
            TreasuryMithril += mithril;
        }

        public int GetTerritoryUpgradeCost(TerritoryUpgradeType upgradeType)
        {
            return upgradeType switch
            {
                TerritoryUpgradeType.Fortress => FortressLevel * 1000000,
                TerritoryUpgradeType.Tower => (TowerCount + 1) * 500000,
                TerritoryUpgradeType.ResourceBuilding => (ResourceBuildingCount + 1) * 300000,
                _ => 0
            };
        }

        public List<string> ValidateAllianceState()
        {
            var errors = new List<string>();

            if (string.IsNullOrWhiteSpace(Name) || Name.Length < 3)
                errors.Add("Alliance name must be at least 3 characters long");

            if (string.IsNullOrWhiteSpace(Tag) || Tag.Length < 2 || Tag.Length > 5)
                errors.Add("Alliance tag must be between 2 and 5 characters");

            if (Level < 1 || Level > 25)
                errors.Add("Alliance level must be between 1 and 25");

            if (MaxMembers < 10 || MaxMembers > MaxMembersForLevel)
                errors.Add($"Max members must be between 10 and {MaxMembersForLevel} for level {Level}");

            if (ActiveMemberCount > MaxMembers)
                errors.Add("Alliance has more active members than maximum allowed");

            return errors;
        }

        public override string ToString()
        {
            return $"Alliance [{Tag}] {Name} (Level {Level}, {ActiveMemberCount}/{MaxMembers} members, Power: {Power:N0})";
        }
    }

    // Supporting Classes
    public class AllianceRole
    {
        public int Id { get; set; }
        public int AllianceId { get; set; }
        public int PlayerId { get; set; }
        public AllianceRank Rank { get; set; }
        public DateTime AssignedAt { get; set; } = DateTime.UtcNow;
        public int AssignedById { get; set; }

        public virtual Alliance Alliance { get; set; } = null!;
        public virtual Player.Player Player { get; set; } = null!;
        public virtual Player.Player AssignedBy { get; set; } = null!;
    }

    public class AllianceInvitation
    {
        public int Id { get; set; }
        public int AllianceId { get; set; }
        public int PlayerId { get; set; }
        public int InvitedById { get; set; }
        public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
        public DateTime ExpiresAt { get; set; } = DateTime.UtcNow.AddDays(7);
        public bool IsAccepted { get; set; } = false;
        public bool IsRejected { get; set; } = false;

        public virtual Alliance Alliance { get; set; } = null!;
        public virtual Player.Player Player { get; set; } = null!;
        public virtual Player.Player InvitedBy { get; set; } = null!;

        public bool IsExpired => DateTime.UtcNow > ExpiresAt;
        public bool IsPending => !IsAccepted && !IsRejected && !IsExpired;
    }

    // Supporting Enums
    public enum AllianceRank
    {
        Member = 1,
        Officer = 2,
        CoLeader = 3,
        DeputyLeader = 4,
        Leader = 5
    }

    public enum AllianceHealthStatus
    {
        Disbanded = 0,
        Critical = 1,
        Struggling = 2,
        Stable = 3,
        Strong = 4,
        Dominant = 5
    }

    public enum ResearchType
    {
        Military = 1,
        Economic = 2,
        Technology = 3
    }

    public enum ResearchCategory
    {
        Attack = 1,
        Defense = 2,
        Health = 3,
        Speed = 4,
        Capacity = 5,
        Gathering = 6,
        Storage = 7,
        Trade = 8,
        Production = 9,
        Construction = 10,
        Upgrade = 11,
        Training = 12,
        Healing = 13
    }

    public enum TerritoryUpgradeType
    {
        Fortress = 1,
        Tower = 2,
        ResourceBuilding = 3
    }
}