// EN: Query to get top selling products.
// VI: Query lấy sản phẩm bán chạy nhất.

using System.Data;
using Dapper;
using MediatR;

namespace OrderService.API.Application.Queries;

/// <summary>
/// EN: Query for top selling products by shop.
/// VI: Query cho sản phẩm bán chạy theo shop.
/// </summary>
public record GetTopProductsQuery(
    Guid ShopId,
    int Limit = 10,
    DateTime? FromDate = null,
    DateTime? ToDate = null
) : IRequest<List<TopProductDto>>;

/// <summary>
/// EN: Top product DTO (class for Dapper compatibility).
/// VI: DTO sản phẩm bán chạy (class cho tương thích Dapper).
/// </summary>
public class TopProductDto
{
    public Guid ProductId { get; set; }
    public string ProductName { get; set; } = string.Empty;
    public long TotalQuantity { get; set; }
    public decimal TotalRevenue { get; set; }
    public long OrderCount { get; set; }
}

/// <summary>
/// EN: Handler for GetTopProductsQuery.
/// VI: Handler cho GetTopProductsQuery.
/// </summary>
public class GetTopProductsQueryHandler : IRequestHandler<GetTopProductsQuery, List<TopProductDto>>
{
    private readonly IDbConnection _connection;

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

    public async Task<List<TopProductDto>> Handle(GetTopProductsQuery request, CancellationToken cancellationToken)
    {
        var (whereClause, parameters) = BuildWhereClause(request.ShopId, request.FromDate, request.ToDate);
        parameters.Add("Limit", request.Limit);

        var sql = $@"
            SELECT
                oi.product_id AS ProductId,
                oi.product_name AS ProductName,
                SUM(oi.quantity) AS TotalQuantity,
                SUM(oi.unit_price * oi.quantity) AS TotalRevenue,
                COUNT(DISTINCT o.id) AS OrderCount
            FROM order_items oi
            INNER JOIN orders o ON o.id = oi.order_id
            {whereClause}
            GROUP BY oi.product_id, oi.product_name
            ORDER BY TotalQuantity DESC
            LIMIT @Limit";

        var result = (await _connection.QueryAsync<TopProductDto>(sql, parameters, commandTimeout: 5)).AsList();
        return result;
    }

    private static (string whereClause, DynamicParameters parameters) BuildWhereClause(
        Guid shopId,
        DateTime? fromDate,
        DateTime? toDate)
    {
        var conditions = new List<string> { "o.shop_id = @ShopId" };
        var parameters = new DynamicParameters();
        parameters.Add("ShopId", shopId);

        if (fromDate.HasValue)
        {
            conditions.Add("o.created_at >= @FromDate");
            parameters.Add("FromDate", fromDate.Value);
        }

        if (toDate.HasValue)
        {
            conditions.Add("o.created_at <= @ToDate");
            parameters.Add("ToDate", toDate.Value);
        }

        return ("WHERE " + string.Join(" AND ", conditions), parameters);
    }
}
