// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.27.0
// source: flows.sql

package database

import (
	"context"
	"database/sql"
	"encoding/json"
	"time"
)

const createFlow = `-- name: CreateFlow :one
INSERT INTO flows (
  title, status, model, model_provider_name, model_provider_type, language, tool_call_id_template, functions, user_id
)
VALUES (
  $1, $2, $3, $4, $5, $6, $7, $8, $9
)
RETURNING id, status, title, model, model_provider_name, language, functions, user_id, created_at, updated_at, deleted_at, trace_id, model_provider_type, tool_call_id_template
`

type CreateFlowParams struct {
	Title              string          `json:"title"`
	Status             FlowStatus      `json:"status"`
	Model              string          `json:"model"`
	ModelProviderName  string          `json:"model_provider_name"`
	ModelProviderType  ProviderType    `json:"model_provider_type"`
	Language           string          `json:"language"`
	ToolCallIDTemplate string          `json:"tool_call_id_template"`
	Functions          json.RawMessage `json:"functions"`
	UserID             int64           `json:"user_id"`
}

func (q *Queries) CreateFlow(ctx context.Context, arg CreateFlowParams) (Flow, error) {
	row := q.db.QueryRowContext(ctx, createFlow,
		arg.Title,
		arg.Status,
		arg.Model,
		arg.ModelProviderName,
		arg.ModelProviderType,
		arg.Language,
		arg.ToolCallIDTemplate,
		arg.Functions,
		arg.UserID,
	)
	var i Flow
	err := row.Scan(
		&i.ID,
		&i.Status,
		&i.Title,
		&i.Model,
		&i.ModelProviderName,
		&i.Language,
		&i.Functions,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.DeletedAt,
		&i.TraceID,
		&i.ModelProviderType,
		&i.ToolCallIDTemplate,
	)
	return i, err
}

const deleteFlow = `-- name: DeleteFlow :one
UPDATE flows
SET deleted_at = CURRENT_TIMESTAMP
WHERE id = $1
RETURNING id, status, title, model, model_provider_name, language, functions, user_id, created_at, updated_at, deleted_at, trace_id, model_provider_type, tool_call_id_template
`

func (q *Queries) DeleteFlow(ctx context.Context, id int64) (Flow, error) {
	row := q.db.QueryRowContext(ctx, deleteFlow, id)
	var i Flow
	err := row.Scan(
		&i.ID,
		&i.Status,
		&i.Title,
		&i.Model,
		&i.ModelProviderName,
		&i.Language,
		&i.Functions,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.DeletedAt,
		&i.TraceID,
		&i.ModelProviderType,
		&i.ToolCallIDTemplate,
	)
	return i, err
}

const getFlow = `-- name: GetFlow :one
SELECT
  f.id, f.status, f.title, f.model, f.model_provider_name, f.language, f.functions, f.user_id, f.created_at, f.updated_at, f.deleted_at, f.trace_id, f.model_provider_type, f.tool_call_id_template
FROM flows f
WHERE f.id = $1 AND f.deleted_at IS NULL
`

func (q *Queries) GetFlow(ctx context.Context, id int64) (Flow, error) {
	row := q.db.QueryRowContext(ctx, getFlow, id)
	var i Flow
	err := row.Scan(
		&i.ID,
		&i.Status,
		&i.Title,
		&i.Model,
		&i.ModelProviderName,
		&i.Language,
		&i.Functions,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.DeletedAt,
		&i.TraceID,
		&i.ModelProviderType,
		&i.ToolCallIDTemplate,
	)
	return i, err
}

const getFlowStats = `-- name: GetFlowStats :one

SELECT
  COALESCE(COUNT(DISTINCT t.id), 0)::bigint AS total_tasks_count,
  COALESCE(COUNT(DISTINCT s.id), 0)::bigint AS total_subtasks_count,
  COALESCE(COUNT(DISTINCT a.id), 0)::bigint AS total_assistants_count
FROM flows f
LEFT JOIN tasks t ON f.id = t.flow_id
LEFT JOIN subtasks s ON t.id = s.task_id
LEFT JOIN assistants a ON f.id = a.flow_id AND a.deleted_at IS NULL
WHERE f.id = $1 AND f.deleted_at IS NULL
`

type GetFlowStatsRow struct {
	TotalTasksCount      int64 `json:"total_tasks_count"`
	TotalSubtasksCount   int64 `json:"total_subtasks_count"`
	TotalAssistantsCount int64 `json:"total_assistants_count"`
}

