<?php

namespace App\Services;

use App\Models\PaymentGateway;
use App\Models\Transaction;
use App\Models\Subscription;
use App\Models\AdPackagePurchase;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;

class PaymentService
{
    protected $gateways = [];

    public function __construct()
    {
        $this->initializeGateways();
    }

    protected function initializeGateways()
    {
        $activeGateways = PaymentGateway::where('is_active', true)->get();
        
        foreach ($activeGateways as $gateway) {
            switch ($gateway->slug) {
                case 'razorpay':
                    $this->gateways['razorpay'] = new RazorpayGateway($gateway);
                    break;
                case 'phonepe':
                    $this->gateways['phonepe'] = new PhonePeGateway($gateway);
                    break;
                case 'stripe':
                    $this->gateways['stripe'] = new StripeGateway($gateway);
                    break;
                case 'paypal':
                    $this->gateways['paypal'] = new PayPalGateway($gateway);
                    break;
            }
        }
    }

    public function createOrder($userId, $amount, $currency, $gatewaySlug, $entityType, $entityId, $description = null)
    {
        $user = User::findOrFail($userId);
        $gateway = $this->getGateway($gatewaySlug);
        
        if (!$gateway) {
            throw new \Exception("Payment gateway not found or not active: $gatewaySlug");
        }

        // Generate unique order ID
        $orderId = $this->generateOrderId();
        $transactionId = $this->generateTransactionId();

        // Create transaction record
        $transaction = Transaction::create([
            'transaction_id' => $transactionId,
            'order_id' => $orderId,
            'user_id' => $user->id,
            'entity_type' => $entityType,
            'entity_id' => $entityId,
            'gateway_slug' => $gatewaySlug,
            'amount' => $amount,
            'currency' => $currency,
            'status' => 'pending',
            'payment_status' => 'pending',
            'description' => $description,
        ]);

        try {
            // Create order with gateway
            $gatewayResponse = $gateway->createOrder($orderId, $amount, $currency, $user, $description);
            
            // Update transaction with gateway response
            $transaction->update([
                'gateway_order_id' => $gatewayResponse['order_id'] ?? null,
                'gateway_response' => $gatewayResponse,
            ]);

            return [
                'success' => true,
                'transaction_id' => $transaction->transaction_id,
                'order_id' => $transaction->order_id,
                'gateway_data' => $gatewayResponse,
            ];

        } catch (\Exception $e) {
            Log::error('Payment order creation failed', [
                'user_id' => $userId,
                'gateway' => $gatewaySlug,
                'amount' => $amount,
                'error' => $e->getMessage(),
            ]);

            $transaction->update([
                'status' => 'failed',
                'gateway_response' => ['error' => $e->getMessage()],
            ]);

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

    public function processPayment($transactionId, $paymentData)
    {
        $transaction = Transaction::where('transaction_id', $transactionId)->firstOrFail();
        $gateway = $this->getGateway($transaction->gateway_slug);

        try {
            // Verify payment with gateway
            $verificationResult = $gateway->verifyPayment($transaction, $paymentData);
            
            if ($verificationResult['success']) {
                // Update transaction status
                $transaction->update([
                    'status' => 'success',
                    'payment_status' => 'captured',
                    'gateway_transaction_id' => $verificationResult['transaction_id'],
                    'gateway_response' => $verificationResult,
                    'paid_at' => now(),
                    'captured_at' => now(),
                ]);

                // Process the entity (subscription or ad package)
                $this->processEntityPayment($transaction);

                return [
                    'success' => true,
                    'transaction' => $transaction,
                ];
            } else {
                $transaction->update([
                    'status' => 'failed',
                    'gateway_response' => $verificationResult,
                ]);

                return [
                    'success' => false,
                    'error' => $verificationResult['error'] ?? 'Payment verification failed',
                ];
            }

        } catch (\Exception $e) {
            Log::error('Payment processing failed', [
                'transaction_id' => $transactionId,
                'error' => $e->getMessage(),
            ]);

            $transaction->update([
                'status' => 'failed',
                'gateway_response' => ['error' => $e->getMessage()],
            ]);

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

    protected function processEntityPayment(Transaction $transaction)
    {
        switch ($transaction->entity_type) {
            case 'subscription':
                $this->processSubscriptionPayment($transaction);
                break;
            case 'ad_package':
                $this->processAdPackagePayment($transaction);
                break;
        }
    }

    protected function processSubscriptionPayment(Transaction $transaction)
    {
        // This would be implemented based on your subscription logic
        // For now, we'll just mark it as processed
        Log::info('Subscription payment processed', [
            'transaction_id' => $transaction->transaction_id,
            'entity_id' => $transaction->entity_id,
        ]);
    }

    protected function processAdPackagePayment(Transaction $transaction)
    {
        $adPackagePurchase = AdPackagePurchase::where('transaction_id', $transaction->transaction_id)->first();
        
        if ($adPackagePurchase) {
            $adPackagePurchase->update([
                'status' => 'active',
                'start_date' => now(),
            ]);

            // Apply features to the ad
            $this->applyAdPackageFeatures($adPackagePurchase);
        }
    }

    protected function applyAdPackageFeatures(AdPackagePurchase $purchase)
    {
        $ad = $purchase->ad;
        $package = $purchase->adPackage;

        // Apply package features to ad
        $ad->update([
            'is_featured' => $package->featured,
            'is_boosted' => $package->boosted,
            'last_bumped_at' => $package->bumped ? now() : $ad->last_bumped_at,
        ]);
    }

    public function createSubscription($userId, $planId, $gatewaySlug)
    {
        $user = User::findOrFail($userId);
        $plan = \App\Models\UserPlan::findOrFail($planId);
        $gateway = $this->getGateway($gatewaySlug);

        if (!$gateway) {
            throw new \Exception("Payment gateway not found or not active: $gatewaySlug");
        }

        try {
            // Create subscription in gateway
            $subscriptionData = $gateway->createSubscription($user, $plan);
            
            // Create local subscription record
            $subscription = Subscription::create([
                'subscription_id' => $this->generateSubscriptionId(),
                'user_id' => $user->id,
                'plan_id' => $plan->id,
                'gateway_subscription_id' => $subscriptionData['subscription_id'],
                'gateway_customer_id' => $subscriptionData['customer_id'] ?? null,
                'gateway_slug' => $gatewaySlug,
                'status' => 'active',
                'payment_status' => 'pending',
                'start_date' => now(),
                'end_date' => now()->addDays($plan->validity_days),
                'next_billing_date' => now()->addDays($plan->validity_days),
                'amount' => $plan->price,
                'currency' => $plan->currency_code ?? 'INR',
                'billing_interval' => 'day',
                'billing_frequency' => $plan->validity_days,
                'auto_renew' => true,
            ]);

            // Update user's current plan
            $user->update([
                'current_plan_id' => $plan->id,
            ]);

            return [
                'success' => true,
                'subscription' => $subscription,
                'gateway_data' => $subscriptionData,
            ];

        } catch (\Exception $e) {
            Log::error('Subscription creation failed', [
                'user_id' => $userId,
                'plan_id' => $planId,
                'gateway' => $gatewaySlug,
                'error' => $e->getMessage(),
            ]);

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

    public function refundTransaction($transactionId, $amount = null, $reason = null)
    {
        $transaction = Transaction::where('transaction_id', $transactionId)->firstOrFail();
        $gateway = $this->getGateway($transaction->gateway_slug);

        if (!$transaction->canBeRefunded()) {
            throw new \Exception('Transaction cannot be refunded');
        }

        try {
            $refundAmount = $amount ?? $transaction->amount;
            $refundResult = $gateway->refundPayment($transaction, $refundAmount, $reason);

            if ($refundResult['success']) {
                // Update transaction refund status
                $refundStatus = ($refundAmount == $transaction->amount) ? 'full' : 'partial';
                
                $transaction->update([
                    'refund_status' => $refundStatus,
                    'refunded_at' => now(),
                    'gateway_response' => array_merge(
                        $transaction->gateway_response ?? [],
                        ['refund' => $refundResult]
                    ),
                ]);

                return [
                    'success' => true,
                    'refund_id' => $refundResult['refund_id'],
                    'refunded_amount' => $refundAmount,
                ];
            } else {
                return [
                    'success' => false,
                    'error' => $refundResult['error'],
                ];
            }

        } catch (\Exception $e) {
            Log::error('Refund failed', [
                'transaction_id' => $transactionId,
                'error' => $e->getMessage(),
            ]);

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

    public function getGateway($slug)
    {
        return $this->gateways[$slug] ?? null;
    }

    public function getActiveGateways()
    {
        return PaymentGateway::where('is_active', true)
            ->with('paymentMethods')
            ->orderBy('sort_order')
            ->get();
    }

    protected function generateOrderId()
    {
        return 'ORD_' . strtoupper(Str::random(10)) . '_' . time();
    }

    protected function generateTransactionId()
    {
        return 'TXN_' . strtoupper(Str::random(12)) . '_' . time();
    }

    protected function generateSubscriptionId()
    {
        return 'SUB_' . strtoupper(Str::random(10)) . '_' . time();
    }
}
