<?php

namespace App\Http\Controllers\Host;

use Laravel\Cashier\Http\Controllers\WebhookController;
use App\Models\User;
use App\Models\Payment;
use App\Models\FeaturedPayment;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Carbon\Carbon;
use Throwable;
use App\Models\Listing;
use Stripe\Exception\SignatureVerificationException;
use Stripe\WebhookSignature;
use App\Mail\TrialEndedMail;
use App\Mail\TrialEndingMail;
use Illuminate\Support\Facades\Mail;
use App\Helpers\AppHelper;

class StripeWebhookController extends WebhookController
{
    /**
     * Invoice Payment Succeeded
     */
    protected function handleInvoicePaymentSucceeded(array $payload)
    {
        Log::info('invoice.payment_succeeded received');

        try {

            $invoice = $payload['data']['object'];

            DB::transaction(function () use ($invoice) {

                $user = User::where('stripe_id', $invoice['customer'])->first();

                if (!$user) {
                    Log::warning('User not found for invoice', [
                        'customer_id' => $invoice['customer']
                    ]);
                    return;
                }

                $amountPaid = ($invoice['amount_paid'] ?? 0) / 100;

                $taxAmount = isset($invoice['total_tax_amounts'][0]['amount'])
                    ? $invoice['total_tax_amounts'][0]['amount'] / 100
                    : 0;

                $periodStart = isset($invoice['lines']['data'][0]['period']['start'])
                    ? Carbon::createFromTimestamp(
                        $invoice['lines']['data'][0]['period']['start']
                    )
                    : null;

                $periodEnd = isset($invoice['lines']['data'][0]['period']['end'])
                    ? Carbon::createFromTimestamp(
                        $invoice['lines']['data'][0]['period']['end']
                    )
                    : null;

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

                $user->hostProfile()->update([
                    'verified' => 1,
                    'verified_at' => now(),
                ]);
            $payment =  Payment::updateOrCreate(
                    [
                        'stripe_invoice_id' => $invoice['id']
                    ],
                    [
                        'payment_number'        => 'PAY-' . now()->format('Ymd') . '-' . strtoupper(Str::random(4)),
                        'user_id'               => $user->id,
                        'subscription_id'       => $invoice['subscription'] ?? null, // use local ID if applicable
                        'amount'                => $amountPaid - $taxAmount,
                        'tax_amount'            => $taxAmount,
                        'total_amount'          => $amountPaid,
                        'currency'              => strtoupper($invoice['currency']),
                        'payment_method'        => 'card',
                        'payment_type'          => 'subscription',
                        'status'                => 'paid',
                        'transaction_id'        => $invoice['payment_intent'] ?? null,
                        'stripe_payment_intent_id' => $invoice['payment_intent'] ?? null,
                        'receipt_url'           => $invoice['hosted_invoice_url'] ?? null,
                        'billing_period_start'  => $periodStart,
                        'billing_period_end'    => $periodEnd,
                        'paid_at'               => now(),
                        'metadata'              => json_encode($invoice['metadata']),
                    ]
                );


                AppHelper::NotificationCreate(
                    $user->id,
                    'payment',
                    'Payment Successful',
                    'Your subscription payment of '.$payment->total_amount.' '.$payment->currency.' was successful.',
                    $user->id,
                    Payment::class,
                    $payment->id,
                    [
                        'payment_id' => $payment->id,
                        'payment_number' => $payment->payment_number
                    ]
                );


                // Notify superadmin
                $superadmin = \App\Models\User::role('admin')->first();

                if ($superadmin) {

                    AppHelper::NotificationCreate(
                        $superadmin->id,
                        'payment',
                        'New Subscription Payment',
                        'A new subscription payment has been received from '.$user->name,
                        $user->id,
                        Payment::class,
                        $payment->id,
                        [
                            'payment_id' => $payment->id,
                            'user_id' => $user->id
                        ]
                    );

                }

                Log::info('Payment inserted/updated successfully', [
                    'invoice_id' => $invoice['id']
                ]);
            });

        } catch (Throwable $e) {

            Log::error('Error in invoice.payment_succeeded', [
                'message' => $e->getMessage(),
            ]);
        }

        return $this->successMethod();
    }

    /**
     * Invoice Payment Failed
     */
    protected function handleInvoicePaymentFailed(array $payload)
    {
        Log::info('invoice.payment_failed received');

        try {

            $invoice = $payload['data']['object'];

            $user = User::where('stripe_id', $invoice['customer'])->first();

            if (!$user) {
                return response()->json();
            }

        $payment =  Payment::updateOrCreate(
                ['stripe_invoice_id' => $invoice['id']],
                [
                    'user_id'               => $user->id,
                    'subscription_id'  => $invoice['subscription'] ?? null,
                    'amount'                => ($invoice['amount_due'] ?? 0) / 100,
                    'total_amount'          => ($invoice['amount_due'] ?? 0) / 100,
                    'currency'              => strtoupper($invoice['currency']),
                    'payment_method'        => 'card',
                    'payment_type'          => 'subscription',
                    'status'                => 'failed',
                    'transaction_id'        => $invoice['payment_intent'] ?? null,
                    'stripe_payment_intent_id' => $invoice['payment_intent'] ?? null,
                    'stripe_invoice_id'     => $invoice['id'],
                    'metadata'              => json_encode($invoice['metadata']),
                ]
            );

        } catch (Throwable $e) {

            Log::error('Error in invoice.payment_failed', [
                'message' => $e->getMessage(),
            ]);
        }

        return response()->json(['status' => 'failed logged']);
    }

