<?php

class CfAutocomplete
{
    public function __construct(
        private \PDO $dbConnection,
        private \PDO $cfsettingsConnection,
        private int $limit = 50
    ) {
    }

    public function getClasses(string $query): array
    {
        $bindData = ['query' => "%{$query}%", 'limit' => $this->limit];
        $stmt = $this->dbConnection->prepare(
            'SELECT contextname AS class 
            FROM __contexts 
            WHERE contextname ILIKE :query
            UNION
            SELECT DISTINCT name AS class 
            FROM __cmdb_host_entries 
            WHERE name ILIKE :query AND type = \'class\'
            ORDER BY class ASC
            LIMIT :limit'
        );
        $stmt->execute($bindData);
        $results = $stmt->fetchAll(\PDO::FETCH_COLUMN);

        $groupsStmt = $this->cfsettingsConnection->prepare(
            'SELECT DISTINCT name AS class 
            FROM shared_host_groups_data_entries 
            WHERE name ILIKE :query AND type = \'class\'
            ORDER BY class ASC
            LIMIT :limit'
        );
        $groupsStmt->execute($bindData);
        $groupsResults = $groupsStmt->fetchAll(\PDO::FETCH_COLUMN);

        return array_slice(
            array_unique(array_merge($results, $groupsResults)),
            offset: 0,
            length: $this->limit
        );
    }

    public function getVariables(string $query): array
    {
        $bindData = ['query' => "%{$query}%", 'limit' => $this->limit];
        $stmt = $this->dbConnection->prepare(
            'SELECT DISTINCT CONCAT(namespace, \':\', bundle, \'.\', variablename) as full_definition,
            variablename as name
            FROM __variables WHERE variablename ILIKE :query
            UNION
            SELECT DISTINCT name as full_definition, name
            FROM __cmdb_host_entries 
            WHERE name ILIKE :query AND type = \'variable\'
            ORDER BY name ASC
            LIMIT :limit'
        );
        $stmt->execute($bindData);
        $variables = $stmt->fetchAll(\PDO::FETCH_ASSOC);
        $results = array_reduce($variables, function ($acc, $item) {
            $acc[$item['full_definition']] = $item['name'];
            return $acc;
        }, []);

        $groupsStmt = $this->cfsettingsConnection->prepare(
            'SELECT DISTINCT name as full_definition, name
            FROM shared_host_groups_data_entries 
            WHERE name ILIKE :query AND type = \'variable\'
            ORDER BY name ASC
            LIMIT :limit'
        );
        $groupsStmt->execute($bindData);
        $groupsResults = array_reduce($groupsStmt->fetchAll(\PDO::FETCH_ASSOC), function ($acc, $item) {
            $acc[$item['full_definition']] = $item['name'];
            return $acc;
        }, []);

        return array_slice(
            array_merge($results, $groupsResults),
            offset: 0,
            length: $this->limit
        );
    }

    public function getInventoryAttributes(string $query): array
    {
        $bindData = ['query' => "%{$query}%", 'limit' => $this->limit];
        $stmt = $this->dbConnection->prepare(
            'SELECT DISTINCT attribute_name
            FROM variables_dictionary 
            WHERE attribute_name ILIKE :query
            UNION
            SELECT DISTINCT name as attribute_name
            FROM __cmdb_host_entries 
            WHERE name ILIKE :query AND type = \'inventory\'
            ORDER BY attribute_name ASC
            LIMIT :limit'
        );
        $stmt->execute($bindData);
        $results = $stmt->fetchAll(\PDO::FETCH_COLUMN);

        $groupsStmt = $this->cfsettingsConnection->prepare(
            'SELECT DISTINCT name AS attribute_name 
            FROM shared_host_groups_data_entries 
            WHERE name ILIKE :query AND type = \'inventory\'
            ORDER BY attribute_name ASC
            LIMIT :limit'
        );
        $groupsStmt->execute($bindData);
        $groupsResults = $groupsStmt->fetchAll(\PDO::FETCH_COLUMN);

        return array_slice(
            array_unique(array_merge($results, $groupsResults)),
            offset: 0,
            length: $this->limit
        );
    }
}
