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

package db

import (
	"context"

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

const archiveAgent = `-- name: ArchiveAgent :one
UPDATE agent SET archived_at = now(), archived_by = $2, updated_at = now()
WHERE id = $1
RETURNING id, workspace_id, name, avatar_url, runtime_mode, runtime_config, visibility, status, max_concurrent_tasks, owner_id, created_at, updated_at, description, tools, triggers, runtime_id, instructions, archived_at, archived_by
`

type ArchiveAgentParams struct {
	ID         pgtype.UUID `json:"id"`
	ArchivedBy pgtype.UUID `json:"archived_by"`
}

func (q *Queries) ArchiveAgent(ctx context.Context, arg ArchiveAgentParams) (Agent, error) {
	row := q.db.QueryRow(ctx, archiveAgent, arg.ID, arg.ArchivedBy)
	var i Agent
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.Name,
		&i.AvatarUrl,
		&i.RuntimeMode,
		&i.RuntimeConfig,
		&i.Visibility,
		&i.Status,
		&i.MaxConcurrentTasks,
		&i.OwnerID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Description,
		&i.Tools,
		&i.Triggers,
		&i.RuntimeID,
		&i.Instructions,
		&i.ArchivedAt,
		&i.ArchivedBy,
	)
	return i, err
}

const cancelAgentTask = `-- name: CancelAgentTask :one
UPDATE agent_task_queue
SET status = 'cancelled', completed_at = now()
WHERE id = $1 AND status IN ('queued', 'dispatched', 'running')
RETURNING id, agent_id, issue_id, status, priority, dispatched_at, started_at, completed_at, result, error, created_at, context, runtime_id, session_id, work_dir, trigger_comment_id
`

func (q *Queries) CancelAgentTask(ctx context.Context, id pgtype.UUID) (AgentTaskQueue, error) {
	row := q.db.QueryRow(ctx, cancelAgentTask, id)
	var i AgentTaskQueue
	err := row.Scan(
		&i.ID,
		&i.AgentID,
		&i.IssueID,
		&i.Status,
		&i.Priority,
		&i.DispatchedAt,
		&i.StartedAt,
		&i.CompletedAt,
		&i.Result,
		&i.Error,
		&i.CreatedAt,
		&i.Context,
		&i.RuntimeID,
		&i.SessionID,
		&i.WorkDir,
		&i.TriggerCommentID,
	)
	return i, err
}

const cancelAgentTasksByAgent = `-- name: CancelAgentTasksByAgent :exec
UPDATE agent_task_queue
SET status = 'cancelled'
WHERE agent_id = $1 AND status IN ('queued', 'dispatched', 'running')
`

func (q *Queries) CancelAgentTasksByAgent(ctx context.Context, agentID pgtype.UUID) error {
	_, err := q.db.Exec(ctx, cancelAgentTasksByAgent, agentID)
	return err
}

const cancelAgentTasksByIssue = `-- name: CancelAgentTasksByIssue :exec
UPDATE agent_task_queue
SET status = 'cancelled'
WHERE issue_id = $1 AND status IN ('queued', 'dispatched', 'running')
`

func (q *Queries) CancelAgentTasksByIssue(ctx context.Context, issueID pgtype.UUID) error {
	_, err := q.db.Exec(ctx, cancelAgentTasksByIssue, issueID)
	return err
}

const claimAgentTask = `-- name: ClaimAgentTask :one
UPDATE agent_task_queue
SET status = 'dispatched', dispatched_at = now()
WHERE id = (
    SELECT atq.id FROM agent_task_queue atq
    WHERE atq.agent_id = $1 AND atq.status = 'queued'
      AND NOT EXISTS (
          SELECT 1 FROM agent_task_queue active
          WHERE active.issue_id = atq.issue_id
            AND active.status IN ('dispatched', 'running')
      )
    ORDER BY atq.priority DESC, atq.created_at ASC
    LIMIT 1
    FOR UPDATE SKIP LOCKED
)
RETURNING id, agent_id, issue_id, status, priority, dispatched_at, started_at, completed_at, result, error, created_at, context, runtime_id, session_id, work_dir, trigger_comment_id
`

