/*
 * File: ShadowedRealms.Core/Models/Player/Player.cs
 * Created: 2025-10-19
 * Last Modified: 2025-10-19
 * Description: Core Player entity representing a game player with castle, resources, troops, and progression systems. Handles player statistics, alliance membership, and combat capabilities.
 * Last Edit Notes: Initial creation with castle progression, resource management, troop systems, and alliance integration
 */

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

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

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

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

        public int? AllianceId { get; set; }

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

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

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

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

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

        // Coordinates
        [Required]
        [Range(-1000, 1000)]
        public int CoordinateX { get; set; } = 0;

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

        // Resources
        [Required]
        [Range(0, long.MaxValue)]
        public long Food { get; set; } = 50000;

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

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

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

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

        // Protected storage (cannot be raided)
        [Required]
        [Range(0, long.MaxValue)]
        public long FoodProtected { get; set; } = 0;

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

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

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

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

        // Premium Currency
        [Required]
        [Range(0, int.MaxValue)]
        public int Gold { get; set; } = 100; // Starting gold

        // Troops - Tier 1 through Tier 13 (T1-T13)
        [Required]
        [Range(0, long.MaxValue)]
        public long InfantryT1 { get; set; } = 0;

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

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

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

        // Higher tier troops (T2-T13) - will be unlocked based on castle level
        [Required]
        [Range(0, long.MaxValue)]
        public long InfantryT2 { get; set; } = 0;

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

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

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

        // T3 Troops
        [Required]
        [Range(0, long.MaxValue)]
        public long InfantryT3 { get; set; } = 0;

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

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

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

        // T4-T10 Troops (Launch maximum is T10 at Castle 30)
        [Required]
        [Range(0, long.MaxValue)]
        public long InfantryT4 { get; set; } = 0;

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

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

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

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

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

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

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

        // T6-T10 (continuing pattern for space efficiency)
        [Required]
        [Range(0, long.MaxValue)]
        public long InfantryT10 { get; set; } = 0;

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

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

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

        // Post-launch expansion troops (T11-T13)
        [Required]
        [Range(0, long.MaxValue)]
        public long InfantryT11 { get; set; } = 0;

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

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

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

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

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

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

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

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

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

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

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

        // Player Statistics
        [Required]
        [Range(0, long.MaxValue)]
        public long AttacksWon { get; set; } = 0;

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

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

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

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

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

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

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

        // Player Settings
        public bool AcceptAllianceInvites { get; set; } = true;
        public bool ShowOnlineStatus { get; set; } = true;
        public bool EnablePushNotifications { get; set; } = true;
        public bool AutoUseSpeedBoosts { get; set; } = false;

        [StringLength(500)]
        public string? Biography { get; set; }

        // VIP and Premium Status
        [Range(0, 15)]
        public int VipLevel { get; set; } = 0;

        public DateTime? VipExpiryDate { get; set; }

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

        public DateTime? DragonExpiryDate { get; set; }

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

        public virtual Alliance.Alliance? Alliance { get; set; }

        // Computed properties
        public bool IsVipActive => VipExpiryDate.HasValue && VipExpiryDate.Value > DateTime.UtcNow;

        public bool IsDragonActive => HasActiveDragon && DragonExpiryDate.HasValue && DragonExpiryDate.Value > DateTime.UtcNow;

        public int DaysInactive => (DateTime.UtcNow - LastActiveAt).Days;

        public bool IsInactive => DaysInactive > 7;

        public bool IsCriticallyInactive => DaysInactive > 30;

        public long TotalTroops => GetTotalTroopsByType(TroopType.All);

        public long TotalResources => Food + Wood + Iron + Silver + Mithril;

        public long TotalProtectedResources => FoodProtected + WoodProtected + IronProtected + SilverProtected + MithrilProtected;

        public long TotalRaidableResources => TotalResources - TotalProtectedResources;

        public int MaxTroopTier => GetMaxUnlockedTroopTier();

        public PlayerRankStatus RankStatus => GetPlayerRankStatus();

        public double WinRate
        {
            get
            {
                var totalBattles = AttacksWon + AttacksLost + DefensesWon + DefensesLost;
                if (totalBattles == 0) return 0;
                var totalWins = AttacksWon + DefensesWon;
                return (double)totalWins / totalBattles * 100;
            }
        }

        public double KillDeathRatio => TroopsLost > 0 ? (double)TroopsKilled / TroopsLost : TroopsKilled;

        // Business logic methods
        public long GetTotalTroopsByType(TroopType troopType)
        {
            return troopType switch
            {
                TroopType.Infantry => InfantryT1 + InfantryT2 + InfantryT3 + InfantryT4 + InfantryT5 + InfantryT10 + InfantryT11 + InfantryT12 + InfantryT13,
                TroopType.Cavalry => CavalryT1 + CavalryT2 + CavalryT3 + CavalryT4 + CavalryT5 + CavalryT10 + CavalryT11 + CavalryT12 + CavalryT13,
                TroopType.Bowmen => BowmenT1 + BowmenT2 + BowmenT3 + BowmenT4 + BowmenT5 + BowmenT10 + BowmenT11 + BowmenT12 + BowmenT13,
                TroopType.Siege => SiegeT1 + SiegeT2 + SiegeT3 + SiegeT4 + SiegeT5 + SiegeT10 + SiegeT11 + SiegeT12 + SiegeT13,
                TroopType.All => GetTotalTroopsByType(TroopType.Infantry) + GetTotalTroopsByType(TroopType.Cavalry) + GetTotalTroopsByType(TroopType.Bowmen) + GetTotalTroopsByType(TroopType.Siege),
                _ => 0
            };
        }

        public int GetMaxUnlockedTroopTier()
        {
            // Based on castle level - launch parameters (T10 max at Castle 30)
            return CastleLevel switch
            {
                >= 44 => 13, // Post-launch: T13 at Castle 44
                >= 40 => 12, // Post-launch: T12 at Castle 40
                >= 35 => 11, // Post-launch: T11 at Castle 35
                >= 30 => 10, // Launch: T10 at Castle 30
                >= 27 => 9,
                >= 24 => 8,
                >= 21 => 7,
                >= 18 => 6,
                >= 15 => 5,
                >= 12 => 4,
                >= 9 => 3,
                >= 6 => 2,
                _ => 1      // T1 troops available from start
            };
        }

        public bool CanTrainTroopTier(int tier)
        {
            return tier <= GetMaxUnlockedTroopTier();
        }

        public long CalculateStorageCapacity()
        {
            // Base storage increases with castle level
            var baseCapacity = CastleLevel * 100000L; // 100k per castle level
            var vipBonus = IsVipActive ? (long)(baseCapacity * (VipLevel * 0.05)) : 0; // 5% per VIP level
            return baseCapacity + vipBonus;
        }

        public long CalculateProtectedStorage()
        {
            // Protected storage is 25% of total capacity, increased by VIP
            var baseProtected = CalculateStorageCapacity() * 0.25;
            var vipBonus = IsVipActive ? baseProtected * (VipLevel * 0.02) : 0; // 2% per VIP level
            return (long)(baseProtected + vipBonus);
        }

        public bool CanAffordResources(long food, long wood, long iron, long silver, long mithril)
        {
            return Food >= food && Wood >= wood && Iron >= iron && Silver >= silver && Mithril >= mithril;
        }

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

            Food = Math.Max(0, Food - food);
            Wood = Math.Max(0, Wood - wood);
            Iron = Math.Max(0, Iron - iron);
            Silver = Math.Max(0, Silver - silver);
            Mithril = Math.Max(0, Mithril - mithril);
        }

        public void AddResources(long food, long wood, long iron, long silver, long mithril)
        {
            var capacity = CalculateStorageCapacity();

            Food = Math.Min(capacity, Food + food);
            Wood = Math.Min(capacity, Wood + wood);
            Iron = Math.Min(capacity, Iron + iron);
            Silver = Math.Min(capacity, Silver + silver);
            Mithril = Math.Min(capacity, Mithril + mithril);
        }

        public PlayerRankStatus GetPlayerRankStatus()
        {
            return CastleLevel switch
            {
                >= 40 => PlayerRankStatus.Legendary,
                >= 35 => PlayerRankStatus.Epic,
                >= 30 => PlayerRankStatus.Elite,
                >= 25 => PlayerRankStatus.Veteran,
                >= 20 => PlayerRankStatus.Advanced,
                >= 15 => PlayerRankStatus.Intermediate,
                >= 10 => PlayerRankStatus.Novice,
                _ => PlayerRankStatus.Beginner
            };
        }

        public void UpdateLastActive()
        {
            LastActiveAt = DateTime.UtcNow;
            if (!IsActive) IsActive = true;
        }

        public bool CanJoinAlliance(Alliance.Alliance alliance)
        {
            if (alliance == null || !alliance.IsActive) return false;
            if (AllianceId.HasValue) return false; // Already in alliance
            if (alliance.KingdomId != KingdomId) return false; // Different kingdom
            if (alliance.Members.Count >= alliance.MaxMembers) return false; // Alliance full

            return true;
        }

        public void CalculatePower()
        {
            // Power calculation based on troops, castle level, and resources
            var troopPower = TotalTroops * 10; // Base 10 power per troop
            var castlePower = CastleLevel * CastleLevel * 1000L; // Exponential castle power
            var resourcePower = TotalResources / 1000; // 1 power per 1k resources

            Power = troopPower + castlePower + resourcePower;
        }

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

            if (CastleLevel < 1 || CastleLevel > 44)
                errors.Add("Castle level must be between 1 and 44");

            if (CoordinateX < -1000 || CoordinateX > 1000 || CoordinateY < -1000 || CoordinateY > 1000)
                errors.Add("Coordinates must be within map boundaries (-1000 to 1000)");

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

            var storageCapacity = CalculateStorageCapacity();
            if (TotalResources > storageCapacity * 1.1) // Allow 10% overflow
                errors.Add("Resource storage significantly exceeded");

            return errors;
        }

        public override string ToString()
        {
            return $"Player {Name} (Castle {CastleLevel}, Power: {Power:N0})";
        }
    }

    // Supporting enums
    public enum TroopType
    {
        Infantry = 1,
        Cavalry = 2,
        Bowmen = 3,
        Siege = 4,
        All = 99
    }

    public enum PlayerRankStatus
    {
        Beginner = 1,
        Novice = 2,
        Intermediate = 3,
        Advanced = 4,
        Veteran = 5,
        Elite = 6,
        Epic = 7,
        Legendary = 8
    }
}