// EN: Handler for GetOrderByIdQuery using Dapper.
// VI: Handler cho GetOrderByIdQuery dùng Dapper.

using System.Data;
using Dapper;
using MediatR;
using OrderService.API.Application.DTOs;

namespace OrderService.API.Application.Queries;

/// <summary>
/// EN: Handler for getting order by ID using optimized Dapper query.
/// VI: Handler lấy order theo ID dùng Dapper query tối ưu.
/// </summary>
public class GetOrderByIdQueryHandler : IRequestHandler<GetOrderByIdQuery, OrderDto?>
{
    private readonly IDbConnection _connection;
    private readonly ILogger<GetOrderByIdQueryHandler> _logger;

    public GetOrderByIdQueryHandler(
        IDbConnection connection,
        ILogger<GetOrderByIdQueryHandler> logger)
    {
        _connection = connection ?? throw new ArgumentNullException(nameof(connection));
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    public async Task<OrderDto?> Handle(
        GetOrderByIdQuery request,
        CancellationToken cancellationToken)
    {
        const string orderSql = @"
            SELECT 
                o.id AS Id,
                o.shop_id AS ShopId,
                o.customer_id AS CustomerId,
                os.name AS Status,
                o.total_amount AS TotalAmount,
                o.created_at AS CreatedAt,
                o.updated_at AS UpdatedAt
            FROM orders o
            INNER JOIN order_statuses os ON o.status_id = os.id
            WHERE o.id = @OrderId AND o.shop_id = @ShopId";

        const string itemsSql = @"
            SELECT
                oi.id AS Id,
                oi.product_id AS ProductId,
                oi.product_name AS ProductName,
                oi.product_type AS ProductType,
                oi.quantity AS Quantity,
                oi.unit_price AS UnitPrice,
                (oi.quantity * oi.unit_price) AS TotalPrice,
                oi.status AS Status
            FROM order_items oi
            WHERE oi.order_id = @OrderId
            ORDER BY oi.id";

        // EN: Query order header
        // VI: Query order header
        var order = await _connection.QueryFirstOrDefaultAsync<OrderDtoRecord>(
            orderSql,
            new { request.OrderId, request.ShopId });

        if (order == null)
        {
            _logger.LogWarning(
                "EN: Order not found / VI: Không tìm thấy order: {OrderId}",
                request.OrderId);
            return null;
        }

        // EN: Query order items
        // VI: Query order items
        var items = await _connection.QueryAsync<OrderItemDto>(
            itemsSql,
            new { request.OrderId });

        return new OrderDto(
            order.Id,
            order.ShopId,
            order.CustomerId,
            order.Status,
            order.TotalAmount,
            order.CreatedAt,
            order.UpdatedAt,
            items.ToList()
        );
    }

    // EN: Helper record for Dapper mapping
    // VI: Record helper cho Dapper mapping
    private record OrderDtoRecord(
        Guid Id,
        Guid ShopId,
        Guid? CustomerId,
        string Status,
        decimal TotalAmount,
        DateTime CreatedAt,
        DateTime? UpdatedAt
    );
}
