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

package database

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

	"github.com/google/uuid"
	"github.com/sqlc-dev/pqtype"
)

const deleteFlowMemoryDocuments = `-- name: DeleteFlowMemoryDocuments :exec
DELETE FROM langchain_pg_embedding
WHERE collection_id = (SELECT uuid FROM langchain_pg_collection WHERE name = 'langchain')
  AND COALESCE(cmetadata ->> 'doc_type', '') = 'memory'
  AND (cmetadata ->> 'flow_id') = $1
`

// Delete all memory-type documents for a specific flow.
// Called on flow deletion to free long-term memory that will never be re-used.
// flow_id is the decimal text representation of the flow ID (e.g. "55"), matching the
// text result of (cmetadata ->> 'flow_id') which uses JSON ->> extraction.
func (q *Queries) DeleteFlowMemoryDocuments(ctx context.Context, flowID sql.NullString) error {
	_, err := q.db.ExecContext(ctx, deleteFlowMemoryDocuments, flowID)
	return err
}

const deleteKnowledgeDocument = `-- name: DeleteKnowledgeDocument :exec
DELETE FROM langchain_pg_embedding
WHERE uuid::text = $1
  AND collection_id = (SELECT uuid FROM langchain_pg_collection WHERE name = 'langchain')
`

// Delete a knowledge document by UUID (admin — no user_id check).
func (q *Queries) DeleteKnowledgeDocument(ctx context.Context, argUuid sql.NullString) error {
	_, err := q.db.ExecContext(ctx, deleteKnowledgeDocument, argUuid)
	return err
}

const deleteUserKnowledgeDocument = `-- name: DeleteUserKnowledgeDocument :exec
DELETE FROM langchain_pg_embedding
WHERE uuid::text = $1
  AND (cmetadata ->> 'user_id') = $2
  AND collection_id = (SELECT uuid FROM langchain_pg_collection WHERE name = 'langchain')
`

type DeleteUserKnowledgeDocumentParams struct {
	Uuid   sql.NullString `json:"uuid"`
	UserID sql.NullString `json:"user_id"`
}

// Delete a knowledge document by UUID, only if it belongs to the given user.
func (q *Queries) DeleteUserKnowledgeDocument(ctx context.Context, arg DeleteUserKnowledgeDocumentParams) error {
	_, err := q.db.ExecContext(ctx, deleteUserKnowledgeDocument, arg.Uuid, arg.UserID)
	return err
}

const getKnowledgeDocument = `-- name: GetKnowledgeDocument :one
SELECT
  e.uuid::text                              AS id,
  COALESCE(e.document, '')                  AS document,
  COALESCE(e.cmetadata::text, '{}')         AS cmetadata
FROM langchain_pg_embedding e
INNER JOIN langchain_pg_collection c ON e.collection_id = c.uuid
WHERE c.name = 'langchain'
  AND e.uuid::text = $1
`

type GetKnowledgeDocumentRow struct {
	ID        string         `json:"id"`
	Document  string         `json:"document"`
	Cmetadata sql.NullString `json:"cmetadata"`
}

// Fetch a single knowledge document by its UUID (admin view — no user_id check).
func (q *Queries) GetKnowledgeDocument(ctx context.Context, argUuid string) (GetKnowledgeDocumentRow, error) {
	row := q.db.QueryRowContext(ctx, getKnowledgeDocument, argUuid)
	var i GetKnowledgeDocumentRow
	err := row.Scan(&i.ID, &i.Document, &i.Cmetadata)
	return i, err
}

const getUserKnowledgeDocument = `-- name: GetUserKnowledgeDocument :one
SELECT
  e.uuid::text                              AS id,
  COALESCE(e.document, '')                  AS document,
  COALESCE(e.cmetadata::text, '{}')         AS cmetadata
FROM langchain_pg_embedding e
INNER JOIN langchain_pg_collection c ON e.collection_id = c.uuid
WHERE c.name = 'langchain'
  AND e.uuid::text = $1
  AND (e.cmetadata ->> 'user_id') = $2
`

type GetUserKnowledgeDocumentParams struct {
	Uuid   string         `json:"uuid"`
	UserID sql.NullString `json:"user_id"`
}

