-- Governed Few-shot examples for the Smilegate Select AI MCP.
-- Existing rows are preserved for audit and only APPROVED rows are retrievable.

DECLARE
  PROCEDURE add_column(p_definition IN VARCHAR2) IS
  BEGIN
    EXECUTE IMMEDIATE 'ALTER TABLE sg_qa_vector_example ADD (' || p_definition || ')';
  EXCEPTION
    WHEN OTHERS THEN
      IF SQLCODE != -1430 THEN
        RAISE;
      END IF;
  END;
BEGIN
  add_column('reference_status VARCHAR2(16) DEFAULT ''DRAFT'' NOT NULL');
  add_column('reference_kind VARCHAR2(32) DEFAULT ''SQL_TEMPLATE'' NOT NULL');
  add_column('target_type VARCHAR2(16) DEFAULT ''ANY'' NOT NULL');
  add_column('object_role VARCHAR2(64)');
  add_column('inspection_status VARCHAR2(16) DEFAULT ''PENDING'' NOT NULL');
  add_column('inspection_note CLOB');
  add_column('verified_at TIMESTAMP(6)');
  add_column('verified_by VARCHAR2(128)');
END;
/

UPDATE sg_qa_vector_example
   SET reference_status = 'RETIRED',
       reference_kind = 'SQL_TEMPLATE',
       target_type = 'SINGLE',
       inspection_status = 'RETIRED',
       inspection_note = 'Executed successfully but maps BUBBLYZ to the CZN physical user-master object. Conflicts with the approved game-target contract.',
       verified_at = SYSTIMESTAMP,
       verified_by = 'SGMP_POC_REVIEW'
 WHERE example_id = 2;

UPDATE sg_qa_vector_example
   SET reference_status = 'RETIRED',
       reference_kind = 'OBJECT_UNAVAILABLE',
       target_type = 'SINGLE',
       object_role = 'GAME_ALIAS_CATALOG',
       inspection_status = 'RETIRED',
       inspection_note = 'Executed successfully with no BUBBLYZ alias rows, but the game literal is not a reusable object-unavailable template. The current game query plan is the authoritative boundary source.',
       verified_at = SYSTIMESTAMP,
       verified_by = 'SGMP_POC_REVIEW'
 WHERE example_id = 3;

UPDATE sg_qa_vector_example
   SET reference_status = 'APPROVED',
       reference_kind = 'SQL_TEMPLATE',
       target_type = 'SINGLE',
       object_role = 'GAME_USER_MASTER',
       inspection_status = 'VERIFIED',
       inspection_note = 'Logical placeholder template. The resolved physical object must come only from the current game query plan.',
       verified_at = SYSTIMESTAMP,
       verified_by = 'SGMP_POC_REVIEW'
 WHERE example_id = 4;

UPDATE sg_qa_vector_example
   SET reference_status = 'APPROVED',
       reference_kind = 'NO_TARGET',
       target_type = 'NONE',
       inspection_status = 'VERIFIED',
       inspection_note = 'Executed successfully with no rows. Canonical boundary for an unscoped game-user-master request.',
       verified_at = SYSTIMESTAMP,
       verified_by = 'SGMP_POC_REVIEW'
 WHERE example_id = 5;

UPDATE sg_qa_vector_example
   SET reference_status = 'RETIRED',
       reference_kind = 'METADATA_POLICY',
       target_type = 'ANY',
       object_role = 'GAME_ALIAS_CATALOG',
       inspection_status = 'RETIRED',
       inspection_note = 'Not directly executable: requires an unbound GAME_TERM placeholder. Game resolution is now supplied by game_query_plan.',
       verified_at = SYSTIMESTAMP,
       verified_by = 'SGMP_POC_REVIEW'
 WHERE example_id = 6;

UPDATE sg_qa_vector_example
   SET reference_status = 'RETIRED',
       reference_kind = 'SQL_TEMPLATE',
       target_type = 'NONE',
       object_role = 'GAME_USER_MASTER',
       inspection_status = 'RETIRED',
       inspection_note = 'Executed successfully but chooses CZN_COMN_USER_MST for a game-unscoped question. Conflicts with the NONE target contract.',
       verified_at = SYSTIMESTAMP,
       verified_by = 'SGMP_POC_REVIEW'
 WHERE example_id IN (7, 8);

CREATE OR REPLACE FUNCTION sg_qa_vector_store(
  p_question   IN CLOB,
  p_answer_sql IN CLOB,
  p_answer     IN CLOB DEFAULT NULL
) RETURN NUMBER
AUTHID DEFINER
IS
  PRAGMA AUTONOMOUS_TRANSACTION;
  v_input      CLOB;
  v_embedding  VECTOR;
  v_example_id NUMBER;
