<?php

use App\Enums\LegalDocumentType;
use App\Enums\UserRole;
use App\Filament\Resources\LegalDocuments\Pages\EditLegalDocument;
use App\Filament\Resources\LegalDocuments\Pages\ListLegalDocuments;
use App\Models\LegalDocument;
use App\Models\User;
use Filament\Facades\Filament;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\TextInput;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;

uses(RefreshDatabase::class);

it('returns the active published legal document by slug', function (): void {
    LegalDocument::factory()->create([
        'slug' => 'privacy-policy',
        'version' => 1,
        'is_active' => false,
    ]);

    LegalDocument::factory()->create([
        'slug' => 'privacy-policy',
        'version' => 2,
        'is_active' => true,
        'published_at' => now(),
        'title' => [
            'fr' => 'Confidentialité Bowli',
        ],
    ]);

    $this
        ->getJson('/api/legal-documents/privacy-policy')
        ->assertOk()
        ->assertJsonPath('data.slug', 'privacy-policy')
        ->assertJsonPath('data.type', LegalDocumentType::PRIVACY_POLICY->value)
        ->assertJsonPath('data.version', 2)
        ->assertJsonPath('data.title.fr', 'Confidentialité Bowli')
        ->assertJsonPath('data.isActive', true);
});

it('does not expose inactive or unpublished legal documents', function (): void {
    LegalDocument::factory()->inactive()->create([
        'slug' => 'privacy-policy',
    ]);

    LegalDocument::factory()->unpublished()->create([
        'slug' => 'terms-of-service',
    ]);

    $this->getJson('/api/legal-documents/privacy-policy')->assertNotFound();
    $this->getJson('/api/legal-documents/terms-of-service')->assertNotFound();
});

it('lists active published legal documents with an optional type filter', function (): void {
    LegalDocument::factory()->create([
        'slug' => 'privacy-policy',
        'type' => LegalDocumentType::PRIVACY_POLICY,
    ]);

    LegalDocument::factory()->terms()->create([
        'slug' => 'terms-of-service',
        'type' => LegalDocumentType::TERMS,
    ]);

    $this
        ->getJson('/api/legal-documents?type=terms')
        ->assertOk()
        ->assertJsonCount(1, 'data')
        ->assertJsonPath('data.0.slug', 'terms-of-service')
        ->assertJsonPath('data.0.type', LegalDocumentType::TERMS->value);
});

it('keeps only one active version per slug', function (): void {
    $firstVersion = LegalDocument::factory()->create([
        'slug' => 'privacy-policy',
        'version' => 1,
        'is_active' => true,
    ]);

    LegalDocument::factory()->create([
        'slug' => 'privacy-policy',
        'version' => 2,
        'is_active' => true,
    ]);

    expect($firstVersion->fresh()->is_active)->toBeFalse();
});

it('exposes legal documents in filament', function (): void {
    app()->setLocale('fr');

    Filament::setCurrentPanel(Filament::getPanel('dashboard'));

    $admin = User::factory()->create([
        'role' => UserRole::ADMIN,
    ]);

    $document = LegalDocument::factory()->create([
        'slug' => 'privacy-policy',
    ]);

    $this->actingAs($admin);

    Livewire::test(ListLegalDocuments::class)
        ->assertTableColumnExists(
            'slug',
            fn (TextColumn $column): bool => $column->getLabel() === 'Slug',
        )
        ->assertTableFilterExists(
            'type',
            fn (SelectFilter $filter): bool => $filter->getLabel() === 'Type'
                && $filter->getOptions() === [
                    'privacy_policy' => 'Politique de confidentialité',
                    'terms' => 'Conditions d’utilisation',
                ],
        )
        ->assertSee('privacy-policy');

    Livewire::test(EditLegalDocument::class, ['record' => $document->getKey()])
        ->assertFormFieldExists(
            'title.fr',
            null,
            fn (TextInput $field): bool => $field->getLabel() === 'Titre',
        )
        ->assertFormFieldExists(
            'content.fr.intro',
            null,
            fn (Repeater $field): bool => $field->getLabel() === 'Introduction',
        )
        ->assertFormFieldExists(
            'content.fr.sections',
            null,
            fn (Repeater $field): bool => $field->getLabel() === 'Sections',
        );
});

it('creates a new inactive unpublished version from filament', function (): void {
    app()->setLocale('fr');

    Filament::setCurrentPanel(Filament::getPanel('dashboard'));

    $admin = User::factory()->create([
        'role' => UserRole::ADMIN,
    ]);
    $document = LegalDocument::factory()->create([
        'slug' => 'privacy-policy',
        'version' => 3,
        'is_active' => true,
        'published_at' => now(),
    ]);

    $this->actingAs($admin);

    Livewire::test(ListLegalDocuments::class)
        ->callTableAction('createNewVersion', $document);

    $newVersion = LegalDocument::query()
        ->where('slug', 'privacy-policy')
        ->where('version', 4)
        ->firstOrFail();

    expect($newVersion->title)->toBe($document->title)
        ->and($newVersion->content)->toBe($document->content)
        ->and($newVersion->is_active)->toBeFalse()
        ->and($newVersion->published_at)->toBeNull();
});
