using Microsoft.Extensions.Logging;
using TakeoutSaaS.Domain.Finance.Repositories;
using TakeoutSaaS.Shared.Abstractions.Tenancy;

namespace TakeoutSaaS.Module.Scheduler.Jobs;

/// <summary>
/// 经营报表快照刷新任务：消费排队中的报表快照并触发生成。
/// </summary>
public sealed class FinanceBusinessReportRefreshJob(
    IFinanceBusinessReportRepository financeBusinessReportRepository,
    ITenantContextAccessor tenantContextAccessor,
    ILogger<FinanceBusinessReportRefreshJob> logger)
{
    private const int BatchSize = 80;

    /// <summary>
    /// 执行报表快照刷新。
    /// </summary>
    public async Task ExecuteAsync()
    {
        // 1. 拉取待处理快照任务。
        var pendingList = await financeBusinessReportRepository.GetPendingSnapshotsAsync(BatchSize, CancellationToken.None);
        if (pendingList.Count == 0)
        {
            logger.LogDebug("定时任务：经营报表快照刷新无待处理任务");
            return;
        }

        // 2. 逐租户上下文执行生成。
        var successCount = 0;
        var failedCount = 0;
        foreach (var pending in pendingList)
        {
            var previousContext = tenantContextAccessor.Current;
            try
            {
                tenantContextAccessor.Current = new TenantContext(
                    pending.TenantId,
                    $"tenant-{pending.TenantId}",
                    "scheduler");

                await financeBusinessReportRepository.GenerateSnapshotAsync(
                    pending.SnapshotId,
                    CancellationToken.None);
                successCount += 1;
            }
            catch (Exception ex)
            {
                failedCount += 1;
                logger.LogError(
                    ex,
                    "定时任务：经营报表快照刷新失败 SnapshotId={SnapshotId}, TenantId={TenantId}",
                    pending.SnapshotId,
                    pending.TenantId);
            }
            finally
            {
                tenantContextAccessor.Current = previousContext;
            }
        }

        // 3. 记录执行结果。
        logger.LogInformation(
            "定时任务：经营报表快照刷新完成，处理 {TotalCount} 条，成功 {SuccessCount} 条，失败 {FailedCount} 条",
            pendingList.Count,
            successCount,
            failedCount);
    }
}
