namespace WalletService.API.Controllers;

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

/// <summary>
/// EN: Controller for payment gateway operations.
/// VI: Controller cho cac thao tac cong thanh toan.
/// </summary>
[ApiController]
[Route("api/v1/[controller]")]
[SwaggerTag("Payment gateway endpoints / Cac endpoint cong thanh toan")]
public class PaymentsController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<PaymentsController> _logger;

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

    /// <summary>
    /// EN: Create a payment through a payment gateway.
    /// VI: Tao thanh toan qua cong thanh toan.
    /// </summary>
    [HttpPost("create")]
    [Authorize]
    [SwaggerOperation(Summary = "Create payment", Description = "Create a payment via payment gateway (VNPay, etc.)")]
    [SwaggerResponse(201, "Payment created", typeof(ApiResponse<CreatePaymentResult>))]
    [SwaggerResponse(400, "Invalid request")]
    public async Task<IActionResult> CreatePayment(
        [FromBody] CreatePaymentRequest request,
        CancellationToken cancellationToken)
    {
        var ipAddress = HttpContext.Connection.RemoteIpAddress?.ToString() ?? "127.0.0.1";

        var command = new CreatePaymentCommand(
            request.OrderId,
            request.Amount,
            request.Currency ?? "VND",
            request.GatewayName ?? "VNPAY",
            request.ReturnUrl,
            ipAddress);

        var result = await _mediator.Send(command, cancellationToken);

        return CreatedAtAction(
            nameof(GetPaymentByOrderId),
            new { orderId = result.OrderId },
            new ApiResponse<CreatePaymentResult>(true, "Payment created / Thanh toan da duoc tao", result));
    }

    /// <summary>
    /// EN: Get payment by order ID.
    /// VI: Lay thanh toan theo ma don hang.
    /// </summary>
    [HttpGet("{orderId:guid}")]
    [Authorize]
    [SwaggerOperation(Summary = "Get payment", Description = "Get payment information by order ID")]
    [SwaggerResponse(200, "Success", typeof(ApiResponse<PaymentDto>))]
    [SwaggerResponse(404, "Payment not found")]
    public async Task<IActionResult> GetPaymentByOrderId(
        Guid orderId,
        CancellationToken cancellationToken)
    {
        var result = await _mediator.Send(new GetPaymentByOrderIdQuery(orderId), cancellationToken);

        if (result == null)
            return NotFound(new ApiResponse<object>(false, "Payment not found / Khong tim thay thanh toan"));

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

    /// <summary>
    /// EN: VN Pay IPN callback endpoint (called by VN Pay server).
    /// VI: Endpoint IPN callback VN Pay (duoc goi boi server VN Pay).
    /// </summary>
    /// <remarks>
    /// EN: This endpoint does NOT require authentication as it is called by VN Pay servers.
    /// VI: Endpoint nay KHONG yeu cau xac thuc vi no duoc goi boi server VN Pay.
    /// </remarks>
    [HttpGet("vnpay/callback")]
    [AllowAnonymous]
    [SwaggerOperation(Summary = "VN Pay IPN callback", Description = "VN Pay server calls this endpoint to notify payment status")]
    [SwaggerResponse(200, "Callback processed")]
    public async Task<IActionResult> VnPayCallback(CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "EN: Received VN Pay IPN callback / " +
            "VI: Nhan IPN callback tu VN Pay");

        // EN: Collect all query parameters
        // VI: Thu thap tat ca cac tham so query
        var parameters = HttpContext.Request.Query
            .ToDictionary(q => q.Key, q => q.Value.ToString());

        var command = new ProcessPaymentCallbackCommand("VNPAY", parameters);
        var result = await _mediator.Send(command, cancellationToken);

        // EN: VN Pay expects specific response format
        // VI: VN Pay yeu cau format phan hoi cu the
        if (result.Success)
        {
            return Ok(new { RspCode = "00", Message = "Confirm Success" });
        }

        return Ok(new { RspCode = "99", Message = result.ErrorMessage ?? "Unknown error" });
    }

    /// <summary>
    /// EN: VN Pay return URL handler (customer is redirected here after payment).
    /// VI: Handler URL tra ve VN Pay (khach hang duoc chuyen huong den day sau thanh toan).
    /// </summary>
    [HttpGet("vnpay/return")]
    [AllowAnonymous]
    [SwaggerOperation(Summary = "VN Pay return", Description = "Customer is redirected here after VN Pay payment")]
    [SwaggerResponse(200, "Payment result")]
    public async Task<IActionResult> VnPayReturn(CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "EN: Customer returned from VN Pay / " +
            "VI: Khach hang quay ve tu VN Pay");

        // EN: Collect all query parameters
        // VI: Thu thap tat ca cac tham so query
        var parameters = HttpContext.Request.Query
            .ToDictionary(q => q.Key, q => q.Value.ToString());

        var command = new ProcessPaymentCallbackCommand("VNPAY", parameters);
        var result = await _mediator.Send(command, cancellationToken);

        return Ok(new ApiResponse<ProcessPaymentCallbackResult>(
            result.Success,
            result.Success
                ? "Payment successful / Thanh toan thanh cong"
                : "Payment failed / Thanh toan that bai",
            result));
    }
}

#region Request DTOs

/// <summary>
/// EN: Request DTO for creating a payment.
/// VI: DTO yeu cau de tao thanh toan.
/// </summary>
public record CreatePaymentRequest(
    Guid OrderId,
    decimal Amount,
    string? Currency,
    string? GatewayName,
    string ReturnUrl
);

#endregion
