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

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

namespace OrderService.API.Application.Queries;

/// <summary>
/// EN: Handler for listing orders by shop with filtering using Dapper.
/// VI: Handler liệt kê orders theo shop với lọc dùng Dapper.
/// </summary>
public class ListOrdersByShopQueryHandler : IRequestHandler<ListOrdersByShopQuery, PagedResult<OrderSummaryDto>>
{
    private readonly IDbConnection _connection;
    private readonly ILogger<ListOrdersByShopQueryHandler> _logger;

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

    public async Task<PagedResult<OrderSummaryDto>> Handle(
        ListOrdersByShopQuery request,
        CancellationToken cancellationToken)
    {
        var (whereClause, parameters) = BuildWhereClause(request);

        // EN: Get total count
        // VI: Lấy tổng số
        var countSql = $"SELECT COUNT(*) FROM orders o INNER JOIN order_statuses os ON o.status_id = os.id {whereClause}";
        var totalCount = await _connection.ExecuteScalarAsync<int>(countSql, parameters);

        // EN: Get paged data
        // VI: Lấy dữ liệu phân trang
        var sql = $@"
            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,
                (SELECT COUNT(*) FROM order_items WHERE order_id = o.id) AS ItemCount
            FROM orders o
            INNER JOIN order_statuses os ON o.status_id = os.id
            {whereClause}
            ORDER BY o.created_at DESC
            LIMIT @PageSize OFFSET @Offset";

        parameters.Add("PageSize", request.PageSize);
        parameters.Add("Offset", (request.Page - 1) * request.PageSize);

        var orders = await _connection.QueryAsync<OrderSummaryDto>(sql, parameters);

        return new PagedResult<OrderSummaryDto>(
            orders.ToList(),
            totalCount,
            request.PageSize,
            request.Page
        );
    }

    private static (string whereClause, DynamicParameters parameters) BuildWhereClause(ListOrdersByShopQuery request)
    {
        var conditions = new List<string> { "o.shop_id = @ShopId" };
        var parameters = new DynamicParameters();
        parameters.Add("ShopId", request.ShopId);

        if (!string.IsNullOrEmpty(request.Status))
        {
            conditions.Add("os.name = @Status");
            parameters.Add("Status", request.Status);
        }

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

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

        var whereClause = conditions.Count > 0
            ? "WHERE " + string.Join(" AND ", conditions)
            : string.Empty;

        return (whereClause, parameters);
    }
}
