<?php

namespace App\Services\Payments\Providers;

use App\Contracts\Payments\PaymentProviderContract;
use App\Models\Plan;
use App\Models\Subscription;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class PolarProvider implements PaymentProviderContract
{
    protected array $config;

    /**
     * Rate limiting: 300 requests per minute for Polar API
     */
    private const RATE_LIMIT_REQUESTS = 300;

    private const RATE_LIMIT_WINDOW = 60; // seconds

    private static array $requestTimes = [];

    public function __construct(array $config = [])
    {
        $isSandbox = $config['sandbox'] ?? config('services.polar.sandbox', false);

        $this->config = array_merge([
            'sandbox' => $isSandbox,
            'api_key' => $isSandbox
                ? config('services.polar.sandbox_api_key')
                : config('services.polar.api_key'),
            'webhook_secret' => $isSandbox
                ? config('services.polar.sandbox_webhook_secret')
                : config('services.polar.webhook_secret'),
            'success_url' => route('payment.success'),
            'cancel_url' => route('payment.cancel'),
            'webhook_url' => route('webhook.payment', 'polar'),
        ], $config);
    }

    protected function getApiBaseUrl(): string
    {
        return $this->config['sandbox']
            ? 'https://sandbox-api.polar.sh/v1'
            : 'https://api.polar.sh/v1';
    }

    public function getName(): string
    {
        return 'polar';
    }

    public function isActive(): bool
    {
        return ! empty($this->config['api_key']) && ! empty($this->config['webhook_secret']);
    }

    /**
     * Check if the provided API key is valid by making a test API call
     */
    public function validateCredentials(): bool
    {
        try {
            return $this->makeAuthenticatedRequest('GET', '/organizations/current')->successful();
        } catch (\Exception $e) {
            Log::error('Polar credentials validation failed', [
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    /**
     * Make authenticated API request with rate limiting
     */
    protected function makeAuthenticatedRequest(string $method, string $endpoint, array $data = []): \Illuminate\Http\Client\Response
    {
        $this->checkRateLimit();

        $url = $this->getApiBaseUrl().$endpoint;

        $headers = [
            'Authorization' => 'Bearer '.$this->config['api_key'],
            'Content-Type' => 'application/json',
            'Accept' => 'application/json',
        ];

        return match ($method) {
            'GET' => Http::withHeaders($headers)->get($url, $data),
            'POST' => Http::withHeaders($headers)->post($url, $data),
            'PATCH' => Http::withHeaders($headers)->patch($url, $data),
            'DELETE' => Http::withHeaders($headers)->delete($url, $data),
            default => throw new \InvalidArgumentException("Unsupported HTTP method: {$method}"),
        };
    }

    /**
     * Simple rate limiting implementation
     */
    private function checkRateLimit(): void
    {
        $now = time();
        $windowStart = $now - self::RATE_LIMIT_WINDOW;

        // Clean old requests outside the current window
        self::$requestTimes = array_filter(self::$requestTimes, fn ($time) => $time > $windowStart);

        // Check if we're at the rate limit
        if (count(self::$requestTimes) >= self::RATE_LIMIT_REQUESTS) {
            $sleepTime = self::RATE_LIMIT_WINDOW - ($now - (self::$requestTimes[0] ?? $now));
            if ($sleepTime > 0) {
                Log::warning('Polar API rate limit reached, sleeping for '.$sleepTime.' seconds');
                sleep($sleepTime);
            }
        }

        // Record this request
        self::$requestTimes[] = $now;
    }

    public function createSubscription(User $user, Plan $plan, array $options = []): array
    {
        try {
            // Get or create Polar customer
            $customer = $this->getOrCreateCustomer($user);

            // Get or create Polar product/price
            $priceId = $this->getOrCreatePrice($plan);

            // Create checkout session with Polar's correct structure
            $checkoutData = [
                'product_price_id' => $priceId,
                'customer_id' => $customer['id'],
                'success_url' => $this->config['success_url'],
                'cancel_url' => $this->config['cancel_url'],
                'customer_email' => $user->email,
                'customer_name' => $user->name,
                'metadata' => [
                    'user_id' => (string) $user->id,
                    'plan_id' => (string) $plan->id,
                    'plan_name' => $plan->name,
                    'external_id' => $user->id, // Polar supports external_id for user mapping
                ],
            ];

            // Add discount codes if provided
            if (isset($options['discount_code'])) {
                $checkoutData['discount_code'] = $options['discount_code'];
            }

            $response = $this->makeAuthenticatedRequest('POST', '/checkouts', $checkoutData);

            if (! $response->successful()) {
                Log::error('Polar checkout creation failed: '.$response->body());
            }

            $checkout = $response->json();

            // Create subscription record
            $subscription = Subscription::create([
                'user_id' => $user->id,
                'plan_id' => $plan->id,
                'type' => 'recurring',
                'stripe_id' => $checkout['id'], // Using stripe_id field for Polar checkout ID
                'stripe_status' => 'pending',
                'provider' => $this->getName(),
                'provider_subscription_id' => $checkout['id'],
                'status' => 'pending_payment',
                'starts_at' => null,
                'ends_at' => null,
                'provider_data' => [
                    'checkout_id' => $checkout['id'],
                    'checkout_url' => $checkout['url'],
                    'customer_id' => $customer['id'],
                    'price_id' => $priceId,
                    'created_at' => now()->toISOString(),
                ],
            ]);

            return [
                'provider_subscription_id' => $checkout['id'],
                'status' => 'pending_payment',
                'checkout_url' => $checkout['url'],
                'customer_id' => $customer['id'],
                'price_id' => $priceId,
                'type' => 'polar_checkout',
                'expires_at' => $checkout['expires_at'] ?? now()->addHours(24)->toISOString(),
            ];

        } catch (\Exception $e) {
            Log::error('Polar subscription creation failed', [
                'user_id' => $user->id,
                'plan_id' => $plan->id,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    public function cancelSubscription(Subscription $subscription, string $reason = ''): bool
    {
        try {
            $polarSubscriptionId = $this->getPolarSubscriptionId($subscription);

            if (! $polarSubscriptionId) {
                // Local cancellation only
                $subscription->update([
                    'status' => 'cancelled',
                    'cancelled_at' => now(),
                    'cancellation_reason' => $reason,
                ]);

                return true;
            }

            $response = $this->makeAuthenticatedRequest('DELETE', '/subscriptions/'.$polarSubscriptionId, [
                'reason' => $reason,
            ]);

            if (! $response->successful()) {
                Log::error('Polar subscription cancellation failed: '.$response->body());
            }

            // Update local subscription
            $subscription->update([
                'status' => 'cancelled',
                'cancelled_at' => now(),
                'cancellation_reason' => $reason,
            ]);

            return true;

        } catch (\Exception $e) {
            Log::error('Polar subscription cancellation failed', [
                'subscription_id' => $subscription->id,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    public function updateSubscription(Subscription $subscription, Plan $newPlan): array
    {
        try {
            $polarSubscriptionId = $this->getPolarSubscriptionId($subscription);

            if (! $polarSubscriptionId) {
                Log::error('No Polar subscription found to update');
            }

            $newPriceId = $this->getOrCreatePrice($newPlan);

            $response = $this->makeAuthenticatedRequest('PATCH', '/subscriptions/'.$polarSubscriptionId, [
                'product_price_id' => $newPriceId,
                'preserve_period' => true, // Polar equivalent of proration behavior
            ]);

            if (! $response->successful()) {
                Log::error('Polar subscription update failed: '.$response->body());
            }

            $updatedSubscription = $response->json();

            // Update local subscription
            $subscription->update([
                'plan_id' => $newPlan->id,
                'provider_data' => array_merge($subscription->provider_data ?? [], [
                    'updated_at' => now()->toISOString(),
                    'polar_subscription' => $updatedSubscription,
                ]),
            ]);

            return [
                'provider_subscription_id' => $updatedSubscription['id'],
                'status' => $updatedSubscription['status'],
                'price_id' => $newPriceId,
                'updated_at' => $updatedSubscription['updated_at'],
            ];

        } catch (\Exception $e) {
            Log::error('Polar subscription update failed', [
                'subscription_id' => $subscription->id,
                'new_plan_id' => $newPlan->id,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    public function pauseSubscription(Subscription $subscription): bool
    {
        try {
            $polarSubscriptionId = $this->getPolarSubscriptionId($subscription);

            if (! $polarSubscriptionId) {
                return false;
            }

            $response = $this->makeAuthenticatedRequest('POST', '/subscriptions/'.$polarSubscriptionId.'/pause');

            if (! $response->successful()) {
                Log::error('Polar subscription pause failed: '.$response->body());
            }

            $subscription->update([
                'status' => 'paused',
                'paused_at' => now(),
            ]);

            return true;

        } catch (\Exception $e) {
            Log::error('Polar subscription pause failed', [
                'subscription_id' => $subscription->id,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    public function resumeSubscription(Subscription $subscription): bool
    {
        try {
            $polarSubscriptionId = $this->getPolarSubscriptionId($subscription);

            if (! $polarSubscriptionId) {
                return false;
            }

            $response = $this->makeAuthenticatedRequest('POST', '/subscriptions/'.$polarSubscriptionId.'/resume');

            if (! $response->successful()) {
                Log::error('Polar subscription resume failed: '.$response->body());
            }

            $subscription->update([
                'status' => 'active',
                'resumed_at' => now(),
            ]);

            return true;

        } catch (\Exception $e) {
            Log::error('Polar subscription resume failed', [
                'subscription_id' => $subscription->id,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    public function getSubscriptionDetails(string $providerSubscriptionId): array
    {
        try {
            $response = $this->makeAuthenticatedRequest('GET', '/subscriptions/'.$providerSubscriptionId);

            if (! $response->successful()) {
                Log::error('Failed to retrieve Polar subscription: '.$response->body());
            }

            $polarSubscription = $response->json();

            return [
                'id' => $polarSubscription['id'],
                'status' => $polarSubscription['status'],
                'customer_id' => $polarSubscription['customer_id'],
                'price_id' => $polarSubscription['price_id'],
                'current_period_start' => $polarSubscription['current_period_start'],
                'current_period_end' => $polarSubscription['current_period_end'],
                'cancel_at_period_end' => $polarSubscription['cancel_at_period_end'] ?? false,
                'trial_start' => $polarSubscription['trial_start'] ?? null,
                'trial_end' => $polarSubscription['trial_end'] ?? null,
                'created_at' => $polarSubscription['created_at'],
                'updated_at' => $polarSubscription['updated_at'],
            ];

        } catch (\Exception $e) {
            Log::error('Polar subscription details retrieval failed', [
                'subscription_id' => $providerSubscriptionId,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    public function createCheckoutSession(User $user, Plan $plan, array $options = []): array
    {
        return $this->createSubscription($user, $plan, $options);
    }

    public function createCustomerPortalSession(User $user): array
    {
        try {
            $customer = $this->getOrCreateCustomer($user);

            $response = $this->makeAuthenticatedRequest('POST', '/customer-portal', [
                'customer_id' => $customer['id'],
                'return_url' => route('dashboard'),
            ]);

            if (! $response->successful()) {
                Log::error('Polar customer portal creation failed: '.$response->body());
            }

            $portal = $response->json();

            return [
                'portal_url' => $portal['url'],
                'customer_id' => $customer['id'],
            ];

        } catch (\Exception $e) {
            Log::error('Polar customer portal creation failed', [
                'user_id' => $user->id,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    public function processWebhook(Request $request): array
    {
        try {
            $payload = $request->getContent();
            $signature = $request->header('Polar-Signature');

            if (! $this->validateWebhook($request)) {
                Log::error('Invalid Polar webhook signature');
            }

            $webhookData = json_decode($payload, true);
            $eventType = $webhookData['type'] ?? 'unknown';

            $result = [
                'event_type' => $eventType,
                'processed' => false,
                'data' => [],
            ];

            switch ($eventType) {
                case 'checkout.created':
                    $result = $this->handleCheckoutCreated($webhookData);
                    break;
                case 'order.created':
                    $result = $this->handleOrderCreated($webhookData);
                    break;
                case 'order.paid':
                    $result = $this->handleOrderPaid($webhookData);
                    break;
                case 'subscription.created':
                    $result = $this->handleSubscriptionCreated($webhookData);
                    break;
                case 'subscription.active':
                    $result = $this->handleSubscriptionActive($webhookData);
                    break;
                case 'subscription.updated':
                    $result = $this->handleSubscriptionUpdated($webhookData);
                    break;
                case 'subscription.cancelled':
                    $result = $this->handleSubscriptionCancelled($webhookData);
                    break;
                case 'customer.state_changed':
                    $result = $this->handleCustomerStateChanged($webhookData);
                    break;
                case 'benefit_grant.created':
                    $result = $this->handleBenefitGrantCreated($webhookData);
                    break;
                default:
                    Log::info('Unhandled Polar webhook event', ['event_type' => $eventType]);
            }

            return $result;

        } catch (\Exception $e) {
            Log::error('Polar webhook processing failed', [
                'error' => $e->getMessage(),
                'payload' => $request->getContent(),
            ]);
            throw $e;
        }
    }

    public function validateWebhook(Request $request): bool
    {
        try {
            $signature = $request->header('Polar-Signature');
            $payload = $request->getContent();

            if (! $signature || ! $this->config['webhook_secret']) {
                return false;
            }

            $expectedSignature = hash_hmac('sha256', $payload, $this->config['webhook_secret']);

            return hash_equals($signature, $expectedSignature);

        } catch (\Exception $e) {
            Log::warning('Polar webhook validation failed', [
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    public function getConfiguration(): array
    {
        return $this->config;
    }

    public function syncSubscriptionStatus(Subscription $subscription): array
    {
        return $this->getSubscriptionDetails($subscription->provider_subscription_id);
    }

    public function getPaymentMethodDetails(string $paymentMethodId): array
    {
        try {
            // Polar doesn't have separate payment method IDs like Stripe
            // Return subscription details instead
            return $this->getSubscriptionDetails($paymentMethodId);

        } catch (\Exception $e) {
            Log::error('Polar payment method details retrieval failed', [
                'payment_method_id' => $paymentMethodId,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    public function processRefund(string $paymentId, float $amount, string $reason = ''): array
    {
        try {
            // Polar handles refunds through their dashboard or API
            // For now, we'll return a NotImplementedError
            Log::error('Polar refunds must be processed through Polar dashboard or API directly');
            todo('Write process refund process');
        } catch (\Exception $e) {
            Log::error('Polar refund processing failed', [
                'payment_id' => $paymentId,
                'amount' => $amount,
                'error' => $e->getMessage(),
            ]);
        }

        return [];
    }

    public function getTransactionHistory(User $user, array $filters = []): array
    {
        try {
            $customer = $this->getOrCreateCustomer($user);

            $params = [
                'customer_id' => $customer['id'],
                'limit' => $filters['limit'] ?? 50,
            ];

            if (isset($filters['start_date'])) {
                $params['start_date'] = $filters['start_date'];
            }

            if (isset($filters['end_date'])) {
                $params['end_date'] = $filters['end_date'];
            }

            $response = Http::withHeaders([
                'Authorization' => 'Bearer '.$this->config['api_key'],
            ])->get($this->getApiBaseUrl().'/v1/subscriptions', $params);

            if (! $response->successful()) {
                Log::error('Failed to retrieve Polar transaction history: '.$response->body());
            }

            $polarSubscriptions = $response->json();
            $transactions = [];

            foreach ($polarSubscriptions['data'] ?? [] as $subscription) {
                $transactions[] = [
                    'id' => $subscription['id'],
                    'status' => $subscription['status'],
                    'amount' => $subscription['amount'] ?? 0,
                    'currency' => $subscription['currency'] ?? 'USD',
                    'created_at' => $subscription['created_at'],
                    'current_period_start' => $subscription['current_period_start'],
                    'current_period_end' => $subscription['current_period_end'],
                ];
            }

            return $transactions;

        } catch (\Exception $e) {
            Log::error('Polar transaction history retrieval failed', [
                'user_id' => $user->id,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    public function calculateFees(float $amount): array
    {
        // Polar fees vary by plan and region (typically 5-8%)
        // Using 6% as default for calculation
        $percentageFee = $amount * 0.06;
        $totalFee = $percentageFee; // Polar typically doesn't have fixed fees

        return [
            'fixed_fee' => 0,
            'percentage_fee' => $percentageFee,
            'total_fee' => $totalFee,
            'net_amount' => $amount - $totalFee,
        ];
    }

    public function getSupportedCurrencies(): array
    {
        return ['USD']; // Polar supports USD, EUR, and other currencies, but USD is most common
    }

    public function supportsRecurring(): bool
    {
        return true;
    }

    public function supportsOneTime(): bool
    {
        return true;
    }

    // Helper methods
    protected function getOrCreateCustomer(User $user): array
    {
        // First, try to find existing customer by email and external_id
        $response = Http::withHeaders([
            'Authorization' => 'Bearer '.$this->config['api_key'],
        ])->get($this->getApiBaseUrl().'/customers', [
            'email' => $user->email,
            'external_id' => $user->id, // Use external_id for better customer matching
        ]);

        if ($response->successful() && ! empty($response->json()['data'])) {
            return $response->json()['data'][0];
        }

        // Create new customer
        $customerData = [
            'email' => $user->email,
            'name' => $user->name,
            'external_id' => $user->id, // Polar supports external_id for user mapping
            'metadata' => [
                'user_id' => (string) $user->id,
                'source' => 'laravel_app',
            ],
        ];

        $response = Http::withHeaders([
            'Authorization' => 'Bearer '.$this->config['api_key'],
            'Content-Type' => 'application/json',
        ])->post($this->getApiBaseUrl().'/customers', $customerData);

        if (! $response->successful()) {
            Log::error('Failed to create Polar customer: '.$response->body());
        }

        return $response->json();
    }

    protected function getOrCreatePrice(Plan $plan): string
    {
        // Look for existing price by plan metadata
        $response = Http::withHeaders([
            'Authorization' => 'Bearer '.$this->config['api_key'],
        ])->get($this->getApiBaseUrl().'/v1/products', [
            'metadata[plan_id]' => $plan->id,
        ]);

        if ($response->successful() && ! empty($response->json()['data'])) {
            $product = $response->json()['data'][0];

            // Get the price for this product
            $priceResponse = Http::withHeaders([
                'Authorization' => 'Bearer '.$this->config['api_key'],
            ])->get($this->getApiBaseUrl().'/v1/prices', [
                'product_id' => $product['id'],
                'recurring_interval' => 'month',
            ]);

            if ($priceResponse->successful() && ! empty($priceResponse->json()['data'])) {
                return $priceResponse->json()['data'][0]['id'];
            }
        }

        // Create new product and price
        $productData = [
            'name' => $plan->name,
            'description' => $plan->description ?? 'Subscription plan',
            'type' => 'service',
            'metadata' => [
                'plan_id' => $plan->id,
                'plan_name' => $plan->name,
            ],
        ];

        $productResponse = Http::withHeaders([
            'Authorization' => 'Bearer '.$this->config['api_key'],
            'Content-Type' => 'application/json',
        ])->post($this->getApiBaseUrl().'/v1/products', $productData);

        if (! $productResponse->successful()) {
            Log::error('Failed to create Polar product: '.$productResponse->body());
        }

        $product = $productResponse->json();

        // Create price for the product
        $priceData = [
            'product_id' => $product['id'],
            'amount' => (int) ($plan->price * 100), // Convert to cents
            'currency' => 'usd',
            'recurring' => [
                'interval' => 'month',
                'interval_count' => 1,
            ],
        ];

        $priceResponse = Http::withHeaders([
            'Authorization' => 'Bearer '.$this->config['api_key'],
            'Content-Type' => 'application/json',
        ])->post($this->getApiBaseUrl().'/v1/prices', $priceData);

        if (! $priceResponse->successful()) {
            Log::error('Failed to create Polar price: '.$priceResponse->body());
        }

        $price = $priceResponse->json();

        return $price['id'];
    }

    protected function getPolarSubscriptionId(Subscription $subscription): ?string
    {
        $providerData = $subscription->provider_data ?? [];

        return $providerData['polar_subscription']['id'] ?? null;
    }

    // Webhook handlers
    protected function handleCheckoutCreated(array $webhookData): array
    {
        $checkout = $webhookData['data']['object'];

        // Update local subscription with checkout ID
        Subscription::where('provider_subscription_id', $checkout['id'])->update([
            'provider_data' => array_merge(
                Subscription::where('provider_subscription_id', $checkout['id'])->first()?->provider_data ?? [],
                [
                    'checkout_id' => $checkout['id'],
                    'customer_id' => $checkout['customer_id'],
                    'polar_checkout' => $checkout,
                ]
            ),
        ]);

        return [
            'event_type' => 'checkout.created',
            'processed' => true,
            'data' => [
                'checkout_id' => $checkout['id'],
                'customer_id' => $checkout['customer_id'],
            ],
        ];
    }

    protected function handleOrderCreated(array $webhookData): array
    {
        $order = $webhookData['data']['object'];

        // Find subscription by checkout ID or customer metadata
        $subscription = Subscription::where('provider', 'polar')
            ->where(function ($query) use ($order) {
                $query->where('provider_subscription_id', $order['checkout_id'] ?? null)
                    ->orWhereHas('user', function ($q) use ($order) {
                        $q->where('email', $order['customer_email'] ?? null);
                    });
            })
            ->first();

        if ($subscription) {
            $subscription->update([
                'provider_data' => array_merge($subscription->provider_data ?? [], [
                    'order_id' => $order['id'],
                    'polar_order' => $order,
                    'order_created_at' => now()->toISOString(),
                ]),
            ]);
        }

        return [
            'event_type' => 'order.created',
            'processed' => true,
            'data' => [
                'order_id' => $order['id'],
                'checkout_id' => $order['checkout_id'] ?? null,
            ],
        ];
    }

    protected function handleOrderPaid(array $webhookData): array
    {
        $order = $webhookData['data']['object'];

        // Find and activate subscription
        $subscription = Subscription::where('provider', 'polar')
            ->where(function ($query) use ($order) {
                $query->where('provider_subscription_id', $order['checkout_id'] ?? null)
                    ->orWhereHas('user', function ($q) use ($order) {
                        $q->where('email', $order['customer_email'] ?? null);
                    });
            })
            ->first();

        if ($subscription && $subscription->status === 'pending_payment') {
            $subscription->update([
                'status' => 'active',
                'starts_at' => now(),
                'provider_data' => array_merge($subscription->provider_data ?? [], [
                    'order_paid_at' => now()->toISOString(),
                    'polar_order' => $order,
                ]),
            ]);
        }

        return [
            'event_type' => 'order.paid',
            'processed' => true,
            'data' => [
                'order_id' => $order['id'],
                'subscription_id' => $subscription?->id,
            ],
        ];
    }

    protected function handleSubscriptionActive(array $webhookData): array
    {
        $polarSubscription = $webhookData['data']['object'];

        Subscription::where('provider', 'polar')
            ->where('provider_subscription_id', $polarSubscription['id'])
            ->update([
                'status' => 'active',
                'starts_at' => Carbon::parse($polarSubscription['current_period_start']),
                'ends_at' => Carbon::parse($polarSubscription['current_period_end']),
                'provider_data' => array_merge(
                    Subscription::where('provider', 'polar')
                        ->where('provider_subscription_id', $polarSubscription['id'])
                        ->first()?->provider_data ?? [],
                    [
                        'polar_subscription' => $polarSubscription,
                        'activated_at' => now()->toISOString(),
                    ]
                ),
            ]);

        return [
            'event_type' => 'subscription.active',
            'processed' => true,
            'data' => [
                'subscription_id' => $polarSubscription['id'],
                'status' => 'active',
            ],
        ];
    }

    protected function handleCustomerStateChanged(array $webhookData): array
    {
        $customer = $webhookData['data']['object'];

        // Update all subscriptions for this customer
        Subscription::whereHas('user', function ($query) use ($customer) {
            $query->where('email', $customer['email']);
        })->where('provider', 'polar')->get()->each(function ($subscription) use ($customer) {
            $subscription->update([
                'provider_data' => array_merge($subscription->provider_data ?? [], [
                    'customer_state' => $customer['state'],
                    'customer_updated_at' => now()->toISOString(),
                ]),
            ]);
        });

        return [
            'event_type' => 'customer.state_changed',
            'processed' => true,
            'data' => [
                'customer_id' => $customer['id'],
                'state' => $customer['state'],
            ],
        ];
    }

    protected function handleBenefitGrantCreated(array $webhookData): array
    {
        $benefitGrant = $webhookData['data']['object'];

        // Log benefit grants for analytics or feature access
        Log::info('Polar benefit grant created', [
            'grant_id' => $benefitGrant['id'],
            'customer_id' => $benefitGrant['customer_id'],
            'benefit_id' => $benefitGrant['benefit_id'],
        ]);

        return [
            'event_type' => 'benefit_grant.created',
            'processed' => true,
            'data' => [
                'grant_id' => $benefitGrant['id'],
                'customer_id' => $benefitGrant['customer_id'],
                'benefit_id' => $benefitGrant['benefit_id'],
            ],
        ];
    }

    protected function handleSubscriptionCreated(array $webhookData): array
    {
        $polarSubscription = $webhookData['data']['object'];

        // Find and update local subscription
        $localSubscription = Subscription::where('provider', 'polar')
            ->where('provider_subscription_id', $polarSubscription['checkout_id'])
            ->first();

        if ($localSubscription) {
            $localSubscription->update([
                'stripe_id' => $polarSubscription['id'],
                'provider_subscription_id' => $polarSubscription['id'],
                'status' => $polarSubscription['status'],
                'starts_at' => Carbon::parse($polarSubscription['current_period_start']),
                'ends_at' => Carbon::parse($polarSubscription['current_period_end']),
                'provider_data' => array_merge($localSubscription->provider_data ?? [], [
                    'polar_subscription' => $polarSubscription,
                    'activated_at' => now()->toISOString(),
                ]),
            ]);
        }

        return [
            'event_type' => 'subscription.created',
            'processed' => true,
            'data' => [
                'subscription_id' => $polarSubscription['id'],
                'status' => $polarSubscription['status'],
            ],
        ];
    }

    protected function handleSubscriptionUpdated(array $webhookData): array
    {
        $polarSubscription = $webhookData['data']['object'];

        Subscription::where('provider', 'polar')
            ->where('provider_subscription_id', $polarSubscription['id'])
            ->update([
                'status' => $polarSubscription['status'],
                'provider_data' => [
                    'polar_subscription' => $polarSubscription,
                    'updated_at' => now()->toISOString(),
                ],
            ]);

        return [
            'event_type' => 'subscription.updated',
            'processed' => true,
            'data' => [
                'subscription_id' => $polarSubscription['id'],
                'status' => $polarSubscription['status'],
            ],
        ];
    }

    protected function handleSubscriptionCancelled(array $webhookData): array
    {
        $polarSubscription = $webhookData['data']['object'];

        Subscription::where('provider', 'polar')
            ->where('provider_subscription_id', $polarSubscription['id'])
            ->update([
                'status' => 'cancelled',
                'cancelled_at' => now(),
                'cancellation_reason' => 'Polar webhook cancellation',
            ]);

        return [
            'event_type' => 'subscription.cancelled',
            'processed' => true,
            'data' => [
                'subscription_id' => $polarSubscription['id'],
            ],
        ];
    }

    protected function handleSubscriptionPaused(array $webhookData): array
    {
        $polarSubscription = $webhookData['data']['object'];

        Subscription::where('provider', 'polar')
            ->where('provider_subscription_id', $polarSubscription['id'])
            ->update([
                'status' => 'paused',
                'paused_at' => now(),
            ]);

        return [
            'event_type' => 'subscription.paused',
            'processed' => true,
            'data' => [
                'subscription_id' => $polarSubscription['id'],
            ],
        ];
    }

    protected function handleSubscriptionResumed(array $webhookData): array
    {
        $polarSubscription = $webhookData['data']['object'];

        Subscription::where('provider', 'polar')
            ->where('provider_subscription_id', $polarSubscription['id'])
            ->update([
                'status' => 'active',
                'resumed_at' => now(),
            ]);

        return [
            'event_type' => 'subscription.resumed',
            'processed' => true,
            'data' => [
                'subscription_id' => $polarSubscription['id'],
            ],
        ];
    }

    // Additional interface methods
    public function getSubscriptionMetadata(Subscription $subscription): array
    {
        return $subscription->provider_data['polar_subscription'] ?? [];
    }

    public function updateSubscriptionMetadata(Subscription $subscription, array $metadata): bool
    {
        try {
            $subscription->update([
                'provider_data' => array_merge($subscription->provider_data ?? [], [
                    'metadata' => $metadata,
                ]),
            ]);

            return true;
        } catch (\Exception $e) {
            Log::error('Failed to update Polar subscription metadata', [
                'subscription_id' => $subscription->id,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    public function startTrial(Subscription $subscription, int $trialDays): bool
    {
        // Polar handles trials through checkout creation
        // This would require creating a new checkout with trial period
        return false;
    }

    public function applyCoupon(Subscription $subscription, string $couponCode): array
    {
        // Polar supports discount codes
        try {
            $polarSubscriptionId = $this->getPolarSubscriptionId($subscription);

            if (! $polarSubscriptionId) {
                Log::error('No Polar subscription found');
            }

            $response = Http::withHeaders([
                'Authorization' => 'Bearer '.$this->config['api_key'],
                'Content-Type' => 'application/json',
            ])->post($this->getApiBaseUrl().'/v1/subscriptions/'.$polarSubscriptionId.'/discount', [
                'coupon_code' => $couponCode,
            ]);

            if (! $response->successful()) {
                Log::error('Failed to apply Polar coupon: '.$response->body());
            }

            return $response->json();

        } catch (\Exception $e) {
            Log::error('Polar coupon application failed', [
                'subscription_id' => $subscription->id,
                'coupon_code' => $couponCode,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    public function removeCoupon(Subscription $subscription): bool
    {
        try {
            $polarSubscriptionId = $this->getPolarSubscriptionId($subscription);

            if (! $polarSubscriptionId) {
                return false;
            }

            $response = Http::withHeaders([
                'Authorization' => 'Bearer '.$this->config['api_key'],
            ])->delete($this->getApiBaseUrl().'/v1/subscriptions/'.$polarSubscriptionId.'/discount');

            return $response->successful();

        } catch (\Exception $e) {
            Log::error('Polar coupon removal failed', [
                'subscription_id' => $subscription->id,
                'error' => $e->getMessage(),
            ]);

            return false;
        }
    }

    public function getUpcomingInvoice(Subscription $subscription): array
    {
        try {
            $polarSubscriptionId = $this->getPolarSubscriptionId($subscription);

            if (! $polarSubscriptionId) {
                return [
                    'amount_due' => 0,
                    'currency' => 'USD',
                    'next_payment_date' => null,
                ];
            }

            $response = Http::withHeaders([
                'Authorization' => 'Bearer '.$this->config['api_key'],
            ])->get($this->getApiBaseUrl().'/v1/subscriptions/'.$polarSubscriptionId.'/upcoming-invoice');

            if (! $response->successful()) {
                Log::error('Failed to retrieve Polar upcoming invoice: '.$response->body());
            }

            $invoice = $response->json();

            return [
                'amount_due' => $invoice['amount_due'] / 100, // Convert from cents
                'currency' => $invoice['currency'],
                'next_payment_date' => $invoice['next_payment_date'],
            ];

        } catch (\Exception $e) {
            Log::error('Polar upcoming invoice retrieval failed', [
                'subscription_id' => $subscription->id,
                'error' => $e->getMessage(),
            ]);
            throw $e;
        }
    }

    public function retryFailedPayment(Subscription $subscription): array
    {
        // Polar doesn't have explicit retry logic - payments are retried automatically
        return $this->syncSubscriptionStatus($subscription);
    }

    public function canModifySubscription(Subscription $subscription): bool
    {
        try {
            $details = $this->getSubscriptionDetails($subscription->provider_subscription_id);

            return in_array($details['status'], ['active', 'trialing']);
        } catch (\Exception $e) {
            return false;
        }
    }

    public function getCancellationTerms(Subscription $subscription): array
    {
        return [
            'immediate_cancellation' => true,
            'refund_policy' => 'no_pro_rated_refunds',
            'cancellation_effective' => 'immediately',
            'billing_cycle_proration' => false,
        ];
    }

    public function exportSubscriptionData(Subscription $subscription): array
    {
        return [
            'provider' => 'polar',
            'provider_subscription_id' => $subscription->provider_subscription_id,
            'data' => $subscription->provider_data,
        ];
    }

    public function importSubscriptionData(User $user, array $subscriptionData): array
    {
        Log::error('Import to Polar payments not implemented');
        todo('Write import subscription data');

        return [];
    }
}
