<?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\FieldBuilder;
use Builder\Core\Foundation\Definition\Section;
use Builder\Core\Foundation\Resources\Resource;
use Builder\Core\Foundation\Resources\ResourceDefinition;
use Illuminate\Database\Eloquent\Model;

final class SimpleResource extends Resource
{
    public static function getSlug(): string
    {
        return 'simple';
    }

    public static function getLabel(): string
    {
        return 'Simple';
    }

    /** @return class-string<Model> */
    public static function getModel(): string
    {
        return Model::class;
    }
}

final class PermissionSetResource extends Resource
{
    public static function getSlug(): string
    {
        return 'perm-set';
    }

    public static function getLabel(): string
    {
        return 'PermSet';
    }

    /** @return class-string<Model> */
    public static function getModel(): string
    {
        return Model::class;
    }

    /** @return list<string> */
    public function getPermissionSet(): array
    {
        return ['read:perm-set', 'create:perm-set', 'update:perm-set', 'delete:perm-set'];
    }
}

it('Resource::getPermissionSet() returns empty array by default', function (): void {
    expect((new SimpleResource)->getPermissionSet())->toBe([]);
});

it('Resource::getPermissionSet() can be overridden', function (): void {
    $resource = new PermissionSetResource;

    expect($resource->getPermissionSet())->toBe([
        'read:perm-set', 'create:perm-set', 'update:perm-set', 'delete:perm-set',
    ]);
});

it('ResourceDefinition::getPermissionSet() delegates to the resource', function (): void {
    $definition = ResourceDefinition::make(new PermissionSetResource);

    expect($definition->getPermissionSet())->toBe([
        'read:perm-set', 'create:perm-set', 'update:perm-set', 'delete:perm-set',
    ]);
});

it('ResourceDefinition::getPermissionSet() is empty for resources without overrides', function (): void {
    $definition = ResourceDefinition::make(new SimpleResource);

    expect($definition->getPermissionSet())->toBe([]);
});

it('UserResource returns correct permission set', function (): void {
    $resource = new UserResource;

    expect($resource->getPermissionSet())->toBe([
        'read:users', 'create:users', 'update:users', 'delete:users',
    ]);
});

it('RoleResource returns correct permission set', function (): void {
    $resource = new RoleResource;

    expect($resource->getPermissionSet())->toBe([
        'read:roles', 'create:roles', 'update:roles', 'delete:roles',
    ]);
});

it('ResourceDefinition::getAllFields() returns top-level and section fields combined', function (): void {
    $definition = ResourceDefinition::make(new PermissionSetResource);

    // PermissionSetResource has no fields or sections, so getAllFields() returns []
    expect($definition->getAllFields())->toBe([]);
});

it('ResourceDefinition::getAllFields() combines top-level and section fields', function (): void {
    $resource = new class extends Resource
    {
        public static function getSlug(): string
        {
            return 'all-fields-test';
        }

        public static function getLabel(): string
        {
            return 'AllFields';
        }

        /** @return class-string<Model> */
        public static function getModel(): string
        {
            return Model::class;
        }

        public function fields(): FieldBuilder
        {
            return FieldBuilder::make()->add(
                Field::text('top_level'),
                Section::make('details')->fields([
                    Field::text('section_field_one'),
                    Field::text('section_field_two'),
                ]),
            );
        }
    };

    $definition = ResourceDefinition::make($resource);
    $all = $definition->getAllFields();

    expect($all)->toHaveCount(3)
        ->and($all[0]->getName())->toBe('top_level')
        ->and($all[1]->getName())->toBe('section_field_one')
        ->and($all[2]->getName())->toBe('section_field_two');
});