type GetUserKnowledgeDocumentRow struct {
	ID        string         `json:"id"`
	Document  string         `json:"document"`
	Cmetadata sql.NullString `json:"cmetadata"`
}

// Fetch a single knowledge document by UUID, scoped to a specific user.
func (q *Queries) GetUserKnowledgeDocument(ctx context.Context, arg GetUserKnowledgeDocumentParams) (GetUserKnowledgeDocumentRow, error) {
	row := q.db.QueryRowContext(ctx, getUserKnowledgeDocument, arg.Uuid, arg.UserID)
	var i GetUserKnowledgeDocumentRow
	err := row.Scan(&i.ID, &i.Document, &i.Cmetadata)
	return i, err
}

const insertKnowledgeDocument = `-- name: InsertKnowledgeDocument :one
INSERT INTO langchain_pg_embedding (uuid, document, embedding, cmetadata, collection_id)
SELECT
  $1::uuid,
  $2,
  $3::vector,
  $4::json,
  c.uuid
FROM langchain_pg_collection c
WHERE c.name = 'langchain'
RETURNING uuid::text AS id
`

type InsertKnowledgeDocumentParams struct {
	Uuid      uuid.UUID       `json:"uuid"`
	Document  sql.NullString  `json:"document"`
	Embedding interface{}     `json:"embedding"`
	Cmetadata json.RawMessage `json:"cmetadata"`
}

// Insert a document with a pre-computed embedding vector and return its UUID.
// embedding must be formatted as a PostgreSQL vector literal: '[f1,f2,...]'
// cmetadata must be valid JSON text.
func (q *Queries) InsertKnowledgeDocument(ctx context.Context, arg InsertKnowledgeDocumentParams) (string, error) {
	row := q.db.QueryRowContext(ctx, insertKnowledgeDocument,
		arg.Uuid,
		arg.Document,
		arg.Embedding,
		arg.Cmetadata,
	)
	var id string
	err := row.Scan(&id)
	return id, err
}

const listAllKnowledgeDocuments = `-- name: ListAllKnowledgeDocuments :many
SELECT
  e.uuid::text                              AS id,
  COALESCE(e.document, '')                  AS document,
  COALESCE(e.cmetadata::text, '{}')         AS cmetadata
FROM langchain_pg_embedding e
INNER JOIN langchain_pg_collection c ON e.collection_id = c.uuid
WHERE c.name = 'langchain'
  AND COALESCE(e.cmetadata ->> 'doc_type', '') NOT IN ('memory')
ORDER BY e.uuid
`

type ListAllKnowledgeDocumentsRow struct {
	ID        string         `json:"id"`
	Document  string         `json:"document"`
	Cmetadata sql.NullString `json:"cmetadata"`
}

