<?php

namespace App\Services;

use Stripe\Stripe;
use Stripe\PaymentIntent;
use Stripe\Customer;
use Stripe\PaymentMethod;
use Stripe\Subscription as StripeSubscription;
use App\Models\Transaction;
use App\Models\Subscription;
use App\Models\User;
use App\Models\UserPlan;
use Exception;
use Illuminate\Support\Facades\Log;

class StripeService
{
    public function __construct()
    {
        Stripe::setApiKey(config('services.stripe.secret'));
    }

    /**
     * Create or retrieve Stripe customer
     */
    public function createOrGetCustomer(User $user)
    {
        try {
            // If user already has a Stripe customer ID, retrieve it
            if ($user->stripe_customer_id) {
                try {
                    return Customer::retrieve($user->stripe_customer_id);
                } catch (Exception $e) {
                    // Customer doesn't exist, create new one
                    Log::warning("Stripe customer not found: {$user->stripe_customer_id}");
                }
            }

            // Create new customer
            $customer = Customer::create([
                'email' => $user->email,
                'name' => $user->name,
                'metadata' => [
                    'user_id' => $user->id,
                ],
            ]);

            // Save customer ID to user
            $user->update(['stripe_customer_id' => $customer->id]);

            return $customer;
        } catch (Exception $e) {
            Log::error("Error creating Stripe customer: " . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Create payment intent
     */
    public function createPaymentIntent($amount, $currency, User $user, $metadata = [])
    {
        try {
            $customer = $this->createOrGetCustomer($user);

            $paymentIntent = PaymentIntent::create([
                'amount' => $amount * 100, // Convert to cents
                'currency' => strtolower($currency),
                'customer' => $customer->id,
                'metadata' => array_merge([
                    'user_id' => $user->id,
                ], $metadata),
                'automatic_payment_methods' => [
                    'enabled' => true,
                ],
            ]);

            return $paymentIntent;
        } catch (Exception $e) {
            Log::error("Error creating payment intent: " . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Create subscription
     */
    public function createSubscription(User $user, UserPlan $plan, $paymentMethodId = null)
    {
        try {
            $customer = $this->createOrGetCustomer($user);

            // Attach payment method if provided
            if ($paymentMethodId) {
                $paymentMethod = PaymentMethod::retrieve($paymentMethodId);
                $paymentMethod->attach(['customer' => $customer->id]);

                // Set as default payment method
                Customer::update($customer->id, [
                    'invoice_settings' => [
                        'default_payment_method' => $paymentMethodId,
                    ],
                ]);
            }

            // Create subscription
            $subscription = StripeSubscription::create([
                'customer' => $customer->id,
                'items' => [
                    ['price_data' => [
                        'currency' => 'inr',
                        'product_data' => [
                            'name' => $plan->name,
                        ],
                        'unit_amount' => $plan->price * 100,
                        'recurring' => [
                            'interval' => 'month',
                        ],
                    ]],
                ],
                'metadata' => [
                    'user_id' => $user->id,
                    'plan_id' => $plan->id,
                ],
            ]);

            // Create local subscription record
            $localSubscription = Subscription::create([
                'subscription_id' => 'sub_' . uniqid(),
                'user_id' => $user->id,
                'plan_id' => $plan->id,
                'gateway_subscription_id' => $subscription->id,
                'gateway_customer_id' => $customer->id,
                'gateway_slug' => 'stripe',
                'status' => $subscription->status,
                'payment_status' => $subscription->status === 'active' ? 'paid' : 'pending',
                'start_date' => now(),
                'end_date' => now()->addMonth(),
                'next_billing_date' => now()->addMonth(),
                'amount' => $plan->price,
                'currency' => 'INR',
                'billing_interval' => 'month',
                'billing_frequency' => 1,
                'auto_renew' => true,
            ]);

            // Update user's plan
            $user->update([
                'plan_id' => $plan->id,
                'plan_expires_at' => now()->addMonth(),
            ]);

            return [
                'stripe_subscription' => $subscription,
                'local_subscription' => $localSubscription,
            ];
        } catch (Exception $e) {
            Log::error("Error creating subscription: " . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Cancel subscription
     */
    public function cancelSubscription($subscriptionId)
    {
        try {
            $subscription = StripeSubscription::retrieve($subscriptionId);
            $cancelled = $subscription->cancel();

            return $cancelled;
        } catch (Exception $e) {
            Log::error("Error cancelling subscription: " . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Create refund
     */
    public function createRefund($paymentIntentId, $amount = null)
    {
        try {
            $refundData = ['payment_intent' => $paymentIntentId];
            
            if ($amount) {
                $refundData['amount'] = $amount * 100; // Convert to cents
            }

            $refund = \Stripe\Refund::create($refundData);

            return $refund;
        } catch (Exception $e) {
            Log::error("Error creating refund: " . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Retrieve payment intent
     */
    public function retrievePaymentIntent($paymentIntentId)
    {
        try {
            return PaymentIntent::retrieve($paymentIntentId);
        } catch (Exception $e) {
            Log::error("Error retrieving payment intent: " . $e->getMessage());
            throw $e;
        }
    }
}
