CREATE VIEW queryCurrentActiveVersions as
SELECT DISTINCT
        q.queryId,
        coalesce(
            (FIRST_VALUE(av.versionId) OVER (PARTITION BY q.queryId ORDER BY av.activeVersionEntryId DESC)),
            0
        )::int as activeVersion
    FROM queries AS q
    LEFT JOIN queryActiveVersions as av on av.queryId = q.queryId;

CREATE VIEW queryLatestVersions as
    SELECT
    q.queryId,
    coalesce(max(v.versionId), 0)::int as latestVersion
    FROM queries AS q
    LEFT JOIN queryVersions as v on v.queryId = q.queryId
        GROUP BY q.queryId;

CREATE VIEW queryCurrentConfigs as
    SELECT av.queryId, c.config
    FROM queryCurrentActiveVersions as av
    LEFT JOIN queryConfigs AS c ON av.queryId = c.queryId
        and isInVersion(av.activeVersion, c.addedVersion, c.removedVersion);

CREATE VIEW queryCurrentRequiredIds as
    SELECT DISTINCT av.queryId, r.requiredQueryId
    FROM queryCurrentActiveVersions as av
    LEFT JOIN requiredQueries AS r ON av.queryId = r.queryId
        and isInVersion(av.activeVersion, r.addedVersion, r.removedVersion);

CREATE VIEW queryCurrentRequiredIdsAGG as
    SELECT queryId,
    coalesce(
        ARRAY_AGG(DISTINCT requiredQueryId)
        FILTER (WHERE requiredQueryId != '00000000-0000-0000-0000-000000000000')::uuid[],
        array[]::uuid[]
    )::uuid[] as requiredIds
    FROM queryCurrentRequiredIds
    GROUP BY queryId;

CREATE VIEW fullActiveQueries AS
SELECT DISTINCT q.queryId, q.queryType, av.activeVersion, lv.latestVersion, c.config, r.requiredIds
    FROM queries AS q
    JOIN queryCurrentActiveVersions as av on q.queryId = av.queryId
    JOIN queryLatestVersions as lv on lv.queryId = q.queryId
    JOIN queryCurrentConfigs AS c ON q.queryId = c.queryId
    JOIN queryCurrentRequiredIdsAGG AS r ON q.queryId = r.queryId;

CREATE VIEW queryActiveDependencies AS
WITH RECURSIVE queryActiveDependencies(queryId, requiredQueryId, path, cycle) AS (
        SELECT
            queryId,
            requiredQueryId,
            ARRAY[queryId, requiredQueryId]::uuid[] AS path,
            false AS cycle
        FROM queryCurrentRequiredIds

        UNION ALL

        SELECT
            q.queryId,
            qd.requiredQueryId,
            path || qd.requiredQueryId,
            qd.requiredQueryId = ANY(path) AS cycle
        FROM queryCurrentRequiredIds as q
        JOIN queryActiveDependencies as qd ON q.queryId = qd.requiredQueryId
        WHERE NOT qd.cycle -- Stop if we detect a cycle
    )
    SELECT DISTINCT queryId as id, requiredQueryId
    FROM queryActiveDependencies
    WHERE NOT cycle;