    /**
     * Charge Refunded
     */
    protected function handleChargeRefunded(array $payload)
    {
        Log::info('charge.refunded received');

        try {

            $charge = $payload['data']['object'];

            $payment = Payment::where('stripe_payment_intent_id', $charge['payment_intent'])->first();

            if (!$payment) {
                Log::warning('Refund payment not found');
                return response()->json();
            }

            $payment->update([
                'status'          => 'refunded',
                'refunded_amount' => ($charge['amount_refunded'] ?? 0) / 100,
                'refunded_at'     => now(),
            ]);

        } catch (Throwable $e) {

            Log::error('Error in charge.refunded', [
                'message' => $e->getMessage(),
            ]);
        }

        return response()->json(['status' => 'refund processed']);
    }






       /**
     * Handle incoming Stripe webhooks.
     * This EXTENDS Cashier's webhook controller so subscription webhooks still work.
     * POST /stripe/webhook  (already registered by Cashier)
     *
     * Add this to your RouteServiceProvider / routes/web.php if you need a separate endpoint:
     * Route::post('/stripe/webhook/featured', [StripeWebhookController::class, 'handleFeaturedWebhook']);
     */

    /**
     * Override Cashier's handlePaymentIntentSucceeded to catch our featured listing payments.
     */
      public function handlePaymentIntentSucceeded(array $payload): \Symfony\Component\HttpFoundation\Response
    {
        $intent = $payload['data']['object'];

        if (
            isset($intent['metadata']['type']) &&
            $intent['metadata']['type'] === 'featured_listing'
        ) {
            $listingId = $intent['metadata']['listing_id'] ?? null;
            $userId    = $intent['metadata']['user_id']    ?? null;

            if ($listingId) {
                $listing = Listing::find($listingId);

                if ($listing && (!$listing->is_featured || !$listing->featured_until?->isFuture())) {
                    $listing->update([
                        'is_featured'    => true,
                        'featured_until' => now()->addMonths(2),
                    ]);

                    Log::info("Listing #{$listingId} featured via webhook until " . now()->addMonths(2)->toDateString());
                }
            }

            // Record payment — use stripe_payment_intent_id as unique key
        $featuredPayment = FeaturedPayment::updateOrCreate(
                [
                    'stripe_payment_intent_id' => $intent['id'],
                ],
                [
                    'payment_number'           => 'FEA-' . now()->format('Ymd') . '-' . rand(1000,9999),
                    'user_id'                  => $userId,
                    'listing_id'               => $listingId,
                    'amount'                   => ($intent['amount'] ?? 0) / 100,
                    'currency'                 => strtoupper($intent['currency'] ?? 'USD'),
                    'payment_method'           => 'card',
                    'status'                   => 'completed',
                    'transaction_id'           => $intent['id'],
                    'stripe_payment_intent_id' => $intent['id'],
                    'stripe_charge_id'         => $intent['latest_charge'] ?? null,
                    'metadata'                 => json_encode($intent['metadata'] ?? []),
                    'featured_start_at'        => now(),
                    'featured_end_at'          => now()->addMonths(2),
                    'duration_days'            => 60,
                    'paid_at'                  => now(),
                ]
            );


            AppHelper::NotificationCreate(
                $userId,
                'featured_listing',
                'Listing Featured Successfully',
                'Your listing has been featured successfully for 60 days.',
                $userId,
                FeaturedPayment::class,
                $featuredPayment->id,
                [
                    'listing_id' => $listingId,
                    'payment_id' => $featuredPayment->id
                ]
            );


            $superadmin = \App\Models\User::role('admin')->first();

            if ($superadmin) {

                AppHelper::NotificationCreate(
                    $superadmin->id,
                    'featured_listing',
                    'New Featured Listing Payment',
                    'A user has purchased featured listing for listing ID '.$listingId,
                    $userId,
                    FeaturedPayment::class,
                    $featuredPayment->id,
                    [
                        'listing_id' => $listingId,
                        'user_id' => $userId
                    ]
                );

            }

            return $this->successMethod();
        }

        // All other payment_intent.succeeded events → Cashier handles them
        return parent::handlePaymentIntentSucceeded($payload);
    }

