<?php

namespace App\Services\Billing;

use App\Models\Subscription;
use App\Models\User;
use App\Models\UserApiKey;

class PaypalWebhookProcessor
{
    /**
     * @param array<string,mixed> $payload
     */
    public function process(string $eventType, array $payload): void
    {
        $resource = $payload['resource'] ?? [];
        if (!is_array($resource)) {
            return;
        }

        $subscriptionId = (string) ($resource['id'] ?? '');
        $email = (string) ($resource['subscriber']['email_address'] ?? '');

        if ($subscriptionId === '' || $email === '') {
            return;
        }

        $user = User::where('email', $email)->first();
        if (!$user) {
            throw new \RuntimeException('User not found for webhook email.');
        }

        if ($eventType === 'BILLING.SUBSCRIPTION.ACTIVATED') {
            Subscription::create([
                'user_id' => $user->id,
                'plan' => 'personal',
                'status' => 'active',
                'provider' => 'paypal',
                'provider_ref' => $subscriptionId,
                'started_at' => now(),
                'expires_at' => null,
            ]);
            $user->update(['tier' => 'personal']);
            return;
        }

        if ($eventType === 'BILLING.SUBSCRIPTION.CANCELLED' || $eventType === 'BILLING.SUBSCRIPTION.SUSPENDED') {
            Subscription::where('user_id', $user->id)
                ->where('provider', 'paypal')
                ->where('provider_ref', $subscriptionId)
                ->where('status', 'active')
                ->update([
                    'status' => $eventType === 'BILLING.SUBSCRIPTION.CANCELLED' ? 'cancelled' : 'suspended',
                    'expires_at' => now(),
                ]);

            $this->syncUserTier($user->id);
        }
    }

    private function syncUserTier(int $userId): void
    {
        $active = Subscription::where('user_id', $userId)
            ->where('status', 'active')
            ->where(function ($q): void {
                $q->whereNull('expires_at')
                    ->orWhere('expires_at', '>', now());
            })
            ->exists();

        User::where('id', $userId)->update([
            'tier' => $active ? 'personal' : 'free',
        ]);
        if (!$active) {
            UserApiKey::where('user_id', $userId)->update(['revoked_at' => now()]);
        }
    }
}
