<?php

declare(strict_types=1);

use Builder\Core\Extensions\Resources\Roles\RoleResource;
use Builder\Core\Extensions\Resources\Users\UserResource;
use Builder\Core\Foundation\Definition\Field;
use Builder\Core\Foundation\Definition\Hook;
use Builder\Core\Foundation\Definition\Section;
use Builder\Core\Foundation\Tables\Column;
use Illuminate\Database\Eloquent\Model;
use Spatie\Permission\Models\Role;

it('UserResource slug is users', function (): void {
    expect(UserResource::getSlug())->toBe('users');
});

it('UserResource label is Users', function (): void {
    expect(UserResource::getLabel())->toBe('Users');
});

it('UserResource model comes from auth config', function (): void {
    $model = UserResource::getModel();

    expect($model)->toBe(config('auth.providers.users.model'));
});

it('UserResource has permission read:users', function (): void {
    expect((new UserResource)->getPermission())->toBe('read:users');
});

it('UserResource has General and Roles sections', function (): void {
    $sections = (new UserResource)->fields()->toSections();
    $keys = array_map(fn (Section $s) => $s->getKey(), $sections);

    expect($sections)->toHaveCount(2)
        ->and($keys)->toContain('general')
        ->and($keys)->toContain('roles');
});

it('UserResource General section contains name and email fields without password', function (): void {
    $sections = (new UserResource)->fields()->toSections();
    $general = array_values(array_filter($sections, fn (Section $s) => $s->getKey() === 'general'))[0];
    $fieldNames = array_map(fn (Field $f) => $f->getName(), $general->getFields());

    expect($fieldNames)->toContain('name')
        ->toContain('email')
        ->not->toContain('password');
});

it('UserResource Roles section contains a single-select roles field', function (): void {
    $sections = (new UserResource)->fields()->toSections();
    $rolesSection = array_values(array_filter($sections, fn (Section $s) => $s->getKey() === 'roles'))[0];
    $fields = $rolesSection->getFields();

    expect($fields)->toHaveCount(1)
        ->and($fields[0]->getName())->toBe('roles')
        ->and($fields[0]->isMultiple())->toBeFalse();
});

it('UserResource General section has priority 10 and Roles section has priority 20', function (): void {
    $sections = (new UserResource)->fields()->toSections();
    $byKey = array_combine(array_map(fn (Section $s) => $s->getKey(), $sections), $sections);

    expect($byKey['general']->getPriority())->toBe(10)
        ->and($byKey['roles']->getPriority())->toBe(20);
});

it('UserResource columns include name and email', function (): void {
    $keys = array_map(fn (Column $c) => $c->getKey(), (new UserResource)->columns());

    expect($keys)->toContain('name')->toContain('email');
});

it('UserResource name and email columns are searchable', function (): void {
    $columns = (new UserResource)->columns();
    $searchable = array_filter($columns, fn (Column $c) => $c->isSearchable());

    expect(count($searchable))->toBeGreaterThanOrEqual(2);
});

it('UserResource eagerLoad returns roles when model has HasRoles', function (): void {
    // eagerLoad is dynamic; only includes 'roles' when the configured model has HasRoles
    $resource = new UserResource;

    // Default test model has no HasRoles trait — eagerLoad returns empty array
    expect($resource->eagerLoad())->toBeArray();
});

it('UserResource hooks include creating, created, updating, and saved hooks', function (): void {
    $hooks = (new UserResource)->hooks();
    $events = array_map(fn (Hook $h) => $h->getEvent(), $hooks);

    expect($events)->toContain('creating')
        ->toContain('created')
        ->toContain('updating')
        ->toContain('saved');
});

it('UserResource rules do not include password', function (): void {
    $createRules = (new UserResource)->rules('create');
    $updateRules = (new UserResource)->rules('update');

    expect($createRules)->not->toHaveKey('password')
        ->and($updateRules)->not->toHaveKey('password');
});

it('UserResource has resend-invite and send-reset-password record actions', function (): void {
    $actions = (new UserResource)->recordActions();

    expect($actions)->toHaveCount(2)
        ->and($actions[0]->key)->toBe('resend-invite')
        ->and($actions[1]->key)->toBe('send-reset-password');
});

it('UserResource rules include roles validation', function (): void {
    $rules = (new UserResource)->rules('create');

    expect($rules)->toHaveKey('roles')
        ->and($rules['roles'])->toContain('nullable')
        ->toContain('integer');
});

it('RoleResource slug is roles', function (): void {
    expect(RoleResource::getSlug())->toBe('roles');
});

it('RoleResource model is Spatie Role', function (): void {
    expect(RoleResource::getModel())->toBe(Role::class);
});

it('RoleResource has permission read:roles', function (): void {
    expect((new RoleResource)->getPermission())->toBe('read:roles');
});
