<?php

declare(strict_types=1);

use Builder\Core\Foundation\Tables\BulkAction;
use Builder\Core\Foundation\Tables\Column;
use Builder\Seo\Models\Redirect;
use Builder\Seo\Resources\RedirectResource;
use Illuminate\Contracts\Validation\Factory;

it('getSlug returns redirects', function (): void {
    expect(RedirectResource::getSlug())->toBe('redirects');
});

it('getModel returns Redirect model class', function (): void {
    expect(RedirectResource::getModel())->toBe(Redirect::class);
});

it('getLabel returns translated label', function (): void {
    expect(RedirectResource::getLabel())->toBeString()->not->toBeEmpty();
});

it('getSingularLabel returns translated singular label', function (): void {
    expect(RedirectResource::getSingularLabel())->toBeString()->not->toBeEmpty();
});

it('getPermission returns read:redirects', function (): void {
    expect((new RedirectResource)->getPermission())->toBe('read:redirects');
});

it('getPermissionSet contains all four CRUD permissions', function (): void {
    $permissions = (new RedirectResource)->getPermissionSet();

    expect($permissions)
        ->toContain('read:redirects')
        ->toContain('create:redirects')
        ->toContain('update:redirects')
        ->toContain('delete:redirects');
});

it('fields returns a FieldBuilder with a general section containing three fields', function (): void {
    $sections = (new RedirectResource)->fields()->toSections();

    expect($sections)->toHaveCount(1);

    $fields = $sections[0]->getFields();
    $names = array_map(fn ($f) => $f->getName(), $fields);

    expect($names)->toContain('from', 'to', 'type');
});

it('columns returns three Column instances', function (): void {
    $columns = (new RedirectResource)->columns();

    expect($columns)->toHaveCount(3)
        ->each->toBeInstanceOf(Column::class);
});

it('searchable returns from and to', function (): void {
    expect((new RedirectResource)->searchable())->toContain('from', 'to');
});

it('bulkActions returns one delete BulkAction', function (): void {
    $actions = (new RedirectResource)->bulkActions();

    expect($actions)->toHaveCount(1)
        ->and($actions[0])->toBeInstanceOf(BulkAction::class)
        ->and($actions[0]->getKey())->toBe('delete');
});

it('rules for any action include from, to, and type', function (): void {
    $rules = (new RedirectResource)->rules('any');

    expect($rules)->toHaveKey('from')
        ->toHaveKey('to')
        ->toHaveKey('type');
});

it('rules for create action include a unique from constraint', function (): void {
    $rules = (new RedirectResource)->rules('create');

    expect($rules['from'])->toContain('required');
});

it('rules for update action include an ignore-aware unique from constraint', function (): void {
    $rules = (new RedirectResource)->rules('update');

    expect($rules['from'])->toContain('required');
});

it('from rule rejects protocol-relative paths', function (): void {
    $rules = (new RedirectResource)->rules('create');
    $validator = app(Factory::class);

    expect($validator->make(['from' => '//evil.com/x', 'to' => '/ok', 'type' => 'permanent'], $rules)->passes())->toBeFalse();
    expect($validator->make(['from' => '/legit', 'to' => '/ok', 'type' => 'permanent'], $rules)->passes())->toBeTrue();
});

it('to rule rejects unsafe schemes', function (): void {
    $rules = (new RedirectResource)->rules('create');
    $validator = app(Factory::class);

    expect($validator->make(['from' => '/a', 'to' => 'javascript:alert(1)', 'type' => 'permanent'], $rules)->passes())->toBeFalse();
    expect($validator->make(['from' => '/a', 'to' => 'data:text/html,<script>', 'type' => 'permanent'], $rules)->passes())->toBeFalse();
    expect($validator->make(['from' => '/a', 'to' => 'https://example.com/page', 'type' => 'permanent'], $rules)->passes())->toBeTrue();
    expect($validator->make(['from' => '/a', 'to' => '/relative', 'type' => 'permanent'], $rules)->passes())->toBeTrue();
});
