<?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\Middleware\BuilderAuth;
use Builder\Core\Foundation\Registry;
use Builder\Core\Foundation\Resources\ResourceDefinition;
use Builder\Core\Foundation\Tables\BulkAction;
use Illuminate\Foundation\Http\FormRequest;

final class BulkResourceRequest extends FormRequest
{
    public function authorize(): bool
    {
        $key = $this->input('action');

        // Built-in bulk actions are authorized inside the controller
        if (in_array($key, ['delete', 'bulk_update'], true)) {
            return true;
        }

        $def = $this->getDefinition();
        $action = collect($def->getBulkActions())->first(fn (BulkAction $a) => $a->getKey() === $key);

        if ($action === null) {
            return false;
        }

        return $this->userHasPermission($action->getPermission());
    }

    /** @return array<string, mixed> */
    public function rules(): array
    {
        return [
            'action' => ['required', 'string'],
            'ids' => ['required_without:select_all', 'array'],
            'ids.*' => ['required_without:select_all', 'integer', 'min:1'],
            'select_all' => ['sometimes', 'boolean'],
            'search' => ['sometimes', 'nullable', 'string'],
            'filters' => ['sometimes', 'nullable', 'array'],
            'data' => ['sometimes', 'nullable', 'array'],
            'data.*' => ['sometimes', 'nullable'],
        ];
    }

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

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

        return $def;
    }

    private 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);
    }
}
