<?php

class MyHostGroupsModel
{
    protected string $defaultSortColumn = 'id';
    protected string $defaultSortDirection = 'ASC';

    private PDO $cfsettingsConnection;
    private PDO $cfdbConnection;

    public function __construct($username)
    {
        $this->cfsettingsConnection = CfSettings::getInstance()->getConnection();
        $this->cfdbConnection = CfdbPdo::getInstance()->getConnection();
        $this->username = $username;
    }

    public function list(array $args, array $where = [], array $whereBindData = []): bool|array
    {
        $offset = intval($args['skip'] ?? 0);
        $limit = intval($args['limit'] ?? 10);
        $includeHostsCount = isset($args['includeHostsCount']) && $args['includeHostsCount'] == 'yes';

        $orderBy = 'ORDER BY "' . ($args['sortColumn'] ?? $this->defaultSortColumn) . '"';
        $orderDirection = isset($args['sortDescending']) ?
            (($args['sortDescending'] == 'true') ? 'DESC' : 'ASC') :
            $this->defaultSortDirection;

        $bindData = ['limit' => $limit, 'offset' => $offset];

        if (isset($args['searchQuery']) && !empty($args['searchQuery'])) {
            $whereBindData['searchQuery'] = trim($args['searchQuery']);
            $where[] = " name LIKE '%' || :searchQuery || '%' ";
        }

        $where = sizeof($where) > 0 ? 'WHERE ' . implode(' AND ', $where) : '';

        // includes personal groups, shared groups created by user and favorite shared groups
        $statement = $this->cfsettingsConnection->prepare(
            "SELECT *,
            CASE 
              WHEN (data_value->'classes')::text <> '{}'::text OR (data_value->'variables')::text <> '{}'::text THEN true
              ELSE false
            END AS has_data 
       FROM (
            SELECT id, name, description, owner,'{}' as data_value, creation_time, filter, filter_sql, (favorite_groups.group_id IS NOT NULL) as is_favorite, '" . PersonalHostGroupsModel::$type . "' as type
            FROM personal_host_groups 
            LEFT JOIN favorite_groups ON favorite_groups.group_id = personal_host_groups.id AND username = :owner
            WHERE owner = :owner
              UNION ALL
            SELECT id, name, description, creator as owner, shgd.value as data_value, creation_time, filter, filter_sql, (favorite_groups.group_id IS NOT NULL) as is_favorite, '" . SharedHostGroupsModel::$type . "' as type
            FROM shared_host_groups
            LEFT JOIN favorite_groups ON favorite_groups.group_id = shared_host_groups.id AND username = :owner
            LEFT JOIN shared_host_groups_data AS shgd ON shgd.group_id = id
            WHERE (creator = :owner OR id IN (SELECT group_id FROM favorite_groups WHERE username = :owner)) AND deletion_time IS NULL
            ) my_groups $where $orderBy $orderDirection LIMIT :limit OFFSET :offset"
        );

        $statement->execute(array_merge($bindData, $whereBindData));

        $groups = $statement->fetchAll(PDO::FETCH_ASSOC);

        $groups = array_map(function ($group) {
            $group['filter'] = json_decode($group['filter'], true);
            return $group;
        }, $groups);


        if ($includeHostsCount) {
            $hostsCountCacheTime = BaseHostGroupsModel::addHostsCountToTheResult($groups, $this->username, $this->cfdbConnection);
        }

        return [
            'data' => $groups,
            'meta' => [
                'count' => sizeof($groups),
                'page' => floor($offset / $limit) + 1,
                'timestamp' => time(),
                'total' => $this->getTotalGroupsCount($where, $whereBindData),
                'hostsCountCacheTime' => $hostsCountCacheTime ?? null
            ]
        ];
    }

    private function getTotalGroupsCount($where, $bind)
    {
        $stmt = $this
            ->cfsettingsConnection
            ->prepare(
                "SELECT count(*) FROM (
            SELECT id
            FROM personal_host_groups 
            WHERE owner = :owner
              UNION ALL
            SELECT id
            FROM shared_host_groups 
            WHERE creator = :owner AND deletion_time IS NULL OR id IN (SELECT group_id FROM favorite_groups WHERE username = :owner)
            ) my_groups $where"
            );
        $stmt->execute($bind);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        return $result['count'];
    }

}
