/*
 * File: D:\shadowed-realms-mobile\ShadowedRealmsMobile\src\server\ShadowedRealms.API\Controllers\Combat\CombatController.cs
 * Created: 2025-10-19
 * Last Modified: 2025-10-25
 * Description: Comprehensive REST API controller for combat operations including field interception system (core innovation), 
 *              battle resolution, march mechanics, dragon integration, and anti-pay-to-win balance.
 * Last Edit Notes: Fixed all compilation errors by matching ICombatService interface methods and actual DTO properties
 */

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using ShadowedRealms.Core.Interfaces.Services;
using ShadowedRealms.Shared.DTOs.Combat;
using ShadowedRealms.Shared.DTOs.Common;
using System.Security.Claims;

namespace ShadowedRealms.API.Controllers.Combat
{
    /// <summary>
    /// REST API controller for comprehensive combat operations including field interception system
    /// </summary>
    [ApiController]
    [Route("api/v1/combat")]
    [Authorize] // JWT authentication required for all combat operations
    [Produces("application/json")]
    [ProducesResponseType(typeof(ErrorResponseDto), 400)]
    [ProducesResponseType(typeof(ErrorResponseDto), 401)]
    [ProducesResponseType(typeof(ErrorResponseDto), 403)]
    [ProducesResponseType(typeof(ErrorResponseDto), 500)]
    public class CombatController : ControllerBase
    {
        private readonly ICombatService _combatService;
        private readonly ILogger<CombatController> _logger;

