<?php

declare(strict_types=1);

namespace Tests\Feature\Academy;

use App\Http\Middleware\ConditionalValidateCsrfToken;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Inertia\Testing\AssertableInertia;
use Laravel\Cashier\SubscriptionBuilder;
use Mockery;
use Tests\TestCase;

final class AcademyBillingCheckoutTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();

        $this->withoutMiddleware(ConditionalValidateCsrfToken::class);
        $this->configureBilling();
    }

    public function test_guest_cannot_start_checkout_and_is_redirected_to_login(): void
    {
        $this->post(route('academy.billing.checkout'), ['plan' => 'creator_monthly'])
            ->assertRedirect(route('login'));
    }

    public function test_guest_can_view_pricing(): void
    {
        $this->get(route('academy.pricing'))
            ->assertOk()
            ->assertInertia(fn (AssertableInertia $page) => $page
                ->component('Academy/Billing/Pricing')
                ->where('currentTier', 'free')
                ->where('isSubscribed', false)
                ->where('activePlanKey', null)
                ->where('catalog.0.plans.0.price_display', '4.99 EUR')
                ->where('catalog.1.plans.0.price_display', '9.99 EUR'));
    }

    public function test_pricing_shows_active_plan_for_subscriber(): void
    {
        $user = User::factory()->create([
            'email_verified_at' => now(),
            'stripe_id' => 'cus_pricing_active_plan',
        ]);

        $subscription = $user->subscriptions()->create([
            'type' => 'academy',
            'stripe_id' => 'sub_pricing_active_plan',
            'stripe_status' => 'active',
            'stripe_price' => 'price_1creatormonth',
            'quantity' => 1,
        ]);

        $subscription->items()->create([
            'stripe_id' => 'si_pricing_active_plan',
            'stripe_product' => 'prod_creator',
            'stripe_price' => 'price_1creatormonth',
            'quantity' => 1,
        ]);

        $this->actingAs($user)
            ->get(route('academy.pricing'))
            ->assertOk()
            ->assertInertia(fn (AssertableInertia $page) => $page
                ->component('Academy/Billing/Pricing')
                ->where('currentTier', 'creator')
                ->where('isSubscribed', true)
                ->where('activePlanKey', 'creator_monthly')
                ->where('activePlanLabel', 'Creator Monthly'));
    }

    public function test_invalid_plan_returns_validation_error(): void
    {
        $user = User::factory()->create(['email_verified_at' => now()]);

        $this->actingAs($user)
            ->from(route('academy.pricing'))
            ->post(route('academy.billing.checkout'), ['plan' => 'not_real'])
            ->assertRedirect(route('academy.pricing'))
            ->assertSessionHasErrors('plan');
    }

    public function test_missing_price_id_fails_safely(): void
    {
        config()->set('academy_billing.plans.creator_monthly.stripe_price_id', '');

        $user = User::factory()->create(['email_verified_at' => now()]);

        $this->actingAs($user)
            ->postJson(route('academy.billing.checkout'), ['plan' => 'creator_monthly'])
            ->assertStatus(422)
            ->assertJsonPath('code', 'academy_billing_price_missing');
    }

    public function test_numeric_price_id_fails_safely_before_stripe(): void
    {
        config()->set('academy_billing.plans.creator_monthly.stripe_price_id', '9.99');

        $user = User::factory()->create(['email_verified_at' => now()]);

        $this->actingAs($user)
            ->postJson(route('academy.billing.checkout'), ['plan' => 'creator_monthly'])
            ->assertStatus(422)
            ->assertJsonPath('code', 'academy_billing_price_invalid');
    }

    public function test_invalid_price_id_redirects_back_with_visible_flash_error(): void
    {
        config()->set('academy_billing.plans.creator_monthly.stripe_price_id', 'prod_not_a_price');

        $user = User::factory()->create(['email_verified_at' => now()]);

        $this->actingAs($user)
            ->from(route('academy.pricing'))
            ->post(route('academy.billing.checkout'), ['plan' => 'creator_monthly'])
            ->assertRedirect(route('academy.pricing'))
            ->assertSessionHas('error', 'The selected Academy plan is misconfigured. Please contact support before continuing.');

        $this->actingAs($user)
            ->withSession([
                'error' => 'The selected Academy plan is misconfigured. Please contact support before continuing.',
            ])
            ->get(route('academy.pricing'))
            ->assertOk()
            ->assertInertia(fn (AssertableInertia $page) => $page
                ->component('Academy/Billing/Pricing')
                ->where('flash.error', 'The selected Academy plan is misconfigured. Please contact support before continuing.'));
    }

    public function test_verified_user_can_start_checkout_for_configured_plan(): void
    {
        $user = User::factory()->create(['email_verified_at' => now()]);
        $user = Mockery::mock($user)->makePartial();

        $builder = Mockery::mock(new SubscriptionBuilder($user, 'academy', 'price_1creatormonth'))->makePartial();
        $builder->shouldReceive('withMetadata')
            ->once()
            ->andReturnSelf();
        $builder->shouldReceive('checkout')
            ->once()
            ->andReturn(redirect('https://checkout.stripe.test/session'));

        $user->shouldReceive('subscription')->once()->with('academy')->andReturn(null);
        $user->shouldReceive('newSubscription')->once()->with('academy', 'price_1creatormonth')->andReturn($builder);

        $this->actingAs($user)
            ->post(route('academy.billing.checkout'), ['plan' => 'creator_monthly'])
            ->assertRedirect('https://checkout.stripe.test/session');
    }

    public function test_existing_subscriber_is_redirected_to_billing_portal(): void
    {
        $user = User::factory()->create([
            'email_verified_at' => now(),
            'stripe_id' => 'cus_checkout_redirect',
        ]);

        $subscription = $user->subscriptions()->create([
            'type' => 'academy',
            'stripe_id' => 'sub_checkout_redirect',
            'stripe_status' => 'active',
            'stripe_price' => 'price_1creatormonth',
            'quantity' => 1,
        ]);

        $subscription->items()->create([
            'stripe_id' => 'si_checkout_redirect',
            'stripe_product' => 'prod_creator',
            'stripe_price' => 'price_1creatormonth',
            'quantity' => 1,
        ]);

        $this->actingAs($user)
            ->post(route('academy.billing.checkout'), ['plan' => 'creator_monthly'])
            ->assertRedirect(route('academy.billing.portal'));
    }

    private function configureBilling(): void
    {
        config()->set('academy.enabled', true);
        config()->set('academy.payments_enabled', true);
        config()->set('academy_billing.enabled', true);
        config()->set('academy_billing.subscription_name', 'academy');
        config()->set('academy_billing.plans', [
            'creator_monthly' => [
                'label' => 'Creator Monthly',
                'tier' => 'creator',
                'interval' => 'monthly',
                'amount' => '4.99',
                'currency' => 'EUR',
                'stripe_price_id' => 'price_1creatormonth',
                'featured' => false,
            ],
            'pro_monthly' => [
                'label' => 'Pro Monthly',
                'tier' => 'pro',
                'interval' => 'monthly',
                'amount' => '9.99',
                'currency' => 'EUR',
                'stripe_price_id' => 'price_1promonth',
                'featured' => true,
            ],
        ]);
    }
}