// Claims the next queued task for an agent, enforcing per-issue serialization:
// a task is only claimable when no other task for the same issue is already
// dispatched or running. This guarantees serial execution within an issue
// while allowing parallel execution across different issues.
func (q *Queries) ClaimAgentTask(ctx context.Context, agentID pgtype.UUID) (AgentTaskQueue, error) {
	row := q.db.QueryRow(ctx, claimAgentTask, agentID)
	var i AgentTaskQueue
	err := row.Scan(
		&i.ID,
		&i.AgentID,
		&i.IssueID,
		&i.Status,
		&i.Priority,
		&i.DispatchedAt,
		&i.StartedAt,
		&i.CompletedAt,
		&i.Result,
		&i.Error,
		&i.CreatedAt,
		&i.Context,
		&i.RuntimeID,
		&i.SessionID,
		&i.WorkDir,
		&i.TriggerCommentID,
	)
	return i, err
}

const completeAgentTask = `-- name: CompleteAgentTask :one
UPDATE agent_task_queue
SET status = 'completed', completed_at = now(), result = $2, session_id = $3, work_dir = $4
WHERE id = $1 AND status = 'running'
RETURNING id, agent_id, issue_id, status, priority, dispatched_at, started_at, completed_at, result, error, created_at, context, runtime_id, session_id, work_dir, trigger_comment_id
`

type CompleteAgentTaskParams struct {
	ID        pgtype.UUID `json:"id"`
	Result    []byte      `json:"result"`
	SessionID pgtype.Text `json:"session_id"`
	WorkDir   pgtype.Text `json:"work_dir"`
}

func (q *Queries) CompleteAgentTask(ctx context.Context, arg CompleteAgentTaskParams) (AgentTaskQueue, error) {
	row := q.db.QueryRow(ctx, completeAgentTask,
		arg.ID,
		arg.Result,
		arg.SessionID,
		arg.WorkDir,
	)
	var i AgentTaskQueue
	err := row.Scan(
		&i.ID,
		&i.AgentID,
		&i.IssueID,
		&i.Status,
		&i.Priority,
		&i.DispatchedAt,
		&i.StartedAt,
		&i.CompletedAt,
		&i.Result,
		&i.Error,
		&i.CreatedAt,
		&i.Context,
		&i.RuntimeID,
		&i.SessionID,
		&i.WorkDir,
		&i.TriggerCommentID,
	)
	return i, err
}

const countRunningTasks = `-- name: CountRunningTasks :one
SELECT count(*) FROM agent_task_queue
WHERE agent_id = $1 AND status IN ('dispatched', 'running')
`

func (q *Queries) CountRunningTasks(ctx context.Context, agentID pgtype.UUID) (int64, error) {
	row := q.db.QueryRow(ctx, countRunningTasks, agentID)
	var count int64
	err := row.Scan(&count)
	return count, err
}

const createAgent = `-- name: CreateAgent :one
INSERT INTO agent (
    workspace_id, name, description, avatar_url, runtime_mode,
    runtime_config, runtime_id, visibility, max_concurrent_tasks, owner_id,
    tools, triggers, instructions
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
RETURNING id, workspace_id, name, avatar_url, runtime_mode, runtime_config, visibility, status, max_concurrent_tasks, owner_id, created_at, updated_at, description, tools, triggers, runtime_id, instructions, archived_at, archived_by
`

type CreateAgentParams struct {
	WorkspaceID        pgtype.UUID `json:"workspace_id"`
	Name               string      `json:"name"`
	Description        string      `json:"description"`
	AvatarUrl          pgtype.Text `json:"avatar_url"`
	RuntimeMode        string      `json:"runtime_mode"`
	RuntimeConfig      []byte      `json:"runtime_config"`
	RuntimeID          pgtype.UUID `json:"runtime_id"`
	Visibility         string      `json:"visibility"`
	MaxConcurrentTasks int32       `json:"max_concurrent_tasks"`
	OwnerID            pgtype.UUID `json:"owner_id"`
	Tools              []byte      `json:"tools"`
	Triggers           []byte      `json:"triggers"`
	Instructions       string      `json:"instructions"`
}

