<?php

namespace App\Http\Controllers\Api;

use App\Models\Payment;
use App\Models\Subscription;
use App\Models\PaymentMethod;
use App\Services\ActionNotificationService;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Stripe\Stripe;
use Stripe\PaymentIntent;

class PaymentController extends \App\Http\Controllers\Controller
{
    public function __construct()
    {
        Stripe::setApiKey(config('services.stripe.secret'));
    }

    /**
     * Get payment checkout data
     */
    public function checkout(Request $request): JsonResponse
    {
        $validated = $request->validate([
            'subscription_id' => 'required|exists:subscriptions,id',
        ]);

        $subscription = Subscription::find($validated['subscription_id']);

        if ($subscription->user_id !== $request->user()->id) {
            return response()->json([
                'success' => false,
                'message' => 'Unauthorized',
            ], 403);
        }

        $paymentMethods = PaymentMethod::where('is_active', true)->get();

        return response()->json([
            'success' => true,
            'data' => [
                'subscription_id' => $subscription->id,
                'package' => $subscription->package->name,
                'drivers' => $subscription->package->driver_limit,
                'trucks' => $subscription->package->truck_limit,
                'amount' => (float)$subscription->package->price,
                'billing_cycle' => $subscription->package->billing_cycle,
                'payment_methods' => $paymentMethods->map(function ($method) {
                    return [
                        'id' => $method->id,
                        'name' => $method->name,
                        'provider' => $method->provider,
                        'description' => $method->description,
                    ];
                }),
            ],
        ], 200);
    }

    /**
     * Process payment
     */
    public function process(Request $request, ActionNotificationService $notifications): JsonResponse
    {
        $validated = $request->validate([
            'subscription_id' => 'required|exists:subscriptions,id',
            'payment_method_id' => 'required|exists:payment_methods,id',
        ]);

        $subscription = Subscription::find($validated['subscription_id']);
        $paymentMethod = PaymentMethod::find($validated['payment_method_id']);

        if ($subscription->user_id !== $request->user()->id) {
            return response()->json([
                'success' => false,
                'message' => 'Unauthorized',
            ], 403);
        }

        // Create payment record
        $payment = Payment::create([
            'subscription_id' => $subscription->id,
            'payment_method_id' => $paymentMethod->id,
            'amount' => $subscription->package->price,
            'status' => 'pending',
        ]);

        $notifications->notifyAction(
            'Payment Initiated',
            $request->user(),
            [
                'channel' => 'mobile',
                'subscription_id' => $subscription->id,
                'payment_id' => $payment->id,
                'amount' => $payment->amount,
                'provider' => $paymentMethod->provider,
            ]
        );

        // Route to appropriate payment processor
        if ($paymentMethod->provider === 'stripe') {
            return $this->processStripePayment($request, $payment, $subscription);
        } elseif ($paymentMethod->provider === 'paypal') {
            return $this->processPayPalPayment($request, $payment, $subscription);
        } elseif ($paymentMethod->provider === 'wise') {
            return $this->processWisePayment($request, $payment, $subscription);
        }

        return response()->json([
            'success' => false,
            'message' => 'Invalid payment method',
        ], 400);
    }

    /**
     * Process Stripe payment
     */
    private function processStripePayment(Request $request, Payment $payment, Subscription $subscription): JsonResponse
    {
        try {
            $intent = PaymentIntent::create([
                'amount' => (int)($subscription->package->price * 100),
                'currency' => 'usd',
                'metadata' => [
                    'subscription_id' => $subscription->id,
                    'payment_id' => $payment->id,
                ],
            ]);

            $payment->update([
                'transaction_id' => $intent->id,
                'metadata' => json_encode(['client_secret' => $intent->client_secret]),
            ]);

            return response()->json([
                'success' => true,
                'message' => 'Payment processing initiated',
                'data' => [
                    'payment_id' => $payment->id,
                    'client_secret' => $intent->client_secret,
                    'amount' => (float)$subscription->package->price,
                    'provider' => 'stripe',
                ],
            ], 200);
        } catch (\Exception $e) {
            $payment->update(['status' => 'failed', 'failure_reason' => $e->getMessage()]);

            return response()->json([
                'success' => false,
                'message' => 'Payment processing failed: ' . $e->getMessage(),
            ], 400);
        }
    }

