<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\EventPackage;
use App\Models\PackagePurchase;
use App\Models\TenantPackage;
use App\Models\User;
use App\Services\Checkout\CheckoutWebhookService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Stripe\Exception\SignatureVerificationException;
use Stripe\Webhook;

class StripeWebhookController extends Controller
{
    public function __construct(private CheckoutWebhookService $checkoutWebhooks) {}

    public function handleWebhook(Request $request)
    {
        $payload = $request->getContent();
        $sigHeader = $request->header('Stripe-Signature');
        $endpointSecret = config('services.stripe.webhook_secret');

        try {
            $event = Webhook::constructEvent(
                $payload,
                $sigHeader,
                $endpointSecret
            );
        } catch (SignatureVerificationException $e) {
            return ApiError::response(
                'stripe_invalid_signature',
                'Ungültige Signatur',
                'Die Signatur der Stripe-Anfrage ist ungültig.',
                400
            );
        } catch (\UnexpectedValueException $e) {
            return ApiError::response(
                'stripe_invalid_payload',
                'Ungültige Daten',
                'Der Stripe Payload konnte nicht gelesen werden.',
                400
            );
        }

        $eventArray = method_exists($event, 'toArray') ? $event->toArray() : (array) $event;

        if ($this->checkoutWebhooks->handleStripeEvent($eventArray)) {
            return response()->json(['status' => 'success'], 200);
        }

        // Legacy handlers for legacy marketing checkout
        return $this->handleLegacyEvent($eventArray);
    }

    private function handleLegacyEvent(array $event)
    {
        $type = $event['type'] ?? null;

        switch ($type) {
            case 'payment_intent.succeeded':
                $paymentIntent = $event['data']['object'] ?? [];
                $this->handlePaymentIntentSucceeded($paymentIntent);
                break;

            case 'invoice.paid':
                $invoice = $event['data']['object'] ?? [];
                $this->handleInvoicePaid($invoice);
                break;

            default:
                Log::info('Unhandled Stripe event', ['type' => $type]);
        }

        return response()->json(['status' => 'success'], 200);
    }

    private function handlePaymentIntentSucceeded(array $paymentIntent): void
    {
        $metadata = $paymentIntent['metadata'] ?? [];
        $packageId = $metadata['package_id'] ?? null;
        $type = $metadata['type'] ?? null;

        if (! $packageId || ! $type) {
            Log::warning('Stripe intent missing metadata payload', ['metadata' => $metadata]);

            return;
        }

        DB::transaction(function () use ($paymentIntent, $metadata, $packageId, $type) {
            $purchase = PackagePurchase::create([
                'package_id' => $packageId,
                'type' => $type,
                'provider_id' => 'stripe',
                'transaction_id' => $paymentIntent['id'] ?? null,
                'price' => isset($paymentIntent['amount_received'])
                    ? $paymentIntent['amount_received'] / 100
                    : 0,
                'metadata' => $metadata,
            ]);

            if ($type === 'endcustomer_event') {
                $eventId = $metadata['event_id'] ?? null;
                if (! $eventId) {
                    return;
                }

                EventPackage::create([
                    'event_id' => $eventId,
                    'package_id' => $packageId,
                    'package_purchase_id' => $purchase->id,
                    'used_photos' => 0,
                    'used_guests' => 0,
                    'expires_at' => now()->addDays(30),
                ]);
            } elseif ($type === 'reseller_subscription') {
                $tenantId = $metadata['tenant_id'] ?? null;
                if (! $tenantId) {
                    return;
                }

                TenantPackage::create([
                    'tenant_id' => $tenantId,
                    'package_id' => $packageId,
                    'package_purchase_id' => $purchase->id,
                    'used_events' => 0,
                    'active' => true,
                    'expires_at' => now()->addYear(),
                ]);

                $user = User::find($metadata['user_id'] ?? null);
                if ($user) {
                    $user->update(['role' => 'tenant_admin']);
                }
            }
        });
    }

    private function handleInvoicePaid(array $invoice): void
    {
        $subscription = $invoice['subscription'] ?? null;
        $metadata = $subscription['metadata'] ?? [];

        if (! isset($metadata['tenant_id'], $metadata['package_id'])) {
            return;
        }

        $tenantId = $metadata['tenant_id'];
        $packageId = $metadata['package_id'];

        $tenantPackage = TenantPackage::where('tenant_id', $tenantId)
            ->where('package_id', $packageId)
            ->where('stripe_subscription_id', $subscription)
            ->first();

        if ($tenantPackage) {
            $tenantPackage->update([
                'active' => true,
                'expires_at' => now()->addYear(),
            ]);
        } else {
            TenantPackage::create([
                'tenant_id' => $tenantId,
                'package_id' => $packageId,
                'stripe_subscription_id' => $subscription,
                'used_events' => 0,
                'active' => true,
                'expires_at' => now()->addYear(),
            ]);

            $user = User::find($metadata['user_id'] ?? null);
            if ($user) {
                $user->update(['role' => 'tenant_admin']);
            }
        }

        PackagePurchase::create([
            'package_id' => $packageId,
            'type' => 'reseller_subscription',
            'provider_id' => 'stripe',
            'transaction_id' => $invoice['id'] ?? null,
            'price' => isset($invoice['amount_paid']) ? $invoice['amount_paid'] / 100 : 0,
            'metadata' => $metadata,
        ]);
    }
}
