/*
 * File: D:\shadowed-realms-mobile\ShadowedRealmsMobile\src\server\ShadowedRealms.API\Controllers\Player\PlayerController.cs
 * Created: 2025-10-19
 * Last Modified: 2025-10-19
 * Description: Comprehensive REST API controller for player management operations.
 *              Exposes all PlayerService functionality through RESTful endpoints with
 *              proper authentication, validation, and error handling.
 * Last Edit Notes: Initial implementation with complete CRUD operations, castle management,
 *                  VIP progression, teleportation, resource management, and social integration.
 */

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

namespace ShadowedRealms.API.Controllers.Player
{
    /// <summary>
    /// REST API controller for comprehensive player management operations
    /// </summary>
    [ApiController]
    [Route("api/v1/players")]
    [Authorize] // JWT authentication required for all endpoints
    [Produces("application/json")]
    [ProducesResponseType(typeof(ErrorResponseDto), 400)]
    [ProducesResponseType(typeof(ErrorResponseDto), 401)]
    [ProducesResponseType(typeof(ErrorResponseDto), 403)]
    [ProducesResponseType(typeof(ErrorResponseDto), 500)]
    public class PlayerController : ControllerBase
    {
        private readonly IPlayerService _playerService;
        private readonly ILogger<PlayerController> _logger;

        public PlayerController(
            IPlayerService playerService,
            ILogger<PlayerController> logger)
        {
            _playerService = playerService ?? throw new ArgumentNullException(nameof(playerService));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        #region Player Information and Profile Management

        /// <summary>
        /// Retrieves current player profile with comprehensive statistics
        /// </summary>
        /// <returns>Complete player profile including castle, resources, VIP status, and alliance</returns>
        [HttpGet("profile")]
        [ProducesResponseType(typeof(PlayerProfileResponseDto), 200)]
        public async Task<IActionResult> GetPlayerProfile()
        {
            try
            {
                var (playerId, kingdomId) = GetAuthenticatedPlayer();
                var playerInfo = await _playerService.GetPlayerInfoAsync(playerId, kingdomId);

                var response = new PlayerProfileResponseDto
                {
                    PlayerId = playerId,
                    KingdomId = kingdomId,
                    PlayerInfo = playerInfo,
                    LastUpdated = DateTime.UtcNow
                };

                _logger.LogInformation("Player profile retrieved successfully for Player {PlayerId} in Kingdom {KingdomId}",
                    playerId, kingdomId);

                return Ok(response);
            }
            catch (UnauthorizedAccessException ex)
            {
                _logger.LogWarning("Unauthorized access attempt: {Message}", ex.Message);
                return Forbid();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error retrieving player profile");
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to retrieve player profile",
                    Code = "PROFILE_ERROR"
                });
            }
        }

