using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Tiku.Application.Jobs;
using Tiku.Domain.Commerce;
using Tiku.Domain.Tenancy;
using Tiku.Infrastructure.Jobs;
using Tiku.Infrastructure.Persistence;

namespace Tiku.Infrastructure.Commerce.Reconciliation;

internal sealed class CommerceReconciliationJobHandler(TikuDbContext dbContext) : IBackgroundJobHandler
{
    public string JobType => "commerce_reconciliation";

    public async Task<BackgroundJobHandlerResult> HandleAsync(
        BackgroundJobExecutionContext context,
        CancellationToken cancellationToken = default)
    {
        var provider = NormalizeProvider(BackgroundJobPayload.GetString(context.Payload, "provider"));
        var hasProviderConfig = await dbContext.TenantExternalProviders.AnyAsync(
            item =>
                item.TenantId == context.TenantId &&
                item.Capability == TenantExternalProviderCapability.Payment &&
                item.Provider == provider &&
                item.Status == TenantExternalProviderStatus.Active,
            cancellationToken);
        if (!hasProviderConfig)
            throw new InvalidOperationException(
                $"Active payment provider '{provider}' is required for commerce reconciliation job.");

        var billDate = BackgroundJobPayload.GetDateOnly(context.Payload, "billDate") ??
                       DateOnly.FromDateTime(DateTime.UtcNow.Date);
        var billType = BackgroundJobPayload.GetEnum(context.Payload, "billType", ReconciliationBillType.Combined);
        var sourceHash = $"background-job:{context.JobId:N}";
        var batch = await dbContext.CommerceReconciliationBatches.SingleOrDefaultAsync(
            item =>
                item.TenantId == context.TenantId &&
                item.Provider == provider &&
                item.Source == ReconciliationSource.ProviderDownload &&
                item.SourceHash == sourceHash,
            cancellationToken);
        if (batch is null)
        {
            batch = new CommerceReconciliationBatch
            {
                TenantId = context.TenantId,
                Provider = provider,
                BillDate = billDate,
                BillType = billType,
                Source = ReconciliationSource.ProviderDownload,
                SourceName = $"provider-bill:{provider}:{billDate:yyyyMMdd}",
                SourceHash = sourceHash,
                Status = ReconciliationBatchStatus.Pending,
                Metadata = JsonSerializer.SerializeToElement(new
                {
                    jobId = context.JobId,
                    note =
                        "Provider bill job created the reconciliation batch; provider download/parser is handled by a dedicated provider processor."
                })
            };
            dbContext.CommerceReconciliationBatches.Add(batch);
            await dbContext.SaveChangesAsync(cancellationToken);
        }

        return new BackgroundJobHandlerResult(JsonSerializer.SerializeToElement(new
        {
            batchId = batch.Id,
            provider,
            billDate,
            billType = billType.ToString(),
            status = batch.Status.ToString()
        }));
    }

    private static string NormalizeProvider(string? provider)
    {
        var normalized = (provider ?? string.Empty).Trim().ToLowerInvariant();
        return string.IsNullOrWhiteSpace(normalized)
            ? throw new InvalidOperationException("Background job provider is required.")
            : normalized;
    }
}
