<?php

namespace Tests\Feature;

use App\Models\Domain;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Artisan;
use Tests\TestCase;

class UserTierTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        Artisan::call('db:seed', ['--class' => 'RoleSeeder']);
    }

    public function test_new_user_is_assigned_free_role_by_default()
    {
        \Livewire\Livewire::test(\App\Livewire\Auth\Register::class)
            ->set('name', 'Test User')
            ->set('email', 'test@example.com')
            ->set('password', 'password')
            ->set('password_confirmation', 'password')
            ->call('register')
            ->assertHasNoErrors()
            ->assertRedirect();

        $user = User::where('email', 'test@example.com')->first();
        $this->assertNotNull($user, 'User was not created');
        $this->assertTrue($user->hasRole('free'));
        $this->assertEquals('FREE', $user->tierLabel());
    }

    public function test_free_user_can_only_access_public_domains()
    {
        $publicDomain = Domain::factory()->create(['allowed_types' => ['public'], 'name' => 'public.com']);
        $premiumDomain = Domain::factory()->create(['allowed_types' => ['premium'], 'name' => 'premium.com']);

        $user = User::factory()->free()->create();

        $accessibleDomains = Domain::accessibleBy($user)->get();

        $this->assertTrue($accessibleDomains->contains($publicDomain));
        $this->assertFalse($accessibleDomains->contains($premiumDomain));
    }

    public function test_pro_user_can_access_public_and_premium_domains()
    {
        $publicDomain = Domain::factory()->create(['allowed_types' => ['public'], 'name' => 'public.com']);
        $premiumDomain = Domain::factory()->create(['allowed_types' => ['premium'], 'name' => 'premium.com']);
        $privateDomain = Domain::factory()->create(['allowed_types' => ['private'], 'name' => 'private.com']);

        $user = User::factory()->pro()->create();

        $accessibleDomains = Domain::accessibleBy($user)->get();

        $this->assertTrue($accessibleDomains->contains($publicDomain));
        $this->assertTrue($accessibleDomains->contains($premiumDomain));
        $this->assertFalse($accessibleDomains->contains($privateDomain));
    }

    public function test_enterprise_user_can_access_all_domains()
    {
        $publicDomain = Domain::factory()->create(['allowed_types' => ['public'], 'name' => 'public.com']);
        $privateDomain = Domain::factory()->create(['allowed_types' => ['private'], 'name' => 'private.com']);

        $user = User::factory()->enterprise()->create();

        $accessibleDomains = Domain::accessibleBy($user)->get();

        $this->assertTrue($accessibleDomains->contains($publicDomain));
        $this->assertTrue($accessibleDomains->contains($privateDomain));
    }

    public function test_guest_can_only_access_public_domains()
    {
        $publicDomain = Domain::factory()->create(['allowed_types' => ['public'], 'name' => 'public.com']);
        $premiumDomain = Domain::factory()->create(['allowed_types' => ['premium'], 'name' => 'premium.com']);

        $accessibleDomains = Domain::accessibleBy(null)->get();

        $this->assertTrue($accessibleDomains->contains($publicDomain));
        $this->assertFalse($accessibleDomains->contains($premiumDomain));
    }

    public function test_mailbox_expiration_is_based_on_user_tier()
    {
        $domain = Domain::factory()->create(['allowed_types' => ['public'], 'name' => 'public.com']);

        // Test Guest (1 day)
        \Livewire\Livewire::test(\App\Livewire\Mailbox::class)
            ->call('autoCreateRandomMailbox');
        $guestMailbox = \App\Models\Mailbox::latest()->first();
        $this->assertEquals(1, round(now()->diffInDays($guestMailbox->expires_at)));

        // Test Free (3 days)
        $freeUser = User::factory()->free()->create();
        $this->actingAs($freeUser);
        \Livewire\Livewire::test(\App\Livewire\Mailbox::class)
            ->call('autoCreateRandomMailbox');
        $freeMailbox = \App\Models\Mailbox::where('user_id', $freeUser->id)->first();
        $this->assertEquals(3, round(now()->diffInDays($freeMailbox->expires_at)));

        // Test Pro (7 days)
        $proUser = User::factory()->pro()->create();
        $this->actingAs($proUser);
        \Livewire\Livewire::test(\App\Livewire\Mailbox::class)
            ->call('autoCreateRandomMailbox');
        $proMailbox = \App\Models\Mailbox::where('user_id', $proUser->id)->first();
        $this->assertEquals(7, round(now()->diffInDays($proMailbox->expires_at)));

        // Test Enterprise (14 days)
        $entUser = User::factory()->enterprise()->create();
        $this->actingAs($entUser);
        \Livewire\Livewire::test(\App\Livewire\Mailbox::class)
            ->call('autoCreateRandomMailbox');
        $entMailbox = \App\Models\Mailbox::where('user_id', $entUser->id)->first();
        $this->assertEquals(14, round(now()->diffInDays($entMailbox->expires_at)));
    }
}
