namespace WalletService.API.Controllers;

using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations;
using WalletService.API.Application.Commands;

/// <summary>
/// EN: Controller for escrow/hold management operations.
/// VI: Controller cho các thao tác quản lý escrow/hold.
/// </summary>
[ApiController]
[Route("api/v1/wallets/{walletId:guid}/holds")]
[Authorize]
[SwaggerTag("Escrow/Hold management endpoints / Các endpoint quản lý ký quỹ")]
public class HoldsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<HoldsController> _logger;

    public HoldsController(IMediator mediator, ILogger<HoldsController> logger)
    {
        _mediator = mediator;
        _logger = logger;
    }

    /// <summary>
    /// EN: Create an escrow hold on a wallet.
    /// VI: Tạo escrow hold trên ví.
    /// </summary>
    [HttpPost]
    [SwaggerOperation(Summary = "Create hold", Description = "Create an escrow hold - lock funds for a campaign or order")]
    [SwaggerResponse(201, "Hold created", typeof(ApiResponse<HoldResult>))]
    [SwaggerResponse(400, "Invalid request or insufficient balance")]
    [SwaggerResponse(404, "Wallet not found")]
    public async Task<IActionResult> CreateHold(Guid walletId, [FromBody] CreateHoldRequest request)
    {
        var command = new CreateHoldCommand(
            request.UserId,
            request.Amount,
            request.CurrencyCode,
            request.ReferenceType,
            request.ReferenceId,
            request.Description,
            request.ExpiresAt);

        var result = await _mediator.Send(command);

        return CreatedAtAction(
            nameof(GetHold),
            new { walletId = result.WalletId, holdId = result.HoldId },
            new ApiResponse<HoldResult>(true, "Hold created", result));
    }

    /// <summary>
    /// EN: Get a specific hold by ID.
    /// VI: Lấy hold theo ID.
    /// </summary>
    [HttpGet("{holdId:guid}")]
    [SwaggerOperation(Summary = "Get hold", Description = "Get escrow hold details by ID")]
    [SwaggerResponse(200, "Success", typeof(ApiResponse<HoldResult>))]
    [SwaggerResponse(404, "Hold not found")]
    public async Task<IActionResult> GetHold(Guid walletId, Guid holdId)
    {
        // For now, return 501 - implement query later
        return StatusCode(501, new ApiResponse<object>(false, "Not implemented - use Query service"));
    }

    /// <summary>
    /// EN: Execute (commit) a portion of an escrow hold.
    /// VI: Thực thi (cam kết) một phần escrow hold.
    /// </summary>
    [HttpPost("{holdId:guid}/execute")]
    [SwaggerOperation(Summary = "Execute hold", Description = "Execute/commit a portion of the escrowed funds")]
    [SwaggerResponse(200, "Execution successful", typeof(ApiResponse<HoldResult>))]
    [SwaggerResponse(400, "Invalid request or insufficient held amount")]
    [SwaggerResponse(404, "Wallet or hold not found")]
    public async Task<IActionResult> ExecuteHold(Guid walletId, Guid holdId, [FromBody] ExecuteHoldRequest request)
    {
        var command = new ExecuteHoldCommand(walletId, holdId, request.Amount, request.ExecutionRef);
        var result = await _mediator.Send(command);

        return Ok(new ApiResponse<HoldResult>(true, "Hold executed", result));
    }

    /// <summary>
    /// EN: Release (return) a portion of an escrow hold back to the wallet.
    /// VI: Giải phóng (trả lại) một phần escrow hold về ví.
    /// </summary>
    [HttpPost("{holdId:guid}/release")]
    [SwaggerOperation(Summary = "Release hold", Description = "Release/return escrowed funds back to wallet")]
    [SwaggerResponse(200, "Release successful", typeof(ApiResponse<HoldResult>))]
    [SwaggerResponse(400, "Invalid request")]
    [SwaggerResponse(404, "Wallet or hold not found")]
    public async Task<IActionResult> ReleaseHold(Guid walletId, Guid holdId, [FromBody] ReleaseHoldRequest request)
    {
        var command = new ReleaseHoldCommand(walletId, holdId, request.Amount);
        var result = await _mediator.Send(command);

        return Ok(new ApiResponse<HoldResult>(true, "Hold released", result));
    }

    /// <summary>
    /// EN: Cancel an escrow hold and release all remaining back to wallet.
    /// VI: Hủy escrow hold và giải phóng tất cả còn lại về ví.
    /// </summary>
    [HttpPost("{holdId:guid}/cancel")]
    [SwaggerOperation(Summary = "Cancel hold", Description = "Cancel hold and release all remaining funds")]
    [SwaggerResponse(200, "Cancel successful", typeof(ApiResponse<HoldResult>))]
    [SwaggerResponse(404, "Wallet or hold not found")]
    public async Task<IActionResult> CancelHold(Guid walletId, Guid holdId)
    {
        var command = new CancelHoldCommand(walletId, holdId);
        var result = await _mediator.Send(command);

        return Ok(new ApiResponse<HoldResult>(true, "Hold cancelled", result));
    }
}

#region Request DTOs

public record CreateHoldRequest(
    Guid UserId,
    decimal Amount,
    string CurrencyCode,
    string ReferenceType,
    Guid ReferenceId,
    string Description,
    DateTime? ExpiresAt = null
);

public record ExecuteHoldRequest(
    decimal Amount,
    string? ExecutionRef = null
);

public record ReleaseHoldRequest(
    decimal? Amount = null  // null = release all remaining
);

#endregion
