<?php

namespace Tests\Feature;

use App\Mail\Welcome;
use App\Models\Package;
use App\Models\PackagePurchase;
use App\Models\Tenant;
use App\Models\TenantPackage;
use App\Models\User;
use App\Support\CheckoutRoutes;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;

class FullUserFlowTest extends TestCase
{
    use RefreshDatabase;

    public function test_full_user_flow_registration_login_paid_purchase()
    {
        Mail::fake();

        // Schritt 1: Registrierung mit Free Package
        $freePackage = Package::factory()->endcustomer()->create(['price' => 0]);

        $registrationData = [
            'email' => 'flow@example.com',
            'password' => 'Password123!',
            'password_confirmation' => 'Password123!',
            'first_name' => 'Max',
            'last_name' => 'Mustermann',
            'privacy_consent' => true,
            'terms' => true,
            'package_id' => $freePackage->id,
            'locale' => 'de',
        ];

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

        $this->assertDatabaseHas('users', ['email' => 'flow@example.com']);
        $user = User::where('email', 'flow@example.com')->first();
        $this->assertDatabaseHas('tenants', ['user_id' => $user->id]);
        $tenant = Tenant::where('user_id', $user->id)->first();

        $this->assertAuthenticated();
        $response->assertOk();

        $this->assertNotNull($user);
        $this->assertNotNull($tenant);
        $this->assertDatabaseHas('tenant_packages', [
            'tenant_id' => $tenant->id,
            'package_id' => $freePackage->id,
            'active' => true,
        ]);

        // Für E2E-Test: Simuliere Email-Verification
        $user->markEmailAsVerified();

        // Schritt 2: Logout und Login
        Auth::logout();

        $this->assertGuest();

        $loginResponse = $this->post(route('login.store'), [
            'login' => 'flow@example.com',
            'password' => 'Password123!',
        ]);

        $this->assertAuthenticated();
        $loginResponse->assertRedirect(CheckoutRoutes::wizardUrl($freePackage->id, 'de'));

        // Schritt 3: Paid Package Bestellung (Mock Paddle)
        $paidPackage = Package::factory()->reseller()->create(['price' => 10]);

        // Simuliere Kauf (GET zu buy.packages, aber da es Redirect ist, prüfe Session oder folge)
        // Für E2E: Angenommen, nach Mock wird Package zugewiesen (in real: Webhook, hier simuliere Success)
        // Erstelle manuell für Test (in real: via Success-Route nach Zahlung)

        // Simuliere Success nach Zahlung
        TenantPackage::create([
            'tenant_id' => $tenant->id,
            'package_id' => $paidPackage->id,
            'active' => true,
            'price' => 10,
            'purchased_at' => now(),
            'expires_at' => now()->addYear(),
        ]);

        PackagePurchase::create([
            'tenant_id' => $tenant->id,
            'package_id' => $paidPackage->id,
            'type' => 'reseller_subscription',
            'provider' => 'paddle',
            'provider_id' => 'paddle_txn_123',
            'price' => 10,
            'purchased_at' => now(),
        ]);

        $tenant->update(['subscription_status' => 'active']);

        // Assertions für gesamten Flow
        $this->assertDatabaseHas('package_purchases', [
            'tenant_id' => $tenant->id,
            'package_id' => $paidPackage->id,
            'type' => 'reseller_subscription',
            'provider' => 'paddle',
        ]);

        $this->assertEquals(1, PackagePurchase::where('tenant_id', $tenant->id)->count());

        // Mock Mails (nur Welcome, da Purchase keine dedizierte Klasse hat)
        Mail::assertQueued(Welcome::class, function ($mail) use ($user) {
            return $mail->to[0]['address'] === $user->email;
        });

        // Finaler Redirect zu Success oder Dashboard
        $successResponse = $this->actingAs($user)->get(route('marketing.success', [
            'locale' => 'de',
            'packageId' => $paidPackage->id,
        ]));
        $successResponse->assertRedirect('/event-admin');
        $successResponse->assertStatus(302);
    }

    public function test_full_user_flow_with_errors()
    {
        // Schritt 1: Fehlgeschlagene Registrierung (kein Consent)
        $response = $this->post('/de/register', [
            'name' => 'Error User',
            'email' => 'error@example.com',
            'password' => 'Password123!',
            'password_confirmation' => 'Password123!',
            'first_name' => 'Max',
            'last_name' => 'Mustermann',
            'privacy_consent' => false,
        ]);

        $response->assertRedirect(route('packages', ['locale' => 'de']));
        $this->assertGuest();
        $this->assertDatabaseMissing('users', ['email' => 'error@example.com']);

        // Schritt 2: Fehlgeschlagener Login (Rate Limit)
        $user = User::factory()->create([
            'email' => 'ratelimit@example.com',
            'password' => bcrypt('password'),
        ]);

        for ($i = 0; $i < 5; $i++) {
            $this->post(route('login.store'), [
                'login' => 'ratelimit@example.com',
                'password' => 'wrong',
            ]);
        }

        $throttleResponse = $this->post(route('login.store'), [
            'login' => 'ratelimit@example.com',
            'password' => 'wrong',
        ]);

        $throttleResponse->assertSessionHasErrors(['login']);
        $errors = session('errors');
        $this->assertMatchesRegularExpression('/Zu viele Login-Versuche\. Bitte versuche es in \d+ Sekunden erneut\./', $errors->first('login'));
        $this->assertGuest();

        // Schritt 3: Bestellung ohne Auth blockiert
        $package = Package::factory()->create(['price' => 10]);
        $buyResponse = $this->get(route('buy.packages', [
            'locale' => 'de',
            'packageId' => $package->id,
        ]));
        $buyResponse->assertRedirect(CheckoutRoutes::wizardUrl($package->id, 'de'));

        // Nach Korrektur: Erfolgreicher Flow (kurz)
        // ... (ähnlich wie oben, aber mit Error-Handling)
    }
}
