<?php

namespace App\Http\Controllers;

use App\Models\Subscription;
use App\Services\PaystackService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Str;

class SubscriptionController extends Controller
{
    public function __construct(private PaystackService $paystack) {}

    // ─────────────────────────────────────────
    // SHOW SUBSCRIPTION PAGE
    // ─────────────────────────────────────────
    public function index()
    {
        $user          = Auth::user();
        $plans         = config('invotrack.plans');
        $activeSubPlan = $user->activeSubscription();

        // Load subscription history
        $subscriptions = Subscription::where('user_id', $user->id)
            ->latest()
            ->take(10)
            ->get();

        return view('settings.subscription', compact(
            'user', 'plans', 'activeSubPlan', 'subscriptions'
        ));
    }

    // ─────────────────────────────────────────
    // INITIATE SUBSCRIPTION PAYMENT
    // Called when user clicks "Upgrade to Pro/Business"
    // ─────────────────────────────────────────
    public function initiate(Request $request)
    {
        $request->validate([
            'plan' => ['required', 'in:pro,business'],
        ]);

        $user  = Auth::user();
        $plan  = $request->plan;
        $plans = config('invotrack.plans');

        // Can't subscribe to current plan
        if ($user->plan === $plan) {
            return back()->with('error', "You are already on the {$plans[$plan]['label']} plan.");
        }

        $amountKobo = $plans[$plan]['amount_kobo'];
        $amountNaira = $plans[$plan]['amount'];
        $reference   = 'SUB-' . strtoupper(Str::random(12));

        // Create a pending subscription record
        $subscription = Subscription::create([
            'user_id'            => $user->id,
            'plan'               => $plan,
            'status'             => 'pending',
            'paystack_reference' => $reference,
            'amount'             => $amountNaira,
            'currency'           => 'NGN',
        ]);

        // Initialize Paystack transaction
        $result = $this->paystack->initializeTransaction([
            'email'        => $user->email,
            'amount'       => $amountKobo,
            'reference'    => $reference,
            'callback_url' => route('subscription.callback'),
            'metadata'     => [
                'subscription_id' => $subscription->id,
                'user_id'         => $user->id,
                'plan'            => $plan,
                'plan_label'      => $plans[$plan]['label'],
            ],
        ]);

        if (! $result['success']) {
            $subscription->update(['status' => 'failed']);
            return back()->with('error', 'Payment initialization failed. Please try again.');
        }

        // Redirect to Paystack payment page
        return redirect($result['authorization_url']);
    }

    // ─────────────────────────────────────────
    // CALLBACK
    // Paystack redirects here after payment
    // ─────────────────────────────────────────
    public function callback(Request $request)
    {
        $reference = $request->query('reference') ?? $request->query('trxref');

        if (! $reference) {
            return redirect()->route('settings.subscription')
                ->with('error', 'No payment reference found.');
        }

        // Verify with Paystack — always server-side
        $result = $this->paystack->verifyTransaction($reference);

        if (! $result['success'] || ! $result['paid']) {
            // Mark subscription as failed
            Subscription::where('paystack_reference', $reference)
                ->update(['status' => 'failed']);

            return redirect()->route('settings.subscription')
                ->with('error', 'Payment was not successful. Please try again.');
        }

        // Process the successful subscription
        $this->processSuccessfulSubscription($reference, $result);

        return redirect()->route('subscription.index')
            ->with('success', '🎉 Subscription activated! Welcome to ' . ucfirst(
                Subscription::where('paystack_reference', $reference)->value('plan')
            ) . ' plan.');
    }

    // ─────────────────────────────────────────
    // WEBHOOK
    // Paystack background confirmation
    // ─────────────────────────────────────────
    public function webhook(Request $request)
    {
        $payload   = $request->getContent();
        $signature = $request->header('x-paystack-signature', '');

        if (! $this->paystack->verifyWebhookSignature($payload, $signature)) {
            return response()->json(['message' => 'Invalid signature'], 401);
        }

        $event     = $request->json('event');
        $data      = $request->json('data');
        $reference = $data['reference'] ?? null;

        if ($event === 'charge.success' && $reference && str_starts_with($reference, 'SUB-')) {
            $result = $this->paystack->verifyTransaction($reference);
            if ($result['success'] && $result['paid']) {
                $this->processSuccessfulSubscription($reference, $result);
            }
        }

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

    // ─────────────────────────────────────────
    // CANCEL SUBSCRIPTION
    // ─────────────────────────────────────────
    public function cancel(Request $request)
    {
        $user = Auth::user();

        if ($user->isFreePlan()) {
            return back()->with('error', 'You are already on the Free plan.');
        }

        DB::transaction(function () use ($user) {
            // Mark active subscription as cancelled
            Subscription::where('user_id', $user->id)
                ->where('status', 'active')
                ->update(['status' => 'cancelled']);

            // Downgrade user to free
            $user->update([
                'plan'            => 'free',
                'plan_expires_at' => null,
            ]);
        });

        return back()->with('success', 'Your subscription has been cancelled. You have been moved to the Free plan.');
    }

    // ─────────────────────────────────────────
    // SHARED: process successful subscription
    // Idempotent — safe to call twice
    // ─────────────────────────────────────────
    private function processSuccessfulSubscription(string $reference, array $result): void
    {
        // Find the pending subscription
        $subscription = Subscription::where('paystack_reference', $reference)
            ->where('status', 'pending')
            ->first();

        if (! $subscription) {
            // Already processed — idempotency check
            return;
        }

        DB::transaction(function () use ($subscription, $result) {
            $startsAt  = now();
            $expiresAt = now()->addDays(30); // 30-day subscription

            // Update subscription record
            $subscription->update([
                'status'                  => 'active',
                'paystack_transaction_id' => $result['transaction_id'],
                'starts_at'               => $startsAt,
                'expires_at'              => $expiresAt,
                'gateway_response'        => $result['gateway_response'],
            ]);

            // Cancel any other active subscriptions for this user
            Subscription::where('user_id', $subscription->user_id)
                ->where('id', '!=', $subscription->id)
                ->where('status', 'active')
                ->update(['status' => 'expired']);

            // Upgrade the user's plan
            $subscription->user->update([
                'plan'            => $subscription->plan,
                'plan_expires_at' => $expiresAt,
            ]);

            // Send confirmation email
            try {
                Mail::to($subscription->user->email)
                    ->send(new \App\Mail\SubscriptionConfirmed($subscription));
            } catch (\Exception $e) {
                Log::error('Subscription email failed: ' . $e->getMessage());
            }
        });

        Log::info('Subscription activated', [
            'user'      => $subscription->user_id,
            'plan'      => $subscription->plan,
            'reference' => $reference,
        ]);
    }
}