        /// <summary>
        /// Updates player profile settings and preferences
        /// </summary>
        /// <param name="request">Profile update settings</param>
        /// <returns>Updated profile information</returns>
        [HttpPut("profile")]
        [ProducesResponseType(typeof(PlayerProfileResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> UpdatePlayerProfile([FromBody] UpdatePlayerProfileRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid profile update data",
                        Code = "INVALID_INPUT",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                // Validate profile update settings
                var validationResult = await _playerService.ValidatePlayerActionsAsync(
                    playerId, kingdomId, "profile_update", request.ToValidationDictionary());

                if (!validationResult.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Profile update validation failed",
                        Code = "VALIDATION_FAILED",
                        Details = validationResult.ValidationErrors
                    });
                }

                // Process profile updates
                var updateResult = await _playerService.UpdatePlayerSettingsAsync(
                    playerId, kingdomId, request.Settings);

                var response = new PlayerProfileResponseDto
                {
                    PlayerId = playerId,
                    KingdomId = kingdomId,
                    PlayerInfo = updateResult,
                    LastUpdated = DateTime.UtcNow
                };

                _logger.LogInformation("Player profile updated successfully for Player {PlayerId}", playerId);
                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error updating player profile");
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to update player profile",
                    Code = "UPDATE_ERROR"
                });
            }
        }

        /// <summary>
        /// Retrieves current player rankings and leaderboard positions
        /// </summary>
        /// <param name="category">Ranking category (power, castle_level, kills, etc.)</param>
        /// <returns>Player rankings and position information</returns>
        [HttpGet("rankings")]
        [ProducesResponseType(typeof(PlayerRankingsResponseDto), 200)]
        public async Task<IActionResult> GetPlayerRankings([FromQuery] string category = "power")
        {
            try
            {
                var (playerId, kingdomId) = GetAuthenticatedPlayer();
                var rankings = await _playerService.GetPlayerRankingsAsync(playerId, kingdomId, category);

                var response = new PlayerRankingsResponseDto
                {
                    PlayerId = playerId,
                    Category = category,
                    Rankings = rankings,
                    LastUpdated = DateTime.UtcNow
                };

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error retrieving player rankings for category {Category}", category);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to retrieve rankings",
                    Code = "RANKINGS_ERROR"
                });
            }
        }

        #endregion

        #region Castle Management and Upgrades

        /// <summary>
        /// Retrieves current castle information including level, upgrades in progress, and requirements
        /// </summary>
        /// <returns>Complete castle status and upgrade information</returns>
        [HttpGet("castle")]
        [ProducesResponseType(typeof(CastleInfoResponseDto), 200)]
        public async Task<IActionResult> GetCastleInfo()
        {
            try
            {
                var (playerId, kingdomId) = GetAuthenticatedPlayer();
                var castleInfo = await _playerService.GetCastleInfoAsync(playerId, kingdomId);

                var response = new CastleInfoResponseDto
                {
                    PlayerId = playerId,
                    CastleInfo = castleInfo,
                    LastUpdated = DateTime.UtcNow
                };

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

        /// <summary>
        /// Initiates castle upgrade process with resource validation and VIP bonuses
        /// </summary>
        /// <param name="request">Castle upgrade parameters</param>
        /// <returns>Upgrade result with new castle level and benefits granted</returns>
        [HttpPost("castle/upgrade")]
        [ProducesResponseType(typeof(CastleUpgradeResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        [ProducesResponseType(typeof(ErrorResponseDto), 409)] // Conflict - upgrade already in progress
        public async Task<IActionResult> UpgradeCastle([FromBody] CastleUpgradeRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid castle upgrade 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, newCastleLevel, benefitsGranted) = await _playerService.UpgradeCastleAsync(
                    playerId, kingdomId, request.UseSpeedups);

                if (!success)
                {
                    return Conflict(new ErrorResponseDto
                    {
                        Message = "Castle upgrade failed - insufficient resources or upgrade already in progress",
                        Code = "UPGRADE_FAILED"
                    });
                }

                var response = new CastleUpgradeResponseDto
                {
                    PlayerId = playerId,
                    Success = success,
                    NewCastleLevel = newCastleLevel,
                    BenefitsGranted = benefitsGranted,
                    UpgradeTime = DateTime.UtcNow
                };

                _logger.LogInformation("Castle upgraded successfully for Player {PlayerId} to level {NewLevel}",
                    playerId, newCastleLevel);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error upgrading castle for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to upgrade castle",
                    Code = "UPGRADE_ERROR"
                });
            }
        }

        #endregion

        #region VIP Management and Progression

        /// <summary>
        /// Retrieves current VIP status including tier, benefits, and progression
        /// </summary>
        /// <returns>Complete VIP information and secret tier status</returns>
        [HttpGet("vip")]
        [ProducesResponseType(typeof(VipStatusResponseDto), 200)]
        public async Task<IActionResult> GetVipStatus()
        {
            try
            {
                var (playerId, kingdomId) = GetAuthenticatedPlayer();
                var vipStatus = await _playerService.GetVipStatusAsync(playerId, kingdomId);

                var response = new VipStatusResponseDto
                {
                    PlayerId = playerId,
                    VipStatus = vipStatus,
                    LastUpdated = DateTime.UtcNow
                };

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

        /// <summary>
        /// Processes VIP advancement based on purchases and milestones
        /// </summary>
        /// <param name="request">VIP advancement parameters</param>
        /// <returns>VIP advancement result with new tier and benefits</returns>
        [HttpPost("vip/advance")]
        [ProducesResponseType(typeof(VipAdvancementResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> AdvanceVip([FromBody] VipAdvancementRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid VIP advancement 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, newVipTier, benefitsGranted, secretTierUnlocked) =
                    await _playerService.ProcessVipAdvancementAsync(
                        playerId, kingdomId, request.PurchaseAmount, request.PurchaseType);

                if (!success)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "VIP advancement failed - invalid purchase or tier requirements not met",
                        Code = "ADVANCEMENT_FAILED"
                    });
                }

                var response = new VipAdvancementResponseDto
                {
                    PlayerId = playerId,
                    Success = success,
                    NewVipTier = newVipTier,
                    BenefitsGranted = benefitsGranted,
                    SecretTierUnlocked = secretTierUnlocked,
                    AdvancementTime = DateTime.UtcNow
                };

                _logger.LogInformation("VIP advancement processed for Player {PlayerId} to tier {NewTier}",
                    playerId, newVipTier);

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

        #endregion

        #region Teleportation and Movement

        /// <summary>
        /// Executes player teleportation with distance calculations and cost validation
        /// </summary>
        /// <param name="request">Teleportation target coordinates and parameters</param>
        /// <returns>Teleportation result with new position and costs</returns>
        [HttpPost("teleport")]
        [ProducesResponseType(typeof(TeleportationResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        [ProducesResponseType(typeof(ErrorResponseDto), 409)] // Conflict - cooldown or proximity block
        public async Task<IActionResult> ExecuteTeleportation([FromBody] TeleportationRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid teleportation 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, newPosition, costsApplied, cooldownApplied, proximityBlocked) =
                    await _playerService.ExecuteTeleportationAsync(
                        playerId, kingdomId, request.TargetX, request.TargetY, request.TeleportType);

                if (!success)
                {
                    var errorMessage = proximityBlocked ? "Teleportation blocked due to proximity restrictions" :
                                      cooldownApplied > TimeSpan.Zero ? "Teleportation on cooldown" :
                                      "Teleportation failed - insufficient resources or invalid target";

                    return Conflict(new ErrorResponseDto
                    {
                        Message = errorMessage,
                        Code = "TELEPORTATION_FAILED",
                        Details = new Dictionary<string, object>
                        {
                            ["proximityBlocked"] = proximityBlocked,
                            ["cooldownRemaining"] = cooldownApplied.TotalSeconds
                        }
                    });
                }

                var response = new TeleportationResponseDto
                {
                    PlayerId = playerId,
                    Success = success,
                    NewPosition = newPosition,
                    CostsApplied = costsApplied,
                    CooldownApplied = cooldownApplied,
                    TeleportationTime = DateTime.UtcNow
                };

                _logger.LogInformation("Teleportation executed successfully for Player {PlayerId} to ({X}, {Y})",
                    playerId, request.TargetX, request.TargetY);

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

        #endregion

        #region Resource Management

        /// <summary>
        /// Retrieves current player resources including production rates and capacity
        /// </summary>
        /// <returns>Complete resource status and production information</returns>
        [HttpGet("resources")]
        [ProducesResponseType(typeof(ResourceStatusResponseDto), 200)]
        public async Task<IActionResult> GetResourceStatus()
        {
            try
            {
                var (playerId, kingdomId) = GetAuthenticatedPlayer();
                var resources = await _playerService.GetResourceStatusAsync(playerId, kingdomId);

                var response = new ResourceStatusResponseDto
                {
                    PlayerId = playerId,
                    Resources = resources,
                    LastUpdated = DateTime.UtcNow
                };

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

        /// <summary>
        /// Collects accumulated resources from production buildings
        /// </summary>
        /// <returns>Resource collection result with amounts collected</returns>
        [HttpPost("resources/collect")]
        [ProducesResponseType(typeof(ResourceCollectionResponseDto), 200)]
        public async Task<IActionResult> CollectResources()
        {
            try
            {
                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var (success, resourcesCollected, bonusesApplied) =
                    await _playerService.CollectResourcesAsync(playerId, kingdomId);

                var response = new ResourceCollectionResponseDto
                {
                    PlayerId = playerId,
                    Success = success,
                    ResourcesCollected = resourcesCollected,
                    BonusesApplied = bonusesApplied,
                    CollectionTime = DateTime.UtcNow
                };

                _logger.LogInformation("Resources collected successfully for Player {PlayerId}", playerId);
                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error collecting resources for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to collect resources",
                    Code = "RESOURCE_COLLECTION_ERROR"
                });
            }
        }

        /// <summary>
        /// Spends resources for various game actions with validation
        /// </summary>
        /// <param name="request">Resource spending parameters</param>
        /// <returns>Resource spending result with validation</returns>
        [HttpPost("resources/spend")]
        [ProducesResponseType(typeof(ResourceSpendingResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> SpendResources([FromBody] ResourceSpendingRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid resource spending 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, remainingResources, spendingValidated) =
                    await _playerService.SpendResourcesAsync(
                        playerId, kingdomId, request.ResourceCosts, request.SpendingReason);

                if (!success)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Resource spending failed - insufficient resources or invalid spending reason",
                        Code = "SPENDING_FAILED"
                    });
                }

                var response = new ResourceSpendingResponseDto
                {
                    PlayerId = playerId,
                    Success = success,
                    RemainingResources = remainingResources,
                    SpendingValidated = spendingValidated,
                    SpendingTime = DateTime.UtcNow
                };

                _logger.LogInformation("Resources spent successfully for Player {PlayerId} - Reason: {Reason}",
                    playerId, request.SpendingReason);

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error spending resources for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to spend resources",
                    Code = "RESOURCE_SPENDING_ERROR"
                });
            }
        }

        #endregion

        #region Combat Integration

        /// <summary>
        /// Prepares player for combat with troop validation and march setup
        /// </summary>
        /// <param name="request">Combat preparation parameters</param>
        /// <returns>Combat preparation result with march details</returns>
        [HttpPost("combat/prepare")]
        [ProducesResponseType(typeof(CombatPreparationResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> PrepareCombat([FromBody] CombatPreparationRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid combat preparation 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, marchDetails, validationResults) =
                    await _playerService.PrepareCombatAsync(
                        playerId, kingdomId, request.TroopComposition, request.TargetType);

                if (!success)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Combat preparation failed - invalid troop composition or target",
                        Code = "PREPARATION_FAILED",
                        Details = validationResults
                    });
                }

                var response = new CombatPreparationResponseDto
                {
                    PlayerId = playerId,
                    Success = success,
                    MarchDetails = marchDetails,
                    ValidationResults = validationResults,
                    PreparationTime = DateTime.UtcNow
                };

                _logger.LogInformation("Combat prepared successfully for Player {PlayerId} - Target: {TargetType}",
                    playerId, request.TargetType);

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

        /// <summary>
        /// Processes combat results and updates player statistics
        /// </summary>
        /// <param name="request">Combat result processing parameters</param>
        /// <returns>Combat result processing outcome</returns>
        [HttpPost("combat/process-results")]
        [ProducesResponseType(typeof(CombatResultsResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> ProcessCombatResults([FromBody] CombatResultsRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid combat results request",
                        Code = "INVALID_REQUEST",
                        ValidationErrors = ModelState.ToDictionary(x => x.Key, x => x.Value?.Errors.Select(e => e.ErrorMessage).ToArray())
                    });
                }

                var (playerId, kingdomId) = GetAuthenticatedPlayer();

                var playerUpdates = await _playerService.ProcessCombatResultsAsync(
                    playerId, kingdomId, request.CombatResult);

                var response = new CombatResultsResponseDto
                {
                    PlayerId = playerId,
                    PlayerUpdates = playerUpdates,
                    ProcessingTime = DateTime.UtcNow
                };

                _logger.LogInformation("Combat results processed successfully for Player {PlayerId}", playerId);
                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing combat results for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to process combat results",
                    Code = "COMBAT_RESULTS_ERROR"
                });
            }
        }

        #endregion

        #region Alliance Integration

        /// <summary>
        /// Processes alliance join request or invitation
        /// </summary>
        /// <param name="request">Alliance join parameters</param>
        /// <returns>Alliance join result with benefits and privileges</returns>
        [HttpPost("alliance/join")]
        [ProducesResponseType(typeof(AllianceJoinResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        [ProducesResponseType(typeof(ErrorResponseDto), 409)]
        public async Task<IActionResult> JoinAlliance([FromBody] AllianceJoinRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid alliance join 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, allianceDetails, newPrivileges) =
                    await _playerService.ProcessAllianceJoinAsync(
                        playerId, kingdomId, request.AllianceId, request.IsInvitation);

                if (!success)
                {
                    return Conflict(new ErrorResponseDto
                    {
                        Message = "Alliance join failed - player already in alliance, alliance full, or invitation invalid",
                        Code = "JOIN_FAILED"
                    });
                }

                var response = new AllianceJoinResponseDto
                {
                    PlayerId = playerId,
                    Success = success,
                    AllianceDetails = allianceDetails,
                    NewPrivileges = newPrivileges,
                    JoinTime = DateTime.UtcNow
                };

                _logger.LogInformation("Player {PlayerId} successfully joined alliance {AllianceId}",
                    playerId, request.AllianceId);

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

        /// <summary>
        /// Processes alliance leave with benefit adjustments
        /// </summary>
        /// <param name="request">Alliance leave parameters</param>
        /// <returns>Alliance leave result with benefit adjustments</returns>
        [HttpPost("alliance/leave")]
        [ProducesResponseType(typeof(AllianceLeaveResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> LeaveAlliance([FromBody] AllianceLeaveRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid alliance leave 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, benefitsLost, territoryEviction) =
                    await _playerService.ProcessAllianceLeaveAsync(
                        playerId, kingdomId, request.Reason);

                if (!success)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Alliance leave failed - player not in alliance or invalid reason",
                        Code = "LEAVE_FAILED"
                    });
                }

                var response = new AllianceLeaveResponseDto
                {
                    PlayerId = playerId,
                    Success = success,
                    BenefitsLost = benefitsLost,
                    TerritoryEviction = territoryEviction,
                    LeaveTime = DateTime.UtcNow
                };

                _logger.LogInformation("Player {PlayerId} left alliance - Reason: {Reason}",
                    playerId, request.Reason);

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

        #endregion

        #region Player Progression and Achievements

        /// <summary>
        /// Processes experience gain and level progression
        /// </summary>
        /// <param name="request">Experience processing parameters</param>
        /// <returns>Experience processing result with level progression</returns>
        [HttpPost("experience/process")]
        [ProducesResponseType(typeof(ExperienceProcessingResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> ProcessExperience([FromBody] ExperienceProcessingRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid experience 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 (success, newLevel, achievementsUnlocked, powerIncrease) =
                    await _playerService.ProcessExperienceAsync(
                        playerId, kingdomId, request.ExperienceGained, request.ExperienceSource);

                if (!success)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Experience processing failed - invalid experience source or amount",
                        Code = "EXPERIENCE_FAILED"
                    });
                }

                var response = new ExperienceProcessingResponseDto
                {
                    PlayerId = playerId,
                    Success = success,
                    NewLevel = newLevel,
                    AchievementsUnlocked = achievementsUnlocked,
                    PowerIncrease = powerIncrease,
                    ProcessingTime = DateTime.UtcNow
                };

                _logger.LogInformation("Experience processed for Player {PlayerId} - Gained: {Experience} from {Source}",
                    playerId, request.ExperienceGained, request.ExperienceSource);

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

        /// <summary>
        /// Retrieves achievement progress and unlocked achievements
        /// </summary>
        /// <returns>Achievement status and progress information</returns>
        [HttpGet("achievements")]
        [ProducesResponseType(typeof(AchievementsResponseDto), 200)]
        public async Task<IActionResult> GetAchievements()
        {
            try
            {
                var (playerId, kingdomId) = GetAuthenticatedPlayer();
                var achievements = await _playerService.GetAchievementProgressAsync(playerId, kingdomId);

                var response = new AchievementsResponseDto
                {
                    PlayerId = playerId,
                    Achievements = achievements,
                    LastUpdated = DateTime.UtcNow
                };

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

        #endregion

        #region Anti-Exploitation and Validation

        /// <summary>
        /// Validates player actions for potential exploitation or cheating
        /// </summary>
        /// <param name="request">Action validation parameters</param>
        /// <returns>Validation result and risk assessment</returns>
        [HttpPost("validate-action")]
        [ProducesResponseType(typeof(ActionValidationResponseDto), 200)]
        [ProducesResponseType(typeof(ErrorResponseDto), 400)]
        public async Task<IActionResult> ValidateAction([FromBody] ActionValidationRequestDto request)
        {
            try
            {
                if (!ModelState.IsValid)
                {
                    return BadRequest(new ErrorResponseDto
                    {
                        Message = "Invalid action 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, riskScore, validationNotes) =
                    await _playerService.ValidatePlayerActionsAsync(
                        playerId, kingdomId, request.ActionType, request.ActionDetails);

                var response = new ActionValidationResponseDto
                {
                    PlayerId = playerId,
                    IsValid = isValid,
                    RiskScore = riskScore,
                    ValidationNotes = validationNotes,
                    ValidationTime = DateTime.UtcNow
                };

                return Ok(response);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error validating action for Player {PlayerId}", GetAuthenticatedPlayer().PlayerId);
                return StatusCode(500, new ErrorResponseDto
                {
                    Message = "Failed to validate action",
                    Code = "VALIDATION_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
    }
}