<?php

declare(strict_types=1);

namespace App\Http\Controllers\Webhooks;

use App\Events\PaymentFailed;
use App\Events\PaymentSucceeded;
use App\Events\SubscriptionCancelled;
use App\Models\Invoice;
use App\Models\PaymentTransaction;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Laravel\Cashier\Http\Controllers\WebhookController;
use Symfony\Component\HttpFoundation\Response;

class StripeWebhookController extends WebhookController
{
    public function handleInvoicePaymentSucceeded(array $payload): Response
    {
        $stripeInvoice = $payload['data']['object'] ?? [];
        $stripeCustomerId = $stripeInvoice['customer'] ?? null;

        $user = User::where('stripe_id', $stripeCustomerId)->first();

        if (! $user) {
            Log::warning('Stripe webhook: user not found for customer', ['stripe_customer' => $stripeCustomerId]);

            return $this->successMethod();
        }

        $transaction = PaymentTransaction::create([
            'user_id' => $user->id,
            'gateway' => 'stripe',
            'gateway_transaction_id' => $stripeInvoice['payment_intent'] ?? $stripeInvoice['id'],
            'amount' => ($stripeInvoice['amount_paid'] ?? 0) / 100,
            'currency' => strtoupper($stripeInvoice['currency'] ?? 'usd'),
            'status' => 'succeeded',
            'payment_method' => 'card',
            'description' => 'Subscription payment',
            'metadata' => [
                'stripe_invoice_id' => $stripeInvoice['id'] ?? null,
                'subscription' => $stripeInvoice['subscription'] ?? null,
            ],
        ]);

        $this->createOrUpdateInvoice($user, $stripeInvoice);

        PaymentSucceeded::dispatch($user, $transaction);

        return $this->successMethod();
    }

    public function handleInvoicePaymentFailed(array $payload): Response
    {
        $stripeInvoice = $payload['data']['object'] ?? [];
        $stripeCustomerId = $stripeInvoice['customer'] ?? null;

        $user = User::where('stripe_id', $stripeCustomerId)->first();

        if (! $user) {
            return $this->successMethod();
        }

        PaymentTransaction::create([
            'user_id' => $user->id,
            'gateway' => 'stripe',
            'gateway_transaction_id' => $stripeInvoice['payment_intent'] ?? $stripeInvoice['id'],
            'amount' => ($stripeInvoice['amount_due'] ?? 0) / 100,
            'currency' => strtoupper($stripeInvoice['currency'] ?? 'usd'),
            'status' => 'failed',
            'payment_method' => 'card',
            'description' => 'Payment failed',
            'metadata' => [
                'stripe_invoice_id' => $stripeInvoice['id'] ?? null,
                'attempt_count' => $stripeInvoice['attempt_count'] ?? null,
            ],
        ]);

        PaymentFailed::dispatch(
            $user,
            'stripe',
            $stripeInvoice['payment_intent'] ?? $stripeInvoice['id'] ?? '',
            ($stripeInvoice['amount_due'] ?? 0) / 100,
            strtoupper($stripeInvoice['currency'] ?? 'usd'),
            'Payment failed',
        );

        return $this->successMethod();
    }

    public function handleCustomerSubscriptionDeleted(array $payload): Response
    {
        $stripeSubscription = $payload['data']['object'] ?? [];
        $stripeCustomerId = $stripeSubscription['customer'] ?? null;

        $user = User::where('stripe_id', $stripeCustomerId)->first();

        if ($user) {
            $subscription = $user->subscriptions()
                ->where('stripe_id', $stripeSubscription['id'] ?? null)
                ->first();

            if ($subscription) {
                $subscription->update(['cancelled_at' => now()]);
                SubscriptionCancelled::dispatch($user, $subscription);
            }
        }

        return parent::handleCustomerSubscriptionDeleted($payload);
    }

    private function createOrUpdateInvoice(User $user, array $stripeInvoice): void
    {
        $subscriptionId = $stripeInvoice['subscription'] ?? null;
        $subscription = $subscriptionId
            ? $user->subscriptions()->where('stripe_id', $subscriptionId)->first()
            : null;

        Invoice::updateOrCreate(
            ['gateway_invoice_id' => $stripeInvoice['id']],
            [
                'user_id' => $user->id,
                'subscription_id' => $subscription?->id,
                'gateway' => 'stripe',
                'number' => $stripeInvoice['number'] ?? config('billing.invoice.prefix', 'INV').'-'.now()->format('Ymd').'-'.strtoupper(Str::random(6)),
                'total' => ($stripeInvoice['amount_paid'] ?? 0) / 100,
                'tax' => ($stripeInvoice['tax'] ?? 0) / 100,
                'currency' => strtoupper($stripeInvoice['currency'] ?? 'usd'),
                'status' => 'paid',
                'invoice_pdf' => $stripeInvoice['invoice_pdf'] ?? null,
                'paid_at' => now(),
            ],
        );
    }
}
