<?php

namespace App\Services\Payments;

use App\Contracts\Payments\PaymentProviderContract;
use App\Models\Coupon;
use App\Models\CouponUsage;
use App\Models\Plan;
use App\Models\Subscription;
use App\Models\SubscriptionChange;
use App\Models\TrialExtension;
use App\Models\User;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class PaymentOrchestrator
{
    protected ProviderRegistry $providerRegistry;

    protected PaymentLogger $logger;

    public function __construct(ProviderRegistry $providerRegistry, PaymentLogger $logger)
    {
        $this->providerRegistry = $providerRegistry;
        $this->logger = $logger;
    }

    /**
     * Create a new subscription using the preferred provider
     */
    public function createSubscription(User $user, Plan $plan, ?string $providerName = null, array $options = []): array
    {
        $provider = $this->getProviderForPlan($plan, $providerName);

        if (! $provider->isActive()) {
            throw new Exception("Payment provider {$provider->getName()} is not active");
        }

        try {
            $this->logger->logEvent('subscription_creation_started', [
                'user_id' => $user->id,
                'plan_id' => $plan->id,
                'provider' => $provider->getName(),
                'options' => $options,
            ]);

            $result = $provider->createSubscription($user, $plan, $options);

            // Create local subscription record
            $subscription = $this->createLocalSubscription($user, $plan, $provider, $result);

            $this->logger->logEvent('subscription_created', [
                'subscription_id' => $subscription->id,
                'provider' => $provider->getName(),
                'provider_subscription_id' => $result['provider_subscription_id'] ?? null,
            ]);

            return [
                'success' => true,
                'subscription' => $subscription,
                'provider_data' => $result,
            ];

        } catch (Exception $e) {
            $this->logger->logError('subscription_creation_failed', [
                'user_id' => $user->id,
                'plan_id' => $plan->id,
                'provider' => $provider->getName(),
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * Cancel a subscription
     */
    public function cancelSubscription(Subscription $subscription, string $reason = ''): bool
    {
        $provider = $this->getProviderForSubscription($subscription);

        try {
            $this->logger->logEvent('subscription_cancellation_started', [
                'subscription_id' => $subscription->id,
                'provider' => $provider->getName(),
                'reason' => $reason,
            ]);

            $result = $provider->cancelSubscription($subscription, $reason);

            if ($result) {
                $subscription->update([
                    'ends_at' => now(),
                    'cancelled_at' => now(),
                    'cancellation_reason' => $reason,
                ]);

                $this->logger->logEvent('subscription_cancelled', [
                    'subscription_id' => $subscription->id,
                    'provider' => $provider->getName(),
                ]);
            }

            return $result;

        } catch (Exception $e) {
            $this->logger->logError('subscription_cancellation_failed', [
                'subscription_id' => $subscription->id,
                'provider' => $provider->getName(),
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * Update subscription plan
     */
    public function updateSubscription(Subscription $subscription, Plan $newPlan): array
    {
        $provider = $this->getProviderForSubscription($subscription);

        try {
            $this->logger->logEvent('subscription_update_started', [
                'subscription_id' => $subscription->id,
                'old_plan_id' => $subscription->plan_id,
                'new_plan_id' => $newPlan->id,
                'provider' => $provider->getName(),
            ]);

            $result = $provider->updateSubscription($subscription, $newPlan);

            $subscription->update([
                'plan_id' => $newPlan->id,
                'updated_at' => now(),
            ]);

            $this->logger->logEvent('subscription_updated', [
                'subscription_id' => $subscription->id,
                'new_plan_id' => $newPlan->id,
                'provider' => $provider->getName(),
            ]);

            return [
                'success' => true,
                'subscription' => $subscription->fresh(),
                'provider_data' => $result,
            ];

        } catch (Exception $e) {
            $this->logger->logError('subscription_update_failed', [
                'subscription_id' => $subscription->id,
                'provider' => $provider->getName(),
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * Create checkout session
     */
    public function createCheckoutSession(User $user, Plan $plan, ?string $providerName = null, array $options = []): array
    {
        $provider = $this->getProviderForPlan($plan, $providerName);

        try {
            $this->logger->logEvent('checkout_session_created', [
                'user_id' => $user->id,
                'plan_id' => $plan->id,
                'provider' => $provider->getName(),
            ]);

            return $provider->createCheckoutSession($user, $plan, $options);

        } catch (Exception $e) {
            $this->logger->logError('checkout_session_failed', [
                'user_id' => $user->id,
                'plan_id' => $plan->id,
                'provider' => $provider->getName(),
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * Create subscription with coupon
     */
    public function createSubscriptionWithCoupon(User $user, Plan $plan, Coupon $coupon, ?string $providerName = null, array $options = []): array
    {
        $provider = $this->getProviderForPlan($plan, $providerName);

        if (! $coupon->isValid($user)) {
            throw new Exception("Coupon {$coupon->code} is not valid for this user");
        }

        try {
            $this->logger->logEvent('coupon_subscription_creation_started', [
                'user_id' => $user->id,
                'plan_id' => $plan->id,
                'coupon_id' => $coupon->id,
                'provider' => $provider->getName(),
            ]);

            // Add coupon to options
            $options['coupon'] = $coupon->code;
            $options['discount_amount'] = $this->calculateDiscountAmount($plan, $coupon);

            $result = $provider->createSubscription($user, $plan, $options);
            $subscription = $this->createLocalSubscription($user, $plan, $provider, $result);

            // Apply coupon to subscription
            $couponUsage = $subscription->applyCoupon($coupon, $options['discount_amount']);

            $this->logger->logEvent('coupon_subscription_created', [
                'subscription_id' => $subscription->id,
                'coupon_id' => $coupon->id,
                'coupon_usage_id' => $couponUsage->id,
                'provider' => $provider->getName(),
            ]);

            return [
                'success' => true,
                'subscription' => $subscription,
                'coupon_usage' => $couponUsage,
                'provider_data' => $result,
            ];

        } catch (Exception $e) {
            $this->logger->logError('coupon_subscription_creation_failed', [
                'user_id' => $user->id,
                'plan_id' => $plan->id,
                'coupon_id' => $coupon->id,
                'provider' => $provider->getName(),
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * Extend subscription trial
     */
    public function extendTrial(Subscription $subscription, int $days, string $reason = '', string $extensionType = 'manual', ?User $grantedBy = null): array
    {
        $provider = $this->getProviderForSubscription($subscription);

        if (! $subscription->isOnTrial()) {
            throw new Exception("Subscription {$subscription->id} is not on trial");
        }

        try {
            $this->logger->logEvent('trial_extension_started', [
                'subscription_id' => $subscription->id,
                'days' => $days,
                'reason' => $reason,
                'extension_type' => $extensionType,
                'granted_by' => $grantedBy?->id,
            ]);

            // Create trial extension record
            $trialExtension = $subscription->extendTrial($days, $reason, $extensionType, $grantedBy);

            // Update provider if supported
            if (method_exists($provider, 'extendTrial')) {
                $provider->extendTrial($subscription, $days, $reason);
            }

            $this->logger->logEvent('trial_extended', [
                'subscription_id' => $subscription->id,
                'trial_extension_id' => $trialExtension->id,
                'new_trial_ends_at' => $trialExtension->new_trial_ends_at,
            ]);

            return [
                'success' => true,
                'trial_extension' => $trialExtension,
                'subscription' => $subscription->fresh(),
            ];

        } catch (Exception $e) {
            $this->logger->logError('trial_extension_failed', [
                'subscription_id' => $subscription->id,
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * Record subscription change
     */
    public function recordSubscriptionChange(Subscription $subscription, string $changeType, string $description, ?array $oldValues = null, ?array $newValues = null, ?string $reason = null): SubscriptionChange
    {
        try {
            $this->logger->logEvent('subscription_change_recorded', [
                'subscription_id' => $subscription->id,
                'change_type' => $changeType,
                'description' => $description,
            ]);

            return $subscription->recordChange($changeType, $description, $oldValues, $newValues, $reason);

        } catch (Exception $e) {
            $this->logger->logError('subscription_change_recording_failed', [
                'subscription_id' => $subscription->id,
                'change_type' => $changeType,
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * Process pending subscription changes
     */
    public function processPendingChanges(Subscription $subscription): array
    {
        try {
            $pendingChanges = $subscription->getPendingChanges();
            $processedCount = 0;
            $errors = [];

            foreach ($pendingChanges as $change) {
                try {
                    $this->processSubscriptionChange($subscription, $change);
                    $change->markAsProcessed();
                    $processedCount++;
                } catch (Exception $e) {
                    $errors[] = [
                        'change_id' => $change->id,
                        'error' => $e->getMessage(),
                    ];
                    $this->logger->logError('subscription_change_processing_failed', [
                        'change_id' => $change->id,
                        'subscription_id' => $subscription->id,
                        'error' => $e->getMessage(),
                    ]);
                }
            }

            $this->logger->logEvent('pending_changes_processed', [
                'subscription_id' => $subscription->id,
                'processed_count' => $processedCount,
                'error_count' => count($errors),
            ]);

            return [
                'success' => true,
                'processed_count' => $processedCount,
                'errors' => $errors,
                'subscription' => $subscription->fresh(),
            ];

        } catch (Exception $e) {
            $this->logger->logError('pending_changes_processing_failed', [
                'subscription_id' => $subscription->id,
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * Migrate subscription between providers
     */
    public function migrateSubscription(Subscription $subscription, string $targetProvider): array
    {
        $sourceProvider = $this->getProviderForSubscription($subscription);
        $targetProviderInstance = $this->providerRegistry->get($targetProvider);

        if (! $targetProviderInstance) {
            throw new Exception("Target provider {$targetProvider} not found");
        }

        if (! $targetProviderInstance->isActive()) {
            throw new Exception("Target provider {$targetProvider} is not active");
        }

        try {
            $this->logger->logEvent('subscription_migration_started', [
                'subscription_id' => $subscription->id,
                'source_provider' => $sourceProvider->getName(),
                'target_provider' => $targetProvider,
            ]);

            // Record the change
            $this->recordSubscriptionChange(
                $subscription,
                'migration',
                "Migrated from {$sourceProvider->getName()} to {$targetProvider}",
                ['provider' => $sourceProvider->getName()],
                ['provider' => $targetProvider],
                'Provider migration for better service'
            );

            // Cancel with source provider if needed
            if (method_exists($sourceProvider, 'cancelSubscription')) {
                $sourceProvider->cancelSubscription($subscription, 'Migration to new provider');
            }

            // Create with target provider
            $newSubscriptionData = $targetProviderInstance->createSubscription(
                $subscription->user,
                $subscription->plan,
                ['migration' => true]
            );

            // Update local subscription
            $subscription->update([
                'provider' => $targetProvider,
                'provider_subscription_id' => $newSubscriptionData['provider_subscription_id'] ?? null,
                'provider_data' => $newSubscriptionData,
                'migration_batch_id' => uniqid('migration_', true),
                'is_migrated' => true,
                'last_provider_sync' => now(),
            ]);

            $this->logger->logEvent('subscription_migration_completed', [
                'subscription_id' => $subscription->id,
                'migration_batch_id' => $subscription->migration_batch_id,
                'target_provider' => $targetProvider,
            ]);

            return [
                'success' => true,
                'subscription' => $subscription->fresh(),
                'provider_data' => $newSubscriptionData,
            ];

        } catch (Exception $e) {
            $this->logger->logError('subscription_migration_failed', [
                'subscription_id' => $subscription->id,
                'source_provider' => $sourceProvider->getName(),
                'target_provider' => $targetProvider,
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * Process webhook from any provider
     */
    public function processWebhook(string $providerName, Request $request): array
    {
        $provider = $this->providerRegistry->get($providerName);

        if (! $provider) {
            $this->logger->logError('webhook_provider_not_found', [
                'provider' => $providerName,
            ]);
            throw new Exception("Payment provider {$providerName} not found");
        }

        if (! $provider->validateWebhook($request)) {
            $this->logger->logError('webhook_validation_failed', [
                'provider' => $providerName,
            ]);
            throw new Exception("Webhook validation failed for {$providerName}");
        }

        try {
            $result = $provider->processWebhook($request);

            $this->logger->logEvent('webhook_processed', [
                'provider' => $providerName,
                'event_type' => $result['event_type'] ?? 'unknown',
                'subscription_id' => $result['subscription_id'] ?? null,
            ]);

            return $result;

        } catch (Exception $e) {
            $this->logger->logError('webhook_processing_failed', [
                'provider' => $providerName,
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * Sync subscription status from provider
     */
    public function syncSubscriptionStatus(Subscription $subscription): array
    {
        $provider = $this->getProviderForSubscription($subscription);

        try {
            $providerData = $provider->syncSubscriptionStatus($subscription);

            // Update local subscription based on provider data
            $this->updateLocalSubscriptionFromProvider($subscription, $providerData);

            $this->logger->logEvent('subscription_synced', [
                'subscription_id' => $subscription->id,
                'provider' => $provider->getName(),
                'status' => $providerData['status'] ?? 'unknown',
            ]);

            return $providerData;

        } catch (Exception $e) {
            $this->logger->logError('subscription_sync_failed', [
                'subscription_id' => $subscription->id,
                'provider' => $provider->getName(),
                'error' => $e->getMessage(),
            ]);

            throw $e;
        }
    }

    /**
     * Get active providers for a plan
     */
    public function getActiveProvidersForPlan(Plan $plan): Collection
    {
        return $this->providerRegistry->getActiveProviders()
            ->filter(function ($provider) use ($plan) {
                return $this->isProviderSupportedForPlan($provider, $plan);
            });
    }

    /**
     * Get subscription transaction history
     */
    public function getTransactionHistoryOld(User $user, array $filters = []): array
    {
        $subscriptions = $user->subscriptions;
        $history = [];

        foreach ($subscriptions as $subscription) {
            $provider = $this->getProviderForSubscription($subscription);
            $providerHistory = $provider->getTransactionHistory($user, $filters);

            $history = array_merge($history, $providerHistory);
        }

        // Sort by date descending
        usort($history, function ($a, $b) {
            return strtotime($b['date']) - strtotime($a['date']);
        });

        return $history;
    }

    public function getTransactionHistory(User $user, array $filters = []): array
    {
        $subscriptions = $user->subscriptions;
        $history = [];

        foreach ($subscriptions as $subscription) {
            $provider = $this->getProviderForSubscription($subscription);
            $providerHistory = $provider->getTransactionHistory($user, $filters);

            // Use array_push with spread operator (PHP 7.4+) or array unpacking
            array_push($history, ...$providerHistory);

            // Alternative: Direct array concatenation
            // foreach ($providerHistory as $transaction) {
            //     $history[] = $transaction;
            // }
        }

        // Sort by date descending
        usort($history, function ($a, $b) {
            return strtotime($b['date']) - strtotime($a['date']);
        });

        return $history;
    }

    /**
     * Get provider for a specific plan
     */
    protected function getProviderForPlan(Plan $plan, ?string $providerName = null): PaymentProviderContract
    {
        Log::info('PaymentOrchestrator: Getting provider for plan', [
            'plan_id' => $plan->id,
            'requested_provider' => $providerName,
        ]);

        if ($providerName) {
            $provider = $this->providerRegistry->get($providerName);
            Log::info('PaymentOrchestrator: Checking specific provider', [
                'provider_name' => $providerName,
                'provider_exists' => $provider ? true : false,
                'provider_active' => $provider?->isActive(),
                'provider_supported' => $provider ? $this->isProviderSupportedForPlan($provider, $plan) : false,
            ]);

            if ($provider && $provider->isActive() && $this->isProviderSupportedForPlan($provider, $plan)) {
                Log::info('PaymentOrchestrator: Using requested provider', [
                    'provider' => $providerName,
                ]);

                return $provider;
            }
        }

        // Find the first active provider that supports this plan
        foreach ($this->providerRegistry->getActiveProviders() as $provider) {
            Log::info('PaymentOrchestrator: Checking fallback provider', [
                'provider' => $provider->getName(),
                'supported' => $this->isProviderSupportedForPlan($provider, $plan),
            ]);

            if ($this->isProviderSupportedForPlan($provider, $plan)) {
                Log::info('PaymentOrchestrator: Using fallback provider', [
                    'provider' => $provider->getName(),
                ]);

                return $provider;
            }
        }

        throw new Exception("No active payment provider available for plan: {$plan->name}");
    }

    /**
     * Get provider for existing subscription
     */
    protected function getProviderForSubscription(Subscription $subscription): PaymentProviderContract
    {
        $providerName = $subscription->provider ?? 'stripe'; // Default to stripe for existing subscriptions
        $provider = $this->providerRegistry->get($providerName);

        if (! $provider) {
            throw new Exception("Payment provider {$providerName} not found for subscription {$subscription->id}");
        }

        return $provider;
    }

    /**
     * Check if provider supports a specific plan
     */
    protected function isProviderSupportedForPlan(PaymentProviderContract $provider, Plan $plan): bool
    {
        // Use the same approach as Plan::supportsProvider() - check database relationship
        $isSupported = $plan->planProviders()
            ->where('provider', $provider->getName())
            ->where('is_enabled', true)
            ->exists();

        if (! $isSupported) {
            return false;
        }

        // Check if provider supports the plan type
        if ($plan->monthly_billing && ! $provider->supportsRecurring()) {
            return false;
        }

        if (! $plan->monthly_billing && ! $provider->supportsOneTime()) {
            return false;
        }

        return true;
    }

    /**
     * Create local subscription record
     */
    protected function createLocalSubscription(User $user, Plan $plan, PaymentProviderContract $provider, array $providerData): Subscription
    {
        return Subscription::create([
            'user_id' => $user->id,
            'plan_id' => $plan->id,
            'provider' => $provider->getName(),
            'provider_subscription_id' => $providerData['provider_subscription_id'] ?? null,
            'status' => $providerData['status'] ?? 'active',
            'starts_at' => $providerData['starts_at'] ?? now(),
            'ends_at' => $providerData['ends_at'] ?? null,
            'trial_ends_at' => $providerData['trial_ends_at'] ?? null,
            'provider_data' => $providerData,
        ]);
    }

    /**
     * Update local subscription from provider data
     */
    protected function updateLocalSubscriptionFromProvider(Subscription $subscription, array $providerData): void
    {
        $subscription->update([
            'status' => $providerData['status'] ?? $subscription->status,
            'ends_at' => $providerData['ends_at'] ?? $subscription->ends_at,
            'trial_ends_at' => $providerData['trial_ends_at'] ?? $subscription->trial_ends_at,
            'provider_data' => array_merge($subscription->provider_data ?? [], $providerData),
            'synced_at' => now(),
        ]);
    }

    /**
     * Get all available providers
     */
    public function getAvailableProviders(): Collection
    {
        return $this->providerRegistry->getAllProviders();
    }

    /**
     * Get active providers only
     */
    public function getActiveProviders(): Collection
    {
        return $this->providerRegistry->getActiveProviders();
    }

    /**
     * Calculate discount amount for a coupon
     */
    protected function calculateDiscountAmount(Plan $plan, Coupon $coupon): float
    {
        $planPrice = $plan->price ?? 0;

        return match ($coupon->discount_type) {
            'percentage' => ($planPrice * $coupon->discount_value) / 100,
            'fixed' => $coupon->discount_value,
            default => 0,
        };
    }

    /**
     * Process individual subscription change
     */
    protected function processSubscriptionChange(Subscription $subscription, SubscriptionChange $change): void
    {
        match ($change->change_type) {
            'plan_upgrade', 'plan_downgrade' => $this->processPlanChange($subscription, $change),
            'pause' => $this->processPauseChange($subscription, $change),
            'resume' => $this->processResumeChange($subscription, $change),
            'cancel' => $this->processCancelChange($subscription, $change),
            default => throw new Exception("Unknown change type: {$change->change_type}"),
        };
    }

    /**
     * Process plan change
     */
    protected function processPlanChange(Subscription $subscription, SubscriptionChange $change): void
    {
        $newPlanId = $change->new_values['plan_id'] ?? null;
        if (! $newPlanId) {
            throw new Exception('Plan ID not found in change values');
        }

        $newPlan = Plan::findOrFail($newPlanId);
        $result = $this->updateSubscription($subscription, $newPlan);

        if (! $result['success']) {
            throw new Exception('Failed to update subscription plan');
        }
    }

    /**
     * Process pause change
     */
    protected function processPauseChange(Subscription $subscription, SubscriptionChange $change): void
    {
        $provider = $this->getProviderForSubscription($subscription);

        if (method_exists($provider, 'pauseSubscription')) {
            $provider->pauseSubscription($subscription);
        }

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

    /**
     * Process resume change
     */
    protected function processResumeChange(Subscription $subscription, SubscriptionChange $change): void
    {
        $provider = $this->getProviderForSubscription($subscription);

        if (method_exists($provider, 'resumeSubscription')) {
            $provider->resumeSubscription($subscription);
        }

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

    /**
     * Process cancel change
     */
    protected function processCancelChange(Subscription $subscription, SubscriptionChange $change): void
    {
        $reason = $change->new_values['reason'] ?? 'Scheduled cancellation';
        $this->cancelSubscription($subscription, $reason);
    }

    /**
     * Get subscription analytics
     */
    public function getSubscriptionAnalytics(array $filters = []): array
    {
        $query = Subscription::query();

        if (isset($filters['provider'])) {
            $query->where('provider', $filters['provider']);
        }

        if (isset($filters['status'])) {
            $query->where('status', $filters['status']);
        }

        if (isset($filters['date_from'])) {
            $query->whereDate('created_at', '>=', $filters['date_from']);
        }

        if (isset($filters['date_to'])) {
            $query->whereDate('created_at', '<=', $filters['date_to']);
        }

        $totalSubscriptions = $query->count();
        $activeSubscriptions = $query->where('status', 'active')->count();
        $trialSubscriptions = $query->where('status', 'trialing')->count();
        $cancelledSubscriptions = $query->where('status', 'cancelled')->count();

        $mrr = $query->where('status', 'active')
            ->join('plans', 'subscriptions.plan_id', '=', 'plans.id')
            ->sum('plans.price');

        $totalRevenue = $query->join('plans', 'subscriptions.plan_id', '=', 'plans.id')
            ->sum('plans.price');

        return [
            'total_subscriptions' => $totalSubscriptions,
            'active_subscriptions' => $activeSubscriptions,
            'trial_subscriptions' => $trialSubscriptions,
            'cancelled_subscriptions' => $cancelledSubscriptions,
            'monthly_recurring_revenue' => $mrr,
            'total_revenue' => $totalRevenue,
            'churn_rate' => $totalSubscriptions > 0 ? ($cancelledSubscriptions / $totalSubscriptions) * 100 : 0,
            'trial_conversion_rate' => $trialSubscriptions > 0 ? (($activeSubscriptions - $trialSubscriptions) / $trialSubscriptions) * 100 : 0,
        ];
    }

    /**
     * Get coupon analytics
     */
    public function getCouponAnalytics(array $filters = []): array
    {
        $query = CouponUsage::query();

        if (isset($filters['date_from'])) {
            $query->whereDate('created_at', '>=', $filters['date_from']);
        }

        if (isset($filters['date_to'])) {
            $query->whereDate('created_at', '<=', $filters['date_to']);
        }

        $totalUsages = $query->count();
        $totalDiscount = $query->sum('discount_amount');
        $uniqueUsers = $query->distinct('user_id')->count('user_id');
        $conversionRate = $uniqueUsers > 0 ? ($totalUsages / $uniqueUsers) * 100 : 0;

        $topCoupons = $query->join('coupons', 'coupon_usages.coupon_id', '=', 'coupons.id')
            ->select('coupons.code', 'coupons.discount_type', 'coupons.discount_value',
                DB::raw('COUNT(*) as usage_count'),
                DB::raw('SUM(coupon_usages.discount_amount) as total_discount'))
            ->groupBy('coupons.id', 'coupons.code', 'coupons.discount_type', 'coupons.discount_value')
            ->orderBy('usage_count', 'desc')
            ->limit(10)
            ->get();

        return [
            'total_usages' => $totalUsages,
            'total_discount_given' => $totalDiscount,
            'unique_users' => $uniqueUsers,
            'conversion_rate' => $conversionRate,
            'top_performing_coupons' => $topCoupons->toArray(),
        ];
    }

    /**
     * Get trial analytics
     */
    public function getTrialAnalytics(array $filters = []): array
    {
        $query = TrialExtension::query();

        if (isset($filters['date_from'])) {
            $query->whereDate('granted_at', '>=', $filters['date_from']);
        }

        if (isset($filters['date_to'])) {
            $query->whereDate('granted_at', '<=', $filters['date_to']);
        }

        $totalExtensions = $query->count();
        $totalDaysExtended = $query->sum('extension_days');
        $uniqueUsers = $query->distinct('user_id')->count('user_id');

        $extensionTypes = $query->select('extension_type', DB::raw('COUNT(*) as count'))
            ->groupBy('extension_type')
            ->pluck('count', 'extension_type')
            ->toArray();

        $commonReasons = $query->select('reason', DB::raw('COUNT(*) as count'))
            ->whereNotNull('reason')
            ->groupBy('reason')
            ->orderBy('count', 'desc')
            ->limit(5)
            ->pluck('count', 'reason')
            ->toArray();

        return [
            'total_extensions' => $totalExtensions,
            'total_days_extended' => $totalDaysExtended,
            'unique_users' => $uniqueUsers,
            'extension_types' => $extensionTypes,
            'common_reasons' => $commonReasons,
            'avg_extension_days' => $totalExtensions > 0 ? $totalDaysExtended / $totalExtensions : 0,
        ];
    }

    /**
     * Check subscription status via provider
     */
    public function checkSubscriptionStatus(User $user, string $providerName, string $providerSubscriptionId): array
    {
        try {
            $provider = $this->providerRegistry->get($providerName);

            if (! $provider) {
                return [
                    'success' => false,
                    'error' => "Provider {$providerName} not found",
                ];
            }

            if (! $provider->isActive()) {
                return [
                    'success' => false,
                    'error' => "Provider {$providerName} is not active",
                ];
            }

            Log::info('PaymentOrchestrator: Checking subscription status', [
                'user_id' => $user->id,
                'provider' => $providerName,
                'provider_subscription_id' => $providerSubscriptionId,
            ]);

            // Get subscription details from provider
            $details = $provider->getSubscriptionDetails($providerSubscriptionId);

            if (empty($details)) {
                return [
                    'success' => false,
                    'error' => 'Unable to fetch subscription details from provider',
                ];
            }

            return [
                'success' => true,
                'status' => $details['status'] ?? 'unknown',
                'details' => $details,
            ];

        } catch (Exception $e) {
            Log::error('PaymentOrchestrator: Error checking subscription status', [
                'user_id' => $user->id,
                'provider' => $providerName,
                'provider_subscription_id' => $providerSubscriptionId,
                'error' => $e->getMessage(),
            ]);

            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }
}
