<?php

namespace App\Http\Controllers;

use App\Models\Subscription;
use App\Models\SubscriptionTransaction;
use App\Models\RazorpaySetting;
use App\Services\RazorpayService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\DB;

class WebhookController extends Controller
{
    protected $razorpayService;

    public function __construct(RazorpayService $razorpayService)
    {
        $this->razorpayService = $razorpayService;
    }

    /**
     * Handle Razorpay webhook.
     */
    public function handle(Request $request)
    {
        try {
            // Verify webhook signature
            if (!$this->verifySignature($request)) {
                Log::error('Razorpay webhook signature verification failed');
                return response()->json(['error' => 'Invalid signature'], 400);
            }

            $payload = $request->all();
            $event = $payload['event'] ?? null;

            Log::info('Razorpay webhook received', ['event' => $event]);

            // Handle different webhook events
            switch ($event) {
                case 'payment.authorized':
                case 'payment.captured':
                    return $this->handlePaymentSuccess($payload);

                case 'payment.failed':
                    return $this->handlePaymentFailed($payload);

                case 'subscription.activated':
                    return $this->handleSubscriptionActivated($payload);

                case 'subscription.charged':
                    return $this->handleSubscriptionCharged($payload);

                case 'subscription.cancelled':
                    return $this->handleSubscriptionCancelled($payload);

                case 'subscription.completed':
                    return $this->handleSubscriptionCompleted($payload);

                case 'subscription.paused':
                    return $this->handleSubscriptionPaused($payload);

                case 'subscription.resumed':
                    return $this->handleSubscriptionResumed($payload);

                case 'refund.created':
                    return $this->handleRefundCreated($payload);

                default:
                    Log::info('Unhandled webhook event', ['event' => $event]);
                    return response()->json(['message' => 'Event not handled'], 200);
            }
        } catch (\Exception $e) {
            Log::error('Webhook processing error: ' . $e->getMessage(), [
                'payload' => $request->all()
            ]);
            return response()->json(['error' => 'Webhook processing failed'], 500);
        }
    }

    /**
     * Verify webhook signature.
     */
    protected function verifySignature(Request $request): bool
    {
        $settings = RazorpaySetting::getInstance();
        
        if (!$settings || !$settings->webhook_secret) {
            Log::warning('Webhook secret not configured');
            return false;
        }

        $webhookSignature = $request->header('X-Razorpay-Signature');
        $webhookBody = $request->getContent();

        $expectedSignature = hash_hmac('sha256', $webhookBody, $settings->webhook_secret);

        return hash_equals($expectedSignature, $webhookSignature);
    }

    /**
     * Handle successful payment.
     */
    protected function handlePaymentSuccess(array $payload)
    {
        $payment = $payload['payload']['payment']['entity'] ?? null;

        if (!$payment) {
            return response()->json(['error' => 'Invalid payload'], 400);
        }

        $paymentId = $payment['id'];
        $orderId = $payment['order_id'] ?? null;
        $amount = $payment['amount'] / 100; // Convert from paise

        // Find subscription by order_id in metadata
        $subscription = Subscription::whereJsonContains('metadata->razorpay_order_id', $orderId)->first();

        if (!$subscription) {
            Log::warning('Subscription not found for payment', ['order_id' => $orderId]);
            return response()->json(['message' => 'Subscription not found'], 404);
        }

        DB::transaction(function () use ($subscription, $payment, $amount) {
            // Update subscription status
            if ($subscription->status !== Subscription::STATUS_ACTIVE) {
                $subscription->update(['status' => Subscription::STATUS_ACTIVE]);
            }

            // Create transaction record if not exists
            SubscriptionTransaction::firstOrCreate(
                ['razorpay_payment_id' => $payment['id']],
                [
                    'subscription_id' => $subscription->id,
                    'user_id' => $subscription->user_id,
                    'razorpay_order_id' => $payment['order_id'] ?? null,
                    'type' => SubscriptionTransaction::TYPE_PAYMENT,
                    'amount' => $amount,
                    'currency' => $payment['currency'],
                    'status' => SubscriptionTransaction::STATUS_SUCCESS,
                    'description' => 'Payment received via webhook',
                    'paid_at' => now(),
                    'metadata' => [
                        'method' => $payment['method'] ?? null,
                        'email' => $payment['email'] ?? null,
                    ],
                ]
            );
        });

        Log::info('Payment success processed', ['payment_id' => $paymentId]);

        return response()->json(['message' => 'Payment processed'], 200);
    }

