<?php

declare(strict_types=1);

namespace Builder\Core\Http\Requests\Resource;

use Builder\Core\Exceptions\ResourceNotFoundException;
use Builder\Core\Foundation\Contracts\BuilderAccessible;
use Builder\Core\Foundation\Definition\Field;
use Builder\Core\Foundation\Middleware\BuilderAuth;
use Builder\Core\Foundation\Registry;
use Builder\Core\Foundation\Resources\FieldHandlerRegistry;
use Builder\Core\Foundation\Resources\ResourceDefinition;
use Illuminate\Foundation\Http\FormRequest;

abstract class ResourceRequest extends FormRequest
{
    /** @return array<string, string> */
    public function attributes(): array
    {
        return array_column(
            array_map(
                fn (Field $field) => [$field->getName(), strtolower($field->getLabel())],
                $this->getDefinition()->getAllFields(),
            ),
            1,
            0,
        );
    }

    /** @return array<string, list<string>> */
    protected function buildHandlerFieldRules(): array
    {
        $definition = $this->getDefinition();
        $registry = app(FieldHandlerRegistry::class);
        $fieldNames = [];

        foreach (array_keys($registry->all()) as $componentName) {
            foreach ($definition->getFieldsByComponent($componentName) as $field) {
                $fieldNames[] = $field->getName();
            }
        }

        foreach ($definition->getVirtualFieldNames() as $fieldName) {
            $fieldNames[] = $fieldName;
        }

        return array_fill_keys(array_unique($fieldNames), ['nullable', 'array']);
    }

    protected function getDefinition(): ResourceDefinition
    {
        $def = app(Registry::class)->resolveBySlug((string) $this->route('resource'));

        if ($def === null) {
            throw ResourceNotFoundException::forSlug((string) $this->route('resource'));
        }

        return $def;
    }

    protected function userHasPermission(?string $permission): bool
    {
        if ($permission === null) {
            return true;
        }

        /** @var BuilderAccessible $user */
        $user = $this->user(BuilderAuth::guard());
        $perms = $user->builderPermissions();

        return in_array('*', $perms, true) || in_array($permission, $perms, true);
    }
}
