namespace WalletService.API.Controllers.Admin;

using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using WalletService.API.Application.Commands;
using WalletService.API.Application.Queries;
using WalletService.API.Controllers;
using WalletService.Domain.AggregatesModel.WalletAggregate;

/// <summary>
/// EN: Admin controller for wallet management operations (Backoffice).
/// VI: Controller Admin cho các thao tác quản lý ví (Backoffice).
/// </summary>
[ApiController]
[Route("api/v1/admin/wallets")]
[Authorize(Roles = "Admin,SuperAdmin")]
[SwaggerTag("Admin Wallet Management / Quản lý ví Admin")]
public class AdminWalletsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly IWalletRepository _walletRepository;
    private readonly ILogger<AdminWalletsController> _logger;

    public AdminWalletsController(
        IMediator mediator,
        IWalletRepository walletRepository,
        ILogger<AdminWalletsController> logger)
    {
        _mediator = mediator;
        _walletRepository = walletRepository;
        _logger = logger;
    }

    /// <summary>
    /// EN: Get all wallets with pagination.
    /// VI: Lấy tất cả ví với phân trang.
    /// </summary>
    [HttpGet]
    [SwaggerOperation(Summary = "Get all wallets", Description = "Get all wallets with pagination (Admin only)")]
    [SwaggerResponse(200, "Success", typeof(ApiResponse<AdminWalletsListDto>))]
    public async Task<IActionResult> GetAllWallets(
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        [FromQuery] string? status = null,
        [FromQuery] string? currency = null)
    {
        var query = new GetAllWalletsQuery(page, pageSize, status, currency);
        var result = await _mediator.Send(query);

        return Ok(new ApiResponse<AdminWalletsListDto>(true, "Success", result));
    }

    /// <summary>
    /// EN: Get wallet details by ID.
    /// VI: Lấy chi tiết ví theo ID.
    /// </summary>
    [HttpGet("{walletId:guid}")]
    [SwaggerOperation(Summary = "Get wallet by ID", Description = "Get wallet details by wallet ID (Admin only)")]
    [SwaggerResponse(200, "Success", typeof(ApiResponse<AdminWalletDetailDto>))]
    [SwaggerResponse(404, "Wallet not found")]
    public async Task<IActionResult> GetWalletById(Guid walletId)
    {
        var query = new GetWalletByIdQuery(walletId);
        var result = await _mediator.Send(query);

        if (result == null)
            return NotFound(new ApiResponse<object>(false, "Wallet not found"));

        return Ok(new ApiResponse<AdminWalletDetailDto>(true, "Success", result));
    }

    /// <summary>
    /// EN: Freeze wallet.
    /// VI: Đóng băng ví.
    /// </summary>
    [HttpPost("{walletId:guid}/freeze")]
    [SwaggerOperation(Summary = "Freeze wallet", Description = "Freeze wallet to prevent transactions (Admin only)")]
    [SwaggerResponse(200, "Wallet frozen")]
    [SwaggerResponse(404, "Wallet not found")]
    public async Task<IActionResult> FreezeWallet(Guid walletId, [FromBody] AdminActionRequest request)
    {
        var command = new AdminFreezeWalletCommand(walletId, request.Reason, GetAdminId());
        var result = await _mediator.Send(command);

        _logger.LogInformation(
            "Admin {AdminId} froze wallet {WalletId}. Reason: {Reason}",
            GetAdminId(), walletId, request.Reason);

        return Ok(new ApiResponse<AdminWalletActionResult>(true, "Wallet frozen successfully", result));
    }

    /// <summary>
    /// EN: Unfreeze wallet.
    /// VI: Mở băng ví.
    /// </summary>
    [HttpPost("{walletId:guid}/unfreeze")]
    [SwaggerOperation(Summary = "Unfreeze wallet", Description = "Unfreeze wallet to allow transactions (Admin only)")]
    [SwaggerResponse(200, "Wallet unfrozen")]
    [SwaggerResponse(404, "Wallet not found")]
    public async Task<IActionResult> UnfreezeWallet(Guid walletId, [FromBody] AdminActionRequest request)
    {
        var command = new AdminUnfreezeWalletCommand(walletId, request.Reason, GetAdminId());
        var result = await _mediator.Send(command);

        _logger.LogInformation(
            "Admin {AdminId} unfroze wallet {WalletId}. Reason: {Reason}",
            GetAdminId(), walletId, request.Reason);

        return Ok(new ApiResponse<AdminWalletActionResult>(true, "Wallet unfrozen successfully", result));
    }

    /// <summary>
    /// EN: Adjust wallet balance (credit/debit).
    /// VI: Điều chỉnh số dư ví (cộng/trừ).
    /// </summary>
    [HttpPost("{walletId:guid}/adjust")]
    [SwaggerOperation(Summary = "Adjust balance", Description = "Adjust wallet balance (Admin only)")]
    [SwaggerResponse(200, "Balance adjusted")]
    [SwaggerResponse(400, "Invalid adjustment")]
    [SwaggerResponse(404, "Wallet not found")]
    public async Task<IActionResult> AdjustBalance(Guid walletId, [FromBody] AdminAdjustBalanceRequest request)
    {
        var command = new AdminAdjustBalanceCommand(
            walletId,
            request.Amount,
            request.CurrencyTypeId,
            request.Reason,
            GetAdminId());

        var result = await _mediator.Send(command);

        _logger.LogInformation(
            "Admin {AdminId} adjusted wallet {WalletId} by {Amount}. Reason: {Reason}",
            GetAdminId(), walletId, request.Amount, request.Reason);

        return Ok(new ApiResponse<AdminAdjustBalanceResult>(true, "Balance adjusted successfully", result));
    }

    /// <summary>
    /// EN: Get wallet statistics.
    /// VI: Lấy thống kê ví.
    /// </summary>
    [HttpGet("statistics")]
    [SwaggerOperation(Summary = "Get statistics", Description = "Get wallet statistics (Admin only)")]
    [SwaggerResponse(200, "Success", typeof(ApiResponse<WalletStatisticsDto>))]
    public async Task<IActionResult> GetStatistics()
    {
        var query = new GetWalletStatisticsQuery();
        var result = await _mediator.Send(query);

        return Ok(new ApiResponse<WalletStatisticsDto>(true, "Success", result));
    }

    /// <summary>
    /// EN: Search wallets by user ID or wallet ID.
    /// VI: Tìm kiếm ví theo user ID hoặc wallet ID.
    /// </summary>
    [HttpGet("search")]
    [SwaggerOperation(Summary = "Search wallets", Description = "Search wallets by user ID or wallet ID (Admin only)")]
    [SwaggerResponse(200, "Success")]
    public async Task<IActionResult> SearchWallets(
        [FromQuery] Guid? userId = null,
        [FromQuery] Guid? walletId = null,
        [FromQuery] string? status = null)
    {
        var query = new SearchWalletsQuery(userId, walletId, status);
        var result = await _mediator.Send(query);

        return Ok(new ApiResponse<List<AdminWalletDetailDto>>(true, "Success", result));
    }

    private Guid GetAdminId()
    {
        var userIdClaim = User.FindFirst("sub")?.Value ?? User.FindFirst("id")?.Value;
        return Guid.TryParse(userIdClaim, out var userId) ? userId : Guid.Empty;
    }
}

#region Admin Request/Response DTOs

public record AdminActionRequest(string Reason);

public record AdminAdjustBalanceRequest(
    decimal Amount,
    int CurrencyTypeId,
    string Reason);

#endregion
