<?php

namespace App\Http\Controllers\Principal;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\SubscriptionPlan;
use App\Models\FeaturedPayment;
use Laravel\Cashier\Subscription;
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;
use App\Models\Payment;
use App\Models\User;
use Stripe\Stripe;
use Carbon\Carbon;
use Stripe\Subscription as StripeSubscription;
use Stripe\Event;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Auth;
use Laravel\Cashier\Exceptions\IncompletePayment;
use App\Models\Listing;
use Stripe\Customer;
use Stripe\PaymentIntent;
use App\Helpers\AppHelper;

class SubscriptionController extends Controller
{
    public function package()
    {
        $user = auth()->user();
        $plans = SubscriptionPlan::all();
        if (!$user || !$user->subscribed('default')) {
            return view('principal.subscription.package', [
                'hasSubscription' => false,
                'plans'          => $plans,
            ]);
        }

        $subscription = $user->subscription('default');
        // dd($subscription);
        // Get invoices (Cashier)
        $invoices = $subscription->invoices();
        $latestInvoice = $invoices->first();
        // dd($latestInvoice->invoice_pdf);
        // Get live Stripe subscription for period dates
        Stripe::setApiKey(config('cashier.secret'));

        $stripeSubscription = StripeSubscription::retrieve(
            $subscription->stripe_id
        );

        $currentStripeSubscription = $subscription->asStripeSubscription();

        $currentAmount = $currentStripeSubscription
            ->items
            ->data[0]
            ->price
            ->unit_amount / 100;
        // dd($currentAmount);
        return view('principal.subscription.package', [
            'hasSubscription'   => true,
            'subscription'      => $subscription,
            'stripeSubscription'=> $stripeSubscription,
            'invoices'          => $latestInvoice->invoice_pdf,
            'plans'          => $plans,
            'currentAmount' => $currentAmount,
        ]);
    }