    /**
     * Process PayPal payment
     */
    private function processPayPalPayment(Request $request, Payment $payment, Subscription $subscription): JsonResponse
    {
        // Placeholder for PayPal integration
        return response()->json([
            'success' => true,
            'message' => 'PayPal payment flow initiated',
            'data' => [
                'payment_id' => $payment->id,
                'provider' => 'paypal',
                'amount' => (float)$subscription->package->price,
                'redirect_url' => route('api.payments.success', $payment->id),
            ],
        ], 200);
    }

    /**
     * Process Wise payment
     */
    private function processWisePayment(Request $request, Payment $payment, Subscription $subscription): JsonResponse
    {
        // Placeholder for Wise integration
        return response()->json([
            'success' => true,
            'message' => 'Wise payment flow initiated',
            'data' => [
                'payment_id' => $payment->id,
                'provider' => 'wise',
                'amount' => (float)$subscription->package->price,
                'redirect_url' => route('api.payments.success', $payment->id),
            ],
        ], 200);
    }

    /**
     * Confirm a mobile payment intent/session and activate the subscription.
     */
    public function confirm(Request $request, ActionNotificationService $notifications): JsonResponse
    {
        $validated = $request->validate([
            'subscription_id' => 'required|exists:subscriptions,id',
            'payment_id' => 'nullable|exists:payments,id',
            'payment_intent_id' => 'nullable|string|max:255',
            'transaction_id' => 'nullable|string|max:255',
        ]);

        if (empty($validated['payment_id']) && empty($validated['payment_intent_id']) && empty($validated['transaction_id'])) {
            return response()->json([
                'success' => false,
                'message' => 'A payment reference is required.',
            ], 422);
        }

        $subscription = Subscription::with('package')->findOrFail($validated['subscription_id']);

        if ($subscription->user_id !== $request->user()->id) {
            return response()->json([
                'success' => false,
                'message' => 'Unauthorized',
            ], 403);
        }

        $payment = Payment::query()
            ->when(!empty($validated['payment_id']), fn ($query) => $query->where('id', $validated['payment_id']))
            ->when(empty($validated['payment_id']) && !empty($validated['payment_intent_id']), fn ($query) => $query->where('transaction_id', $validated['payment_intent_id']))
            ->when(empty($validated['payment_id']) && empty($validated['payment_intent_id']) && !empty($validated['transaction_id']), fn ($query) => $query->where('transaction_id', $validated['transaction_id']))
            ->where('subscription_id', $subscription->id)
            ->first();

        if (!$payment) {
            return response()->json([
                'success' => false,
                'message' => 'Payment not found.',
            ], 404);
        }

        $transactionId = $validated['payment_intent_id'] ?? $validated['transaction_id'] ?? $payment->transaction_id;
        $billingEndsAt = $subscription->billing_cycle === 'yearly' ? now()->addYear() : now()->addMonth();

        $payment->update([
            'status' => 'completed',
            'transaction_id' => $transactionId,
            'processed_at' => now(),
            'failure_reason' => null,
        ]);

        $subscription->update([
            'status' => 'active',
            'payment_status' => 'completed',
            'amount_paid' => $payment->amount,
            'started_at' => now(),
            'ends_at' => $billingEndsAt,
            'next_billing_date' => $billingEndsAt,
        ]);

        $notifications->notifyAction(
            'Payment Confirmed',
            $request->user(),
            [
                'channel' => 'mobile',
                'payment_id' => $payment->id,
                'subscription_id' => $subscription->id,
                'amount' => $payment->amount,
            ]
        );

        return response()->json([
            'success' => true,
            'message' => 'Payment confirmed successfully',
            'data' => [
                'payment' => [
                    'id' => $payment->id,
                    'status' => $payment->status,
                    'transaction_id' => $payment->transaction_id,
                    'amount' => (float) $payment->amount,
                    'processed_at' => $payment->processed_at,
                ],
                'subscription' => [
                    'id' => $subscription->id,
                    'status' => $subscription->status,
                    'payment_status' => $subscription->payment_status,
                    'started_at' => $subscription->started_at,
                    'ends_at' => $subscription->ends_at,
                ],
            ],
        ], 200);
    }