    /**
     * Handle failed payment.
     */
    protected function handlePaymentFailed(array $payload)
    {
        $payment = $payload['payload']['payment']['entity'] ?? null;

        if (!$payment) {
            return response()->json(['error' => 'Invalid payload'], 400);
        }

        $paymentId = $payment['id'];
        $orderId = $payment['order_id'] ?? null;
        $errorDescription = $payment['error_description'] ?? 'Payment failed';

        // Find subscription
        $subscription = Subscription::whereJsonContains('metadata->razorpay_order_id', $orderId)->first();

        if ($subscription) {
            // Create failed transaction record
            SubscriptionTransaction::create([
                'subscription_id' => $subscription->id,
                'user_id' => $subscription->user_id,
                'razorpay_payment_id' => $paymentId,
                'razorpay_order_id' => $orderId,
                'type' => SubscriptionTransaction::TYPE_PAYMENT,
                'amount' => ($payment['amount'] ?? 0) / 100,
                'currency' => $payment['currency'] ?? 'INR',
                'status' => SubscriptionTransaction::STATUS_FAILED,
                'description' => 'Payment failed: ' . $errorDescription,
                'metadata' => [
                    'error_code' => $payment['error_code'] ?? null,
                    'error_description' => $errorDescription,
                ],
            ]);

            // Update subscription status to past_due
            $subscription->update(['status' => Subscription::STATUS_PAST_DUE]);
        }

        Log::info('Payment failure processed', ['payment_id' => $paymentId]);

        return response()->json(['message' => 'Payment failure processed'], 200);
    }

    /**
     * Handle subscription activated.
     */
    protected function handleSubscriptionActivated(array $payload)
    {
        $razorpaySubscription = $payload['payload']['subscription']['entity'] ?? null;

        if (!$razorpaySubscription) {
            return response()->json(['error' => 'Invalid payload'], 400);
        }

        $subscriptionId = $razorpaySubscription['id'];

        $subscription = Subscription::where('razorpay_subscription_id', $subscriptionId)->first();

        if ($subscription) {
            $subscription->update([
                'status' => Subscription::STATUS_ACTIVE,
                'current_period_start' => now(),
                'current_period_end' => now()->addMonth(),
            ]);

            Log::info('Subscription activated', ['subscription_id' => $subscriptionId]);
        }

        return response()->json(['message' => 'Subscription activated'], 200);
    }

    /**
     * Handle subscription charged (renewal).
     */
    protected function handleSubscriptionCharged(array $payload)
    {
        $razorpaySubscription = $payload['payload']['subscription']['entity'] ?? null;
        $payment = $payload['payload']['payment']['entity'] ?? null;

        if (!$razorpaySubscription || !$payment) {
            return response()->json(['error' => 'Invalid payload'], 400);
        }

        $subscriptionId = $razorpaySubscription['id'];
        $subscription = Subscription::where('razorpay_subscription_id', $subscriptionId)->first();

        if ($subscription) {
            DB::transaction(function () use ($subscription, $payment) {
                // Renew subscription
                $subscription->renew();

                // Create transaction record
                SubscriptionTransaction::create([
                    'subscription_id' => $subscription->id,
                    'user_id' => $subscription->user_id,
                    'razorpay_payment_id' => $payment['id'],
                    'type' => SubscriptionTransaction::TYPE_PAYMENT,
                    'amount' => $payment['amount'] / 100,
                    'currency' => $payment['currency'],
                    'status' => SubscriptionTransaction::STATUS_SUCCESS,
                    'description' => 'Subscription renewal payment',
                    'paid_at' => now(),
                ]);
            });

            Log::info('Subscription charged', ['subscription_id' => $subscriptionId]);
        }

        return response()->json(['message' => 'Subscription charged'], 200);
    }

