// EN: Orders REST API Controller.
// VI: Controller REST API cho Orders.

using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using OrderService.API.Application.Commands;
using OrderService.API.Application.DTOs;
using OrderService.API.Application.Queries;

namespace OrderService.API.Controllers;

/// <summary>
/// EN: Orders API Controller for order management.
/// VI: Controller API Orders cho quản lý đơn hàng.
/// </summary>
[ApiController]
[Route("api/v1/orders")]
[Authorize]
public class OrdersController : ControllerBase
{
    private readonly IMediator _mediator;
    private readonly ILogger<OrdersController> _logger;

    public OrdersController(
        IMediator mediator,
        ILogger<OrdersController> logger)
    {
        _mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    /// <summary>
    /// EN: Create a new order.
    /// VI: Tạo order mới.
    /// </summary>
    [HttpPost]
    [ProducesResponseType(typeof(CreateOrderResult), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<CreateOrderResult>> CreateOrder(
        [FromBody] CreateOrderCommand command,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Creating order for shop {ShopId} / VI: Tạo order cho shop {ShopId}",
            command.ShopId);

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

        return CreatedAtAction(
            nameof(GetOrderById),
            new { id = result.OrderId },
            result);
    }

    /// <summary>
    /// EN: Get order by ID.
    /// VI: Lấy order theo ID.
    /// </summary>
    [HttpGet("{id}")]
    [ProducesResponseType(typeof(OrderDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<OrderDto>> GetOrderById(
        Guid id,
        [FromQuery] Guid shopId,
        CancellationToken cancellationToken = default)
    {
        var query = new GetOrderByIdQuery(id, shopId);
        var result = await _mediator.Send(query, cancellationToken);

        if (result == null)
        {
            return NotFound(new { success = false, error = new { code = "ORDER_NOT_FOUND", message = $"Order with ID {id} not found" } });
        }

        return Ok(result);
    }

    /// <summary>
    /// EN: List orders by shop with filtering and pagination.
    /// VI: Liệt kê orders theo shop có lọc và phân trang.
    /// </summary>
    [HttpGet]
    [ProducesResponseType(typeof(PagedResult<OrderSummaryDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResult<OrderSummaryDto>>> ListOrdersByShop(
        [FromQuery] Guid shopId,
        [FromQuery] string? status = null,
        [FromQuery] DateTime? fromDate = null,
        [FromQuery] DateTime? toDate = null,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        CancellationToken cancellationToken = default)
    {
        var query = new ListOrdersByShopQuery(
            shopId,
            status,
            fromDate,
            toDate,
            page,
            pageSize);

        var result = await _mediator.Send(query, cancellationToken);
        return Ok(result);
    }

    /// <summary>
    /// EN: Process payment for an order with payment method details.
    /// VI: Xử lý thanh toán cho order với chi tiết phương thức thanh toán.
    /// </summary>
    [HttpPost("{id}/pay")]
    [ProducesResponseType(typeof(PayOrderResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<PayOrderResult>> PayOrder(
        Guid id,
        [FromQuery] Guid shopId,
        [FromBody] PayOrderRequest? request = null,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Processing {Method} payment for order {OrderId} / VI: Xử lý thanh toán {Method} cho order {OrderId}",
            request?.PaymentMethod ?? "unknown", id);

        var command = new PayOrderCommand(
            id,
            shopId,
            request?.PaymentMethod ?? "cash",
            request?.AmountTendered,
            request?.ReturnUrl,
            HttpContext.Connection.RemoteIpAddress?.ToString());

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

        if (!result.Success)
        {
            return BadRequest(new { success = false, error = new { code = "PAYMENT_FAILED", message = result.ErrorMessage } });
        }

        return Ok(new { success = true, data = result });
    }

    /// <summary>
    /// EN: Payment callback endpoint — called by wallet-service after payment gateway confirms.
    /// VI: Endpoint callback thanh toán — được gọi bởi wallet-service sau khi cổng thanh toán xác nhận.
    /// </summary>
    [HttpPost("{id}/payment-callback")]
    [ProducesResponseType(typeof(CompleteOrderPaymentResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CompleteOrderPaymentResult>> PaymentCallback(
        Guid id,
        [FromBody] PaymentCallbackRequest request,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Payment callback for order {OrderId}, success: {IsSuccess} / VI: Callback thanh toán cho order {OrderId}, thành công: {IsSuccess}",
            id, request.IsSuccess);

        var command = new CompleteOrderPaymentCommand(
            id,
            request.GatewayTransactionId,
            request.IsSuccess,
            request.GatewayResponseCode);

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

        if (!result.Success)
        {
            return BadRequest(new { success = false, error = new { code = "PAYMENT_CALLBACK_FAILED", message = result.ErrorMessage } });
        }

        return Ok(new { success = true, data = result });
    }

    /// <summary>
    /// EN: Cancel an order.
    /// VI: Hủy order.
    /// </summary>
    [HttpPost("{id}/cancel")]
    [ProducesResponseType(typeof(CancelOrderResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CancelOrderResult>> CancelOrder(
        Guid id,
        [FromQuery] Guid shopId,
        [FromBody] CancelOrderRequest request,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Cancelling order {OrderId} / VI: Hủy order {OrderId}",
            id);

        var command = new CancelOrderCommand(id, shopId, request.Reason);
        var result = await _mediator.Send(command, cancellationToken);

        return Ok(result);
    }

    /// <summary>
    /// EN: Complete an order.
    /// VI: Hoàn thành order.
    /// </summary>
    [HttpPost("{id}/complete")]
    [ProducesResponseType(typeof(CompleteOrderResult), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CompleteOrderResult>> CompleteOrder(
        Guid id,
        [FromQuery] Guid shopId,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Completing order {OrderId} / VI: Hoàn thành order {OrderId}",
            id);

        var command = new CompleteOrderCommand(id, shopId);
        var result = await _mediator.Send(command, cancellationToken);

        return Ok(result);
    }

    /// <summary>
    /// EN: Get POS dashboard stats for today.
    /// VI: Lấy thống kê dashboard POS cho hôm nay.
    /// </summary>
    [HttpGet("dashboard")]
    [ProducesResponseType(typeof(PosDashboardDto), StatusCodes.Status200OK)]
    public async Task<ActionResult<PosDashboardDto>> GetPosDashboard(
        [FromQuery] Guid shopId,
        [FromQuery] string? period = "today",
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Getting POS dashboard for shop {ShopId} period {Period} / VI: Lấy dashboard POS cho shop {ShopId} kỳ {Period}",
            shopId, period);

        var query = new GetPosDashboardQuery(shopId, period);
        var result = await _mediator.Send(query, cancellationToken);

        return Ok(result);
    }

    /// <summary>
    /// EN: Get active (unpaid) orders grouped by table for a shop.
    /// VI: Lấy orders chưa thanh toán nhóm theo bàn cho shop.
    /// </summary>
    [HttpGet("active-by-table")]
    [ProducesResponseType(typeof(List<ActiveTableOrderDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<List<ActiveTableOrderDto>>> GetActiveTableOrders(
        [FromQuery] Guid shopId,
        CancellationToken cancellationToken = default)
    {
        var query = new GetActiveTableOrdersQuery(shopId);
        var result = await _mediator.Send(query, cancellationToken);
        return Ok(result);
    }

    /// <summary>
    /// EN: Process a return for a completed order.
    /// VI: Xử lý trả hàng cho đơn hàng đã hoàn thành.
    /// </summary>
    [HttpPost("returns")]
    [ProducesResponseType(typeof(CreateReturnResult), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<CreateReturnResult>> CreateReturn(
        [FromBody] CreateReturnCommand command,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Creating return for order {OriginalOrderId} in shop {ShopId} / VI: Tạo trả hàng cho đơn {OriginalOrderId} trong shop {ShopId}",
            command.OriginalOrderId, command.ShopId);

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

        if (!result.Success)
        {
            return BadRequest(new { success = false, error = new { code = "RETURN_FAILED", message = result.ErrorMessage } });
        }

        return Created($"/api/v1/orders/{result.ReturnOrderId}", new { success = true, data = result });
    }

    /// <summary>
    /// EN: Process an exchange (return + new order).
    /// VI: Xử lý đổi hàng (trả hàng + đơn mới).
    /// </summary>
    [HttpPost("exchanges")]
    [ProducesResponseType(typeof(CreateExchangeResult), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<ActionResult<CreateExchangeResult>> CreateExchange(
        [FromBody] CreateExchangeCommand command,
        CancellationToken cancellationToken = default)
    {
        _logger.LogInformation(
            "EN: Creating exchange for order {OriginalOrderId} in shop {ShopId} / VI: Tạo đổi hàng cho đơn {OriginalOrderId} trong shop {ShopId}",
            command.OriginalOrderId, command.ShopId);

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

        if (!result.Success)
        {
            return BadRequest(new { success = false, error = new { code = "EXCHANGE_FAILED", message = result.ErrorMessage } });
        }

        return Created($"/api/v1/orders/{result.NewOrderId}", new { success = true, data = result });
    }

    /// <summary>
    /// EN: Get return history for an order.
    /// VI: Lấy lịch sử trả hàng cho đơn hàng.
    /// </summary>
    [HttpGet("{orderId}/returns")]
    [ProducesResponseType(typeof(List<ReturnOrderDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<List<ReturnOrderDto>>> GetOrderReturns(
        Guid orderId,
        CancellationToken cancellationToken = default)
    {
        var query = new GetOrderReturnsQuery(orderId);
        var result = await _mediator.Send(query, cancellationToken);
        return Ok(new { success = true, data = result });
    }

    /// <summary>
    /// EN: Get orders by customer.
    /// VI: Lấy orders theo khách hàng.
    /// </summary>
    [HttpGet("customer/{customerId}")]
    [ProducesResponseType(typeof(PagedResult<OrderSummaryDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResult<OrderSummaryDto>>> GetOrdersByCustomer(
        Guid customerId,
        [FromQuery] int page = 1,
        [FromQuery] int pageSize = 20,
        CancellationToken cancellationToken = default)
    {
        var query = new GetOrdersByCustomerQuery(customerId, page, pageSize);
        var result = await _mediator.Send(query, cancellationToken);

        return Ok(result);
    }
}

/// <summary>
/// EN: Request to cancel an order.
/// VI: Yêu cầu hủy order.
/// </summary>
public record CancelOrderRequest(string Reason);

/// <summary>
/// EN: Request to pay an order with payment method details.
/// VI: Yêu cầu thanh toán order với chi tiết phương thức thanh toán.
/// </summary>
public record PayOrderRequest(
    string? PaymentMethod,      // EN: "cash", "card", "vnpay", "momo", "qr", "transfer" / VI: Phương thức thanh toán
    decimal? AmountTendered,    // EN: For cash payments / VI: Cho thanh toán tiền mặt
    string? ReturnUrl           // EN: For online payments / VI: Cho thanh toán trực tuyến
);

/// <summary>
/// EN: Payment callback request from wallet-service.
/// VI: Yêu cầu callback thanh toán từ wallet-service.
/// </summary>
public record PaymentCallbackRequest(
    string GatewayTransactionId,
    bool IsSuccess,
    string? GatewayResponseCode
);