    /**
     * Payment success
     */
    public function success(Request $request, $id, ActionNotificationService $notifications): JsonResponse
    {
        $payment = Payment::find($id);

        if (!$payment) {
            return response()->json([
                'success' => false,
                'message' => 'Payment not found',
            ], 404);
        }

        // Mark as completed
        if ($payment->status !== 'completed') {
            $payment->update(['status' => 'completed']);

            // Activate subscription
            $subscription = $payment->subscription;
            $subscription->update([
                'status' => 'active',
                'payment_status' => 'completed',
                'amount_paid' => $subscription->package->price,
                'started_at' => now(),
                'ends_at' => now()->addMonth(),
            ]);

            $notifications->notifyAction(
                'Payment Confirmed',
                $request->user(),
                [
                    'channel' => 'mobile',
                    'payment_id' => $payment->id,
                    'subscription_id' => $subscription->id,
                    'amount' => $payment->amount,
                ]
            );
        }

        return response()->json([
            'success' => true,
            'message' => 'Payment confirmed successfully',
            'data' => [
                'payment_id' => $payment->id,
                'transaction_id' => $payment->transaction_id,
                'amount' => (float)$payment->amount,
                'status' => $payment->status,
                'subscription' => [
                    'id' => $payment->subscription->id,
                    'status' => $payment->subscription->status,
                    'started_at' => $payment->subscription->started_at,
                    'ends_at' => $payment->subscription->ends_at,
                ],
            ],
        ], 200);
    }

    /**
     * Get user's payments
     */
    public function index(Request $request): JsonResponse
    {
        $payments = Payment::whereHas('subscription', function ($q) {
            $q->where('user_id', auth()->user()->id);
        })->paginate($request->input('per_page', 10));

        return response()->json([
            'success' => true,
            'data' => $payments->map(function ($payment) {
                return [
                    'id' => $payment->id,
                    'subscription_id' => $payment->subscription_id,
                    'package' => $payment->subscription->package->name,
                    'amount' => (float)$payment->amount,
                    'payment_method' => $payment->paymentMethod->name,
                    'status' => $payment->status,
                    'transaction_id' => $payment->transaction_id,
                    'created_at' => $payment->created_at,
                ];
            }),
            'pagination' => [
                'current_page' => $payments->currentPage(),
                'per_page' => $payments->perPage(),
                'total' => $payments->total(),
                'last_page' => $payments->lastPage(),
            ],
        ], 200);
    }

    /**
     * Get single payment
     */
    public function show(Request $request, $id): JsonResponse
    {
        $payment = Payment::find($id);

        if (!$payment || $payment->subscription->user_id !== $request->user()->id) {
            return response()->json([
                'success' => false,
                'message' => 'Payment not found or unauthorized',
            ], 404);
        }

        return response()->json([
            'success' => true,
            'data' => [
                'id' => $payment->id,
                'subscription_id' => $payment->subscription_id,
                'package' => $payment->subscription->package->name,
                'amount' => (float)$payment->amount,
                'payment_method' => $payment->paymentMethod->name,
                'status' => $payment->status,
                'transaction_id' => $payment->transaction_id,
                'created_at' => $payment->created_at,
            ],
        ], 200);
    }

