<?php

namespace App\Jobs;

use App\Models\EventPurchase;
use App\Models\Tenant;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ValidateStripeWebhookJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $payload;
    public $sig;
    public $tries = 3;
    public $backoff = [60, 300, 600]; // Retry delays

    public function __construct($payload, $sig)
    {
        $this->payload = $payload;
        $this->sig = $sig;
    }

    public function handle()
    {
        $secret = config('services.stripe.webhook');

        if (!$secret) {
            Log::error('No Stripe webhook secret configured');
            return;
        }

        $expectedSig = 'v1=' . hash_hmac('sha256', $this->payload, $secret);

        if (!hash_equals($expectedSig, $this->sig)) {
            Log::error('Invalid signature in Stripe webhook job');
            return;
        }

        $event = json_decode($this->payload, true);

        if (json_last_error() !== JSON_ERROR_NONE) {
            Log::error('Invalid JSON in Stripe webhook job: ' . json_last_error_msg());
            return;
        }

        if ($event['type'] === 'checkout.session.completed') {
            $session = $event['data']['object'];
            $receiptId = $session['id'];

            if (EventPurchase::where('external_receipt_id', $receiptId)->exists()) {
                return;
            }

            $tenantId = $session['metadata']['tenant_id'] ?? null;

            if (!$tenantId) {
                Log::warning('No tenant_id in Stripe metadata job', ['receipt_id' => $receiptId]);
                return;
            }

            $tenant = Tenant::find($tenantId);

            if (!$tenant) {
                Log::error('Tenant not found in Stripe webhook job', ['tenant_id' => $tenantId]);
                return;
            }

            $amount = $session['amount_total'] / 100;
            $currency = $session['currency'];
            $eventsPurchased = (int) ($session['metadata']['events_purchased'] ?? 1);

            DB::transaction(function () use ($tenant, $amount, $currency, $eventsPurchased, $receiptId) {
                $purchase = EventPurchase::create([
                    'tenant_id' => $tenant->id,
                    'events_purchased' => $eventsPurchased,
                    'amount' => $amount,
                    'currency' => $currency,
                    'provider' => 'stripe',
                    'external_receipt_id' => $receiptId,
                    'status' => 'completed',
                    'purchased_at' => now(),
                ]);

            });

            Log::info('Processed Stripe purchase via job', ['receipt_id' => $receiptId, 'tenant_id' => $tenantId]);
        } else {
            Log::info('Unhandled Stripe event in job', ['type' => $event['type']]);
        }
    }
}
