// EN: Command to close the business day and generate final report.
// VI: Command dong ngay kinh doanh va tao bao cao cuoi cung.

using System.Data;
using Dapper;
using MediatR;
using OrderService.API.Application.Queries.Reports;

namespace OrderService.API.Application.Commands.Reports;

/// <summary>
/// EN: Command to close the business day for a shop and generate the final EOD report.
/// VI: Command dong ngay kinh doanh cho shop va tao bao cao cuoi ngay cuoi cung.
/// </summary>
public record CloseDayCommand(
    Guid ShopId,
    DateTime CloseDate
) : IRequest<CloseDayResult>;

/// <summary>
/// EN: Result of day close operation with final report.
/// VI: Ket qua thao tac dong ngay voi bao cao cuoi cung.
/// </summary>
public record CloseDayResult(
    bool Success,
    EodReportDto? Report,
    string? Message,
    int PendingOrderCount = 0
);

/// <summary>
/// EN: Handler for CloseDayCommand — validates no pending orders and generates final EOD report.
/// VI: Handler cho CloseDayCommand — kiem tra khong co don hang cho xu ly va tao bao cao cuoi ngay.
/// </summary>
public class CloseDayCommandHandler : IRequestHandler<CloseDayCommand, CloseDayResult>
{
    private readonly IDbConnection _connection;
    private readonly IMediator _mediator;
    private readonly ILogger<CloseDayCommandHandler> _logger;

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

    public async Task<CloseDayResult> Handle(CloseDayCommand request, CancellationToken cancellationToken)
    {
        _logger.LogInformation(
            "EN: Closing day for shop {ShopId} on {Date} / VI: Dong ngay cho shop {ShopId} ngay {Date}",
            request.ShopId, request.CloseDate.ToString("yyyy-MM-dd"));

        var dayStart = request.CloseDate.Date;
        var dayEnd = dayStart.AddDays(1);

        var parameters = new DynamicParameters();
        parameters.Add("ShopId", request.ShopId);
        parameters.Add("DayStart", dayStart);
        parameters.Add("DayEnd", dayEnd);

        // EN: Check for pending/in-progress orders (status: Draft=1, Validated=2, Paid=3, Processing=4, PaymentPending=7)
        // VI: Kiem tra don hang dang cho/dang xu ly (trang thai: Draft=1, Validated=2, Paid=3, Processing=4, PaymentPending=7)
        var pendingSql = @"
            SELECT COUNT(*)
            FROM orders o
            WHERE o.shop_id = @ShopId
              AND o.created_at >= @DayStart
              AND o.created_at < @DayEnd
              AND o.status_id IN (1, 2, 3, 4, 7)";

        var pendingCount = await _connection.ExecuteScalarAsync<int>(pendingSql, parameters, commandTimeout: 5);

        string? warningMessage = null;
        if (pendingCount > 0)
        {
            warningMessage = $"EN: Warning: {pendingCount} order(s) are still pending/in-progress. / " +
                             $"VI: Canh bao: {pendingCount} don hang van dang cho xu ly.";
            _logger.LogWarning(
                "EN: Closing day with {Count} pending orders for shop {ShopId} / VI: Dong ngay voi {Count} don hang dang cho cho shop {ShopId}",
                pendingCount, request.ShopId);
        }

        // EN: Generate the EOD report via the query handler / VI: Tao bao cao cuoi ngay qua query handler
        var report = await _mediator.Send(new GetEodReportQuery(request.ShopId, request.CloseDate), cancellationToken);

        _logger.LogInformation(
            "EN: Day closed for shop {ShopId} — {Orders} orders, {Revenue:C} revenue / " +
            "VI: Da dong ngay cho shop {ShopId} — {Orders} don hang, {Revenue:C} doanh thu",
            request.ShopId, report.TotalOrders, report.TotalRevenue);

        return new CloseDayResult(
            Success: true,
            Report: report,
            Message: warningMessage,
            PendingOrderCount: pendingCount);
    }
}
