-- Keep semantic vector retrieval, but do not inject weak trailing neighbours
-- when a materially stronger example has already been found.
MERGE INTO sg_game_scope_policy t
USING (
  SELECT 'QA_VECTOR_NEIGHBOR_DISTANCE_MARGIN' AS policy_key,
         0.120000 AS number_value,
         'Maximum additional cosine distance from the best runtime Few-shot candidate.' AS description
    FROM dual
) s
ON (t.policy_key = s.policy_key)
WHEN MATCHED THEN UPDATE SET
  t.number_value = s.number_value,
  t.description = s.description,
  t.active_yn = 'Y',
  t.updated_at = SYSTIMESTAMP
WHEN NOT MATCHED THEN INSERT (
  policy_key, number_value, text_value, description, active_yn
) VALUES (
  s.policy_key, s.number_value, NULL, s.description, 'Y'
)
/

CREATE OR REPLACE FUNCTION sg_qa_vector_search(
  p_question    IN CLOB,
  p_top_k       IN PLS_INTEGER DEFAULT 3,
  p_target_type IN VARCHAR2 DEFAULT 'ANY'
) RETURN SYS_REFCURSOR AUTHID DEFINER
IS
  v_query_vector VECTOR;
  v_results SYS_REFCURSOR;
  v_target_type VARCHAR2(16) := UPPER(TRIM(NVL(p_target_type, 'ANY')));
  v_max_cosine_distance NUMBER;
  v_neighbor_margin NUMBER;
BEGIN
  IF p_question IS NULL THEN RAISE_APPLICATION_ERROR(-20003, 'question is required.'); END IF;
  IF p_top_k IS NULL OR p_top_k < 1 OR p_top_k > 20 THEN
    RAISE_APPLICATION_ERROR(-20004, 'top_k must be between 1 and 20.');
  END IF;
  IF v_target_type NOT IN ('NONE', 'SINGLE', 'MULTI', 'ALL', 'ANY') THEN
    RAISE_APPLICATION_ERROR(-20005, 'invalid target type.');
  END IF;

  SELECT number_value INTO v_max_cosine_distance
    FROM sg_game_scope_policy
   WHERE policy_key = 'QA_VECTOR_MAX_COSINE_DISTANCE'
     AND active_yn = 'Y'
     AND number_value IS NOT NULL;

  SELECT number_value INTO v_neighbor_margin
    FROM sg_game_scope_policy
   WHERE policy_key = 'QA_VECTOR_NEIGHBOR_DISTANCE_MARGIN'
     AND active_yn = 'Y'
     AND number_value IS NOT NULL;

  v_query_vector := DBMS_VECTOR.UTL_TO_EMBEDDING(
    p_question, JSON(sg_qa_vector_params('search_query'))
  );

  OPEN v_results FOR
    SELECT example_id, question, answer_sql, answer_text, embedding_model,
           reference_kind, target_type, object_role, source_case_id, source_type,
           cosine_distance
      FROM (
        SELECT c.*,
               MIN(c.cosine_distance) OVER () AS best_cosine_distance
          FROM (
            SELECT example_id, question, answer_sql, answer_text, embedding_model,
                   reference_kind, target_type, object_role, source_case_id, source_type,
                   VECTOR_DISTANCE(embedding, v_query_vector, COSINE) AS cosine_distance
              FROM sg_qa_vector_example
             WHERE reference_status = 'APPROVED'
               AND inspection_status = 'VERIFIED'
               AND answer_sql IS NOT NULL
               AND (source_type = 'POLICY_TEMPLATE'
                    OR NOT REGEXP_LIKE(answer_sql, '<[A-Z][A-Z0-9_]*>', 'i'))
               AND (target_type = 'ANY' OR v_target_type = 'ANY' OR target_type = v_target_type)
          ) c
         WHERE c.cosine_distance <= v_max_cosine_distance
      )
     WHERE cosine_distance <= best_cosine_distance + v_neighbor_margin
     ORDER BY cosine_distance, example_id
     FETCH FIRST p_top_k ROWS ONLY;
  RETURN v_results;
END;
/

COMMIT
