<?php

use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Validation;

class BaseAutoComplete extends CfProtectedResource
{
    protected CfAutocomplete $autocomplete;
    public function __construct($parameters)
    {
        parent::__construct($parameters);
        $this->autocomplete = new CfAutocomplete(
            dbConnection: CfdbPdo::getInstance()->getConnection(),
            cfsettingsConnection: CfSettings::getInstance()->getConnection()
        );
    }
    protected static function validateRequest(array $requestData)
    {
        $validator = Validation::createValidator();
        $constraints = new Assert\Collection(
            fields: [
                'query' => new Assert\Required([
                    new Assert\Type(type: 'string'),
                    new Assert\Length(max: 100, min: 1),
                    new Assert\Regex(
                        pattern: '/^[a-zA-Z0-9_\ .:]+$/',
                        message: 'This field should contain only letters, numbers, dots, colons or underscores.'
                    )
                ])
            ]
        );

        $issues = $validator->validate($requestData, $constraints);
        if (count($issues) > 0) {
            $response = [
                'success' => false,
                'errors' => []
            ];
            foreach ($issues as $issue) {
                $response['errors'][] = [
                    'field' => $issue->getPropertyPath(),
                    'message' => $issue->getMessage()
                ];
            }
            throw new \InvalidArgumentException(json_encode($response));
        }
    }
}


/**
 * @uri /autocomplete/classes
 */
class AutocompleteClasses extends BaseAutoComplete
{
    /**
     * @param $request
     *
     * @rbacName Search classes
     * @rbacDescription This request bypasses database RBAC and allows seeing any class name in the system
     * @rbacGroup Autocomplete API
     * @rbacAlias autocomplete.get.classes
     * @rbacAllowedByDefault
     *
     * @return Response
     * @throws ResponseException
     */
    public function get($request): Response
    {
        self::validateRequest($_GET);
        $response = new Response($request);
        $classes = $this->autocomplete->getClasses($_GET['query']);
        $response->body = json_encode($classes);
        return $response;
    }
}


/**
 * @uri /autocomplete/variables
 */
class AutocompleteVariables extends BaseAutoComplete
{
    /**
     * @param $request
     *
     * @rbacName Search variables
     * @rbacDescription This request bypasses database RBAC and allows seeing any variable name in the system
     * @rbacGroup Autocomplete API
     * @rbacAlias autocomplete.get.variables
     * @rbacAllowedByDefault
     *
     * @return Response
     * @throws ResponseException
     */
    public function get($request): Response
    {
        self::validateRequest($_GET);
        $response = new Response($request);
        $variables = $this->autocomplete->getVariables($_GET['query']);
        $response->body = json_encode($variables);
        return $response;
    }
}

/**
 * @uri /autocomplete/inventory
 */
class AutocompleteInventory extends BaseAutoComplete
{
    /**
     * @param $request
     *
     * Do not need rbac rules because inventory attributes
     * are available without restrictions.
     * @return Response
     * @throws ResponseException
     */
    public function get($request): Response
    {
        self::validateRequest($_GET);
        $response = new Response($request);
        $inventoryNames = $this->autocomplete->getInventoryAttributes($_GET['query']);
        $response->body = json_encode($inventoryNames);
        return $response;
    }
}
