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

package sqlc

import (
	"context"
	"time"

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

const deleteSkillGitPackagesBySkillId = `-- name: DeleteSkillGitPackagesBySkillId :exec
DELETE FROM skill_git_package WHERE skill_id = $1
`

func (q *Queries) DeleteSkillGitPackagesBySkillId(ctx context.Context, skillID uuid.UUID) error {
	_, err := q.db.Exec(ctx, deleteSkillGitPackagesBySkillId, skillID)
	return err
}

const deleteSkillOciPackagesBySkillId = `-- name: DeleteSkillOciPackagesBySkillId :exec
DELETE FROM skill_oci_package WHERE skill_id = $1
`

func (q *Queries) DeleteSkillOciPackagesBySkillId(ctx context.Context, skillID uuid.UUID) error {
	_, err := q.db.Exec(ctx, deleteSkillOciPackagesBySkillId, skillID)
	return err
}

const deleteSkillsByRegistry = `-- name: DeleteSkillsByRegistry :exec
WITH skill_entries AS (
    SELECT DISTINCT v.entry_id
      FROM entry_version v
      JOIN registry_entry e ON v.entry_id = e.id
      JOIN skill s ON v.id = s.version_id
     WHERE e.source_id = $1
)
DELETE FROM registry_entry
 WHERE id IN (SELECT entry_id FROM skill_entries)
`

func (q *Queries) DeleteSkillsByRegistry(ctx context.Context, sourceID uuid.UUID) error {
	_, err := q.db.Exec(ctx, deleteSkillsByRegistry, sourceID)
	return err
}

const getSkillVersion = `-- name: GetSkillVersion :many
SELECT src.source_type AS registry_type,
       v.id,
       e.name,
       v.version,
       (l.latest_version_id IS NOT NULL)::boolean AS is_latest,
       v.created_at,
       v.updated_at,
       v.description,
       v.title,
       s.version_id AS skill_version_id,
       s.namespace,
       s.status,
       s.license,
       s.compatibility,
       s.allowed_tools,
       s.repository,
       s.icons,
       s.metadata,
       s.extension_meta,
       e.claims,
       rs.source_id,
       -- Sources not linked to the requested registry have no position; default to max int16
       -- so they sort after all explicitly positioned sources (lower position = higher priority).
       COALESCE(rs.position, 32767)::integer AS position
  FROM entry_version v
  JOIN registry_entry e ON e.id = v.entry_id
  JOIN registry_source rs ON rs.source_id = e.source_id
                          AND rs.registry_id = $1::uuid
  JOIN source src ON e.source_id = src.id
  JOIN skill s ON s.version_id = v.id
  LEFT JOIN latest_entry_version l ON v.id = l.latest_version_id
 WHERE v.name = $2
   AND (v.version = $3::text
       OR ($3::text = 'latest' AND l.latest_version_id = v.id)
   )
   AND ($4::text IS NULL OR src.name = $4::text)
   AND ($5::text IS NULL OR s.namespace = $5::text)
   AND (
       $6::integer IS NULL
       OR (rs.position > $6::integer
           AND rs.source_id > $7::uuid
       )
   )
 ORDER BY rs.position ASC, rs.source_id ASC
 LIMIT $8::bigint
`

type GetSkillVersionParams struct {
	RegistryID     uuid.UUID   `json:"registry_id"`
	Name           string      `json:"name"`
	Version        string      `json:"version"`
	SourceName     *string     `json:"source_name"`
	Namespace      *string     `json:"namespace"`
	CursorPosition pgtype.Int4 `json:"cursor_position"`
	CursorSourceID *uuid.UUID  `json:"cursor_source_id"`
	Size           int64       `json:"size"`
}

type GetSkillVersionRow struct {
	RegistryType   string      `json:"registry_type"`
	ID             uuid.UUID   `json:"id"`
	Name           string      `json:"name"`
	Version        string      `json:"version"`
	IsLatest       bool        `json:"is_latest"`
	CreatedAt      *time.Time  `json:"created_at"`
	UpdatedAt      *time.Time  `json:"updated_at"`
	Description    *string     `json:"description"`
	Title          *string     `json:"title"`
	SkillVersionID uuid.UUID   `json:"skill_version_id"`
	Namespace      string      `json:"namespace"`
	Status         SkillStatus `json:"status"`
	License        *string     `json:"license"`
	Compatibility  *string     `json:"compatibility"`
	AllowedTools   []string    `json:"allowed_tools"`
	Repository     []byte      `json:"repository"`
	Icons          []byte      `json:"icons"`
	Metadata       []byte      `json:"metadata"`
	ExtensionMeta  []byte      `json:"extension_meta"`
	Claims         []byte      `json:"claims"`
	SourceID       uuid.UUID   `json:"source_id"`
	Position       int32       `json:"position"`
}

// Despite the name, this query returns multiple rows. The actual number of
// records is bounded by the number of sources that provide the same name and
// version, which we currently don't expect to be more than a few.
// Cursor-based pagination using (position, source_id) compound cursor.
// position is the sort key but may not be unique; source_id is the tiebreaker.
func (q *Queries) GetSkillVersion(ctx context.Context, arg GetSkillVersionParams) ([]GetSkillVersionRow, error) {
	rows, err := q.db.Query(ctx, getSkillVersion,
		arg.RegistryID,
		arg.Name,
		arg.Version,
		arg.SourceName,
		arg.Namespace,
		arg.CursorPosition,
		arg.CursorSourceID,
		arg.Size,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []GetSkillVersionRow{}
	for rows.Next() {
		var i GetSkillVersionRow
		if err := rows.Scan(
			&i.RegistryType,
			&i.ID,
			&i.Name,
			&i.Version,
			&i.IsLatest,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.Description,
			&i.Title,
			&i.SkillVersionID,
			&i.Namespace,
			&i.Status,
			&i.License,
			&i.Compatibility,
			&i.AllowedTools,
			&i.Repository,
			&i.Icons,
			&i.Metadata,
			&i.ExtensionMeta,
			&i.Claims,
			&i.SourceID,
			&i.Position,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const getSkillVersionBySourceName = `-- name: GetSkillVersionBySourceName :one
SELECT src.source_type AS registry_type,
       v.id,
       e.name,
       v.version,
       (l.latest_version_id IS NOT NULL)::boolean AS is_latest,
       v.created_at,
       v.updated_at,
       v.description,
       v.title,
       s.version_id AS skill_version_id,
       s.namespace,
       s.status,
       s.license,
       s.compatibility,
       s.allowed_tools,
       s.repository,
       s.icons,
       s.metadata,
       s.extension_meta,
       e.claims,
       0::integer AS position
  FROM skill s
  JOIN entry_version v ON s.version_id = v.id
  JOIN registry_entry e ON v.entry_id = e.id
  JOIN source src ON e.source_id = src.id
  LEFT JOIN latest_entry_version l ON v.id = l.latest_version_id
 WHERE v.name = $1
   AND v.version = $2
   AND src.name = $3
`

type GetSkillVersionBySourceNameParams struct {
	Name       string `json:"name"`
	Version    string `json:"version"`
	SourceName string `json:"source_name"`
}

type GetSkillVersionBySourceNameRow struct {
	RegistryType   string      `json:"registry_type"`
	ID             uuid.UUID   `json:"id"`
	Name           string      `json:"name"`
	Version        string      `json:"version"`
	IsLatest       bool        `json:"is_latest"`
	CreatedAt      *time.Time  `json:"created_at"`
	UpdatedAt      *time.Time  `json:"updated_at"`
	Description    *string     `json:"description"`
	Title          *string     `json:"title"`
	SkillVersionID uuid.UUID   `json:"skill_version_id"`
	Namespace      string      `json:"namespace"`
	Status         SkillStatus `json:"status"`
	License        *string     `json:"license"`
	Compatibility  *string     `json:"compatibility"`
	AllowedTools   []string    `json:"allowed_tools"`
	Repository     []byte      `json:"repository"`
	Icons          []byte      `json:"icons"`
	Metadata       []byte      `json:"metadata"`
	ExtensionMeta  []byte      `json:"extension_meta"`
	Claims         []byte      `json:"claims"`
	Position       int32       `json:"position"`
}

// Source-scoped variant of GetSkillVersion used by the publish fetch-back path.
// source_name and version are required; registry filtering is not applied.
func (q *Queries) GetSkillVersionBySourceName(ctx context.Context, arg GetSkillVersionBySourceNameParams) (GetSkillVersionBySourceNameRow, error) {
	row := q.db.QueryRow(ctx, getSkillVersionBySourceName, arg.Name, arg.Version, arg.SourceName)
	var i GetSkillVersionBySourceNameRow
	err := row.Scan(
		&i.RegistryType,
		&i.ID,
		&i.Name,
		&i.Version,
		&i.IsLatest,
		&i.CreatedAt,
		&i.UpdatedAt,
		&i.Description,
		&i.Title,
		&i.SkillVersionID,
		&i.Namespace,
		&i.Status,
		&i.License,
		&i.Compatibility,
		&i.AllowedTools,
		&i.Repository,
		&i.Icons,
		&i.Metadata,
		&i.ExtensionMeta,
		&i.Claims,
		&i.Position,
	)
	return i, err
}

const insertSkillGitPackage = `-- name: InsertSkillGitPackage :exec
INSERT INTO skill_git_package (
    skill_id,
    url,
    ref,
    commit_sha,
    subfolder
) VALUES (
    $1,
    $2,
    $3,
    $4,
    $5
)
`

type InsertSkillGitPackageParams struct {
	SkillID   uuid.UUID `json:"skill_id"`
	Url       string    `json:"url"`
	Ref       *string   `json:"ref"`
	CommitSha *string   `json:"commit_sha"`
	Subfolder *string   `json:"subfolder"`
}

func (q *Queries) InsertSkillGitPackage(ctx context.Context, arg InsertSkillGitPackageParams) error {
	_, err := q.db.Exec(ctx, insertSkillGitPackage,
		arg.SkillID,
		arg.Url,
		arg.Ref,
		arg.CommitSha,
		arg.Subfolder,
	)
	return err
}

const insertSkillOciPackage = `-- name: InsertSkillOciPackage :exec
INSERT INTO skill_oci_package (
    skill_id,
    identifier,
    digest,
    media_type
) VALUES (
    $1,
    $2,
    $3,
    $4
)
`

type InsertSkillOciPackageParams struct {
	SkillID    uuid.UUID `json:"skill_id"`
	Identifier string    `json:"identifier"`
	Digest     *string   `json:"digest"`
	MediaType  *string   `json:"media_type"`
}

func (q *Queries) InsertSkillOciPackage(ctx context.Context, arg InsertSkillOciPackageParams) error {
	_, err := q.db.Exec(ctx, insertSkillOciPackage,
		arg.SkillID,
		arg.Identifier,
		arg.Digest,
		arg.MediaType,
	)
	return err
}

const insertSkillVersion = `-- name: InsertSkillVersion :one
INSERT INTO skill (
    version_id,
    namespace,
    status,
    license,
    compatibility,
    allowed_tools,
    repository,
    icons,
    metadata,
    extension_meta
) VALUES (
    $1,
    $2,
    COALESCE($3::skill_status, 'ACTIVE'),
    $4,
    $5,
    $6,
    $7,
    $8,
    $9,
    $10
)
RETURNING version_id
`

type InsertSkillVersionParams struct {
	VersionID     uuid.UUID       `json:"version_id"`
	Namespace     string          `json:"namespace"`
	Status        NullSkillStatus `json:"status"`
	License       *string         `json:"license"`
	Compatibility *string         `json:"compatibility"`
	AllowedTools  []string        `json:"allowed_tools"`
	Repository    []byte          `json:"repository"`
	Icons         []byte          `json:"icons"`
	Metadata      []byte          `json:"metadata"`
	ExtensionMeta []byte          `json:"extension_meta"`
}

func (q *Queries) InsertSkillVersion(ctx context.Context, arg InsertSkillVersionParams) (uuid.UUID, error) {
	row := q.db.QueryRow(ctx, insertSkillVersion,
		arg.VersionID,
		arg.Namespace,
		arg.Status,
		arg.License,
		arg.Compatibility,
		arg.AllowedTools,
		arg.Repository,
		arg.Icons,
		arg.Metadata,
		arg.ExtensionMeta,
	)
	var version_id uuid.UUID
	err := row.Scan(&version_id)
	return version_id, err
}

const insertSkillVersionForSync = `-- name: InsertSkillVersionForSync :one
INSERT INTO skill (
    version_id,
    namespace,
    status,
    license,
    compatibility,
    allowed_tools,
    repository,
    icons,
    metadata,
    extension_meta
) VALUES (
    $1,
    $2,
    COALESCE($3::skill_status, 'ACTIVE'),
    $4,
    $5,
    $6,
    $7,
    $8,
    $9,
    $10
)
RETURNING version_id
`

type InsertSkillVersionForSyncParams struct {
	VersionID     uuid.UUID       `json:"version_id"`
	Namespace     string          `json:"namespace"`
	Status        NullSkillStatus `json:"status"`
	License       *string         `json:"license"`
	Compatibility *string         `json:"compatibility"`
	AllowedTools  []string        `json:"allowed_tools"`
	Repository    []byte          `json:"repository"`
	Icons         []byte          `json:"icons"`
	Metadata      []byte          `json:"metadata"`
	ExtensionMeta []byte          `json:"extension_meta"`
}

func (q *Queries) InsertSkillVersionForSync(ctx context.Context, arg InsertSkillVersionForSyncParams) (uuid.UUID, error) {
	row := q.db.QueryRow(ctx, insertSkillVersionForSync,
		arg.VersionID,
		arg.Namespace,
		arg.Status,
		arg.License,
		arg.Compatibility,
		arg.AllowedTools,
		arg.Repository,
		arg.Icons,
		arg.Metadata,
		arg.ExtensionMeta,
	)
	var version_id uuid.UUID
	err := row.Scan(&version_id)
	return version_id, err
}

const listSkillGitPackages = `-- name: ListSkillGitPackages :many
SELECT p.id,
       p.skill_id,
       p.url,
       p.ref,
       p.commit_sha,
       p.subfolder
  FROM skill_git_package p
  JOIN skill s ON p.skill_id = s.version_id
 WHERE s.version_id = ANY($1::UUID[])
`

func (q *Queries) ListSkillGitPackages(ctx context.Context, versionIds []uuid.UUID) ([]SkillGitPackage, error) {
	rows, err := q.db.Query(ctx, listSkillGitPackages, versionIds)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []SkillGitPackage{}
	for rows.Next() {
		var i SkillGitPackage
		if err := rows.Scan(
			&i.ID,
			&i.SkillID,
			&i.Url,
			&i.Ref,
			&i.CommitSha,
			&i.Subfolder,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listSkillOciPackages = `-- name: ListSkillOciPackages :many
SELECT p.id,
       p.skill_id,
       p.identifier,
       p.digest,
       p.media_type
  FROM skill_oci_package p
  JOIN skill s ON p.skill_id = s.version_id
 WHERE s.version_id = ANY($1::UUID[])
`

func (q *Queries) ListSkillOciPackages(ctx context.Context, versionIds []uuid.UUID) ([]SkillOciPackage, error) {
	rows, err := q.db.Query(ctx, listSkillOciPackages, versionIds)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []SkillOciPackage{}
	for rows.Next() {
		var i SkillOciPackage
		if err := rows.Scan(
			&i.ID,
			&i.SkillID,
			&i.Identifier,
			&i.Digest,
			&i.MediaType,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listSkills = `-- name: ListSkills :many
SELECT src.source_type AS registry_type,
       s.version_id,
       e.name,
       v.version,
       (l.latest_version_id IS NOT NULL)::boolean AS is_latest,
       v.created_at,
       v.updated_at,
       v.description,
       v.title,
       s.namespace,
       s.status,
       s.license,
       s.compatibility,
       s.allowed_tools,
       s.repository,
       s.icons,
       s.metadata,
       s.extension_meta,
       e.claims,
       -- Sources not linked to the requested registry have no position; default to max int16
       -- so they sort after all explicitly positioned sources (lower position = higher priority).
       COALESCE(rs.position, 32767)::integer AS position
  FROM skill s
  JOIN entry_version v ON s.version_id = v.id
  JOIN registry_entry e ON v.entry_id = e.id
  JOIN source src ON e.source_id = src.id
  LEFT JOIN latest_entry_version l ON v.id = l.latest_version_id
  JOIN registry_source rs ON rs.source_id = e.source_id
                          AND rs.registry_id = $1::uuid
 WHERE ($2::text IS NULL OR s.namespace = $2::text)
   AND ($3::text IS NULL OR e.name = $3::text)
   AND ($4::text IS NULL OR (
       LOWER(e.name) LIKE LOWER('%' || $4::text || '%')
       OR LOWER(v.title) LIKE LOWER('%' || $4::text || '%')
       OR LOWER(v.description) LIKE LOWER('%' || $4::text || '%')
   ))
   AND ($5::timestamp with time zone IS NULL OR v.updated_at > $5::timestamp with time zone)
   AND (
       $6::text IS NULL
       OR (v.name, v.version) > ($6::text, $7::text)
   )
 ORDER BY v.name ASC, v.version ASC, rs.position ASC
 LIMIT $8::bigint
`

type ListSkillsParams struct {
	RegistryID    uuid.UUID  `json:"registry_id"`
	Namespace     *string    `json:"namespace"`
	Name          *string    `json:"name"`
	Search        *string    `json:"search"`
	UpdatedSince  *time.Time `json:"updated_since"`
	CursorName    *string    `json:"cursor_name"`
	CursorVersion *string    `json:"cursor_version"`
	Size          int64      `json:"size"`
}

type ListSkillsRow struct {
	RegistryType  string      `json:"registry_type"`
	VersionID     uuid.UUID   `json:"version_id"`
	Name          string      `json:"name"`
	Version       string      `json:"version"`
	IsLatest      bool        `json:"is_latest"`
	CreatedAt     *time.Time  `json:"created_at"`
	UpdatedAt     *time.Time  `json:"updated_at"`
	Description   *string     `json:"description"`
	Title         *string     `json:"title"`
	Namespace     string      `json:"namespace"`
	Status        SkillStatus `json:"status"`
	License       *string     `json:"license"`
	Compatibility *string     `json:"compatibility"`
	AllowedTools  []string    `json:"allowed_tools"`
	Repository    []byte      `json:"repository"`
	Icons         []byte      `json:"icons"`
	Metadata      []byte      `json:"metadata"`
	ExtensionMeta []byte      `json:"extension_meta"`
	Claims        []byte      `json:"claims"`
	Position      int32       `json:"position"`
}

// Cursor-based pagination using (name, version) compound cursor.
// The cursor_name and cursor_version parameters define the starting point.
// When cursor is provided, results start AFTER the specified (name, version) tuple.
// Returns position from registry_source for source priority ordering.
func (q *Queries) ListSkills(ctx context.Context, arg ListSkillsParams) ([]ListSkillsRow, error) {
	rows, err := q.db.Query(ctx, listSkills,
		arg.RegistryID,
		arg.Namespace,
		arg.Name,
		arg.Search,
		arg.UpdatedSince,
		arg.CursorName,
		arg.CursorVersion,
		arg.Size,
	)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	items := []ListSkillsRow{}
	for rows.Next() {
		var i ListSkillsRow
		if err := rows.Scan(
			&i.RegistryType,
			&i.VersionID,
			&i.Name,
			&i.Version,
			&i.IsLatest,
			&i.CreatedAt,
			&i.UpdatedAt,
			&i.Description,
			&i.Title,
			&i.Namespace,
			&i.Status,
			&i.License,
			&i.Compatibility,
			&i.AllowedTools,
			&i.Repository,
			&i.Icons,
			&i.Metadata,
			&i.ExtensionMeta,
			&i.Claims,
			&i.Position,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const upsertLatestSkillVersion = `-- name: UpsertLatestSkillVersion :one
INSERT INTO latest_entry_version (
    source_id,
    name,
    version,
    latest_version_id
) VALUES (
    $1,
    $2,
    $3,
    $4
) ON CONFLICT (source_id, name)
  DO UPDATE SET
    version = $3,
    latest_version_id = $4
RETURNING latest_version_id
`

type UpsertLatestSkillVersionParams struct {
	SourceID  uuid.UUID `json:"source_id"`
	Name      string    `json:"name"`
	Version   string    `json:"version"`
	VersionID uuid.UUID `json:"version_id"`
}

func (q *Queries) UpsertLatestSkillVersion(ctx context.Context, arg UpsertLatestSkillVersionParams) (uuid.UUID, error) {
	row := q.db.QueryRow(ctx, upsertLatestSkillVersion,
		arg.SourceID,
		arg.Name,
		arg.Version,
		arg.VersionID,
	)
	var latest_version_id uuid.UUID
	err := row.Scan(&latest_version_id)
	return latest_version_id, err
}

const upsertSkillVersionForSync = `-- name: UpsertSkillVersionForSync :one
INSERT INTO skill (
    version_id,
    namespace,
    status,
    license,
    compatibility,
    allowed_tools,
    repository,
    icons,
    metadata,
    extension_meta
) VALUES (
    $1,
    $2,
    COALESCE($3::skill_status, 'ACTIVE'),
    $4,
    $5,
    $6,
    $7,
    $8,
    $9,
    $10
)
ON CONFLICT (version_id)
DO UPDATE SET
    status = COALESCE($3::skill_status, skill.status),
    license = $4,
    compatibility = $5,
    allowed_tools = $6,
    repository = $7,
    icons = $8,
    metadata = $9,
    extension_meta = $10
RETURNING version_id
`

type UpsertSkillVersionForSyncParams struct {
	VersionID     uuid.UUID       `json:"version_id"`
	Namespace     string          `json:"namespace"`
	Status        NullSkillStatus `json:"status"`
	License       *string         `json:"license"`
	Compatibility *string         `json:"compatibility"`
	AllowedTools  []string        `json:"allowed_tools"`
	Repository    []byte          `json:"repository"`
	Icons         []byte          `json:"icons"`
	Metadata      []byte          `json:"metadata"`
	ExtensionMeta []byte          `json:"extension_meta"`
}

func (q *Queries) UpsertSkillVersionForSync(ctx context.Context, arg UpsertSkillVersionForSyncParams) (uuid.UUID, error) {
	row := q.db.QueryRow(ctx, upsertSkillVersionForSync,
		arg.VersionID,
		arg.Namespace,
		arg.Status,
		arg.License,
		arg.Compatibility,
		arg.AllowedTools,
		arg.Repository,
		arg.Icons,
		arg.Metadata,
		arg.ExtensionMeta,
	)
	var version_id uuid.UUID
	err := row.Scan(&version_id)
	return version_id, err
}