func (q *Queries) CreateAgent(ctx context.Context, arg CreateAgentParams) (Agent, error) {
	row := q.db.QueryRow(ctx, createAgent,
		arg.WorkspaceID,
		arg.Name,
		arg.Description,
		arg.AvatarUrl,
		arg.RuntimeMode,
		arg.RuntimeConfig,
		arg.RuntimeID,
		arg.Visibility,
		arg.MaxConcurrentTasks,
		arg.OwnerID,
		arg.Tools,
		arg.Triggers,
		arg.Instructions,
	)
	var i Agent
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.Name,
		&i.AvatarUrl,
		&i.RuntimeMode,
		&i.RuntimeConfig,
		&i.Visibility,
		&i.Status,
		&i.MaxConcurrentTasks,
		&i.OwnerID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Description,
		&i.Tools,
		&i.Triggers,
		&i.RuntimeID,
		&i.Instructions,
		&i.ArchivedAt,
		&i.ArchivedBy,
	)
	return i, err
}

const createAgentTask = `-- name: CreateAgentTask :one
INSERT INTO agent_task_queue (agent_id, runtime_id, issue_id, status, priority, trigger_comment_id)
VALUES ($1, $2, $3, 'queued', $4, $5)
RETURNING id, agent_id, issue_id, status, priority, dispatched_at, started_at, completed_at, result, error, created_at, context, runtime_id, session_id, work_dir, trigger_comment_id
`

type CreateAgentTaskParams struct {
	AgentID          pgtype.UUID `json:"agent_id"`
	RuntimeID        pgtype.UUID `json:"runtime_id"`
	IssueID          pgtype.UUID `json:"issue_id"`
	Priority         int32       `json:"priority"`
	TriggerCommentID pgtype.UUID `json:"trigger_comment_id"`
}

func (q *Queries) CreateAgentTask(ctx context.Context, arg CreateAgentTaskParams) (AgentTaskQueue, error) {
	row := q.db.QueryRow(ctx, createAgentTask,
		arg.AgentID,
		arg.RuntimeID,
		arg.IssueID,
		arg.Priority,
		arg.TriggerCommentID,
	)
	var i AgentTaskQueue
	err := row.Scan(
		&i.ID,
		&i.AgentID,
		&i.IssueID,
		&i.Status,
		&i.Priority,
		&i.DispatchedAt,
		&i.StartedAt,
		&i.CompletedAt,
		&i.Result,
		&i.Error,
		&i.CreatedAt,
		&i.Context,
		&i.RuntimeID,
		&i.SessionID,
		&i.WorkDir,
		&i.TriggerCommentID,
	)
	return i, err
}

const failAgentTask = `-- name: FailAgentTask :one
UPDATE agent_task_queue
SET status = 'failed', completed_at = now(), error = $2
WHERE id = $1 AND status IN ('dispatched', 'running')
RETURNING id, agent_id, issue_id, status, priority, dispatched_at, started_at, completed_at, result, error, created_at, context, runtime_id, session_id, work_dir, trigger_comment_id
`

type FailAgentTaskParams struct {
	ID    pgtype.UUID `json:"id"`
	Error pgtype.Text `json:"error"`
}

func (q *Queries) FailAgentTask(ctx context.Context, arg FailAgentTaskParams) (AgentTaskQueue, error) {
	row := q.db.QueryRow(ctx, failAgentTask, arg.ID, arg.Error)
	var i AgentTaskQueue
	err := row.Scan(
		&i.ID,
		&i.AgentID,
		&i.IssueID,
		&i.Status,
		&i.Priority,
		&i.DispatchedAt,
		&i.StartedAt,
		&i.CompletedAt,
		&i.Result,
		&i.Error,
		&i.CreatedAt,
		&i.Context,
		&i.RuntimeID,
		&i.SessionID,
		&i.WorkDir,
		&i.TriggerCommentID,
	)
	return i, err
}

const failStaleTasks = `-- name: FailStaleTasks :many
UPDATE agent_task_queue
SET status = 'failed', completed_at = now(), error = 'task timed out'
WHERE (status = 'dispatched' AND dispatched_at < now() - make_interval(secs => $1::double precision))
   OR (status = 'running' AND started_at < now() - make_interval(secs => $2::double precision))
RETURNING id, agent_id, issue_id
`

