/*
 * File: ShadowedRealms.Core/Models/Combat/CombatLog.cs
 * Created: 2025-10-19
 * Last Modified: 2025-10-19
 * Description: Combat logging system for tracking all battle activities including field interception, castle sieges, and KvK events. Provides comprehensive audit trail for combat resolution and analytics.
 * Last Edit Notes: Added IKingdomScoped interface implementation to fix repository compatibility
 */

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

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

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

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

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

        public int? AttackerAllianceId { get; set; }

        public int? DefenderAllianceId { get; set; }

        [Required]
        public CombatType CombatType { get; set; }

        [Required]
        public CombatResult Result { get; set; }

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

        // Battle Location and Context
        [Required]
        [Range(-1000, 1000)]
        public int BattleX { get; set; }

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

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

        public int? InterceptorPlayerId { get; set; }

        public InterceptionType? InterceptionType { get; set; }

        // March Information
        [Required]
        public DateTime MarchStartTime { get; set; }

        [Required]
        public DateTime MarchArrivalTime { get; set; }

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

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

        [Range(0, 10)]
        public int SpeedBoostLevel { get; set; } = 0;

        // Attacker Army Composition (before battle)
        [Required]
        [Range(0, long.MaxValue)]
        public long AttackerInfantryBefore { get; set; }

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

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

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

        [Range(1, 13)]
        public int AttackerHighestTroopTier { get; set; } = 1;

        // Attacker Army Composition (after battle)
        [Required]
        [Range(0, long.MaxValue)]
        public long AttackerInfantryAfter { get; set; }

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

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

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

        // Defender Army Composition (before battle)
        [Required]
        [Range(0, long.MaxValue)]
        public long DefenderInfantryBefore { get; set; }

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

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

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

        [Range(1, 13)]
        public int DefenderHighestTroopTier { get; set; } = 1;

        // Defender Army Composition (after battle)
        [Required]
        [Range(0, long.MaxValue)]
        public long DefenderInfantryAfter { get; set; }

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

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

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

        // Combat Statistics
        [Required]
        [Range(0, long.MaxValue)]
        public long AttackerPowerBefore { get; set; }

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

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

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

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

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

        // Dragon System Integration
        public bool AttackerHadDragon { get; set; } = false;

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

        [StringLength(100)]
        public string? AttackerDragonSkillsUsed { get; set; }

        [StringLength(100)]
        public string? DefenderDragonSkillsUsed { get; set; }

        [Range(0, 100)]
        public double AttackerDragonBonus { get; set; } = 0;

        [Range(0, 100)]
        public double DefenderDragonBonus { get; set; } = 0;

        // Resource Transfer
        [Required]
        [Range(0, long.MaxValue)]
        public long FoodTransferred { get; set; } = 0;

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

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

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

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

        // Alliance Research Bonuses Applied
        [Range(0, 100)]
        public double AttackerAllianceAttackBonus { get; set; } = 0;

        [Range(0, 100)]
        public double AttackerAllianceDefenseBonus { get; set; } = 0;

        [Range(0, 100)]
        public double AttackerAllianceHealthBonus { get; set; } = 0;

        [Range(0, 100)]
        public double DefenderAllianceAttackBonus { get; set; } = 0;

        [Range(0, 100)]
        public double DefenderAllianceDefenseBonus { get; set; } = 0;

        [Range(0, 100)]
        public double DefenderAllianceHealthBonus { get; set; } = 0;

        // KvK Context
        public bool WasKvKBattle { get; set; } = false;

        public int? KvKEventId { get; set; }

        public int? CoalitionId { get; set; }

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

        [Range(0, 100)]
        public double ForestSpeedReduction { get; set; } = 0;

        // Battle Report Data (JSON storage for detailed breakdown)
        [StringLength(4000)]
        public string? DetailedBattleReport { get; set; }

        [StringLength(1000)]
        public string? BattleNotes { get; set; }

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

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

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

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

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

        public virtual Player.Player? InterceptorPlayer { get; set; }

        // Computed Properties
        public long AttackerTotalTroopsBefore => AttackerInfantryBefore + AttackerCavalryBefore + AttackerBowmenBefore + AttackerSiegeBefore;

        public long AttackerTotalTroopsAfter => AttackerInfantryAfter + AttackerCavalryAfter + AttackerBowmenAfter + AttackerSiegeAfter;

        public long DefenderTotalTroopsBefore => DefenderInfantryBefore + DefenderCavalryBefore + DefenderBowmenBefore + DefenderSiegeBefore;

        public long DefenderTotalTroopsAfter => DefenderInfantryAfter + DefenderCavalryAfter + DefenderBowmenAfter + DefenderSiegeAfter;

        public double AttackerCasualtyRate => AttackerTotalTroopsBefore > 0 ? (double)AttackerCasualties / AttackerTotalTroopsBefore * 100 : 0;

        public double DefenderCasualtyRate => DefenderTotalTroopsBefore > 0 ? (double)DefenderCasualties / DefenderTotalTroopsBefore * 100 : 0;

        public long TotalResourcesTransferred => FoodTransferred + WoodTransferred + IronTransferred + SilverTransferred + MithrilTransferred;

        public bool WasDecisiveVictory => Result != CombatResult.Draw && (AttackerCasualtyRate < 10 || DefenderCasualtyRate < 10);

        public bool WasMajorBattle => AttackerTotalTroopsBefore + DefenderTotalTroopsBefore > 100000;

        public TimeSpan ActualMarchDuration => MarchArrivalTime - MarchStartTime;

        public double SpeedBoostEffectiveness => MarchDurationSeconds > 0 ? (double)ActualMarchDuration.TotalSeconds / MarchDurationSeconds : 1.0;

        // Business Logic Methods
        public CombatEffectivenessRating GetCombatEffectiveness(bool forAttacker = true)
        {
            var casualties = forAttacker ? AttackerCasualties : DefenderCasualties;
            var totalTroops = forAttacker ? AttackerTotalTroopsBefore : DefenderTotalTroopsBefore;
            var won = forAttacker ?
                (Result == CombatResult.AttackerVictory) :
                (Result == CombatResult.DefenderVictory);

            if (totalTroops == 0) return CombatEffectivenessRating.NoEngagement;

            var casualtyRate = (double)casualties / totalTroops * 100;

            if (won)
            {
                return casualtyRate switch
                {
                    <= 5 => CombatEffectivenessRating.Overwhelming,
                    <= 15 => CombatEffectivenessRating.Decisive,
                    <= 30 => CombatEffectivenessRating.Clear,
                    <= 50 => CombatEffectivenessRating.Narrow,
                    _ => CombatEffectivenessRating.Pyrrhic
                };
            }
            else
            {
                return casualtyRate switch
                {
                    <= 10 => CombatEffectivenessRating.ValiantDefense,
                    <= 25 => CombatEffectivenessRating.StubbornResistance,
                    <= 50 => CombatEffectivenessRating.FoughtHard,
                    <= 75 => CombatEffectivenessRating.Overwhelmed,
                    _ => CombatEffectivenessRating.Crushed
                };
            }
        }

        public TroopComposition GetAttackerArmyBefore()
        {
            return new TroopComposition
            {
                Infantry = AttackerInfantryBefore,
                Cavalry = AttackerCavalryBefore,
                Bowmen = AttackerBowmenBefore,
                Siege = AttackerSiegeBefore,
                HighestTier = AttackerHighestTroopTier
            };
        }

        public TroopComposition GetDefenderArmyBefore()
        {
            return new TroopComposition
            {
                Infantry = DefenderInfantryBefore,
                Cavalry = DefenderCavalryBefore,
                Bowmen = DefenderBowmenBefore,
                Siege = DefenderSiegeBefore,
                HighestTier = DefenderHighestTroopTier
            };
        }

        public CombatSummary GenerateCombatSummary()
        {
            return new CombatSummary
            {
                BattleType = CombatType,
                Result = Result,
                AttackerName = AttackerPlayer?.Name ?? "Unknown",
                DefenderName = DefenderPlayer?.Name ?? "Unknown",
                AttackerAlliance = AttackerAlliance?.Tag,
                DefenderAlliance = DefenderAlliance?.Tag,
                AttackerCasualties = AttackerCasualties,
                DefenderCasualties = DefenderCasualties,
                ResourcesLooted = TotalResourcesTransferred,
                WasFieldInterception = WasFieldInterception,
                BattleEffectiveness = GetCombatEffectiveness(Result == CombatResult.AttackerVictory),
                Timestamp = Timestamp
            };
        }

        public bool InvolvesAlliances()
        {
            return AttackerAllianceId.HasValue || DefenderAllianceId.HasValue;
        }

        public bool WasCrossAllianceBattle()
        {
            return AttackerAllianceId.HasValue && DefenderAllianceId.HasValue &&
                   AttackerAllianceId != DefenderAllianceId;
        }

        public void SetDetailedBattleReport(DetailedBattleReport report)
        {
            DetailedBattleReport = JsonSerializer.Serialize(report);
        }

        public DetailedBattleReport? GetDetailedBattleReport()
        {
            if (string.IsNullOrWhiteSpace(DetailedBattleReport)) return null;

            try
            {
                return JsonSerializer.Deserialize<DetailedBattleReport>(DetailedBattleReport);
            }
            catch
            {
                return null;
            }
        }

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

            if (AttackerPlayerId == DefenderPlayerId)
                errors.Add("Attacker and defender cannot be the same player");

            if (MarchStartTime >= MarchArrivalTime)
                errors.Add("March start time must be before arrival time");

            if (Timestamp < MarchStartTime)
                errors.Add("Battle timestamp cannot be before march start time");

            if (AttackerTotalTroopsBefore == 0)
                errors.Add("Attacker must have troops to engage in combat");

            if (AttackerCasualties > AttackerTotalTroopsBefore)
                errors.Add("Attacker casualties cannot exceed total troops");

            if (DefenderCasualties > DefenderTotalTroopsBefore)
                errors.Add("Defender casualties cannot exceed total troops");

            if (WasFieldInterception && !InterceptorPlayerId.HasValue)
                errors.Add("Field interception requires an interceptor player");

            if (WasKvKBattle && !KvKEventId.HasValue)
                errors.Add("KvK battle requires a KvK event ID");

            return errors;
        }

        public override string ToString()
        {
            var attackerName = AttackerPlayer?.Name ?? $"Player {AttackerPlayerId}";
            var defenderName = DefenderPlayer?.Name ?? $"Player {DefenderPlayerId}";
            var resultText = Result switch
            {
                CombatResult.AttackerVictory => $"{attackerName} defeated {defenderName}",
                CombatResult.DefenderVictory => $"{defenderName} defended against {attackerName}",
                CombatResult.Draw => $"{attackerName} vs {defenderName} ended in a draw",
                _ => "Unknown battle result"
            };

            var interceptionText = WasFieldInterception ? " (Field Interception)" : "";
            var kvkText = WasKvKBattle ? " [KvK]" : "";

            return $"{CombatType}: {resultText}{interceptionText}{kvkText}";
        }
    }

    // Supporting Classes and Data Structures
    public class TroopComposition
    {
        public long Infantry { get; set; }
        public long Cavalry { get; set; }
        public long Bowmen { get; set; }
        public long Siege { get; set; }
        public int HighestTier { get; set; }

        public long Total => Infantry + Cavalry + Bowmen + Siege;
    }

    public class CombatSummary
    {
        public CombatType BattleType { get; set; }
        public CombatResult Result { get; set; }
        public string AttackerName { get; set; } = string.Empty;
        public string DefenderName { get; set; } = string.Empty;
        public string? AttackerAlliance { get; set; }
        public string? DefenderAlliance { get; set; }
        public long AttackerCasualties { get; set; }
        public long DefenderCasualties { get; set; }
        public long ResourcesLooted { get; set; }
        public bool WasFieldInterception { get; set; }
        public CombatEffectivenessRating BattleEffectiveness { get; set; }
        public DateTime Timestamp { get; set; }
    }

    public class DetailedBattleReport
    {
        public List<BattleRound> Rounds { get; set; } = new List<BattleRound>();
        public Dictionary<string, double> AttackerBonuses { get; set; } = new Dictionary<string, double>();
        public Dictionary<string, double> DefenderBonuses { get; set; } = new Dictionary<string, double>();
        public string? SpecialEvents { get; set; }
        public TimeSpan BattleDuration { get; set; }
    }

    public class BattleRound
    {
        public int RoundNumber { get; set; }
        public long AttackerDamageDealt { get; set; }
        public long DefenderDamageDealt { get; set; }
        public long AttackerCasualties { get; set; }
        public long DefenderCasualties { get; set; }
        public string? SpecialEffects { get; set; }
    }

    // Supporting Enums
    public enum CombatType
    {
        LightningRaid = 1,      // Unrestricted speed, small force
        StandardAttack = 2,     // Normal restrictions
        CastleSiege = 3,        // Fully restricted, large force
        ResourceGathering = 4,  // Attacking resource nodes
        AllianceWarfare = 5,    // Alliance vs Alliance
        KvKBattle = 6,         // Kingdom vs Kingdom
        DefensiveBattle = 7,   // Defending castle/territory
        FieldInterception = 8  // Meeting attackers before they reach target
    }

    public enum CombatResult
    {
        AttackerVictory = 1,
        DefenderVictory = 2,
        Draw = 3,
        AttackerWithdrew = 4,
        DefenderFled = 5
    }

    public enum InterceptionType
    {
        AutomaticDefense = 1,  // System-triggered interception
        ManualIntercept = 2,   // Player-initiated interception
        AllianceSupport = 3,   // Alliance member intercepting
        CoalitionDefense = 4   // Coalition member intercepting (KvK)
    }

    public enum CombatEffectivenessRating
    {
        NoEngagement = 0,
        Crushed = 1,
        Overwhelmed = 2,
        FoughtHard = 3,
        StubbornResistance = 4,
        ValiantDefense = 5,
        Pyrrhic = 6,
        Narrow = 7,
        Clear = 8,
        Decisive = 9,
        Overwhelming = 10
    }
}