        public CombatController(
            ICombatService combatService,
            ILogger<CombatController> logger)
        {
            _combatService = combatService ?? throw new ArgumentNullException(nameof(combatService));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        #region Field Interception System (Core Innovation)

        /// <summary>
        /// Calculates available field interception opportunities for defending players
        /// </summary>
        /// <param name="request">Interception calculation parameters including attacking march details</param>
        /// <returns>All available interception opportunities with timing and positioning data</returns>
        [HttpPost("field-interception/calculate")]
        [ProducesResponseType(typeof(InterceptionOpportunitiesResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> CalculateInterceptionOpportunities([FromBody] InterceptionCalculationRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid interception calculation request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                // Convert the route to the format expected by the service
                var attackRouteDict = new Dictionary<string, object>
                {
                    ["RoutePoints"] = request.AttackRoute.Select(point => new { X = point.X, Y = point.Y }).ToList(),
                    ["EstimatedArrival"] = request.EstimatedArrivalTime,
                    ["CalculationParameters"] = request.CalculationParameters ?? new Dictionary<string, object>()
                };

                var opportunities = await _combatService.CalculateInterceptionOpportunitiesAsync(
                    request.AttackingPlayerId, playerId, kingdomId, attackRouteDict);

                var response = new InterceptionOpportunitiesResponseDto
                {
                    DefendingPlayerId = playerId,
                    AttackingPlayerId = request.AttackingPlayerId,
                    InterceptionOpportunities = opportunities,
                    CalculationTime = DateTime.UtcNow
                };

                _logger.LogInformation("Interception opportunities calculated for Player {PlayerId} defending against Player {AttackingPlayerId}",
                    playerId, request.AttackingPlayerId);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error calculating interception opportunities for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to calculate interception opportunities",
                    Code = "INTERCEPTION_CALCULATION_ERROR"
                });
            }
        }

        /// <summary>
        /// Executes field interception attempt with defender troops meeting attacker before castle siege
        /// </summary>
        /// <param name="request">Field interception execution parameters</param>
        /// <returns>Interception execution result and battle initiation details</returns>
        [HttpPost("field-interception/execute")]
        [ProducesResponseType(typeof(FieldInterceptionResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        [ProducesResponseType(typeof(ErrorResponseDto), 409)] // Conflict - interception conditions not met
        public async Task<IActionResult> ExecuteFieldInterception([FromBody] FieldInterceptionRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid field interception request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var (success, battleSetup, battleStartTime) = await _combatService.ExecuteFieldInterceptionAsync(
                    playerId, request.AttackingPlayerId, kingdomId,
                    (request.InterceptionPoint.X, request.InterceptionPoint.Y), request.DefenderTroops);

                if (!success)
                {
                    return Conflict(new ErrorResponseDto
                    {
                        Message = "Field interception failed - timing window missed or insufficient troops",
                        Code = "INTERCEPTION_FAILED"
                    });
                }

                var response = new FieldInterceptionResponseDto
                {
                    DefenderId = playerId,  // Changed from DefendingPlayerId
                    AttackerId = request.AttackingPlayerId,  // Changed from AttackingPlayerId
                    InterceptionPositions = new List<Dictionary<string, object>> { battleSetup }, // Changed from InterceptionPoint and BattleSetup
                    InterceptionSuccess = success,  // Changed from Success
                    CalculationTime = battleStartTime  // Changed from InterceptionStartTime
                };

                _logger.LogInformation("Field interception executed successfully - Player {DefenderId} intercepted Player {AttackerId} at ({X}, {Y})",
                    playerId, request.AttackingPlayerId, request.InterceptionPoint.X, request.InterceptionPoint.Y);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error executing field interception for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to execute field interception",
                    Code = "INTERCEPTION_EXECUTION_ERROR"
                });
            }
        }

        /// <summary>
        /// Validates field interception attempt with comprehensive requirement checking
        /// </summary>
        /// <param name="request">Interception validation parameters</param>
        /// <returns>Validation result with requirements, timing, and restrictions</returns>
        [HttpPost("field-interception/validate")]
        [ProducesResponseType(typeof(InterceptionValidationResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> ValidateFieldInterception([FromBody] InterceptionValidationRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid interception validation request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                // Extract coordinates from the request
                var coordinates = (
                    X: (int)request.InterceptionCoordinates.GetValueOrDefault("X", 0),
                    Y: (int)request.InterceptionCoordinates.GetValueOrDefault("Y", 0)
                );

                var (canIntercept, requirements, timing, restrictions) =
                    await _combatService.ValidateFieldInterceptionAsync(
                        playerId, request.TargetMarchId, kingdomId, coordinates);

                var response = new InterceptionValidationResponseDto
                {
                    InterceptorId = playerId,  // Changed from PlayerId
                    IsValid = canIntercept,  // Changed from CanIntercept
                    ValidationErrors = requirements.Concat(restrictions).ToList(), // Changed from ValidationRequirements
                    SpeedRequirements = timing,  // Changed from TimingDetails
                    ValidationMetadata = new Dictionary<string, object> // Changed from ValidationRestrictions
                    {
                        ["Restrictions"] = restrictions
                    }
                };

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error validating field interception for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to validate field interception",
                    Code = "INTERCEPTION_VALIDATION_ERROR"
                });
            }
        }

        /// <summary>
        /// Calculates optimal interception routes with multiple strategic options
        /// </summary>
        /// <param name="request">Route optimization parameters</param>
        /// <returns>Optimized interception routes with strategic analysis</returns>
        [HttpPost("field-interception/optimize-routes")]
        [ProducesResponseType(typeof(OptimalRoutesResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> CalculateOptimalInterceptionRoutes([FromBody] RouteOptimizationRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid route optimization request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var attackRouteDict = new Dictionary<string, object>
                {
                    ["RoutePoints"] = request.StartCoordinates,  // Changed from AttackRoute
                    ["OptimizationParameters"] = request.OptimizationPreferences ?? new Dictionary<string, object>()  // Changed from OptimizationParameters
                };

                var optimalRoutes = await _combatService.CalculateOptimalInterceptionRoutesAsync(
                    playerId, attackRouteDict, kingdomId);

                var response = new OptimalRoutesResponseDto
                {
                    PlayerId = playerId,
                    StartCoordinates = request.StartCoordinates,  // Changed from AttackRoute
                    AlternativeRoutes = new List<Dictionary<string, object>> { optimalRoutes }, // Changed from OptimalRoutes
                    RouteAnalysis = new Dictionary<string, object>()  // Changed from RecommendedInterceptionPoints
                };

                _logger.LogInformation("Optimal interception routes calculated for Player {PlayerId}", playerId);
                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error calculating optimal interception routes for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to calculate optimal routes",
                    Code = "ROUTE_OPTIMIZATION_ERROR"
                });
            }
        }

        #endregion

        #region March Mechanics

        /// <summary>
        /// Initiates combat march with speed calculations and grace periods
        /// </summary>
        /// <param name="request">March initiation parameters including troops and target</param>
        /// <returns>March initiation result with timing and arrival details</returns>
        [HttpPost("march/initiate")]
        [ProducesResponseType(typeof(MarchInitiationResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        [ProducesResponseType(typeof(ErrorResponseDto), 409)] // Conflict - insufficient troops or invalid target
        public async Task<IActionResult> InitiateMarch([FromBody] MarchInitiationRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid march initiation request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var targetCoords = (
                    X: (int)request.Destination.X,  // Changed from TargetCoordinates
                    Y: (int)request.Destination.Y
                );

                var (success, marchId, estimatedArrival, marchDetails) =
                    await _combatService.InitiateCombatMarchAsync(
                        playerId, kingdomId, targetCoords,
                        request.Troops, request.MarchType, request.DragonDetails != null);  // Changed from TroopComposition, DragonEquipped

                if (!success)
                {
                    return Conflict(new ErrorResponseDto
                    {
                        Message = "March initiation failed - insufficient troops, invalid target, or march limit reached",
                        Code = "MARCH_FAILED"
                    });
                }

                var response = new MarchInitiationResponseDto
                {
                    PlayerId = playerId,
                    MarchId = int.TryParse(marchId, out int parsedMarchId) ? parsedMarchId : 0, // Fixed string-to-int conversion
                    MarchTarget = new Dictionary<string, object> { ["Destination"] = request.Destination },
                    MarchingTroops = request.Troops.ToDictionary(t => t.Key, t => (long)t.Value),
                    MarchMetadata = marchDetails
                };

                _logger.LogInformation("March initiated successfully for Player {PlayerId} - March ID: {MarchId}, Target: ({X}, {Y})",
                    playerId, marchId, targetCoords.X, targetCoords.Y);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error initiating march for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to initiate march",
                    Code = "MARCH_INITIATION_ERROR"
                });
            }
        }

        /// <summary>
        /// Calculates march speed with diminishing returns and bonus factors
        /// </summary>
        /// <param name="request">Speed calculation parameters</param>
        /// <returns>Detailed march speed calculation with all modifiers</returns>
        [HttpPost("march/calculate-speed")]
        [ProducesResponseType(typeof(MarchSpeedResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> CalculateMarchSpeed([FromBody] MarchSpeedRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid march speed calculation request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var speedCalculation = await _combatService.CalculateMarchSpeedAsync(
                    request.ArmyComposition.ToDictionary(t => t.Key, t => (int)t.Value), // Fixed type conversion
                    (double)request.SpeedParameters.GetValueOrDefault("Distance", 100.0), // Fixed type conversion
                    (int)request.SpeedParameters.GetValueOrDefault("PlayerVipTier", 0), // Fixed type conversion
                    new Dictionary<string, double>(),
                    request.DragonSpeedSkills.Count > 0 ? 10.0 : 0.0);

                var response = new MarchSpeedResponseDto
                {
                    // Removed PlayerId - it doesn't exist in the DTO
                    BaseSpeed = (decimal)speedCalculation.GetValueOrDefault("BaseSpeed", 0.0),
                    FinalSpeed = (decimal)speedCalculation.GetValueOrDefault("FinalSpeed", 0.0),
                    SpeedModifiers = speedCalculation.GetValueOrDefault("SpeedModifiers", new Dictionary<string, object>()) is Dictionary<string, object> speedMods ?
                        speedMods.ToDictionary(kvp => kvp.Key, kvp => (decimal)Convert.ToDouble(kvp.Value ?? 0)) :
                        new Dictionary<string, decimal>(),
                    EstimatedTravelTime = (TimeSpan)speedCalculation.GetValueOrDefault("EstimatedTravelTime", TimeSpan.Zero),
                    MovementRestrictions = new List<string>(), // Add this property that exists
                    CalculatedAt = DateTime.UtcNow
                };

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error calculating march speed for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to calculate march speed",
                    Code = "SPEED_CALCULATION_ERROR"
                });
            }
        }

        /// <summary>
        /// Cancels active march with appropriate penalties
        /// </summary>
        /// <param name="marchId">March identifier to cancel</param>
        /// <returns>March cancellation result with penalties applied</returns>
        [HttpPost("march/{marchId}/cancel")]
        [ProducesResponseType(typeof(MarchCancellationResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        [ProducesResponseType(typeof(ErrorResponseDto), 404)] // March not found
        public async Task<IActionResult> CancelMarch(string marchId)
        {
            try
            {
                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var (success, penalties, troopReturnTime) =
                    await _combatService.CancelMarchAsync(marchId, playerId, kingdomId);

                if (!success)
                {
                    return NotFound(new ErrorResponseDto
                    {
                        Message = "March not found or cannot be cancelled",
                        Code = "MARCH_NOT_FOUND"
                    });
                }

                var response = new MarchCancellationResponseDto
                {
                    PlayerId = playerId,
                    MarchId = int.TryParse(marchId, out int cancelMarchId) ? cancelMarchId : 0,
                    CancellationTime = DateTime.UtcNow,
                    // Use actual DTO properties:
                    ResourcesLost = penalties.ContainsKey("ResourcePenalty") ?
        new Dictionary<string, long> { ["General"] = 100 } : new Dictionary<string, long>(), // Changed from CancellationPenalties
                    TroopsReturned = new Dictionary<string, long>(), // Changed from TroopReturnETA  
                    CancellationSuccess = success, // Use actual property name
                    CancellationMetadata = new Dictionary<string, object> { ["Penalties"] = penalties } // For additional data
                };

                _logger.LogInformation("March cancelled successfully for Player {PlayerId} - March ID: {MarchId}",
                    playerId, marchId);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error cancelling march for Player {PlayerId}, March: {MarchId}",
                    GetAuthenticatedPlayer().PlayerId, marchId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to cancel march",
                    Code = "MARCH_CANCELLATION_ERROR"
                });
            }
        }

        /// <summary>
        /// Processes march arrival and initiates combat engagement
        /// </summary>
        /// <param name="request">March arrival processing parameters</param>
        /// <returns>Arrival processing result with combat initiation</returns>
        [HttpPost("march/process-arrival")]
        [ProducesResponseType(typeof(MarchArrivalResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> ProcessMarchArrival([FromBody] MarchArrivalRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid march arrival request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var arrivalResult = await _combatService.ProcessMarchArrivalAsync(request.MarchId.ToString(), kingdomId);

                var response = new MarchArrivalResponseDto
                {
                    PlayerId = playerId,
                    MarchId = request.MarchId, // Already int, no conversion needed
                    MarchType = "Unknown", // Remove request.MarchType - doesn't exist
                    ArrivalCoordinates = new Dictionary<string, decimal>(),
                    ArrivingTroops = new Dictionary<string, long>(),
                    ArrivalTime = DateTime.UtcNow,
                    ArrivalEventData = arrivalResult
                };

                _logger.LogInformation("March arrival processed for Player {PlayerId} - March ID: {MarchId}",
                    playerId, request.MarchId);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing march arrival for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to process march arrival",
                    Code = "ARRIVAL_PROCESSING_ERROR"
                });
            }
        }

        #endregion

        #region Battle Resolution

        /// <summary>
        /// Executes complete battle resolution with statistical combat system
        /// </summary>
        /// <param name="request">Battle execution parameters with all participants</param>
        /// <returns>Complete battle results with casualties and rewards</returns>
        [HttpPost("battle/execute")]
        [ProducesResponseType(typeof(BattleExecutionResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> ExecuteBattle([FromBody] BattleExecutionRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid battle execution request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var battleResults = await _combatService.ResolveBattleAsync(
                    playerId, playerId, kingdomId, // Remove request.AttackerId, DefenderId - don't exist
                    request.TacticalFormations);

                var response = new BattleExecutionResponseDto
                {
                    BattleId = int.TryParse(battleResults.GetValueOrDefault("BattleId", "0").ToString(), out int battleId) ? battleId : 0,
                    AttackerPlayerId = playerId, // Use playerId instead of non-existent request properties
                    DefenderPlayerId = playerId,
                    Winner = battleResults.GetValueOrDefault("Victor", "Unknown").ToString(),
                    BattleResults = battleResults,
                    ExperienceGains = new Dictionary<string, object>(),
                    ResourceTransfers = new Dictionary<string, object>(),
                    BattleTime = DateTime.UtcNow
                };

                _logger.LogInformation("Battle executed successfully for Player {PlayerId} - Battle ID: {BattleId}",
                    playerId, response.BattleId);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error executing battle for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to execute battle",
                    Code = "BATTLE_EXECUTION_ERROR"
                });
            }
        }

        /// <summary>
        /// Calculates battle prediction based on troop compositions and modifiers
        /// </summary>
        /// <param name="request">Battle prediction parameters</param>
        /// <returns>Battle prediction with casualty estimates and victory probabilities</returns>
        [HttpPost("battle/predict")]
        [ProducesResponseType(typeof(BattlePredictionResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> CalculateBattlePrediction([FromBody] BattlePredictionRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid battle prediction request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var predictionResult = await _combatService.CalculateBattlePredictionAsync(
                    request.AttackingArmy.ToDictionary(k => k.Key, v => (int)v.Value), // Use AttackingArmy, DefendingArmy
                    request.DefendingArmy.ToDictionary(k => k.Key, v => (int)v.Value),
                    new Dictionary<string, object> { ["BattleType"] = request.BattleType }); // Use BattleType from request

                var response = new BattlePredictionResponseDto
                {
                    ScenarioId = 1, // Remove PlayerId - doesn't exist in DTO
                    AttackerId = request.AttackerId,
                    DefenderId = request.DefenderId,
                    OutcomeProbabilities = new Dictionary<string, decimal>(), // Remove AttackerForces, DefenderForces, BattleModifiers, PredictionResults
                    PredictionAnalytics = predictionResult, // Use PredictionAnalytics instead
                    PredictionTime = DateTime.UtcNow
                };

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error calculating battle prediction for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to calculate battle prediction",
                    Code = "PREDICTION_ERROR"
                });
            }
        }

        /// <summary>
        /// Processes battle casualties with hospital mechanics and wounded troops
        /// </summary>
        /// <param name="request">Casualty processing parameters</param>
        /// <returns>Casualty processing result with hospital admissions and deaths</returns>
        [HttpPost("battle/process-casualties")]
        [ProducesResponseType(typeof(CasualtyProcessingResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> ProcessBattleCasualties([FromBody] CasualtyProcessingRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid casualty processing request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var casualtyResult = await _combatService.ProcessBattleCasualtiesAsync(
                    new Dictionary<string, object>(), // Remove request.BattleResult, AttackingPlayerId, DefendingPlayerId - don't exist
                    playerId, playerId, kingdomId);

                var response = new CasualtyProcessingResponseDto
                {
                    PlayerId = playerId,
                    CombatLogId = request.CombatLogId,
                    // Use actual DTO properties:
                    TotalCasualties = new Dictionary<string, long>(),
                    TroopsKilled = new Dictionary<string, long>(),
                    TroopsWounded = new Dictionary<string, long>(),
                    ProcessingMetadata = casualtyResult, // Put service result in ProcessingMetadata
                    ProcessingTime = DateTime.UtcNow
                };

                _logger.LogInformation("Battle casualties processed for Player {PlayerId}", playerId);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing battle casualties for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to process casualties",
                    Code = "CASUALTY_PROCESSING_ERROR"
                });
            }
        }

        /// <summary>
        /// Distributes battle rewards based on participation and victory conditions
        /// </summary>
        /// <param name="request">Reward distribution parameters</param>
        /// <returns>Reward distribution result with all benefits granted</returns>
        [HttpPost("battle/distribute-rewards")]
        [ProducesResponseType(typeof(RewardDistributionResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> DistributeBattleRewards([FromBody] RewardDistributionRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid reward distribution request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var rewardResult = await _combatService.ProcessBattleRewardsAsync(
                    playerId, playerId, kingdomId, new Dictionary<string, object>()); // Use placeholders

                var response = new RewardDistributionResponseDto
                {
                    PlayerId = playerId,
                    CombatLogId = request.CombatLogId,
                    BattleOutcome = request.BattleOutcome,
                    // Use actual DTO properties:
                    ResourceRewards = new Dictionary<string, long>(),
                    ExperienceReward = 0,
                    ItemRewards = new List<Dictionary<string, object>>(),
                    RewardMetadata = rewardResult, // Put service result in RewardMetadata
                    DistributionTime = DateTime.UtcNow
                };

                _logger.LogInformation("Battle rewards distributed successfully for Player {PlayerId}", playerId);
                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error distributing battle rewards for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to distribute rewards",
                    Code = "REWARD_DISTRIBUTION_ERROR"
                });
            }
        }

        #endregion

        #region Dragon Integration

        /// <summary>
        /// Validates dragon participation in combat with skill and equipment checks
        /// </summary>
        /// <param name="request">Dragon validation parameters</param>
        /// <returns>Dragon validation result with optimal configurations</returns>
        [HttpPost("dragons/validate-participation")]
        [ProducesResponseType(typeof(DragonValidationResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> ValidateDragonParticipation([FromBody] DragonValidationRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid dragon validation request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var (isValid, validationErrors, optimalSetup) = // Keep tuple deconstruction
                    await _combatService.ValidateDragonCombatSetupAsync(
                        playerId, kingdomId, new List<string>()); // Remove request.ProposedSkills - doesn't exist

                var response = new DragonValidationResponseDto
                {
                    PlayerId = playerId,
                    DragonId = 1, // Remove request.DragonId - doesn't exist
                    CanParticipate = isValid, // Use CanParticipate instead of IsValid
                    ValidationErrors = validationErrors,
                    ValidationMetadata = optimalSetup, // Remove ProposedSkills, OptimalSetup
                    ValidationTime = DateTime.UtcNow
                };

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error validating dragon participation for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to validate dragon participation",
                    Code = "DRAGON_VALIDATION_ERROR"
                });
            }
        }

        /// <summary>
        /// Executes dragon skill activation during combat with cooldown management
        /// </summary>
        /// <param name="request">Dragon skill execution parameters</param>
        /// <returns>Skill execution result with effects applied and cooldowns</returns>
        [HttpPost("dragons/execute-skill")]
        [ProducesResponseType(typeof(DragonSkillResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        [ProducesResponseType(typeof(ErrorResponseDto), 409)] // Skill on cooldown or unavailable
        public async Task<IActionResult> ExecuteDragonSkill([FromBody] DragonSkillRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid dragon skill request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var dragonIntegration = await _combatService.IntegrateDragonCombatAsync(
                    playerId, kingdomId, new List<string> { request.SkillName }, // Use SkillName instead of SkillsToExecute, BattleContext
                    new Dictionary<string, object>());

                var response = new DragonSkillResponseDto
                {
                    PlayerId = playerId,
                    DragonId = request.DragonId,
                    SkillName = request.SkillName, // Use SkillName instead of SkillsToExecute, BattleContext
                    SkillMetadata = dragonIntegration, // Use SkillMetadata instead of SkillExecutionResults, ExecutionTime
                    SkillTime = DateTime.UtcNow
                };

                _logger.LogInformation("Dragon skills executed for Player {PlayerId} - Dragon: {DragonId}",
                    playerId, request.DragonId);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error executing dragon skill for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to execute dragon skill",
                    Code = "DRAGON_SKILL_ERROR"
                });
            }
        }

        /// <summary>
        /// Optimizes dragon equipment setup for specific combat scenarios
        /// </summary>
        /// <param name="request">Equipment optimization parameters</param>
        /// <returns>Optimal equipment configuration recommendations</returns>
        [HttpPost("dragons/optimize-equipment")]
        [ProducesResponseType(typeof(DragonEquipmentResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> OptimizeDragonEquipment([FromBody] DragonEquipmentRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid dragon equipment request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var cooldownResult = await _combatService.CalculateDragonSkillCooldownsAsync(
                    playerId, kingdomId, new List<string>()); // Remove request.CurrentSkills - doesn't exist

                var response = new DragonEquipmentResponseDto
                {
                    PlayerId = playerId,
                    DragonId = request.DragonId,
                    EquippedItems = new Dictionary<string, Dictionary<string, object>>(), // Remove CombatScenario, CurrentSkills, EquipmentOptimization, OptimizationTime
                    EquipmentBonuses = new Dictionary<string, decimal>(),
                    CombatEffectiveness = new Dictionary<string, long>()
                };

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error optimizing dragon equipment for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to optimize dragon equipment",
                    Code = "EQUIPMENT_OPTIMIZATION_ERROR"
                });
            }
        }

        #endregion

        #region Anti-Pay-to-Win Balance

        /// <summary>
        /// Monitors combat effectiveness to ensure balanced gameplay between spending and free players
        /// </summary>
        /// <param name="request">Combat effectiveness analysis parameters</param>
        /// <returns>Combat effectiveness analysis with balance recommendations</returns>
        [HttpPost("balance/monitor-effectiveness")]
        [ProducesResponseType(typeof(CombatEffectivenessResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> MonitorCombatEffectiveness([FromBody] CombatEffectivenessRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid combat effectiveness request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var effectivenessAnalysis = await _combatService.ValidateCombatEffectivenessAsync(
                    playerId, kingdomId, request.TimeframeDays);

                var response = new CombatEffectivenessResponseDto
                {
                    PlayerId = playerId,
                    OverallEffectiveness = 75.0m, // Remove TimeframeDays, EffectivenessResults - don't exist
                    AnalyticsMetadata = effectivenessAnalysis, // Use AnalyticsMetadata instead
                    AnalysisTime = DateTime.UtcNow
                };

                _logger.LogInformation("Combat effectiveness analyzed for Player {PlayerId} over {Days} days",
                    playerId, request.TimeframeDays);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error monitoring combat effectiveness for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to monitor combat effectiveness",
                    Code = "EFFECTIVENESS_MONITORING_ERROR"
                });
            }
        }

        #endregion

        #region Combat Analytics

        /// <summary>
        /// Retrieves comprehensive combat history and performance analytics
        /// </summary>
        /// <param name="timeframeDays">Historical period to analyze (default: 30 days)</param>
        /// <returns>Combat statistics and performance metrics</returns>
        [HttpGet("analytics/history")]
        [ProducesResponseType(typeof(CombatAnalyticsResponseDto), 200)]
        public async Task<IActionResult> GetCombatAnalytics([FromQuery] int timeframeDays = 30)
        {
            try
            {
                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var analytics = await _combatService.GetCombatHistoryAnalyticsAsync(
                    playerId, kingdomId, timeframeDays);

                var response = new CombatAnalyticsResponseDto
                {
                    PlayerId = playerId,
                    TimeframeDays = timeframeDays,
                    Analytics = analytics, // Remove AnalyticsResults, GeneratedTime - don't exist
                    GeneratedAt = DateTime.UtcNow // Use GeneratedAt instead of GeneratedTime
                };

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error retrieving combat analytics for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to retrieve combat analytics",
                    Code = "ANALYTICS_ERROR"
                });
            }
        }