BEGIN
  IF p_question IS NULL OR p_answer_sql IS NULL THEN
    RAISE_APPLICATION_ERROR(-20002, 'question and answer_sql are required.');
  END IF;

  v_input := TO_CLOB('Question: ') || p_question
          || TO_CLOB(CHR(10) || 'Answer SQL: ') || p_answer_sql
          || CASE WHEN p_answer IS NULL THEN NULL ELSE TO_CLOB(CHR(10) || 'Answer: ') || p_answer END;
  v_embedding := DBMS_VECTOR.UTL_TO_EMBEDDING(
    v_input,
    JSON(sg_qa_vector_params('search_document'))
  );

  INSERT INTO sg_qa_vector_example (
    question, answer_sql, answer_text, embedding_input, embedding, embedding_model,
    reference_status, reference_kind, target_type, inspection_status
  ) VALUES (
    p_question, p_answer_sql, p_answer, v_input, v_embedding, 'cohere.embed-v4.0',
    'DRAFT', 'SQL_TEMPLATE', 'ANY', 'PENDING'
  ) RETURNING example_id INTO v_example_id;

  COMMIT;
  RETURN v_example_id;
EXCEPTION
  WHEN OTHERS THEN
    ROLLBACK;
    RAISE;
END;
/

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')));
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, 'target_type must be NONE, SINGLE, MULTI, ALL, or ANY.');
  END IF;

  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,
           vector_distance(embedding, v_query_vector, COSINE) AS cosine_distance
      FROM sg_qa_vector_example
     WHERE reference_status = 'APPROVED'
       AND (target_type = 'ANY' OR v_target_type = 'ANY' OR target_type = v_target_type)
     ORDER BY vector_distance(embedding, v_query_vector, COSINE), example_id
     FETCH FIRST p_top_k ROWS ONLY;
  RETURN v_results;
END;
/

CREATE OR REPLACE FUNCTION sg_qa_vector_context(
  p_question    IN CLOB,
  p_top_k       IN PLS_INTEGER DEFAULT 3,
  p_target_type IN VARCHAR2 DEFAULT 'ANY'
) RETURN CLOB
AUTHID DEFINER
IS
  v_results SYS_REFCURSOR;
  v_id      NUMBER;
  v_q       CLOB;
  v_sql     CLOB;
  v_answer  CLOB;
  v_model   VARCHAR2(128);
  v_kind    VARCHAR2(32);
  v_target  VARCHAR2(16);
  v_role    VARCHAR2(64);
  v_dist    NUMBER;
  v_context CLOB := EMPTY_CLOB();
BEGIN
  v_results := sg_qa_vector_search(p_question, p_top_k, p_target_type);
  LOOP
    FETCH v_results INTO v_id, v_q, v_sql, v_answer, v_model, v_kind, v_target, v_role, v_dist;
    EXIT WHEN v_results%NOTFOUND;
    v_context := v_context
      || CASE WHEN DBMS_LOB.GETLENGTH(v_context) = 0 THEN NULL ELSE CHR(10) || CHR(10) END
      || '[Example ' || v_id || ', kind=' || v_kind || ', target_type=' || v_target
      || ', cosine_distance=' || TO_CHAR(v_dist, 'FM0D000000') || ']' || CHR(10)
      || 'Question: ' || v_q || CHR(10)
      || 'Answer SQL: ' || v_sql
      || CASE WHEN v_answer IS NULL THEN NULL ELSE CHR(10) || 'Answer: ' || v_answer END;
  END LOOP;
  CLOSE v_results;
  RETURN v_context;
END;
/

COMMENT ON COLUMN sg_qa_vector_example.reference_status IS
  'Few-shot retrieval lifecycle: DRAFT, APPROVED, or RETIRED. Only APPROVED is retrievable.';
COMMENT ON COLUMN sg_qa_vector_example.reference_kind IS
  'Few-shot semantic kind: SQL_TEMPLATE, NO_TARGET, OBJECT_UNAVAILABLE, or METADATA_POLICY.';
COMMENT ON COLUMN sg_qa_vector_example.target_type IS
  'Applicable game query-plan target type: NONE, SINGLE, MULTI, ALL, or ANY.';
COMMENT ON COLUMN sg_qa_vector_example.object_role IS
  'Logical object role; physical object names must be sourced from the current game query plan.';
