using Hangfire;
using Meezi.API.Jobs;
using Meezi.Core.Delivery;
using Meezi.Core.Entities;
using Meezi.Core.Enums;
using Meezi.Infrastructure.Data;

namespace Meezi.API.Services.Delivery;

public record WebhookIngressResult(bool Accepted, string? WebhookLogId, string? ErrorCode, string? Message);

public interface IDeliveryWebhookIngressService
{
    Task<WebhookIngressResult> ReceiveAsync(
        DeliveryPlatform platform,
        string rawBody,
        string? signatureHeader,
        CancellationToken ct = default);
}

public class DeliveryWebhookIngressService : IDeliveryWebhookIngressService
{
    private readonly AppDbContext _db;
    private readonly IWebhookSignatureService _signatures;
    private readonly IOrderNormalizer _normalizer;

    public DeliveryWebhookIngressService(
        AppDbContext db,
        IWebhookSignatureService signatures,
        IOrderNormalizer normalizer)
    {
        _db = db;
        _signatures = signatures;
        _normalizer = normalizer;
    }

    public async Task<WebhookIngressResult> ReceiveAsync(
        DeliveryPlatform platform,
        string rawBody,
        string? signatureHeader,
        CancellationToken ct = default)
    {
        var signatureValid = _signatures.Verify(platform, rawBody, signatureHeader);

        var log = new WebhookLog
        {
            Id = $"wh_{Guid.NewGuid():N}"[..24],
            Platform = platform,
            RawBody = rawBody,
            SignatureHeader = signatureHeader,
            SignatureValid = signatureValid,
            CreatedAt = DateTime.UtcNow
        };

        _db.WebhookLogs.Add(log);
        await _db.SaveChangesAsync(ct);

        if (!signatureValid)
            return new WebhookIngressResult(false, log.Id, "UNAUTHORIZED", "Invalid signature.");

        var unified = _normalizer.FromJson(platform, rawBody);
        if (unified is null)
        {
            log.Success = false;
            log.Processed = true;
            log.ErrorMessage = "Could not normalize payload.";
            log.ProcessedAt = DateTime.UtcNow;
            await _db.SaveChangesAsync(ct);
            return new WebhookIngressResult(false, log.Id, "VALIDATION_ERROR", log.ErrorMessage);
        }

        BackgroundJob.Enqueue<ProcessDeliveryOrderJob>(job =>
            job.ExecuteAsync(log.Id, unified, CancellationToken.None));

        return new WebhookIngressResult(true, log.Id, null, null);
    }
}