type FailStaleTasksParams struct {
	DispatchTimeoutSecs float64 `json:"dispatch_timeout_secs"`
	RunningTimeoutSecs  float64 `json:"running_timeout_secs"`
}

type FailStaleTasksRow struct {
	ID      pgtype.UUID `json:"id"`
	AgentID pgtype.UUID `json:"agent_id"`
	IssueID pgtype.UUID `json:"issue_id"`
}

// Fails tasks stuck in dispatched/running beyond the given thresholds.
// Handles cases where the daemon is alive but the task is orphaned
// (e.g. agent process hung, daemon failed to report completion).
func (q *Queries) FailStaleTasks(ctx context.Context, arg FailStaleTasksParams) ([]FailStaleTasksRow, error) {
	rows, err := q.db.Query(ctx, failStaleTasks, arg.DispatchTimeoutSecs, arg.RunningTimeoutSecs)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []FailStaleTasksRow{}
	for rows.Next() {
		var i FailStaleTasksRow
		if err := rows.Scan(&i.ID, &i.AgentID, &i.IssueID); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getAgent = `-- name: GetAgent :one
SELECT id, workspace_id, name, avatar_url, runtime_mode, runtime_config, visibility, status, max_concurrent_tasks, owner_id, created_at, updated_at, description, tools, triggers, runtime_id, instructions, archived_at, archived_by FROM agent
WHERE id = $1
`

func (q *Queries) GetAgent(ctx context.Context, id pgtype.UUID) (Agent, error) {
	row := q.db.QueryRow(ctx, getAgent, id)
	var i Agent
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.Name,
		&i.AvatarUrl,
		&i.RuntimeMode,
		&i.RuntimeConfig,
		&i.Visibility,
		&i.Status,
		&i.MaxConcurrentTasks,
		&i.OwnerID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Description,
		&i.Tools,
		&i.Triggers,
		&i.RuntimeID,
		&i.Instructions,
		&i.ArchivedAt,
		&i.ArchivedBy,
	)
	return i, err
}

const getAgentInWorkspace = `-- name: GetAgentInWorkspace :one
SELECT id, workspace_id, name, avatar_url, runtime_mode, runtime_config, visibility, status, max_concurrent_tasks, owner_id, created_at, updated_at, description, tools, triggers, runtime_id, instructions, archived_at, archived_by FROM agent
WHERE id = $1 AND workspace_id = $2
`

type GetAgentInWorkspaceParams struct {
	ID          pgtype.UUID `json:"id"`
	WorkspaceID pgtype.UUID `json:"workspace_id"`
}

func (q *Queries) GetAgentInWorkspace(ctx context.Context, arg GetAgentInWorkspaceParams) (Agent, error) {
	row := q.db.QueryRow(ctx, getAgentInWorkspace, arg.ID, arg.WorkspaceID)
	var i Agent
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.Name,
		&i.AvatarUrl,
		&i.RuntimeMode,
		&i.RuntimeConfig,
		&i.Visibility,
		&i.Status,
		&i.MaxConcurrentTasks,
		&i.OwnerID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Description,
		&i.Tools,
		&i.Triggers,
		&i.RuntimeID,
		&i.Instructions,
		&i.ArchivedAt,
		&i.ArchivedBy,
	)
	return i, err
}

const getAgentTask = `-- name: GetAgentTask :one
SELECT id, agent_id, issue_id, status, priority, dispatched_at, started_at, completed_at, result, error, created_at, context, runtime_id, session_id, work_dir, trigger_comment_id FROM agent_task_queue
WHERE id = $1
`

func (q *Queries) GetAgentTask(ctx context.Context, id pgtype.UUID) (AgentTaskQueue, error) {
	row := q.db.QueryRow(ctx, getAgentTask, id)
	var i AgentTaskQueue
	err := row.Scan(
		&i.ID,
		&i.AgentID,
		&i.IssueID,
		&i.Status,
		&i.Priority,
		&i.DispatchedAt,
		&i.StartedAt,
		&i.CompletedAt,
		&i.Result,
		&i.Error,
		&i.CreatedAt,
		&i.Context,
		&i.RuntimeID,
		&i.SessionID,
		&i.WorkDir,
		&i.TriggerCommentID,
	)
	return i, err
}

