// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.30.0
// source: repository_egress_policies.sql

package db

import (
	"context"

	"github.com/jackc/pgx/v5/pgtype"
)

const getRepositoryEgressPolicy = `-- name: GetRepositoryEgressPolicy :one
SELECT repository_id, allow_domains, updated_by, created_at, updated_at
FROM repository_egress_policies
WHERE repository_id = $1
`

func (q *Queries) GetRepositoryEgressPolicy(ctx context.Context, repositoryID int64) (RepositoryEgressPolicy, error) {
	row := q.db.QueryRow(ctx, getRepositoryEgressPolicy, repositoryID)
	var i RepositoryEgressPolicy
	err := row.Scan(
		&i.RepositoryID,
		&i.AllowDomains,
		&i.UpdatedBy,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}

const listRepositoryLiveSandboxIDs = `-- name: ListRepositoryLiveSandboxIDs :many
SELECT DISTINCT sandbox_id::text
FROM (
    SELECT w.vm_id AS sandbox_id
    FROM workspaces w
    WHERE w.repository_id = $1
      AND w.status = 'running'
      AND w.vm_id <> ''
      AND w.deleted_at IS NULL
    UNION
    SELECT t.vm_id AS sandbox_id
    FROM workflow_tasks t
    JOIN agent_sessions s ON s.workflow_run_id = t.workflow_run_id
    WHERE t.repository_id = $1
      AND t.status IN ('assigned', 'running')
      AND COALESCE(t.vm_id, '') <> ''
) live
ORDER BY sandbox_id
`

// The sandboxes of a repository whose egress proxy may be running and was
// created from the repository's policy: its running workspaces and the VMs
// of its agent sessions' live workflow tasks.
func (q *Queries) ListRepositoryLiveSandboxIDs(ctx context.Context, repositoryID int64) ([]string, error) {
	rows, err := q.db.Query(ctx, listRepositoryLiveSandboxIDs, repositoryID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []string{}
	for rows.Next() {
		var sandbox_id string
		if err := rows.Scan(&sandbox_id); err != nil {
			return nil, err
		}
		items = append(items, sandbox_id)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const patchRepositoryEgressPolicy = `-- name: PatchRepositoryEgressPolicy :one
INSERT INTO repository_egress_policies AS p (repository_id, allow_domains, updated_by)
SELECT $1, fresh.domains, $2
FROM (
    SELECT ARRAY(
        SELECT DISTINCT d COLLATE "C" FROM unnest(COALESCE($3::text[], '{}')) AS d
        WHERE NOT d = ANY(COALESCE($4::text[], '{}'))
        ORDER BY d COLLATE "C"
    )::text[] AS domains
) fresh
WHERE cardinality(fresh.domains) <= $5::int
ON CONFLICT (repository_id)
DO UPDATE SET
    allow_domains = ARRAY(
        SELECT DISTINCT d COLLATE "C" FROM unnest(p.allow_domains || EXCLUDED.allow_domains) AS d
        WHERE NOT d = ANY(COALESCE($4::text[], '{}'))
        ORDER BY d COLLATE "C"
    )::text[],
    updated_by = EXCLUDED.updated_by,
    updated_at = NOW()
WHERE cardinality(ARRAY(
    SELECT DISTINCT d FROM unnest(p.allow_domains || EXCLUDED.allow_domains) AS d
    WHERE NOT d = ANY(COALESCE($4::text[], '{}'))
)) <= $5::int
RETURNING repository_id, allow_domains, updated_by, created_at, updated_at
`

type PatchRepositoryEgressPolicyParams struct {
	RepositoryID  int64       `json:"repository_id"`
	UpdatedBy     pgtype.Int8 `json:"updated_by"`
	AddDomains    []string    `json:"add_domains"`
	RemoveDomains []string    `json:"remove_domains"`
	MaxDomains    int32       `json:"max_domains"`
}

// Adds and removes hosts in one statement: the row lock of ON CONFLICT makes
// overlapping writers apply one after the other, so neither loses the
// other's change. The list stays deduplicated and sorted byte-wise. A result
// longer than max_domains writes nothing and returns no row.
func (q *Queries) PatchRepositoryEgressPolicy(ctx context.Context, arg PatchRepositoryEgressPolicyParams) (RepositoryEgressPolicy, error) {
	row := q.db.QueryRow(ctx, patchRepositoryEgressPolicy,
		arg.RepositoryID,
		arg.UpdatedBy,
		arg.AddDomains,
		arg.RemoveDomains,
		arg.MaxDomains,
	)
	var i RepositoryEgressPolicy
	err := row.Scan(
		&i.RepositoryID,
		&i.AllowDomains,
		&i.UpdatedBy,
		&i.CreatedAt,
		&i.UpdatedAt,
	)
	return i, err
}