    /**
     * Admin: Get all payments
     */
    public function adminIndex(Request $request): JsonResponse
    {
        $query = Payment::with('subscription.user', 'subscription.package', 'paymentMethod');

        if ($request->has('status')) {
            $query->where('status', $request->input('status'));
        }

        $payments = $query->paginate($request->input('per_page', 20));

        return response()->json([
            'success' => true,
            'data' => $payments->map(function ($payment) {
                return [
                    'id' => $payment->id,
                    'user' => $payment->subscription->user->name,
                    'email' => $payment->subscription->user->email,
                    'package' => $payment->subscription->package->name,
                    'amount' => (float)$payment->amount,
                    'payment_method' => $payment->paymentMethod->name,
                    'status' => $payment->status,
                    'transaction_id' => $payment->transaction_id,
                    'created_at' => $payment->created_at,
                ];
            }),
            'pagination' => [
                'current_page' => $payments->currentPage(),
                'per_page' => $payments->perPage(),
                'total' => $payments->total(),
                'last_page' => $payments->lastPage(),
            ],
        ], 200);
    }

    /**
     * Admin: Update payment status
     */
    public function updateStatus(Request $request, $id): JsonResponse
    {
        $payment = Payment::find($id);

        if (!$payment) {
            return response()->json([
                'success' => false,
                'message' => 'Payment not found',
            ], 404);
        }

        $validated = $request->validate([
            'status' => 'required|in:pending,completed,failed,refunded',
        ]);

        $oldStatus = $payment->status;
        $payment->update(['status' => $validated['status']]);

        // If marked as completed, activate subscription
        if ($validated['status'] === 'completed' && $oldStatus !== 'completed') {
            $subscription = $payment->subscription;
            $subscription->update([
                'status' => 'active',
                'payment_status' => 'completed',
                'amount_paid' => $subscription->package->price,
                'started_at' => now(),
                'ends_at' => now()->addMonth(),
            ]);
        }

        return response()->json([
            'success' => true,
            'message' => 'Payment status updated successfully',
            'data' => [
                'id' => $payment->id,
                'status' => $payment->status,
            ],
        ], 200);
    }

    /**
     * Stripe Webhook
     */
    public function stripeWebhook(Request $request): JsonResponse
    {
        // Verify signature
        $signature = $request->header('Stripe-Signature');
        $payload = $request->getContent();
        $signingSecret = config('services.stripe.webhook_secret');

        try {
            $event = \Stripe\Webhook::constructEvent($payload, $signature, $signingSecret);
        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 400);
        }

        if ($event->type === 'payment_intent.succeeded') {
            $paymentIntent = $event->data->object;
            $payment = Payment::where('transaction_id', $paymentIntent->id)->first();

            if ($payment) {
                $payment->update(['status' => 'completed']);
                $subscription = $payment->subscription;
                $subscription->update([
                    'status' => 'active',
                    'payment_status' => 'completed',
                    'amount_paid' => $subscription->package->price,
                    'started_at' => now(),
                    'ends_at' => now()->addMonth(),
                ]);
            }
        } elseif ($event->type === 'payment_intent.payment_failed') {
            $paymentIntent = $event->data->object;
            $payment = Payment::where('transaction_id', $paymentIntent->id)->first();

            if ($payment) {
                $payment->update([
                    'status' => 'failed',
                    'failure_reason' => $paymentIntent->last_payment_error?->message,
                ]);
            }
        }

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

    /**
     * PayPal Webhook
     */
    public function paypalWebhook(Request $request): JsonResponse
    {
        // Implement PayPal webhook verification
        return response()->json(['success' => true], 200);
    }

    /**
     * Wise Webhook
     */
    public function wiseWebhook(Request $request): JsonResponse
    {
        // Implement Wise webhook verification
        return response()->json(['success' => true], 200);
    }
}