// ==================== Flows Analytics Queries ====================
// Get total count of tasks, subtasks, and assistants for a specific flow
func (q *Queries) GetFlowStats(ctx context.Context, id int64) (GetFlowStatsRow, error) {
	row := q.db.QueryRowContext(ctx, getFlowStats, id)
	var i GetFlowStatsRow
	err := row.Scan(&i.TotalTasksCount, &i.TotalSubtasksCount, &i.TotalAssistantsCount)
	return i, err
}

const getFlows = `-- name: GetFlows :many
SELECT
  f.id, f.status, f.title, f.model, f.model_provider_name, f.language, f.functions, f.user_id, f.created_at, f.updated_at, f.deleted_at, f.trace_id, f.model_provider_type, f.tool_call_id_template
FROM flows f
WHERE f.deleted_at IS NULL
ORDER BY f.created_at DESC
`

func (q *Queries) GetFlows(ctx context.Context) ([]Flow, error) {
	rows, err := q.db.QueryContext(ctx, getFlows)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []Flow
	for rows.Next() {
		var i Flow
		if err := rows.Scan(
			&i.ID,
			&i.Status,
			&i.Title,
			&i.Model,
			&i.ModelProviderName,
			&i.Language,
			&i.Functions,
			&i.UserID,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.DeletedAt,
			&i.TraceID,
			&i.ModelProviderType,
			&i.ToolCallIDTemplate,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getFlowsStatsByDay = `-- name: GetFlowsStatsByDay :many
WITH bounds AS (
  SELECT
    ((NOW() AT TIME ZONE $1::text)::date - $2::int) AS first_day,
    (NOW() AT TIME ZONE $1::text)::date AS last_day
),
days AS (
  SELECT generate_series(b.first_day, b.last_day, INTERVAL '1 day')::date AS day
  FROM bounds b
),
agg AS (
  SELECT
    (f.created_at AT TIME ZONE $1::text)::date AS day,
    COUNT(DISTINCT f.id)::bigint AS total_flows_count,
    COUNT(DISTINCT t.id)::bigint AS total_tasks_count,
    COUNT(DISTINCT s.id)::bigint AS total_subtasks_count,
    COUNT(DISTINCT a.id)::bigint AS total_assistants_count
  FROM flows f
  LEFT JOIN tasks t ON f.id = t.flow_id
  LEFT JOIN subtasks s ON t.id = s.task_id
  LEFT JOIN assistants a ON f.id = a.flow_id AND a.deleted_at IS NULL
  WHERE f.deleted_at IS NULL
    AND f.user_id = $3
    -- The coarse bounds keep the index; the exact test repeats the grouping
    -- expression, because an ambiguous local midnight resolves to the later
    -- instant and would drop the earlier hour of that day.
    AND f.created_at >= (((SELECT first_day FROM bounds) - 1)::timestamp AT TIME ZONE $1::text)
    AND f.created_at < (((SELECT last_day FROM bounds) + 2)::timestamp AT TIME ZONE $1::text)
    AND (f.created_at AT TIME ZONE $1::text)::date
        BETWEEN (SELECT first_day FROM bounds) AND (SELECT last_day FROM bounds)
  GROUP BY 1
)
SELECT
  (d.day::timestamp AT TIME ZONE $1::text) AS date,
  COALESCE(a.total_flows_count, 0)::bigint AS total_flows_count,
  COALESCE(a.total_tasks_count, 0)::bigint AS total_tasks_count,
  COALESCE(a.total_subtasks_count, 0)::bigint AS total_subtasks_count,
  COALESCE(a.total_assistants_count, 0)::bigint AS total_assistants_count
FROM days d
LEFT JOIN agg a ON a.day = d.day
ORDER BY date DESC
`

type GetFlowsStatsByDayParams struct {
	Tz     string `json:"tz"`
	Days   int32  `json:"days"`
	UserID int64  `json:"user_id"`
}

type GetFlowsStatsByDayRow struct {
	Date                 time.Time `json:"date"`
	TotalFlowsCount      int64     `json:"total_flows_count"`
	TotalTasksCount      int64     `json:"total_tasks_count"`
	TotalSubtasksCount   int64     `json:"total_subtasks_count"`
	TotalAssistantsCount int64     `json:"total_assistants_count"`
}

// One dense row per calendar day in the caller's timezone, zeros included.
func (q *Queries) GetFlowsStatsByDay(ctx context.Context, arg GetFlowsStatsByDayParams) ([]GetFlowsStatsByDayRow, error) {
	rows, err := q.db.QueryContext(ctx, getFlowsStatsByDay, arg.Tz, arg.Days, arg.UserID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []GetFlowsStatsByDayRow
	for rows.Next() {
		var i GetFlowsStatsByDayRow
		if err := rows.Scan(
			&i.Date,
			&i.TotalFlowsCount,
			&i.TotalTasksCount,
			&i.TotalSubtasksCount,
			&i.TotalAssistantsCount,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getUserFlow = `-- name: GetUserFlow :one
SELECT
  f.id, f.status, f.title, f.model, f.model_provider_name, f.language, f.functions, f.user_id, f.created_at, f.updated_at, f.deleted_at, f.trace_id, f.model_provider_type, f.tool_call_id_template
FROM flows f
INNER JOIN users u ON f.user_id = u.id
WHERE f.id = $1 AND f.user_id = $2 AND f.deleted_at IS NULL
`

type GetUserFlowParams struct {
	ID     int64 `json:"id"`
	UserID int64 `json:"user_id"`
}

func (q *Queries) GetUserFlow(ctx context.Context, arg GetUserFlowParams) (Flow, error) {
	row := q.db.QueryRowContext(ctx, getUserFlow, arg.ID, arg.UserID)
	var i Flow
	err := row.Scan(
		&i.ID,
		&i.Status,
		&i.Title,
		&i.Model,
		&i.ModelProviderName,
		&i.Language,
		&i.Functions,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.DeletedAt,
		&i.TraceID,
		&i.ModelProviderType,
		&i.ToolCallIDTemplate,
	)
	return i, err
}

const getUserFlows = `-- name: GetUserFlows :many
SELECT
  f.id, f.status, f.title, f.model, f.model_provider_name, f.language, f.functions, f.user_id, f.created_at, f.updated_at, f.deleted_at, f.trace_id, f.model_provider_type, f.tool_call_id_template
FROM flows f
INNER JOIN users u ON f.user_id = u.id
WHERE f.user_id = $1 AND f.deleted_at IS NULL
ORDER BY f.created_at DESC
`

func (q *Queries) GetUserFlows(ctx context.Context, userID int64) ([]Flow, error) {
	rows, err := q.db.QueryContext(ctx, getUserFlows, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []Flow
	for rows.Next() {
		var i Flow
		if err := rows.Scan(
			&i.ID,
			&i.Status,
			&i.Title,
			&i.Model,
			&i.ModelProviderName,
			&i.Language,
			&i.Functions,
			&i.UserID,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.DeletedAt,
			&i.TraceID,
			&i.ModelProviderType,
			&i.ToolCallIDTemplate,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getUserTotalFlowsStats = `-- name: GetUserTotalFlowsStats :one
SELECT
  COALESCE(COUNT(DISTINCT f.id), 0)::bigint AS total_flows_count,
  COALESCE(COUNT(DISTINCT t.id), 0)::bigint AS total_tasks_count,
  COALESCE(COUNT(DISTINCT s.id), 0)::bigint AS total_subtasks_count,
  COALESCE(COUNT(DISTINCT a.id), 0)::bigint AS total_assistants_count
FROM flows f
LEFT JOIN tasks t ON f.id = t.flow_id
LEFT JOIN subtasks s ON t.id = s.task_id
LEFT JOIN assistants a ON f.id = a.flow_id AND a.deleted_at IS NULL
WHERE f.user_id = $1 AND f.deleted_at IS NULL
`

type GetUserTotalFlowsStatsRow struct {
	TotalFlowsCount      int64 `json:"total_flows_count"`
	TotalTasksCount      int64 `json:"total_tasks_count"`
	TotalSubtasksCount   int64 `json:"total_subtasks_count"`
	TotalAssistantsCount int64 `json:"total_assistants_count"`
}

// Get total count of flows, tasks, subtasks, and assistants for a user
func (q *Queries) GetUserTotalFlowsStats(ctx context.Context, userID int64) (GetUserTotalFlowsStatsRow, error) {
	row := q.db.QueryRowContext(ctx, getUserTotalFlowsStats, userID)
	var i GetUserTotalFlowsStatsRow
	err := row.Scan(
		&i.TotalFlowsCount,
		&i.TotalTasksCount,
		&i.TotalSubtasksCount,
		&i.TotalAssistantsCount,
	)
	return i, err
}

const updateFlow = `-- name: UpdateFlow :one
UPDATE flows
SET title = $1, model = $2, language = $3, tool_call_id_template = $4, functions = $5, trace_id = $6
WHERE id = $7
RETURNING id, status, title, model, model_provider_name, language, functions, user_id, created_at, updated_at, deleted_at, trace_id, model_provider_type, tool_call_id_template
`

type UpdateFlowParams struct {
	Title              string          `json:"title"`
	Model              string          `json:"model"`
	Language           string          `json:"language"`
	ToolCallIDTemplate string          `json:"tool_call_id_template"`
	Functions          json.RawMessage `json:"functions"`
	TraceID            sql.NullString  `json:"trace_id"`
	ID                 int64           `json:"id"`
}

func (q *Queries) UpdateFlow(ctx context.Context, arg UpdateFlowParams) (Flow, error) {
	row := q.db.QueryRowContext(ctx, updateFlow,
		arg.Title,
		arg.Model,
		arg.Language,
		arg.ToolCallIDTemplate,
		arg.Functions,
		arg.TraceID,
		arg.ID,
	)
	var i Flow
	err := row.Scan(
		&i.ID,
		&i.Status,
		&i.Title,
		&i.Model,
		&i.ModelProviderName,
		&i.Language,
		&i.Functions,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.DeletedAt,
		&i.TraceID,
		&i.ModelProviderType,
		&i.ToolCallIDTemplate,
	)
	return i, err
}

const updateFlowLanguage = `-- name: UpdateFlowLanguage :one
UPDATE flows
SET language = $1
WHERE id = $2
RETURNING id, status, title, model, model_provider_name, language, functions, user_id, created_at, updated_at, deleted_at, trace_id, model_provider_type, tool_call_id_template
`

type UpdateFlowLanguageParams struct {
	Language string `json:"language"`
	ID       int64  `json:"id"`
}

func (q *Queries) UpdateFlowLanguage(ctx context.Context, arg UpdateFlowLanguageParams) (Flow, error) {
	row := q.db.QueryRowContext(ctx, updateFlowLanguage, arg.Language, arg.ID)
	var i Flow
	err := row.Scan(
		&i.ID,
		&i.Status,
		&i.Title,
		&i.Model,
		&i.ModelProviderName,
		&i.Language,
		&i.Functions,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.DeletedAt,
		&i.TraceID,
		&i.ModelProviderType,
		&i.ToolCallIDTemplate,
	)
	return i, err
}

const updateFlowProvider = `-- name: UpdateFlowProvider :one
UPDATE flows
SET model_provider_name = $1, model_provider_type = $2, tool_call_id_template = $3, model = $4
WHERE id = $5
RETURNING id, status, title, model, model_provider_name, language, functions, user_id, created_at, updated_at, deleted_at, trace_id, model_provider_type, tool_call_id_template
`

type UpdateFlowProviderParams struct {
	ModelProviderName  string       `json:"model_provider_name"`
	ModelProviderType  ProviderType `json:"model_provider_type"`
	ToolCallIDTemplate string       `json:"tool_call_id_template"`
	Model              string       `json:"model"`
	ID                 int64        `json:"id"`
}

func (q *Queries) UpdateFlowProvider(ctx context.Context, arg UpdateFlowProviderParams) (Flow, error) {
	row := q.db.QueryRowContext(ctx, updateFlowProvider,
		arg.ModelProviderName,
		arg.ModelProviderType,
		arg.ToolCallIDTemplate,
		arg.Model,
		arg.ID,
	)
	var i Flow
	err := row.Scan(
		&i.ID,
		&i.Status,
		&i.Title,
		&i.Model,
		&i.ModelProviderName,
		&i.Language,
		&i.Functions,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.DeletedAt,
		&i.TraceID,
		&i.ModelProviderType,
		&i.ToolCallIDTemplate,
	)
	return i, err
}

const updateFlowStatus = `-- name: UpdateFlowStatus :one
UPDATE flows
SET status = $1
WHERE id = $2
RETURNING id, status, title, model, model_provider_name, language, functions, user_id, created_at, updated_at, deleted_at, trace_id, model_provider_type, tool_call_id_template
`

type UpdateFlowStatusParams struct {
	Status FlowStatus `json:"status"`
	ID     int64      `json:"id"`
}

func (q *Queries) UpdateFlowStatus(ctx context.Context, arg UpdateFlowStatusParams) (Flow, error) {
	row := q.db.QueryRowContext(ctx, updateFlowStatus, arg.Status, arg.ID)
	var i Flow
	err := row.Scan(
		&i.ID,
		&i.Status,
		&i.Title,
		&i.Model,
		&i.ModelProviderName,
		&i.Language,
		&i.Functions,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.DeletedAt,
		&i.TraceID,
		&i.ModelProviderType,
		&i.ToolCallIDTemplate,
	)
	return i, err
}

const updateFlowTitle = `-- name: UpdateFlowTitle :one
UPDATE flows
SET title = $1
WHERE id = $2
RETURNING id, status, title, model, model_provider_name, language, functions, user_id, created_at, updated_at, deleted_at, trace_id, model_provider_type, tool_call_id_template
`

type UpdateFlowTitleParams struct {
	Title string `json:"title"`
	ID    int64  `json:"id"`
}

func (q *Queries) UpdateFlowTitle(ctx context.Context, arg UpdateFlowTitleParams) (Flow, error) {
	row := q.db.QueryRowContext(ctx, updateFlowTitle, arg.Title, arg.ID)
	var i Flow
	err := row.Scan(
		&i.ID,
		&i.Status,
		&i.Title,
		&i.Model,
		&i.ModelProviderName,
		&i.Language,
		&i.Functions,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.DeletedAt,
		&i.TraceID,
		&i.ModelProviderType,
		&i.ToolCallIDTemplate,
	)
	return i, err
}

const updateFlowToolCallIDTemplate = `-- name: UpdateFlowToolCallIDTemplate :one
UPDATE flows
SET tool_call_id_template = $1
WHERE id = $2
RETURNING id, status, title, model, model_provider_name, language, functions, user_id, created_at, updated_at, deleted_at, trace_id, model_provider_type, tool_call_id_template
`

type UpdateFlowToolCallIDTemplateParams struct {
	ToolCallIDTemplate string `json:"tool_call_id_template"`
	ID                 int64  `json:"id"`
}

func (q *Queries) UpdateFlowToolCallIDTemplate(ctx context.Context, arg UpdateFlowToolCallIDTemplateParams) (Flow, error) {
	row := q.db.QueryRowContext(ctx, updateFlowToolCallIDTemplate, arg.ToolCallIDTemplate, arg.ID)
	var i Flow
	err := row.Scan(
		&i.ID,
		&i.Status,
		&i.Title,
		&i.Model,
		&i.ModelProviderName,
		&i.Language,
		&i.Functions,
		&i.UserID,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.DeletedAt,
		&i.TraceID,
		&i.ModelProviderType,
		&i.ToolCallIDTemplate,
	)
	return i, err
}

const updateFlowsProviderNameByOldName = `-- name: UpdateFlowsProviderNameByOldName :many
UPDATE flows
SET model_provider_name = $1
WHERE user_id = $2 AND model_provider_name = $3 AND deleted_at IS NULL
RETURNING id, status, title, model, model_provider_name, language, functions, user_id, created_at, updated_at, deleted_at, trace_id, model_provider_type, tool_call_id_template
`

type UpdateFlowsProviderNameByOldNameParams struct {
	NewName string `json:"new_name"`
	UserID  int64  `json:"user_id"`
	OldName string `json:"old_name"`
}

// Bulk-renames every flow row of a user still pointing at a provider's old name
// (the user renamed a custom LLM provider, or deleted one and the reference is
// reset to the built-in name of its type). Matching on old_name makes the
// statement idempotent: once rewritten, a row no longer matches, so it is safe
// to call unconditionally and to retry.
func (q *Queries) UpdateFlowsProviderNameByOldName(ctx context.Context, arg UpdateFlowsProviderNameByOldNameParams) ([]Flow, error) {
	rows, err := q.db.QueryContext(ctx, updateFlowsProviderNameByOldName, arg.NewName, arg.UserID, arg.OldName)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []Flow
	for rows.Next() {
		var i Flow
		if err := rows.Scan(
			&i.ID,
			&i.Status,
			&i.Title,
			&i.Model,
			&i.ModelProviderName,
			&i.Language,
			&i.Functions,
			&i.UserID,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.DeletedAt,
			&i.TraceID,
			&i.ModelProviderType,
			&i.ToolCallIDTemplate,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Close(); err != nil {
		return nil, err
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}
