<?php

namespace Tests\Feature\Checkout;

use App\Models\CheckoutSession;
use App\Models\Package;
use App\Models\Tenant;
use App\Models\User;
use App\Services\Checkout\CheckoutSessionService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;

class CheckoutSessionStatusTest extends TestCase
{
    use RefreshDatabase;

    public function test_user_can_fetch_checkout_session_status(): void
    {
        $tenant = Tenant::factory()->create();
        $user = User::factory()->for($tenant)->create();
        $package = Package::factory()->create();

        /** @var CheckoutSessionService $sessions */
        $sessions = app(CheckoutSessionService::class);
        $session = $sessions->createOrResume($user, $package, [
            'tenant' => $tenant,
        ]);
        $sessions->markCompleted($session, now());

        $this->actingAs($user);

        $response = $this->getJson(route('checkout.session.status', $session));

        $response->assertOk()
            ->assertJsonPath('status', CheckoutSession::STATUS_COMPLETED);
    }

    public function test_user_cannot_fetch_other_users_checkout_session_status(): void
    {
        $tenant = Tenant::factory()->create();
        $owner = User::factory()->for($tenant)->create();
        $otherUser = User::factory()->create();
        $package = Package::factory()->create();

        /** @var CheckoutSessionService $sessions */
        $sessions = app(CheckoutSessionService::class);
        $session = $sessions->createOrResume($owner, $package, [
            'tenant' => $tenant,
        ]);

        $this->actingAs($otherUser);

        $response = $this->getJson(route('checkout.session.status', $session));

        $response->assertForbidden();
    }

    public function test_session_status_recovers_completed_paddle_transaction(): void
    {
        $tenant = Tenant::factory()->create();
        $user = User::factory()->for($tenant)->create([
            'pending_purchase' => true,
        ]);
        $package = Package::factory()->create([
            'type' => 'endcustomer',
            'price' => 99,
        ]);

        /** @var CheckoutSessionService $sessions */
        $sessions = app(CheckoutSessionService::class);
        $session = $sessions->createOrResume($user, $package, [
            'tenant' => $tenant,
        ]);
        $sessions->selectProvider($session, CheckoutSession::PROVIDER_PADDLE);
        $session->forceFill([
            'provider_metadata' => [
                'paddle_checkout_id' => 'chk_123',
            ],
        ])->save();

        config()->set([
            'paddle.api_key' => 'test-key',
            'paddle.base_url' => 'https://paddle.test',
            'paddle.environment' => 'sandbox',
        ]);

        Http::fake([
            'https://paddle.test/*' => Http::response([
                'data' => [
                    [
                        'id' => 'txn_123',
                        'status' => 'completed',
                        'details' => [
                            'totals' => [
                                'currency_code' => 'EUR',
                                'total' => ['amount' => 9900],
                            ],
                        ],
                        'custom_data' => [
                            'checkout_session_id' => $session->id,
                        ],
                    ],
                ],
            ], 200),
        ]);

        Mail::fake();
        Notification::fake();

        $this->actingAs($user);

        $response = $this->getJson(route('checkout.session.status', $session));

        $response->assertOk()
            ->assertJsonPath('status', CheckoutSession::STATUS_COMPLETED);

        $this->assertDatabaseHas('checkout_sessions', [
            'id' => $session->id,
            'status' => CheckoutSession::STATUS_COMPLETED,
        ]);

        $this->assertDatabaseHas('package_purchases', [
            'tenant_id' => $tenant->id,
            'package_id' => $package->id,
        ]);
    }

    public function test_session_confirm_recovers_completed_paddle_transaction(): void
    {
        $tenant = Tenant::factory()->create();
        $user = User::factory()->for($tenant)->create([
            'pending_purchase' => true,
        ]);
        $package = Package::factory()->create([
            'type' => 'endcustomer',
            'price' => 79,
        ]);

        /** @var CheckoutSessionService $sessions */
        $sessions = app(CheckoutSessionService::class);
        $session = $sessions->createOrResume($user, $package, [
            'tenant' => $tenant,
        ]);
        $sessions->selectProvider($session, CheckoutSession::PROVIDER_PADDLE);

        config()->set([
            'paddle.api_key' => 'test-key',
            'paddle.base_url' => 'https://paddle.test',
            'paddle.environment' => 'sandbox',
        ]);

        Http::fake([
            'https://paddle.test/transactions/txn_987' => Http::response([
                'data' => [
                    'id' => 'txn_987',
                    'status' => 'completed',
                    'details' => [
                        'totals' => [
                            'currency_code' => 'EUR',
                            'total' => ['amount' => 7900],
                        ],
                    ],
                    'custom_data' => [
                        'checkout_session_id' => $session->id,
                    ],
                ],
            ], 200),
        ]);

        Mail::fake();
        Notification::fake();

        $this->actingAs($user);

        $response = $this->postJson(route('checkout.session.confirm', $session), [
            'transaction_id' => 'txn_987',
            'checkout_id' => 'che_987',
        ]);

        $response->assertOk()
            ->assertJsonPath('status', CheckoutSession::STATUS_COMPLETED);

        $this->assertDatabaseHas('checkout_sessions', [
            'id' => $session->id,
            'status' => CheckoutSession::STATUS_COMPLETED,
        ]);
    }
}
