<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Stripe\StripeClient;
use Stripe\Event;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;


use App\Cart;
use App\Mail\GenericMail;
use App\Model\Client\SmtpSetting;
use App\Model\Client\UserPackage;
use App\Model\Client\wallet;
use App\Model\Client\walletTransaction;
use App\Model\Master\ClientPackage;
use App\Model\Master\Order;
use App\Model\Master\OrdersItem;
use App\Model\Master\Package;
use App\Model\Master\PaymentTransaction;
use App\Services\MailService;
use Exception;
use Illuminate\Database\Eloquent\Model;
use App\Http\Controllers\StripeController;

class StripeWebhookController extends Controller
{
    public function handleWebhook(Request $request)
    {
        Log::debug('Webhook endpoint hit', ['payload' => $request->all(), 'headers' => $request->headers->all()]);

        // Initialize Stripe client
        $stripe = new StripeClient(env('STRIPE_SECRET'));
        $endpoint_secret = env('STRIPE_WEBHOOK_SECRET');

        // Get the webhook payload and signature
        $payload = $request->getContent();
        $sig_header = $request->header('Stripe-Signature');

        try {
            // Verify webhook signature
            $event = \Stripe\Webhook::constructEvent($payload, $sig_header, $endpoint_secret);
            Log::info('Stripe webhook received', [
                'event_id' => $event->id,
                'event_type' => $event->type,
            ]);

            // Handle events
            switch ($event->type) {
                case 'customer.subscription.updated':
                    $subscription = $event->data->object;
                    $subscriptionId = $subscription->id;
                    $customerId = $subscription->customer;
                    $status = $subscription->status;
                    $latestInvoiceId = $subscription->latest_invoice;
                    $currentPeriodEnd = Carbon::createFromTimestampUTC($subscription->current_period_end);

                    Log::info('Processing customer.subscription.updated', [
                        'subscription_id' => $subscriptionId,
                        'customer_id' => $customerId,
                        'status' => $status,
                        'latest_invoice' => $latestInvoiceId,
                        'current_period_end' => $currentPeriodEnd->toDateTimeString(),
                    ]);

                    // Find the order associated with the subscription
                    $order = Order::where('stripe_subscription_id', $subscriptionId)->first();
                    if (!$order) {
                        // Create a new order if not found
                        $order = new Order();
                        $order->client_id = 3; // Default to client_id: 3
                        $order->stripe_subscription_id = $subscriptionId;
                        $order->stripe_customer_id = $customerId;
                        $order->status = $status === 'active' ? 'success' : 'pending';
                        $order->net_amount = 0; // Update if needed
                        $order->gross_amount = 0; // Update if needed
                        $order->save();
                        Log::info('New order created for subscription', [
                            'order_id' => $order->id,
                            'subscription_id' => $subscriptionId,
                        ]);
                    }

                    // Fetch the latest invoice for payment details
                    $invoice = $stripe->invoices->retrieve($latestInvoiceId, ['expand' => ['payment_intent']]);
                    $paymentIntent = $invoice->payment_intent;

                    // Update order status
                    $order->status = $status === 'active' ? 'success' : 'pending';
                    $order->save();

                    // Create payment transaction for the renewal
                    $paymentTransaction = new PaymentTransaction();
                    $paymentTransaction->order_id = $order->id;
                    $paymentTransaction->payment_gateway_type = 'stripe';
                    $paymentTransaction->response = json_encode($paymentIntent);
                    $paymentTransaction->status = $paymentIntent->status === 'succeeded' ? 'success' : 'pending';
                    $paymentTransaction->saveOrFail();

                    if ($paymentIntent->status !== 'succeeded') {
                        Log::error('Subscription renewal payment failed', [
                            'subscription_id' => $subscriptionId,
                            'order_id' => $order->id,
                            'payment_intent_status' => $paymentIntent->status,
                        ]);
                        return response()->json(['status' => 'error', 'message' => 'Renewal payment failed'], 400);
                    }

                    // Update client_packages for the client
                    $clientPackages = ClientPackage::where('client_id', $order->client_id)
                        ->where('end_time', '>=', Carbon::now())
                        ->get();
                    foreach ($clientPackages as $clientPackage) {
                        $clientPackage->end_time = $currentPeriodEnd;
                        $clientPackage->expiry_time = $currentPeriodEnd;
                        $clientPackage->payment_time = Carbon::now();
                        $clientPackage->payment_cent_amount = $invoice->amount_paid;
                        $clientPackage->saveOrFail();
                        Log::info('Client package updated', [
                            'client_package_id' => $clientPackage->id,
                            'end_time' => $clientPackage->end_time,
                        ]);
                    }

                    // Update user_packages
                    $userPackages = UserPackage::on('mysql_' . $order->client_id)
                        ->whereIn('client_package_id', $clientPackages->pluck('id'))
                        ->get();
                    foreach ($userPackages as $userPackage) {
                        $userPackage->free_reset_time = $currentPeriodEnd;
                        $userPackage->saveOrFail();
                        Log::info('User package updated', [
                            'user_package_id' => $userPackage->id,
                            'free_reset_time' => $userPackage->free_reset_time,
                        ]);
                    }

                    Log::info('Subscription renewal processed successfully', [
                        'subscription_id' => $subscriptionId,
                        'order_id' => $order->id,
                    ]);
                    break;

                case 'invoice.payment_succeeded':
                    $invoice = $event->data->object;
                    $invoiceId = $invoice->id;
                    $customerId = $invoice->customer;
                    $subscriptionId = $invoice->parent->subscription_details->subscription ?? null;
                    $amountPaid = $invoice->amount_paid;
                    $billingReason = $invoice->billing_reason;

                    Log::info('Processing invoice.payment_succeeded', [
                        'invoice_id' => $invoiceId,
                        'customer_id' => $customerId,
                        'subscription_id' => $subscriptionId,
                        'amount_paid' => $amountPaid,
                        'billing_reason' => $billingReason,
                    ]);

                    if (!$subscriptionId) {
                        Log::warning('No subscription ID in invoice.payment_succeeded', [
                            'invoice_id' => $invoiceId,
                        ]);
                        return response()->json(['status' => 'ignored'], 200);
                    }

                    // Find the order associated with the subscription
                    $order = Order::where('stripe_subscription_id', $subscriptionId)->first();
                    if (!$order) {
                        // Create a new order if not found
                        $order = new Order();
                        $order->client_id = 3; // Default to client_id: 3
                        $order->stripe_subscription_id = $subscriptionId;
                        $order->stripe_customer_id = $customerId;
                        $order->status = 'success';
                        $order->net_amount = $amountPaid;
                        $order->gross_amount = $amountPaid;
                        $order->save();
                        Log::info('New order created for invoice', [
                            'order_id' => $order->id,
                            'subscription_id' => $subscriptionId,
                        ]);
                    }

                    // Create payment transaction for the invoice payment
                    $paymentTransaction = new PaymentTransaction();
                    $paymentTransaction->order_id = $order->id;
                    $paymentTransaction->payment_gateway_type = 'stripe';
                    $paymentTransaction->response = json_encode($invoice);
                    $paymentTransaction->status = 'success';
                    $paymentTransaction->saveOrFail();

                    // Update client_packages for the client
                    $clientPackages = ClientPackage::where('client_id', $order->client_id)
                        ->where('end_time', '>=', Carbon::now())
                        ->get();
                    foreach ($clientPackages as $clientPackage) {
                        $clientPackage->payment_time = Carbon::now();
                        $clientPackage->payment_cent_amount = $amountPaid;
                        $clientPackage->saveOrFail();
                        Log::info('Client package updated for invoice', [
                            'client_package_id' => $clientPackage->id,
                            'payment_cent_amount' => $amountPaid,
                        ]);
                    }

                    Log::info('Invoice payment processed successfully', [
                        'invoice_id' => $invoiceId,
                        'order_id' => $order->id,
                    ]);
                    break;

                default:
                    Log::info('Webhook event ignored', ['event_type' => $event->type]);
                    return response()->json(['status' => 'ignored'], 200);
            }

            return response()->json(['status' => 'success'], 200);

        } catch (\Stripe\Exception\SignatureVerificationException $e) {
            Log::error('Invalid Stripe webhook signature', ['error' => $e->getMessage()]);
            return response()->json(['status' => 'error', 'message' => 'Invalid signature'], 400);
        } catch (\Throwable $e) {
            Log::error('Stripe webhook processing failed', [
                'event_id' => $event->id ?? 'unknown',
                'event_type' => $event->type ?? 'unknown',
                'error' => $e->getMessage(),
            ]);
            return response()->json(['status' => 'error', 'message' => 'Webhook processing failed'], 500);
        }
    }
}
?>