-- Recommendation tuning lab queries (#1250). Seeding happens via the
-- recsettings boot reconcile; shipped defaults live in Go only.

-- name: UpsertWeightProfileDefaults :exec
-- Boot reconcile: insert the shipped defaults for a profile if the row
-- doesn't exist yet. Never overwrites operator-tuned values.
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;

-- name: ListWeightProfiles :many
SELECT * FROM recommendation_weight_profiles ORDER BY profile;

-- 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 *;

-- 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;

-- name: GetTasteTuning :one
SELECT * FROM taste_tuning WHERE singleton = true;

-- 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 *;

-- name: UpsertDiscoverTuningDefaults :exec
-- Boot reconcile for the Discover scope (#2377). Never overwrites
-- operator-tuned values, same contract as the other two.
INSERT INTO discover_tuning (singleton, tag_overlap_weight, snooze_days)
VALUES (true, $1, $2)
ON CONFLICT (singleton) DO NOTHING;

-- name: GetDiscoverTuning :one
SELECT * FROM discover_tuning WHERE singleton = true;

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

-- name: InsertTuningAudit :exec
-- changes is a jsonb array of {field, old, new} objects.
INSERT INTO recommendation_tuning_audit (scope, action, changes)
VALUES ($1, $2, $3);

-- name: ListTuningAudit :many
-- Newest first; consumed by the metrics trend view (#1251) to annotate
-- knob turns on the timeline.
SELECT id, changed_at, scope, action, changes
  FROM recommendation_tuning_audit
 ORDER BY changed_at DESC, id DESC
 LIMIT $1;
