<?php

namespace Tests\Feature\Checkout;

use App\Models\Package;
use App\Models\User;
use App\Support\CheckoutRoutes;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class CheckoutAuthTest extends TestCase
{
    use RefreshDatabase;

    private function registrationPayload(Package $package, array $overrides = []): array
    {
        return array_merge([
            'email' => 'test@example.com',
            'password' => 'password123',
            'password_confirmation' => 'password123',
            'first_name' => 'Test',
            'last_name' => 'User',
            'terms' => true,
            'privacy_consent' => true,
            'package_id' => $package->id,
            'locale' => 'de',
        ], $overrides);
    }

    public function test_checkout_login_returns_json_response_with_valid_credentials()
    {
        $user = User::factory()->create(['pending_purchase' => false]);

        $response = $this->postJson(route('checkout.login'), [
            'identifier' => $user->email,
            'password' => 'password',
            'remember' => false,
            'locale' => 'de',
        ]);

        $response->assertStatus(200)
            ->assertJsonStructure([
                'user' => [
                    'id',
                    'email',
                    'name',
                    'pending_purchase',
                ],
                'message',
            ])
            ->assertJson([
                'message' => 'Login erfolgreich',
                'user' => [
                    'id' => $user->id,
                    'email' => $user->email,
                    'pending_purchase' => false,
                ],
            ]);

        $this->assertAuthenticatedAs($user);
        $this->assertDatabaseHas('users', [
            'id' => $user->id,
            'pending_purchase' => false,
        ]);
    }

    public function test_checkout_login_marks_pending_purchase_when_package_provided(): void
    {
        $user = User::factory()->create(['pending_purchase' => false]);
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.login'), [
            'identifier' => $user->email,
            'password' => 'password',
            'remember' => false,
            'locale' => 'de',
            'package_id' => $package->id,
        ]);

        $response->assertStatus(200)
            ->assertJsonPath('user.pending_purchase', true);

        $this->assertDatabaseHas('users', [
            'id' => $user->id,
            'pending_purchase' => true,
        ]);
    }

    public function test_checkout_login_returns_validation_errors_with_invalid_credentials()
    {
        $response = $this->postJson(route('checkout.login'), [
            'identifier' => 'invalid@example.com',
            'password' => 'wrong-password',
            'remember' => false,
            'locale' => 'de',
        ]);

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'identifier' => [],
                ],
            ])
            ->assertJsonPath('errors.identifier.0', 'Ungültige Anmeldedaten.');

        $this->assertGuest();
    }

    public function test_checkout_login_with_username()
    {
        $user = User::factory()->create(['username' => 'testuser', 'pending_purchase' => false]);

        $response = $this->postJson(route('checkout.login'), [
            'identifier' => 'testuser',
            'password' => 'password',
            'remember' => false,
            'locale' => 'de',
        ]);

        $response->assertStatus(200)
            ->assertJsonStructure([
                'user' => [
                    'id',
                    'email',
                    'name',
                    'pending_purchase',
                ],
                'message',
            ])
            ->assertJson([
                'message' => 'Login erfolgreich',
                'user' => [
                    'id' => $user->id,
                    'email' => $user->email,
                    'pending_purchase' => false,
                ],
            ]);

        $this->assertAuthenticatedAs($user);
        $this->assertDatabaseHas('users', [
            'id' => $user->id,
            'pending_purchase' => false,
        ]);
    }

    public function test_checkout_register_creates_user_and_tenant_successfully()
    {
        $package = Package::factory()->create(['price' => 0]); // Free package

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package));

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'pending_purchase' => true,
            ])
            ->assertJsonStructure([
                'user' => [
                    'id',
                    'email',
                    'name',
                    'pending_purchase',
                    'email_verified_at',
                ],
                'redirect',
            ]);

        $this->assertDatabaseHas('users', [
            'username' => 'test@example.com',
            'email' => 'test@example.com',
            'first_name' => 'Test',
            'last_name' => 'User',
            'pending_purchase' => true,
        ]);

        $this->assertDatabaseHas('tenants', [
            'email' => 'test@example.com',
            'contact_email' => 'test@example.com',
        ]);

        $this->assertDatabaseHas('tenant_packages', [
            'package_id' => $package->id,
            'active' => 1,
        ]);

        $this->assertAuthenticated();
    }

    public function test_checkout_register_with_paid_package_sets_pending_purchase()
    {
        $package = Package::factory()->create(['price' => 99.99]); // Paid package

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package));

        $response->assertStatus(200)
            ->assertJson([
                'success' => true,
                'pending_purchase' => true,
            ]);

        $this->assertDatabaseHas('users', [
            'username' => 'test@example.com',
            'email' => 'test@example.com',
            'pending_purchase' => true,
        ]);

        $this->assertAuthenticated();
    }

    public function test_checkout_register_validation_errors()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'email' => 'invalid-email',
            'password' => '123',
            'password_confirmation' => '456',
            'first_name' => '',
            'last_name' => '',
            'terms' => false,
            'privacy_consent' => false,
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'email' => [],
                    'password' => [],
                    'first_name' => [],
                    'last_name' => [],
                    'terms' => [],
                    'privacy_consent' => [],
                ],
            ]);

        $this->assertGuest();
        $this->assertDatabaseMissing('users', ['email' => 'invalid-email']);
    }

    public function test_checkout_register_unique_username_and_email()
    {
        User::factory()->create([
            'username' => 'existinguser',
            'email' => 'existing@example.com',
        ]);

        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'email' => 'existing@example.com',
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'email' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_without_package()
    {
        $response = $this->postJson(route('checkout.register'), [
            'email' => 'test@example.com',
            'password' => 'password123',
            'password_confirmation' => 'password123',
            'first_name' => 'Test',
            'last_name' => 'User',
            'terms' => true,
            'privacy_consent' => true,
            'locale' => 'de',
        ]);

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'package_id' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_login_sets_locale()
    {
        $user = User::factory()->create();

        $response = $this->postJson(route('checkout.login'), [
            'identifier' => $user->email,
            'password' => 'password',
            'remember' => false,
            'locale' => 'en',
        ]);

        $response->assertStatus(200);
    }

    public function test_checkout_register_sets_locale()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'locale' => 'en',
        ]));

        $response->assertStatus(200);

        $this->assertDatabaseHas('users', [
            'email' => 'test@example.com',
            'preferred_locale' => 'en',
        ]);
    }

    public function test_checkout_show_renders_wizard_page()
    {
        $package = Package::factory()->create();

        $response = $this->get(CheckoutRoutes::wizardUrl($package, 'de'));

        $response->assertStatus(200)
            ->assertInertia(fn ($page) => $page
                ->component('marketing/CheckoutWizardPage')
                ->has('package')
                ->has('packageOptions')
                ->has('privacyHtml')
                ->has('auth')
                ->has('auth.user')
                ->has('googleAuth')
                ->has('paddle')
                ->has('paddle.environment')
                ->has('paddle.client_token')
                ->where('package.id', $package->id)
            );
    }

    public function test_checkout_show_with_invalid_package_redirects_to_packages()
    {
        $response = $this->get(CheckoutRoutes::wizardUrl(999, 'de'));

        $response
            ->assertRedirect(route('packages', ['locale' => 'de']))
            ->assertSessionHas('error', __('marketing.packages.package_not_found'));
    }

    public function test_checkout_register_missing_required_fields()
    {
        $response = $this->postJson(route('checkout.register'), [
            // All required fields missing
            'locale' => 'de',
        ]);

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'email' => [],
                    'password' => [],
                    'first_name' => [],
                    'last_name' => [],
                    'package_id' => [],
                    'terms' => [],
                    'privacy_consent' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_invalid_email_format()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'email' => 'invalid-email-format',
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'email' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_password_too_short()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'password' => '123',
            'password_confirmation' => '123',
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'password' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_password_confirmation_mismatch()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'password_confirmation' => 'differentpassword',
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'password' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_missing_password_confirmation()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'password_confirmation' => null,
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'password' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_email_conflicts_with_existing_username()
    {
        User::factory()->create([
            'username' => 'taken@example.com',
            'email' => 'other@example.com',
        ]);

        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'email' => 'taken@example.com',
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'email' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_email_too_long()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'email' => str_repeat('a', 246).'@example.com',
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'email' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_address_too_long()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'address' => str_repeat('a', 501),
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'address' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_phone_too_long()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'phone' => str_repeat('1', 256),
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'phone' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_invalid_package_id()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'package_id' => 'invalid-string',
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'package_id' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_nonexistent_package_id()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'package_id' => 99999,
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'package_id' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_privacy_consent_not_accepted()
    {
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'privacy_consent' => false,
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'privacy_consent' => [],
                ],
            ]);

        $this->assertGuest();
    }

    public function test_checkout_register_duplicate_email_is_rejected()
    {
        User::factory()->create(['email' => 'existing@example.com']);
        $package = Package::factory()->create();

        $response = $this->postJson(route('checkout.register'), $this->registrationPayload($package, [
            'email' => 'existing@example.com',
        ]));

        $response->assertStatus(422)
            ->assertJsonStructure([
                'errors' => [
                    'email' => [],
                ],
            ]);

        $this->assertGuest();
    }
}