const getLastTaskSession = `-- name: GetLastTaskSession :one
SELECT session_id, work_dir FROM agent_task_queue
WHERE agent_id = $1 AND issue_id = $2 AND status = 'completed' AND session_id IS NOT NULL
ORDER BY completed_at DESC
LIMIT 1
`

type GetLastTaskSessionParams struct {
	AgentID pgtype.UUID `json:"agent_id"`
	IssueID pgtype.UUID `json:"issue_id"`
}

type GetLastTaskSessionRow struct {
	SessionID pgtype.Text `json:"session_id"`
	WorkDir   pgtype.Text `json:"work_dir"`
}

// Returns the session_id and work_dir from the most recent completed task
// for a given (agent_id, issue_id) pair, used for session resumption.
func (q *Queries) GetLastTaskSession(ctx context.Context, arg GetLastTaskSessionParams) (GetLastTaskSessionRow, error) {
	row := q.db.QueryRow(ctx, getLastTaskSession, arg.AgentID, arg.IssueID)
	var i GetLastTaskSessionRow
	err := row.Scan(&i.SessionID, &i.WorkDir)
	return i, err
}

const hasActiveTaskForIssue = `-- name: HasActiveTaskForIssue :one
SELECT count(*) > 0 AS has_active FROM agent_task_queue
WHERE issue_id = $1 AND status IN ('queued', 'dispatched', 'running')
`

// Returns true if there is any queued, dispatched, or running task for the issue.
func (q *Queries) HasActiveTaskForIssue(ctx context.Context, issueID pgtype.UUID) (bool, error) {
	row := q.db.QueryRow(ctx, hasActiveTaskForIssue, issueID)
	var has_active bool
	err := row.Scan(&has_active)
	return has_active, err
}

const hasPendingTaskForIssue = `-- name: HasPendingTaskForIssue :one
SELECT count(*) > 0 AS has_pending FROM agent_task_queue
WHERE issue_id = $1 AND status IN ('queued', 'dispatched')
`

// Returns true if there is a queued or dispatched (but not yet running) task for the issue.
// Used by the coalescing queue: allow enqueue when a task is running (so
// the agent picks up new comments on the next cycle) but skip if a pending
// task already exists (natural dedup).
func (q *Queries) HasPendingTaskForIssue(ctx context.Context, issueID pgtype.UUID) (bool, error) {
	row := q.db.QueryRow(ctx, hasPendingTaskForIssue, issueID)
	var has_pending bool
	err := row.Scan(&has_pending)
	return has_pending, err
}

const hasPendingTaskForIssueAndAgent = `-- name: HasPendingTaskForIssueAndAgent :one
SELECT count(*) > 0 AS has_pending FROM agent_task_queue
WHERE issue_id = $1 AND agent_id = $2 AND status IN ('queued', 'dispatched')
`

type HasPendingTaskForIssueAndAgentParams struct {
	IssueID pgtype.UUID `json:"issue_id"`
	AgentID pgtype.UUID `json:"agent_id"`
}

// Returns true if a specific agent already has a queued or dispatched task
// for the given issue. Used by @mention trigger dedup.
func (q *Queries) HasPendingTaskForIssueAndAgent(ctx context.Context, arg HasPendingTaskForIssueAndAgentParams) (bool, error) {
	row := q.db.QueryRow(ctx, hasPendingTaskForIssueAndAgent, arg.IssueID, arg.AgentID)
	var has_pending bool
	err := row.Scan(&has_pending)
	return has_pending, err
}

const listActiveTasksByIssue = `-- name: ListActiveTasksByIssue :many
SELECT id, agent_id, issue_id, status, priority, dispatched_at, started_at, completed_at, result, error, created_at, context, runtime_id, session_id, work_dir, trigger_comment_id FROM agent_task_queue
WHERE issue_id = $1 AND status IN ('dispatched', 'running')
ORDER BY created_at DESC
`