        /// <summary>
        /// Analyzes kingdom-wide combat trends and power balance metrics
        /// </summary>
        /// <param name="analysisType">Type of analysis to perform (power_balance, alliance_strength, etc.)</param>
        /// <returns>Kingdom combat analytics and trend analysis</returns>
        [HttpGet("analytics/kingdom-trends")]
        [ProducesResponseType(typeof(KingdomTrendsResponseDto), 200)]
        public async Task<IActionResult> AnalyzeKingdomCombatTrends([FromQuery] string analysisType = "power_balance")
        {
            try
            {
                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var trends = await _combatService.AnalyzeKingdomCombatTrendsAsync(kingdomId, analysisType);

                var response = new KingdomTrendsResponseDto
                {
                    KingdomId = kingdomId,
                    CombatActivity = new Dictionary<string, long>(), // Remove AnalysisType, TrendResults, GeneratedTime - don't exist
                    KingdomAnalytics = trends, // Use KingdomAnalytics instead
                    AnalysisCompletionTime = DateTime.UtcNow // Use AnalysisCompletionTime instead of GeneratedTime
                };

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error analyzing kingdom combat trends for Kingdom {KingdomId}", GetAuthenticatedPlayer().KingdomId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to analyze kingdom trends",
                    Code = "TREND_ANALYSIS_ERROR"
                });
            }
        }

        /// <summary>
        /// Generates battle replay data for post-combat analysis
        /// </summary>
        /// <param name="combatLogId">Combat log identifier for replay generation</param>
        /// <returns>Battle replay data and analysis points</returns>
        [HttpGet("analytics/battle-replay/{combatLogId}")]
        [ProducesResponseType(typeof(BattleReplayResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 404)]
        public async Task<IActionResult> GenerateBattleReplay(int combatLogId)
        {
            try
            {
                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var replayData = await _combatService.GenerateBattleReplayAsync(combatLogId, kingdomId);

                if (!replayData.ContainsKey("found") || !(bool)replayData["found"])
                {
                    return NotFound(new ErrorResponseDto
                    {
                        Message = "Combat log not found or access denied",
                        Code = "COMBAT_LOG_NOT_FOUND"
                    });
                }

                var response = new BattleReplayResponseDto
                {
                    BattleId = combatLogId, // Remove CombatLogId, PlayerId, GeneratedTime - don't exist
                    ReplayData = replayData,
                    Participants = new Dictionary<string, object>(),
                    BattleTimeline = new List<Dictionary<string, object>>(),
                    ReplayGeneratedAt = DateTime.UtcNow // Use ReplayGeneratedAt instead of GeneratedTime
                };

                _logger.LogInformation("Battle replay generated for Combat Log {CombatLogId} by Player {PlayerId}",
                    combatLogId, playerId);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error generating battle replay for Combat Log {CombatLogId}", combatLogId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to generate battle replay",
                    Code = "REPLAY_GENERATION_ERROR"
                });
            }
        }

        #endregion

        #region Helper Methods

        /// <summary>
        /// Extracts authenticated player information from JWT claims
        /// </summary>
        /// <returns>Player ID and Kingdom ID from authentication context</returns>
        /// <exception cref="UnauthorizedAccessException">Thrown when authentication claims are invalid</exception>
        private (int PlayerId, int KingdomId) GetAuthenticatedPlayer()
        {
            var playerIdClaim = User.FindFirst("player_id")?.Value;
            var kingdomIdClaim = User.FindFirst("kingdom_id")?.Value;

            if (string.IsNullOrEmpty(playerIdClaim) || string.IsNullOrEmpty(kingdomIdClaim))
            {
                throw new UnauthorizedAccessException("Invalid authentication claims - player or kingdom not found");
            }

            if (!int.TryParse(playerIdClaim, out int playerId) ||
                !int.TryParse(kingdomIdClaim, out int kingdomId))
            {
                throw new UnauthorizedAccessException("Invalid authentication claims - unable to parse player or kingdom ID");
            }

            return (playerId, kingdomId);
        }

        #endregion
    }
}