// Code generated by sqlc. DO NOT EDIT.
// versions:
//   sqlc v1.31.1
// source: recommendation_tuning.sql

package dbq

import (
	"context"
)

const getDiscoverTuning = `-- name: GetDiscoverTuning :one
SELECT singleton, tag_overlap_weight, snooze_days, updated_at FROM discover_tuning WHERE singleton = true
`

func (q *Queries) GetDiscoverTuning(ctx context.Context) (DiscoverTuning, error) {
	row := q.db.QueryRow(ctx, getDiscoverTuning)
	var i DiscoverTuning
	err := row.Scan(
		&i.Singleton,
		&i.TagOverlapWeight,
		&i.SnoozeDays,
		&i.UpdatedAt,
	)
	return i, err
}

const getTasteTuning = `-- name: GetTasteTuning :one
SELECT singleton, half_life_days, engagement_hard_skip, engagement_neutral, engagement_full, updated_at, enriched_tag_scale, era_scale, mood_scale FROM taste_tuning WHERE singleton = true
`

func (q *Queries) GetTasteTuning(ctx context.Context) (TasteTuning, error) {
	row := q.db.QueryRow(ctx, getTasteTuning)
	var i TasteTuning
	err := row.Scan(
		&i.Singleton,
		&i.HalfLifeDays,
		&i.EngagementHardSkip,
		&i.EngagementNeutral,
		&i.EngagementFull,
		&i.UpdatedAt,
		&i.EnrichedTagScale,
		&i.EraScale,
		&i.MoodScale,
	)
	return i, err
}

const insertTuningAudit = `-- name: InsertTuningAudit :exec
INSERT INTO recommendation_tuning_audit (scope, action, changes)
VALUES ($1, $2, $3)
`

type InsertTuningAuditParams struct {
	Scope   string
	Action  string
	Changes []byte
}

// changes is a jsonb array of {field, old, new} objects.
func (q *Queries) InsertTuningAudit(ctx context.Context, arg InsertTuningAuditParams) error {
	_, err := q.db.Exec(ctx, insertTuningAudit, arg.Scope, arg.Action, arg.Changes)
	return err
}

const listTuningAudit = `-- name: ListTuningAudit :many
SELECT id, changed_at, scope, action, changes
  FROM recommendation_tuning_audit
 ORDER BY changed_at DESC, id DESC
 LIMIT $1
`