func (q *Queries) ListActiveTasksByIssue(ctx context.Context, issueID pgtype.UUID) ([]AgentTaskQueue, error) {
	rows, err := q.db.Query(ctx, listActiveTasksByIssue, issueID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []AgentTaskQueue{}
	for rows.Next() {
		var i AgentTaskQueue
		if err := rows.Scan(
			&i.ID,
			&i.AgentID,
			&i.IssueID,
			&i.Status,
			&i.Priority,
			&i.DispatchedAt,
			&i.StartedAt,
			&i.CompletedAt,
			&i.Result,
			&i.Error,
			&i.CreatedAt,
			&i.Context,
			&i.RuntimeID,
			&i.SessionID,
			&i.WorkDir,
			&i.TriggerCommentID,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listAgentTasks = `-- name: ListAgentTasks :many
SELECT id, agent_id, issue_id, status, priority, dispatched_at, started_at, completed_at, result, error, created_at, context, runtime_id, session_id, work_dir, trigger_comment_id FROM agent_task_queue
WHERE agent_id = $1
ORDER BY created_at DESC
`

func (q *Queries) ListAgentTasks(ctx context.Context, agentID pgtype.UUID) ([]AgentTaskQueue, error) {
	rows, err := q.db.Query(ctx, listAgentTasks, agentID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []AgentTaskQueue{}
	for rows.Next() {
		var i AgentTaskQueue
		if err := rows.Scan(
			&i.ID,
			&i.AgentID,
			&i.IssueID,
			&i.Status,
			&i.Priority,
			&i.DispatchedAt,
			&i.StartedAt,
			&i.CompletedAt,
			&i.Result,
			&i.Error,
			&i.CreatedAt,
			&i.Context,
			&i.RuntimeID,
			&i.SessionID,
			&i.WorkDir,
			&i.TriggerCommentID,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listAgents = `-- name: ListAgents :many
SELECT id, workspace_id, name, avatar_url, runtime_mode, runtime_config, visibility, status, max_concurrent_tasks, owner_id, created_at, updated_at, description, tools, triggers, runtime_id, instructions, archived_at, archived_by FROM agent
WHERE workspace_id = $1 AND archived_at IS NULL
ORDER BY created_at ASC
`

func (q *Queries) ListAgents(ctx context.Context, workspaceID pgtype.UUID) ([]Agent, error) {
	rows, err := q.db.Query(ctx, listAgents, workspaceID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []Agent{}
	for rows.Next() {
		var i Agent
		if err := rows.Scan(
			&i.ID,
			&i.WorkspaceID,
			&i.Name,
			&i.AvatarUrl,
			&i.RuntimeMode,
			&i.RuntimeConfig,
			&i.Visibility,
			&i.Status,
			&i.MaxConcurrentTasks,
			&i.OwnerID,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.Description,
			&i.Tools,
			&i.Triggers,
			&i.RuntimeID,
			&i.Instructions,
			&i.ArchivedAt,
			&i.ArchivedBy,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listAllAgents = `-- name: ListAllAgents :many
SELECT id, workspace_id, name, avatar_url, runtime_mode, runtime_config, visibility, status, max_concurrent_tasks, owner_id, created_at, updated_at, description, tools, triggers, runtime_id, instructions, archived_at, archived_by FROM agent
WHERE workspace_id = $1
ORDER BY created_at ASC
`

func (q *Queries) ListAllAgents(ctx context.Context, workspaceID pgtype.UUID) ([]Agent, error) {
	rows, err := q.db.Query(ctx, listAllAgents, workspaceID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []Agent{}
	for rows.Next() {
		var i Agent
		if err := rows.Scan(
			&i.ID,
			&i.WorkspaceID,
			&i.Name,
			&i.AvatarUrl,
			&i.RuntimeMode,
			&i.RuntimeConfig,
			&i.Visibility,
			&i.Status,
			&i.MaxConcurrentTasks,
			&i.OwnerID,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.Description,
			&i.Tools,
			&i.Triggers,
			&i.RuntimeID,
			&i.Instructions,
			&i.ArchivedAt,
			&i.ArchivedBy,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listPendingTasksByRuntime = `-- name: ListPendingTasksByRuntime :many
SELECT id, agent_id, issue_id, status, priority, dispatched_at, started_at, completed_at, result, error, created_at, context, runtime_id, session_id, work_dir, trigger_comment_id FROM agent_task_queue
WHERE runtime_id = $1 AND status IN ('queued', 'dispatched')
ORDER BY priority DESC, created_at ASC
`

func (q *Queries) ListPendingTasksByRuntime(ctx context.Context, runtimeID pgtype.UUID) ([]AgentTaskQueue, error) {
	rows, err := q.db.Query(ctx, listPendingTasksByRuntime, runtimeID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []AgentTaskQueue{}
	for rows.Next() {
		var i AgentTaskQueue
		if err := rows.Scan(
			&i.ID,
			&i.AgentID,
			&i.IssueID,
			&i.Status,
			&i.Priority,
			&i.DispatchedAt,
			&i.StartedAt,
			&i.CompletedAt,
			&i.Result,
			&i.Error,
			&i.CreatedAt,
			&i.Context,
			&i.RuntimeID,
			&i.SessionID,
			&i.WorkDir,
			&i.TriggerCommentID,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listTasksByIssue = `-- name: ListTasksByIssue :many
SELECT id, agent_id, issue_id, status, priority, dispatched_at, started_at, completed_at, result, error, created_at, context, runtime_id, session_id, work_dir, trigger_comment_id FROM agent_task_queue
WHERE issue_id = $1
ORDER BY created_at DESC
`

func (q *Queries) ListTasksByIssue(ctx context.Context, issueID pgtype.UUID) ([]AgentTaskQueue, error) {
	rows, err := q.db.Query(ctx, listTasksByIssue, issueID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []AgentTaskQueue{}
	for rows.Next() {
		var i AgentTaskQueue
		if err := rows.Scan(
			&i.ID,
			&i.AgentID,
			&i.IssueID,
			&i.Status,
			&i.Priority,
			&i.DispatchedAt,
			&i.StartedAt,
			&i.CompletedAt,
			&i.Result,
			&i.Error,
			&i.CreatedAt,
			&i.Context,
			&i.RuntimeID,
			&i.SessionID,
			&i.WorkDir,
			&i.TriggerCommentID,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const restoreAgent = `-- name: RestoreAgent :one
UPDATE agent SET archived_at = NULL, archived_by = NULL, updated_at = now()
WHERE id = $1
RETURNING id, workspace_id, name, avatar_url, runtime_mode, runtime_config, visibility, status, max_concurrent_tasks, owner_id, created_at, updated_at, description, tools, triggers, runtime_id, instructions, archived_at, archived_by
`

func (q *Queries) RestoreAgent(ctx context.Context, id pgtype.UUID) (Agent, error) {
	row := q.db.QueryRow(ctx, restoreAgent, id)
	var i Agent
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.Name,
		&i.AvatarUrl,
		&i.RuntimeMode,
		&i.RuntimeConfig,
		&i.Visibility,
		&i.Status,
		&i.MaxConcurrentTasks,
		&i.OwnerID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Description,
		&i.Tools,
		&i.Triggers,
		&i.RuntimeID,
		&i.Instructions,
		&i.ArchivedAt,
		&i.ArchivedBy,
	)
	return i, err
}

const startAgentTask = `-- name: StartAgentTask :one
UPDATE agent_task_queue
SET status = 'running', started_at = now()
WHERE id = $1 AND status = 'dispatched'
RETURNING id, agent_id, issue_id, status, priority, dispatched_at, started_at, completed_at, result, error, created_at, context, runtime_id, session_id, work_dir, trigger_comment_id
`

func (q *Queries) StartAgentTask(ctx context.Context, id pgtype.UUID) (AgentTaskQueue, error) {
	row := q.db.QueryRow(ctx, startAgentTask, id)
	var i AgentTaskQueue
	err := row.Scan(
		&i.ID,
		&i.AgentID,
		&i.IssueID,
		&i.Status,
		&i.Priority,
		&i.DispatchedAt,
		&i.StartedAt,
		&i.CompletedAt,
		&i.Result,
		&i.Error,
		&i.CreatedAt,
		&i.Context,
		&i.RuntimeID,
		&i.SessionID,
		&i.WorkDir,
		&i.TriggerCommentID,
	)
	return i, err
}

const updateAgent = `-- name: UpdateAgent :one
UPDATE agent SET
    name = COALESCE($2, name),
    description = COALESCE($3, description),
    avatar_url = COALESCE($4, avatar_url),
    runtime_config = COALESCE($5, runtime_config),
    runtime_mode = COALESCE($6, runtime_mode),
    runtime_id = COALESCE($7, runtime_id),
    visibility = COALESCE($8, visibility),
    status = COALESCE($9, status),
    max_concurrent_tasks = COALESCE($10, max_concurrent_tasks),
    tools = COALESCE($11, tools),
    triggers = COALESCE($12, triggers),
    instructions = COALESCE($13, instructions),
    updated_at = now()
WHERE id = $1
RETURNING id, workspace_id, name, avatar_url, runtime_mode, runtime_config, visibility, status, max_concurrent_tasks, owner_id, created_at, updated_at, description, tools, triggers, runtime_id, instructions, archived_at, archived_by
`

type UpdateAgentParams struct {
	ID                 pgtype.UUID `json:"id"`
	Name               pgtype.Text `json:"name"`
	Description        pgtype.Text `json:"description"`
	AvatarUrl          pgtype.Text `json:"avatar_url"`
	RuntimeConfig      []byte      `json:"runtime_config"`
	RuntimeMode        pgtype.Text `json:"runtime_mode"`
	RuntimeID          pgtype.UUID `json:"runtime_id"`
	Visibility         pgtype.Text `json:"visibility"`
	Status             pgtype.Text `json:"status"`
	MaxConcurrentTasks pgtype.Int4 `json:"max_concurrent_tasks"`
	Tools              []byte      `json:"tools"`
	Triggers           []byte      `json:"triggers"`
	Instructions       pgtype.Text `json:"instructions"`
}

func (q *Queries) UpdateAgent(ctx context.Context, arg UpdateAgentParams) (Agent, error) {
	row := q.db.QueryRow(ctx, updateAgent,
		arg.ID,
		arg.Name,
		arg.Description,
		arg.AvatarUrl,
		arg.RuntimeConfig,
		arg.RuntimeMode,
		arg.RuntimeID,
		arg.Visibility,
		arg.Status,
		arg.MaxConcurrentTasks,
		arg.Tools,
		arg.Triggers,
		arg.Instructions,
	)
	var i Agent
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.Name,
		&i.AvatarUrl,
		&i.RuntimeMode,
		&i.RuntimeConfig,
		&i.Visibility,
		&i.Status,
		&i.MaxConcurrentTasks,
		&i.OwnerID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Description,
		&i.Tools,
		&i.Triggers,
		&i.RuntimeID,
		&i.Instructions,
		&i.ArchivedAt,
		&i.ArchivedBy,
	)
	return i, err
}

const updateAgentStatus = `-- name: UpdateAgentStatus :one
UPDATE agent SET status = $2, updated_at = now()
WHERE id = $1
RETURNING id, workspace_id, name, avatar_url, runtime_mode, runtime_config, visibility, status, max_concurrent_tasks, owner_id, created_at, updated_at, description, tools, triggers, runtime_id, instructions, archived_at, archived_by
`

type UpdateAgentStatusParams struct {
	ID     pgtype.UUID `json:"id"`
	Status string      `json:"status"`
}

func (q *Queries) UpdateAgentStatus(ctx context.Context, arg UpdateAgentStatusParams) (Agent, error) {
	row := q.db.QueryRow(ctx, updateAgentStatus, arg.ID, arg.Status)
	var i Agent
	err := row.Scan(
		&i.ID,
		&i.WorkspaceID,
		&i.Name,
		&i.AvatarUrl,
		&i.RuntimeMode,
		&i.RuntimeConfig,
		&i.Visibility,
		&i.Status,
		&i.MaxConcurrentTasks,
		&i.OwnerID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Description,
		&i.Tools,
		&i.Triggers,
		&i.RuntimeID,
		&i.Instructions,
		&i.ArchivedAt,
		&i.ArchivedBy,
	)
	return i, err
}