// List all knowledge documents excluding the noisy memory type (admin view).
func (q *Queries) ListAllKnowledgeDocuments(ctx context.Context) ([]ListAllKnowledgeDocumentsRow, error) {
	rows, err := q.db.QueryContext(ctx, listAllKnowledgeDocuments)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListAllKnowledgeDocumentsRow
	for rows.Next() {
		var i ListAllKnowledgeDocumentsRow
		if err := rows.Scan(&i.ID, &i.Document, &i.Cmetadata); 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 listFlowKnowledgeDocuments = `-- name: ListFlowKnowledgeDocuments :many
SELECT
  e.uuid::text                              AS id,
  COALESCE(e.document, '')                  AS document,
  COALESCE(e.cmetadata::text, '{}')         AS cmetadata
FROM langchain_pg_embedding e
INNER JOIN langchain_pg_collection c ON e.collection_id = c.uuid
WHERE c.name = 'langchain'
  AND COALESCE(e.cmetadata ->> 'doc_type', '') NOT IN ('memory')
  AND (e.cmetadata ->> 'flow_id') = $1
ORDER BY e.uuid
`

type ListFlowKnowledgeDocumentsRow struct {
	ID        string         `json:"id"`
	Document  string         `json:"document"`
	Cmetadata sql.NullString `json:"cmetadata"`
}

// List non-memory knowledge documents belonging to a specific flow (admin scoped).
func (q *Queries) ListFlowKnowledgeDocuments(ctx context.Context, flowID sql.NullString) ([]ListFlowKnowledgeDocumentsRow, error) {
	rows, err := q.db.QueryContext(ctx, listFlowKnowledgeDocuments, flowID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListFlowKnowledgeDocumentsRow
	for rows.Next() {
		var i ListFlowKnowledgeDocumentsRow
		if err := rows.Scan(&i.ID, &i.Document, &i.Cmetadata); 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 listUserKnowledgeDocuments = `-- name: ListUserKnowledgeDocuments :many
SELECT
  e.uuid::text                              AS id,
  COALESCE(e.document, '')                  AS document,
  COALESCE(e.cmetadata::text, '{}')         AS cmetadata
FROM langchain_pg_embedding e
INNER JOIN langchain_pg_collection c ON e.collection_id = c.uuid
WHERE c.name = 'langchain'
  AND COALESCE(e.cmetadata ->> 'doc_type', '') NOT IN ('memory')
  AND (e.cmetadata ->> 'user_id') = $1
ORDER BY e.uuid
`

type ListUserKnowledgeDocumentsRow struct {
	ID        string         `json:"id"`
	Document  string         `json:"document"`
	Cmetadata sql.NullString `json:"cmetadata"`
}

// List all non-memory knowledge documents owned by a specific user (user-scoped view).
func (q *Queries) ListUserKnowledgeDocuments(ctx context.Context, userID sql.NullString) ([]ListUserKnowledgeDocumentsRow, error) {
	rows, err := q.db.QueryContext(ctx, listUserKnowledgeDocuments, userID)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []ListUserKnowledgeDocumentsRow
	for rows.Next() {
		var i ListUserKnowledgeDocumentsRow
		if err := rows.Scan(&i.ID, &i.Document, &i.Cmetadata); 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 searchKnowledgeDocuments = `-- name: SearchKnowledgeDocuments :many
SELECT
  e.uuid::text                                                         AS id,
  COALESCE(e.document, '')                                             AS document,
  COALESCE(e.cmetadata::text, '{}')                                   AS cmetadata,
  (1.0 - (e.embedding <=> $1::vector))::float8       AS score
FROM langchain_pg_embedding e
INNER JOIN langchain_pg_collection c ON e.collection_id = c.uuid
WHERE c.name = 'langchain'
  AND COALESCE(e.cmetadata ->> 'doc_type', '') NOT IN ('memory')
  AND (e.embedding <=> $1::vector)::float8 < $2::float8
ORDER BY e.embedding <=> $1::vector
LIMIT $3::int
`

type SearchKnowledgeDocumentsParams struct {
	Embedding   interface{} `json:"embedding"`
	MaxDistance float64     `json:"max_distance"`
	Lim         int32       `json:"lim"`
}

type SearchKnowledgeDocumentsRow struct {
	ID        string         `json:"id"`
	Document  string         `json:"document"`
	Cmetadata sql.NullString `json:"cmetadata"`
	Score     float64        `json:"score"`
}

// Vector similarity search over all knowledge documents (admin view, no user filter).
// Returns rows ordered by cosine similarity descending (highest score first).
// embedding    query vector as a PostgreSQL vector literal, e.g. '[0.1,0.2,...]'
// max_distance cosine-distance upper bound (exclusive); equals (1 - score_threshold),
//
//	e.g. pass 0.8 to get documents with similarity score > 0.2
//
// lim          maximum number of rows to return
func (q *Queries) SearchKnowledgeDocuments(ctx context.Context, arg SearchKnowledgeDocumentsParams) ([]SearchKnowledgeDocumentsRow, error) {
	rows, err := q.db.QueryContext(ctx, searchKnowledgeDocuments, arg.Embedding, arg.MaxDistance, arg.Lim)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []SearchKnowledgeDocumentsRow
	for rows.Next() {
		var i SearchKnowledgeDocumentsRow
		if err := rows.Scan(
			&i.ID,
			&i.Document,
			&i.Cmetadata,
			&i.Score,
		); 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 searchUserKnowledgeDocuments = `-- name: SearchUserKnowledgeDocuments :many
SELECT
  e.uuid::text                                                         AS id,
  COALESCE(e.document, '')                                             AS document,
  COALESCE(e.cmetadata::text, '{}')                                   AS cmetadata,
  (1.0 - (e.embedding <=> $1::vector))::float8       AS score
FROM langchain_pg_embedding e
INNER JOIN langchain_pg_collection c ON e.collection_id = c.uuid
WHERE c.name = 'langchain'
  AND COALESCE(e.cmetadata ->> 'doc_type', '') NOT IN ('memory')
  AND (e.cmetadata ->> 'user_id') = $2
  AND (e.embedding <=> $1::vector)::float8 < $3::float8
ORDER BY e.embedding <=> $1::vector
LIMIT $4::int
`

type SearchUserKnowledgeDocumentsParams struct {
	Embedding   interface{}    `json:"embedding"`
	UserID      sql.NullString `json:"user_id"`
	MaxDistance float64        `json:"max_distance"`
	Lim         int32          `json:"lim"`
}

type SearchUserKnowledgeDocumentsRow struct {
	ID        string         `json:"id"`
	Document  string         `json:"document"`
	Cmetadata sql.NullString `json:"cmetadata"`
	Score     float64        `json:"score"`
}

// Vector similarity search scoped to a specific user (by cmetadata user_id).
// Returns rows ordered by cosine similarity descending (highest score first).
// embedding    query vector as a PostgreSQL vector literal, e.g. '[0.1,0.2,...]'
// max_distance cosine-distance upper bound (exclusive); equals (1 - score_threshold)
// lim          maximum number of rows to return
// user_id      owner filter as a decimal text string (e.g. "42")
func (q *Queries) SearchUserKnowledgeDocuments(ctx context.Context, arg SearchUserKnowledgeDocumentsParams) ([]SearchUserKnowledgeDocumentsRow, error) {
	rows, err := q.db.QueryContext(ctx, searchUserKnowledgeDocuments,
		arg.Embedding,
		arg.UserID,
		arg.MaxDistance,
		arg.Lim,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []SearchUserKnowledgeDocumentsRow
	for rows.Next() {
		var i SearchUserKnowledgeDocumentsRow
		if err := rows.Scan(
			&i.ID,
			&i.Document,
			&i.Cmetadata,
			&i.Score,
		); 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 updateKnowledgeDocument = `-- name: UpdateKnowledgeDocument :one
UPDATE langchain_pg_embedding
SET
  embedding = $1::vector,
  document  = $2,
  cmetadata = $3::json
WHERE uuid::text = $4
  AND collection_id = (SELECT uuid FROM langchain_pg_collection WHERE name = 'langchain')
RETURNING
  uuid::text                              AS id,
  COALESCE(document, '')                  AS document,
  COALESCE(cmetadata::text, '{}')         AS cmetadata
`

type UpdateKnowledgeDocumentParams struct {
	Embedding string                `json:"embedding"`
	Document  sql.NullString        `json:"document"`
	Cmetadata pqtype.NullRawMessage `json:"cmetadata"`
	Uuid      sql.NullString        `json:"uuid"`
}

type UpdateKnowledgeDocumentRow struct {
	ID        string         `json:"id"`
	Document  string         `json:"document"`
	Cmetadata sql.NullString `json:"cmetadata"`
}

// Update an existing document's embedding, text and metadata atomically.
// embedding must be formatted as a PostgreSQL vector literal: '[f1,f2,...]'
// cmetadata must be valid JSON text.
func (q *Queries) UpdateKnowledgeDocument(ctx context.Context, arg UpdateKnowledgeDocumentParams) (UpdateKnowledgeDocumentRow, error) {
	row := q.db.QueryRowContext(ctx, updateKnowledgeDocument,
		arg.Embedding,
		arg.Document,
		arg.Cmetadata,
		arg.Uuid,
	)
	var i UpdateKnowledgeDocumentRow
	err := row.Scan(&i.ID, &i.Document, &i.Cmetadata)
	return i, err
}