    /**
     * Handle subscription cancelled.
     */
    protected function handleSubscriptionCancelled(array $payload)
    {
        $razorpaySubscription = $payload['payload']['subscription']['entity'] ?? null;

        if (!$razorpaySubscription) {
            return response()->json(['error' => 'Invalid payload'], 400);
        }

        $subscriptionId = $razorpaySubscription['id'];
        $subscription = Subscription::where('razorpay_subscription_id', $subscriptionId)->first();

        if ($subscription) {
            $subscription->cancel(immediately: false);
            Log::info('Subscription cancelled', ['subscription_id' => $subscriptionId]);
        }

        return response()->json(['message' => 'Subscription cancelled'], 200);
    }

    /**
     * Handle subscription completed.
     */
    protected function handleSubscriptionCompleted(array $payload)
    {
        $razorpaySubscription = $payload['payload']['subscription']['entity'] ?? null;

        if (!$razorpaySubscription) {
            return response()->json(['error' => 'Invalid payload'], 400);
        }

        $subscriptionId = $razorpaySubscription['id'];
        $subscription = Subscription::where('razorpay_subscription_id', $subscriptionId)->first();

        if ($subscription) {
            $subscription->markAsExpired();
            Log::info('Subscription completed', ['subscription_id' => $subscriptionId]);
        }

        return response()->json(['message' => 'Subscription completed'], 200);
    }

    /**
     * Handle subscription paused.
     */
    protected function handleSubscriptionPaused(array $payload)
    {
        $razorpaySubscription = $payload['payload']['subscription']['entity'] ?? null;

        if (!$razorpaySubscription) {
            return response()->json(['error' => 'Invalid payload'], 400);
        }

        $subscriptionId = $razorpaySubscription['id'];
        $subscription = Subscription::where('razorpay_subscription_id', $subscriptionId)->first();

        if ($subscription) {
            $subscription->update(['status' => Subscription::STATUS_CANCELLED]);
            Log::info('Subscription paused', ['subscription_id' => $subscriptionId]);
        }

        return response()->json(['message' => 'Subscription paused'], 200);
    }

    /**
     * Handle subscription resumed.
     */
    protected function handleSubscriptionResumed(array $payload)
    {
        $razorpaySubscription = $payload['payload']['subscription']['entity'] ?? null;

        if (!$razorpaySubscription) {
            return response()->json(['error' => 'Invalid payload'], 400);
        }

        $subscriptionId = $razorpaySubscription['id'];
        $subscription = Subscription::where('razorpay_subscription_id', $subscriptionId)->first();

        if ($subscription) {
            $subscription->resume();
            Log::info('Subscription resumed', ['subscription_id' => $subscriptionId]);
        }

        return response()->json(['message' => 'Subscription resumed'], 200);
    }

    /**
     * Handle refund created.
     */
    protected function handleRefundCreated(array $payload)
    {
        $refund = $payload['payload']['refund']['entity'] ?? null;

        if (!$refund) {
            return response()->json(['error' => 'Invalid payload'], 400);
        }

        $paymentId = $refund['payment_id'];
        $amount = $refund['amount'] / 100;

        // Find transaction
        $transaction = SubscriptionTransaction::where('razorpay_payment_id', $paymentId)->first();

        if ($transaction) {
            $transaction->update(['status' => SubscriptionTransaction::STATUS_REFUNDED]);
            Log::info('Refund processed', ['payment_id' => $paymentId, 'amount' => $amount]);
        }

        return response()->json(['message' => 'Refund processed'], 200);
    }
}