// EN: Query to get active (unpaid) orders for a shop, grouped by table — includes items.
// VI: Query lấy orders chưa thanh toán của shop, nhóm theo bàn — bao gồm items.

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

namespace OrderService.API.Application.Queries;

public record GetActiveTableOrdersQuery(Guid ShopId) : IRequest<List<ActiveTableOrderDto>>;

public record ActiveTableOrderDto
{
    public Guid OrderId { get; init; }
    public Guid? TableId { get; init; }
    public decimal TotalAmount { get; init; }
    public DateTime CreatedAt { get; init; }
    public List<ActiveTableOrderItemDto> Items { get; init; } = new();
}

public record ActiveTableOrderItemDto
{
    public Guid ProductId { get; init; }
    public string ProductName { get; init; } = string.Empty;
    public int Quantity { get; init; }
    public decimal UnitPrice { get; init; }
}

public class GetActiveTableOrdersQueryHandler : IRequestHandler<GetActiveTableOrdersQuery, List<ActiveTableOrderDto>>
{
    private readonly IDbConnection _connection;

    public GetActiveTableOrdersQueryHandler(IDbConnection connection)
    {
        _connection = connection ?? throw new ArgumentNullException(nameof(connection));
    }

    public async Task<List<ActiveTableOrderDto>> Handle(
        GetActiveTableOrdersQuery request,
        CancellationToken cancellationToken)
    {
        // EN: Get active orders (status = Validated=2) with table_id for this shop
        // VI: Lấy orders đang active (status = Validated=2) có table_id cho shop này
        var ordersSql = @"
            SELECT o.id AS OrderId, o.table_id AS TableId, o.total_amount AS TotalAmount, o.created_at AS CreatedAt
            FROM orders o
            WHERE o.shop_id = @ShopId AND o.status_id = 2 AND o.table_id IS NOT NULL
            ORDER BY o.created_at";

        var orders = (await _connection.QueryAsync<ActiveTableOrderDto>(ordersSql, new { request.ShopId }, commandTimeout: 5)).ToList();
        if (!orders.Any()) return orders;

        // EN: Get items for all active orders in one query
        // VI: Lấy items cho tất cả active orders trong 1 query
        var orderIds = orders.Select(o => o.OrderId).ToArray();
        var itemsSql = @"
            SELECT oi.order_id AS OrderId, oi.product_id AS ProductId, oi.product_name AS ProductName,
                   oi.quantity AS Quantity, oi.unit_price AS UnitPrice
            FROM order_items oi
            WHERE oi.order_id = ANY(@OrderIds)";

        var items = await _connection.QueryAsync<(Guid OrderId, Guid ProductId, string ProductName, int Quantity, decimal UnitPrice)>(
            itemsSql, new { OrderIds = orderIds }, commandTimeout: 5);

        var itemsByOrder = items.GroupBy(i => i.OrderId).ToDictionary(g => g.Key, g => g.ToList());

        return orders.Select(o => o with
        {
            Items = itemsByOrder.TryGetValue(o.OrderId, out var orderItems)
                ? orderItems.Select(i => new ActiveTableOrderItemDto
                {
                    ProductId = i.ProductId,
                    ProductName = i.ProductName,
                    Quantity = i.Quantity,
                    UnitPrice = i.UnitPrice
                }).ToList()
                : new()
        }).ToList();
    }
}
