using FastEndpoints;
using Microsoft.Extensions.Options;
using Stripe;
using Stripe.Checkout;
using TrackQrApi.Features.Billing.Services;
using TrackQrApi.Features.Billing.Settings;

namespace TrackQrApi.Features.Billing.Endpoints;

public class StripeWebhookEndpoint(
    IStripeService stripeService,
    IOptions<StripeSettings> settings,
    ILogger<StripeWebhookEndpoint> logger)
    : EndpointWithoutRequest
{
    private readonly StripeSettings _settings = settings.Value;

    public override void Configure()
    {
        Post("/billing/webhook");
        AllowAnonymous();
    }

    public override async Task HandleAsync(CancellationToken ct)
    {
        var json = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync(ct);

        try
        {
            var stripeSignature = HttpContext.Request.Headers["Stripe-Signature"].ToString();
            var stripeEvent = EventUtility.ConstructEvent(
                json,
                stripeSignature,
                _settings.WebhookSecret
            );

            logger.LogInformation("Received Stripe event: {EventType} ({EventId})", stripeEvent.Type, stripeEvent.Id);

            switch (stripeEvent.Type)
            {
                case "checkout.session.completed":
                    var session = stripeEvent.Data.Object as Session;
                    if (session != null) await stripeService.HandleCheckoutCompletedAsync(session, ct);
                    break;

                case "customer.subscription.updated":
                    var updatedSubscription = stripeEvent.Data.Object as Subscription;
                    if (updatedSubscription != null)
                        await stripeService.HandleSubscriptionUpdatedAsync(updatedSubscription, ct);
                    break;

                case "customer.subscription.deleted":
                    var deletedSubscription = stripeEvent.Data.Object as Subscription;
                    if (deletedSubscription != null)
                        await stripeService.HandleSubscriptionDeletedAsync(deletedSubscription, ct);
                    break;

                case "invoice.payment_failed":
                    logger.LogWarning("Payment failed for invoice: {InvoiceId}",
                        (stripeEvent.Data.Object as Invoice)?.Id);
                    break;

                default:
                    logger.LogDebug("Unhandled Stripe event type: {EventType}", stripeEvent.Type);
                    break;
            }

            await HttpContext.Response.SendAsync(new { received = true }, cancellation: ct);
        }
        catch (StripeException ex)
        {
            logger.LogError(ex, "Stripe webhook signature verification failed");
            await HttpContext.Response.SendAsync(new { error = "Webhook signature verification failed" }, 400,
                cancellation: ct);
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "Error processing Stripe webhook");
            await HttpContext.Response.SendAsync(new { error = "Webhook processing failed" }, 500, cancellation: ct);
        }
    }
}