    public function subscribe(Request $request)
    {
        $request->validate([
            'payment_method' => 'required|string',
            'priceID'        => 'required|string',
            'name'           => 'required|string',
            'line1'          => 'required|string',
            'city'           => 'required|string',
            'country'        => 'required|string',
        ]);

        $user = Auth::user();

        $plan = SubscriptionPlan::where('stripe_price_id_monthly', $request->priceID)
            ->where('is_active', 1)
            ->firstOrFail();

        /*
        |--------------------------------------------------------------------------
        | EXISTING SUBSCRIPTION → UPGRADE / DOWNGRADE
        |--------------------------------------------------------------------------
        */

        if ($user->subscribed('default')) {

            $subscription = $user->subscription('default');

            $currentPriceId = $subscription->items->first()->stripe_price;

            if ($currentPriceId === $plan->stripe_price_id_monthly) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'You are already subscribed to this plan.'
                ]);
            }

            try {

                $currentPlan = SubscriptionPlan::where('stripe_price_id_monthly', $currentPriceId)->first();

                $isUpgrade = $plan->price_monthly > $currentPlan->price;

                /*
                |--------------------------------------------------------------------------
                | UPGRADE → IMMEDIATE (PRORATION)
                |--------------------------------------------------------------------------
                */

                if ($isUpgrade) {

                    $subscription->swap($plan->stripe_price_id_monthly);

                } else {

                    /*
                    |--------------------------------------------------------------------------
                    | DOWNGRADE → NEXT BILLING CYCLE
                    |--------------------------------------------------------------------------
                    */

                    $subscription->swap($plan->stripe_price_id_monthly, [
                        'proration_behavior' => 'none',
                    ]);
                }

                $invoice = $subscription->latestInvoice();

                if ($invoice && $invoice->payment_intent) {

                    $paymentIntent = $invoice->payment_intent;

                    if ($paymentIntent->status === 'requires_action') {

                        return response()->json([
                            'status' => 'requires_action',
                            'client_secret' => $paymentIntent->client_secret,
                        ]);
                    }
                }

                return response()->json([
                    'status' => 'success',
                    'message' => $isUpgrade
                        ? 'Plan upgraded successfully.'
                        : 'Plan will active at the next billing cycle.'
                ]);

            } catch (IncompletePayment $exception) {

                return response()->json([
                    'status' => 'requires_action',
                    'client_secret' => $exception->payment->client_secret,
                ]);

            } catch (\Exception $e) {

                return response()->json([
                    'status' => 'error',
                    'message' => $e->getMessage()
                ]);
            }
        }

        /*
        |--------------------------------------------------------------------------
        | NEW SUBSCRIPTION
        |--------------------------------------------------------------------------
        */

        if ($plan->trial_days > 0 && $user->subscriptions()->count() > 0) {
            return response()->json([
                'status' => 'error',
                'message' => 'Trial available only for new users.'
            ]);
        }

        $user->createOrGetStripeCustomer();

        $user->updateStripeCustomer([
            'name' => $request->name,
            'address' => [
                'line1'   => $request->line1,
                'city'    => $request->city,
                'country' => $request->country,
            ],
        ]);

        $user->addPaymentMethod($request->payment_method);
        $user->updateDefaultPaymentMethod($request->payment_method);

        try {

            $builder = $user->newSubscription('default', $plan->stripe_price_id_monthly);

            if ($plan->trial_days > 0) {
                $builder->trialDays($plan->trial_days);
            }

            $subscription = $builder->create($request->payment_method, [
                'payment_behavior' => 'default_incomplete',
            ]);

            if ($subscription->stripe_status === 'incomplete') {

                $invoice = $subscription->latestInvoice();

                if ($invoice && $invoice->payment_intent) {

                    return response()->json([
                        'status' => 'requires_action',
                        'client_secret' => $invoice->payment_intent->client_secret,
                    ]);
                }
            }

            /*
            |--------------------------------------------------------------------------
            | RECORD PAYMENT
            |--------------------------------------------------------------------------
            */

            if ($subscription->active() || $subscription->onTrial()){

                $invoice = $subscription->latestInvoice();
                $paymentIntent = $invoice->payment_intent;

                $payment = Payment::create([
                    'payment_number' => 'PAY-' . now()->format('Ymd') . '-' . strtoupper(Str::random(4)),
                    'user_id' => $user->id,
                    'subscription_id' => $subscription->id,
                    'total_amount' => $invoice->amount_paid / 100,
                    'tax_amount' => $invoice->amount_paid / 100,
                    'amount' => $invoice->amount_paid / 100,
                    'currency' => strtoupper($invoice->currency),
                    'payment_method' => 'card',
                    'payment_type' => 'subscription',
                    'status' => 'completed',
                    'transaction_id' => $paymentIntent->id ?? null,
                    'stripe_payment_intent_id' => $paymentIntent->id ?? null,
                    'stripe_invoice_id' => $invoice->id,
                    'receipt_url' => $invoice->hosted_invoice_url,
                    'billing_period_start' => date('Y-m-d H:i:s', $invoice->period_start),
                    'billing_period_end' => date('Y-m-d H:i:s', $invoice->period_end),
                    'paid_at' => now(),
                ]);


                // ✅ UPDATE USER STATUS
                $user->update([
                    'status' => 1,
                    'email_verified_at' => now(),
                ]);

                $user->hostProfile()->update([
                    'verified' => 1,
                    'verified_at' => now(),
                ]);



                if ($subscription->onTrial()) {

                    $trialEnd = $subscription->trial_ends_at;

                    AppHelper::NotificationCreate(
                        $user->id,
                        'subscription_trial',
                        'Free Trial Started',
                        'Your free trial will end on '.$trialEnd->format('d M Y').'.',
                        $user->id,
                        Payment::class,
                        $payment->id,
                        [
                            'payment_id' => $payment->id,
                            'payment_number' => $payment->payment_number
                        ]
                    );
                }
            }

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

        } catch (IncompletePayment $exception) {

            return response()->json([
                'status' => 'requires_action',
                'client_secret' => $exception->payment->client_secret,
            ]);
        }
    }


    public function success(Request $request)
    {
        $user = auth()->user();

        if (!$user) {
            return redirect()->route('login');
        }

        // Refresh subscription from Stripe
        $subscription = $user->subscription('default');

        if (!$subscription) {
            return redirect()->route('plans')
                ->with('error', 'Subscription not found. Please contact support.');
        }

        if (!$subscription->valid()) {
            return redirect()->route('plans')
                ->with('error', 'Subscription is not active.');
        }

        return view('subscription.success', [
            'subscription' => $subscription
        ]);
    }


    public function cancel()
    {
        $user = Auth::user();

        $user->subscription('default')->cancel();

        return response()->json([
            'status' => true,
            'message' => 'Subscription cancelled successfully.'
        ]);
    }


    public function Subscription_index(Request $request)
    {
        $user = Auth::user();

        $query = Payment::where('user_id', $user->id);

        // Filter: Payment Number
        if ($request->filled('payment_no')) {
            $query->where('payment_number', 'like', '%' . $request->payment_no . '%');
        }

        // Filter: Status
        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        // Filter: Type
        if ($request->filled('type')) {
            $query->where('payment_type', $request->type);
        }

        $payments = $query->latest()
            ->paginate(10)
            ->appends($request->all()); // keep filters during pagination

        $sumTotal = Payment::where('user_id', $user->id)->sum('total_amount');
        $paidPayment = Payment::where('user_id', $user->id)->where('status','paid')->count();
        $cancelledPayment = Payment::where('user_id', $user->id)->where('status','cancelled')->count();
        $refundedPayment = Payment::where('user_id', $user->id)->where('status','refunded')->count();
        $failedPayment = Payment::where('user_id', $user->id)->where('status','failed')->count();

        return view('host.subscriptions.index', compact('payments','sumTotal','paidPayment','cancelledPayment','refundedPayment','failedPayment'));
    }


    public function featuredPayments(Request $request)
    {
        $user = Auth::user();
        $query = FeaturedPayment::with(['user', 'listing'])->where('user_id', $user->id);

        if ($request->filled('search')) {
            $search = $request->search;
            $query->where(function ($q) use ($search) {
                $q->where('payment_number', 'like', '%' . $search . '%')
                ->orWhere('transaction_id', 'like', '%' . $search . '%')
                ->orWhereHas('user', function ($q2) use ($search) {
                    $q2->where('name', 'like', '%' . $search . '%')
                        ->orWhere('email', 'like', '%' . $search . '%');
                });
            });
        }

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

        if ($request->filled('payment_method')) {
            $query->where('payment_method', $request->payment_method);
        }

        if ($request->filled('host_id')) {
            $query->where('user_id', $request->host_id);
        }

        if ($request->filled('date_from')) {
            $query->whereDate('created_at', '>=', $request->date_from);
        }

        if ($request->filled('date_to')) {
            $query->whereDate('created_at', '<=', $request->date_to);
        }

        $sort  = $request->get('sort', 'created_at');
        $order = $request->get('order', 'desc');
        $query->orderBy($sort, $order);

        $payments = $query->paginate(20)->withQueryString();

        $totalRevenue  = FeaturedPayment::where('status', 'paid')->where('user_id', $user->id)->sum('amount');
        $totalPending  = FeaturedPayment::where('status', 'pending')->where('user_id', $user->id)->count();
        $totalRefunded = FeaturedPayment::whereNotNull('refunded_at')->where('user_id', $user->id)->sum('refunded_amount');
        $todayRevenue  = FeaturedPayment::where('status', 'paid')
                            ->whereDate('paid_at', Carbon::today())->where('user_id', $user->id)
                            ->sum('amount');

        $statuses = ['pending', 'paid', 'failed', 'refunded', 'cancelled'];

        $hosts      = User::role('host')->orderBy('name')->get(['id', 'name', 'email']);
        $totalHosts = $hosts->count();

        return view('host.subscriptions.featured', compact(
            'payments',
            'totalRevenue',
            'totalRefunded',
            'totalPending',
            'todayRevenue',
            'statuses',
            'hosts',
            'totalHosts'
        ));
    }

    public function showFeatured($id)
    {
        $payment = FeaturedPayment::with(['user', 'listing'])->findOrFail($id);
        return view('host.subscriptions.show-featured', compact('payment'));
    }
    /**
     * Display the specified subscription
     */
    public function Subscription_show($id)
    {
        $subscription = Subscription::with('user')
            ->findOrFail($id);

        $payments = Payment::where('user_id', $subscription->user_id)
            ->where('subscription_id', $subscription->stripe_id)
            ->latest()
            ->get();

        return view('host.subscriptions.show', compact('subscription', 'payments'));
    }



    public function subscriptionShow($id)
    {
        $payment = Payment::where('id', $id)
            ->where('user_id', Auth::id())
            ->firstOrFail();

        return view('host.subscriptions.payment_detail', compact('payment'));
    }


    /**
     * Create a Stripe PaymentIntent with India export compliance fields.
     * POST /listings/{listing}/feature/checkout
     *
     * RBI requirement: buyer name + billing address + description on every
     * international (non-INR) PaymentIntent from an India-based Stripe account.
     */
    public function createPaymentIntent(Request $request, Listing $listing)
    {
        if ($listing->is_featured && $listing->featured_until && $listing->featured_until->isFuture()) {
            return response()->json([
                'error' => 'This listing is already featured until ' . $listing->featured_until->format('M d, Y'),
            ], 422);
        }

        // All fields required by Stripe India export regulations
        $validated = $request->validate([
            'name'             => 'required|string|max:255',
            'address_line1'    => 'required|string|max:255',
            'address_city'     => 'required|string|max:100',
            'address_state'    => 'nullable|string|max:100',
            'address_zip'      => 'required|string|max:20',
            'address_country'  => 'required|string|size:2', // ISO 3166-1 alpha-2 e.g. "US"
        ]);

        Stripe::setApiKey('sk_test_51PIlyJSIEXIA1SQjpnciXjAVBjHIXeZ1kPfsnhxUr4oPJHPSNDv8phlq7mq5IJS8igAg9pYyxJxwxyG5mrL6zWZY00L20FY88N');

        // Step 1: Create a Stripe Customer with name + billing address
        // This is what Stripe India requires to satisfy RBI export reporting
        $customer = Customer::create([
            'name'    => $validated['name'],
            'email'   => Auth::user()->email,
            'address' => [
                'line1'        => $validated['address_line1'],
                'city'         => $validated['address_city'],
                'state'        => $validated['address_state'] ?? '',
                'postal_code'  => $validated['address_zip'],
                'country'      => strtoupper($validated['address_country']),
            ],
        ]);

        // Step 2: Create PaymentIntent linked to that customer
        // 'description' is also mandatory for India export transactions
        $intent = PaymentIntent::create([
            'amount'      => 15000, // $150.00 USD in cents
            'currency'    => 'usd',
            'customer'    => $customer->id,
            'description' => 'Featured Property Listing Service – 2 months front-page placement',
            'metadata'    => [
                'listing_id' => $listing->id,
                'user_id'    => Auth::id(),
                'type'       => 'featured_listing',
            ],
        ]);

        return response()->json([
            'clientSecret' => $intent->client_secret,
            'intentId'     => $intent->id,
        ]);
    }

    /**
     * Server-side confirm after Stripe.js succeeds on the frontend.
     * POST /listings/{listing}/feature/confirm
     */
    public function confirmPayment(Request $request, Listing $listing)
    {
        $request->validate([
            'payment_intent_id' => 'required|string',
        ]);

        Stripe::setApiKey(config('cashier.secret'));

        $intent = PaymentIntent::retrieve($request->payment_intent_id);

        if (
            $intent->metadata['listing_id'] != $listing->id ||
            $intent->metadata['user_id'] != Auth::id()
        ) {
            return response()->json(['error' => 'Intent mismatch'], 403);
        }

        if ($intent->status === 'succeeded') {
            $listing->update([
                'is_featured'    => true,
                'featured_until' => now()->addMonths(2),
            ]);

            return response()->json([
                'success'        => true,
                'message'        => 'Your listing is now featured for 2 months!',
                'featured_until' => $listing->fresh()->featured_until->format('M d, Y'),
            ]);
        }

        return response()->json([
            'success' => false,
            'message' => 'Payment not completed. Status: ' . $intent->status,
        ], 422);
    }

    /**
     * Activate featured status on the listing.
     */
    private function activateFeatured(Listing $listing): void
    {
        $listing->update([
            'is_featured'   => true,
            'featured_until' => now()->addMonths(2),
        ]);
    }


    
}