// Newest first; consumed by the metrics trend view (#1251) to annotate
// knob turns on the timeline.
func (q *Queries) ListTuningAudit(ctx context.Context, limit int32) ([]RecommendationTuningAudit, error) {
	rows, err := q.db.Query(ctx, listTuningAudit, limit)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []RecommendationTuningAudit
	for rows.Next() {
		var i RecommendationTuningAudit
		if err := rows.Scan(
			&i.ID,
			&i.ChangedAt,
			&i.Scope,
			&i.Action,
			&i.Changes,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const listWeightProfiles = `-- name: ListWeightProfiles :many
SELECT profile, base_weight, like_boost, recency_weight, skip_penalty, jitter_magnitude, context_weight, similarity_weight, taste_weight, updated_at, context_time_weight FROM recommendation_weight_profiles ORDER BY profile
`

func (q *Queries) ListWeightProfiles(ctx context.Context) ([]RecommendationWeightProfile, error) {
	rows, err := q.db.Query(ctx, listWeightProfiles)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	var items []RecommendationWeightProfile
	for rows.Next() {
		var i RecommendationWeightProfile
		if err := rows.Scan(
			&i.Profile,
			&i.BaseWeight,
			&i.LikeBoost,
			&i.RecencyWeight,
			&i.SkipPenalty,
			&i.JitterMagnitude,
			&i.ContextWeight,
			&i.SimilarityWeight,
			&i.TasteWeight,
			&i.UpdatedAt,
			&i.ContextTimeWeight,
		); err != nil {
			return nil, err
		}
		items = append(items, i)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return items, nil
}

const updateDiscoverTuning = `-- name: UpdateDiscoverTuning :one
UPDATE discover_tuning
   SET tag_overlap_weight = $1,
       snooze_days        = $2,
       updated_at         = now()
 WHERE singleton = true
RETURNING singleton, tag_overlap_weight, snooze_days, updated_at
`

type UpdateDiscoverTuningParams struct {
	TagOverlapWeight float64
	SnoozeDays       float64
}

func (q *Queries) UpdateDiscoverTuning(ctx context.Context, arg UpdateDiscoverTuningParams) (DiscoverTuning, error) {
	row := q.db.QueryRow(ctx, updateDiscoverTuning, arg.TagOverlapWeight, arg.SnoozeDays)
	var i DiscoverTuning
	err := row.Scan(
		&i.Singleton,
		&i.TagOverlapWeight,
		&i.SnoozeDays,
		&i.UpdatedAt,
	)
	return i, err
}

const updateTasteTuning = `-- name: UpdateTasteTuning :one
UPDATE taste_tuning
   SET half_life_days       = $1,
       engagement_hard_skip = $2,
       engagement_neutral   = $3,
       engagement_full      = $4,
       enriched_tag_scale   = $5,
       era_scale            = $6,
       mood_scale           = $7,
       updated_at           = now()
 WHERE singleton = true
RETURNING singleton, half_life_days, engagement_hard_skip, engagement_neutral, engagement_full, updated_at, enriched_tag_scale, era_scale, mood_scale
`

type UpdateTasteTuningParams struct {
	HalfLifeDays       float64
	EngagementHardSkip float64
	EngagementNeutral  float64
	EngagementFull     float64
	EnrichedTagScale   float64
	EraScale           float64
	MoodScale          float64
}

func (q *Queries) UpdateTasteTuning(ctx context.Context, arg UpdateTasteTuningParams) (TasteTuning, error) {
	row := q.db.QueryRow(ctx, updateTasteTuning,
		arg.HalfLifeDays,
		arg.EngagementHardSkip,
		arg.EngagementNeutral,
		arg.EngagementFull,
		arg.EnrichedTagScale,
		arg.EraScale,
		arg.MoodScale,
	)
	var i TasteTuning
	err := row.Scan(
		&i.Singleton,
		&i.HalfLifeDays,
		&i.EngagementHardSkip,
		&i.EngagementNeutral,
		&i.EngagementFull,
		&i.UpdatedAt,
		&i.EnrichedTagScale,
		&i.EraScale,
		&i.MoodScale,
	)
	return i, err
}

const updateWeightProfile = `-- name: UpdateWeightProfile :one
UPDATE recommendation_weight_profiles
   SET base_weight         = $2,
       like_boost          = $3,
       recency_weight      = $4,
       skip_penalty        = $5,
       jitter_magnitude    = $6,
       context_weight      = $7,
       similarity_weight   = $8,
       taste_weight        = $9,
       context_time_weight = $10,
       updated_at          = now()
 WHERE profile = $1
RETURNING profile, base_weight, like_boost, recency_weight, skip_penalty, jitter_magnitude, context_weight, similarity_weight, taste_weight, updated_at, context_time_weight
`

type UpdateWeightProfileParams struct {
	Profile           string
	BaseWeight        float64
	LikeBoost         float64
	RecencyWeight     float64
	SkipPenalty       float64
	JitterMagnitude   float64
	ContextWeight     float64
	SimilarityWeight  float64
	TasteWeight       float64
	ContextTimeWeight float64
}

func (q *Queries) UpdateWeightProfile(ctx context.Context, arg UpdateWeightProfileParams) (RecommendationWeightProfile, error) {
	row := q.db.QueryRow(ctx, updateWeightProfile,
		arg.Profile,
		arg.BaseWeight,
		arg.LikeBoost,
		arg.RecencyWeight,
		arg.SkipPenalty,
		arg.JitterMagnitude,
		arg.ContextWeight,
		arg.SimilarityWeight,
		arg.TasteWeight,
		arg.ContextTimeWeight,
	)
	var i RecommendationWeightProfile
	err := row.Scan(
		&i.Profile,
		&i.BaseWeight,
		&i.LikeBoost,
		&i.RecencyWeight,
		&i.SkipPenalty,
		&i.JitterMagnitude,
		&i.ContextWeight,
		&i.SimilarityWeight,
		&i.TasteWeight,
		&i.UpdatedAt,
		&i.ContextTimeWeight,
	)
	return i, err
}

const upsertDiscoverTuningDefaults = `-- name: UpsertDiscoverTuningDefaults :exec
INSERT INTO discover_tuning (singleton, tag_overlap_weight, snooze_days)
VALUES (true, $1, $2)
ON CONFLICT (singleton) DO NOTHING
`

type UpsertDiscoverTuningDefaultsParams struct {
	TagOverlapWeight float64
	SnoozeDays       float64
}

// Boot reconcile for the Discover scope (#2377). Never overwrites
// operator-tuned values, same contract as the other two.
func (q *Queries) UpsertDiscoverTuningDefaults(ctx context.Context, arg UpsertDiscoverTuningDefaultsParams) error {
	_, err := q.db.Exec(ctx, upsertDiscoverTuningDefaults, arg.TagOverlapWeight, arg.SnoozeDays)
	return err
}

const upsertTasteTuningDefaults = `-- name: UpsertTasteTuningDefaults :exec
INSERT INTO taste_tuning (
    singleton, half_life_days, engagement_hard_skip,
    engagement_neutral, engagement_full, enriched_tag_scale, era_scale,
    mood_scale
) VALUES (true, $1, $2, $3, $4, $5, $6, $7)
ON CONFLICT (singleton) DO NOTHING
`

type UpsertTasteTuningDefaultsParams struct {
	HalfLifeDays       float64
	EngagementHardSkip float64
	EngagementNeutral  float64
	EngagementFull     float64
	EnrichedTagScale   float64
	EraScale           float64
	MoodScale          float64
}

func (q *Queries) UpsertTasteTuningDefaults(ctx context.Context, arg UpsertTasteTuningDefaultsParams) error {
	_, err := q.db.Exec(ctx, upsertTasteTuningDefaults,
		arg.HalfLifeDays,
		arg.EngagementHardSkip,
		arg.EngagementNeutral,
		arg.EngagementFull,
		arg.EnrichedTagScale,
		arg.EraScale,
		arg.MoodScale,
	)
	return err
}

const upsertWeightProfileDefaults = `-- name: UpsertWeightProfileDefaults :exec

INSERT INTO recommendation_weight_profiles (
    profile, base_weight, like_boost, recency_weight, skip_penalty,
    jitter_magnitude, context_weight, similarity_weight, taste_weight,
    context_time_weight
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
ON CONFLICT (profile) DO NOTHING
`

type UpsertWeightProfileDefaultsParams struct {
	Profile           string
	BaseWeight        float64
	LikeBoost         float64
	RecencyWeight     float64
	SkipPenalty       float64
	JitterMagnitude   float64
	ContextWeight     float64
	SimilarityWeight  float64
	TasteWeight       float64
	ContextTimeWeight float64
}

// Recommendation tuning lab queries (#1250). Seeding happens via the
// recsettings boot reconcile; shipped defaults live in Go only.
// Boot reconcile: insert the shipped defaults for a profile if the row
// doesn't exist yet. Never overwrites operator-tuned values.
func (q *Queries) UpsertWeightProfileDefaults(ctx context.Context, arg UpsertWeightProfileDefaultsParams) error {
	_, err := q.db.Exec(ctx, upsertWeightProfileDefaults,
		arg.Profile,
		arg.BaseWeight,
		arg.LikeBoost,
		arg.RecencyWeight,
		arg.SkipPenalty,
		arg.JitterMagnitude,
		arg.ContextWeight,
		arg.SimilarityWeight,
		arg.TasteWeight,
		arg.ContextTimeWeight,
	)
	return err
}