    /**
     * Standalone webhook endpoint (dedicated route, separate from Cashier's /stripe/webhook).
     *
     * Add to routes/web.php:
     *   Route::post('/stripe/webhook/featured', [StripeWebhookController::class, 'handleFeaturedWebhook'])
     *        ->name('stripe.webhook.featured');
     *
     * Add to VerifyCsrfToken $except:
     *   'stripe/*'
     */
    public function handleFeaturedWebhook(Request $request)
    {
        $payload   = $request->getContent();
        $sigHeader = $request->header('Stripe-Signature');
        $secret    = config('cashier.webhook.secret'); // STRIPE_WEBHOOK_SECRET in .env

        try {
            WebhookSignature::verifyHeader($payload, $sigHeader, $secret);
        } catch (SignatureVerificationException $e) {
            Log::warning('Stripe webhook signature mismatch: ' . $e->getMessage());
            return response('Invalid signature', 400);
        }

        $event = json_decode($payload, true);

        if ($event['type'] === 'payment_intent.succeeded') {
            $intent = $event['data']['object'];

            if (
                isset($intent['metadata']['type']) &&
                $intent['metadata']['type'] === 'featured_listing'
            ) {
                $listingId = $intent['metadata']['listing_id'] ?? null;
                $userId    = $intent['metadata']['user_id']    ?? null;

                // Update listing featured status
                if ($listingId) {
                    $listing = Listing::find($listingId);

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

                        Log::info("Webhook: Listing #{$listingId} featured until " . now()->addMonths(2)->toDateString());
                    }
                }

                // Upsert payment record
            $featuredPayment =   FeaturedPayment::updateOrCreate(
                    [
                        'stripe_payment_intent_id' => $intent['id'],
                    ],
                    [
                        'payment_number'           => 'FEA-' . now()->format('Ymd') . '-' . rand(1000,9999),
                        'user_id'                  => $userId,
                        'listing_id'               => $listingId,
                        'amount'                   => ($intent['amount'] ?? 0) / 100,
                        'currency'                 => strtoupper($intent['currency'] ?? 'USD'),
                        'payment_method'           => 'card',
                        'status'                   => 'completed',
                        'transaction_id'           => $intent['id'],
                        'stripe_payment_intent_id' => $intent['id'],
                        'stripe_charge_id'         => $intent['latest_charge'] ?? null,
                        'metadata'                 => json_encode($intent['metadata'] ?? []),
                        'paid_at'                  => now(),
                    ]
                );


                AppHelper::NotificationCreate(
                $userId,
                'featured_listing',
                'Listing Featured Successfully',
                'Your listing has been featured successfully for 60 days.',
                $userId,
                FeaturedPayment::class,
                $featuredPayment->id,
                [
                    'listing_id' => $listingId,
                    'payment_id' => $featuredPayment->id
                ]
            );


            $superadmin = \App\Models\User::role('admin')->first();

            if ($superadmin) {

                AppHelper::NotificationCreate(
                    $superadmin->id,
                    'featured_listing',
                    'New Featured Listing Payment',
                    'A user has purchased featured listing for listing ID '.$listingId,
                    $userId,
                    FeaturedPayment::class,
                    $featuredPayment->id,
                    [
                        'listing_id' => $listingId,
                        'user_id' => $userId
                    ]
                );

            }
                
            }
        }

        return response('Webhook handled', 200);
    }



    /**
     * 3 days before trial ends → warning email
     */
    public function handleCustomerSubscriptionTrialWillEnd(array $payload): void
    {
        $user = $this->getUserByStripeId($payload['data']['object']['customer']);
        if ($user) {
            Mail::to($user->email)->send(new TrialEndingMail($user));
        }
    }



    /**
     * Subscription updated → catch trial_end transition
     */
    public function handleCustomerSubscriptionUpdated(array $payload): void
    {
        parent::handleCustomerSubscriptionUpdated($payload); // Let Cashier sync first

        $stripeSubscription = $payload['data']['object'];
        $user = $this->getUserByStripeId($stripeSubscription['customer']);

        if (!$user) return;

        $previousAttributes = $payload['data']['previous_attributes'] ?? [];

        // Trial just ended (trial_end was set, now status changed)
        $trialJustEnded = isset($previousAttributes['status'])
            && $previousAttributes['status'] === 'trialing'
            && in_array($stripeSubscription['status'], ['past_due', 'incomplete', 'canceled']);

        if ($trialJustEnded) {
            Mail::to($user->email)->send(new TrialEndedMail($user));
            // Middleware will handle the redirect — no action needed here
        }
    }



    /**
     * Subscription fully canceled (after grace period / 7 days unpaid) → disable properties
     */
    public function handleCustomerSubscriptionDeleted(array $payload): void
    {
        parent::handleCustomerSubscriptionDeleted($payload); // Let Cashier sync

        $user = $this->getUserByStripeId($payload['data']['object']['customer']);

        if ($user) {
            $user->properties()->whereNull('disabled_at')
                ->update(['disabled_at' => now()]);
        }
    }

    protected function getUserByStripeId($stripeId)
    {
        return User::where('stripe_id', $stripeId)->first();
    }

}