-- Import the 47 customer QA benchmark rows as governed Few-shot candidates.
-- This migration deliberately creates DRAFT records only.  Retrieval continues
-- to use APPROVED rows only (see 82_sgmp_qa_fewshot_reference_governance.sql).

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('source_case_id VARCHAR2(30)');
  add_column('source_type VARCHAR2(30)');
END;
/

BEGIN
  EXECUTE IMMEDIATE
    'CREATE UNIQUE INDEX sg_qa_vector_example_source_uk '
    || 'ON sg_qa_vector_example (source_type, source_case_id)';
EXCEPTION
  WHEN OTHERS THEN
    IF SQLCODE != -955 THEN
      RAISE;
    END IF;
END;
/

CREATE OR REPLACE FUNCTION sg_qa_vector_seed_benchmark
RETURN NUMBER
AUTHID DEFINER
IS
  PRAGMA AUTONOMOUS_TRANSACTION;
  v_input       CLOB;
  v_embedding   VECTOR;
  v_answer_sql  CLOB;
  v_answer_text CLOB;
  v_exists      NUMBER;
  v_inserted    NUMBER := 0;
BEGIN
  FOR item IN (
    SELECT question_code,
           question_text,
           baseline_sql,
           baseline_answer,
           expected_focus,
           support_level
      FROM sg_ai_qa_question
     WHERE question_source = 'CUSTOMER_EXCEL'
       AND active_yn = 'Y'
     ORDER BY question_code
  ) LOOP
    SELECT CASE
             WHEN EXISTS (
               SELECT 1
                 FROM sg_qa_vector_example existing
                WHERE existing.source_type = 'CUSTOMER_QA_BENCHMARK'
                  AND existing.source_case_id = item.question_code
             ) THEN 1 ELSE 0
           END
      INTO v_exists
      FROM dual;

    IF v_exists = 0 THEN
      v_answer_sql := CASE
        WHEN item.baseline_sql IS NULL OR DBMS_LOB.GETLENGTH(TRIM(item.baseline_sql)) = 0
          THEN TO_CLOB('SELECT CAST(NULL AS NUMBER) AS "NO_BASELINE" FROM DUAL WHERE 1 = 0')
        ELSE item.baseline_sql
      END;
      v_answer_text := TO_CLOB('Expected focus: ') || item.expected_focus
        || CASE WHEN item.baseline_answer IS NULL THEN NULL
                ELSE TO_CLOB(CHR(10) || 'Historical answer: ') || item.baseline_answer END;
      v_input := TO_CLOB('Customer QA case: ') || item.question_code
        || TO_CLOB(CHR(10) || 'Question: ') || item.question_text
        || TO_CLOB(CHR(10) || 'Expected focus: ') || item.expected_focus
        || TO_CLOB(CHR(10) || 'Candidate SQL: ') || v_answer_sql;
      v_embedding := DBMS_VECTOR.UTL_TO_EMBEDDING(
        v_input,
        JSON(sg_qa_vector_params('search_document'))
      );

      BEGIN
        INSERT INTO sg_qa_vector_example (
          question, answer_sql, answer_text, embedding_input, embedding, embedding_model,
          reference_status, reference_kind, target_type, inspection_status,
          inspection_note, source_case_id, source_type
        ) VALUES (
          item.question_text, v_answer_sql, v_answer_text, v_input, v_embedding, 'cohere.embed-v4.0',
          'DRAFT',
          CASE WHEN item.support_level = 'UNSUPPORTED' THEN 'OBJECT_UNAVAILABLE'
               ELSE 'SQL_TEMPLATE' END,
          'ANY',
          'PENDING',
          'Imported from the customer benchmark. A candidate cannot be retrieved until scope, logical object role, and SQL safety are reviewed.',
          item.question_code,
          'CUSTOMER_QA_BENCHMARK'
        );
        v_inserted := v_inserted + 1;
      EXCEPTION
        WHEN DUP_VAL_ON_INDEX THEN
          NULL;
      END;
    END IF;
  END LOOP;

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

CREATE OR REPLACE FUNCTION sg_qa_vector_approve_verified_benchmark
RETURN NUMBER
AUTHID DEFINER
IS
  PRAGMA AUTONOMOUS_TRANSACTION;
  v_target_type VARCHAR2(16);
  v_input       CLOB;
  v_answer_text CLOB;
  v_embedding   VECTOR;
  v_approved    NUMBER := 0;
BEGIN
  FOR item IN (
    WITH latest_answer AS (
      SELECT answer.question_id,
             answer.generated_sql,
             answer.answer_text,
             answer.result_json,
             answer.judgment_status,
             answer.execution_status,
             ROW_NUMBER() OVER (
               PARTITION BY answer.question_id ORDER BY answer.answer_seq DESC
             ) AS row_rank
        FROM sg_ai_qa_answer answer
    )
    SELECT example.example_id,
           question.question_text,
           question.expected_focus,
           question.support_level,
           latest.generated_sql,
           latest.answer_text AS live_answer,
           latest.result_json,
           latest.judgment_status,
           latest.execution_status
      FROM sg_qa_vector_example example
      JOIN sg_ai_qa_question question
        ON question.question_code = example.source_case_id
      LEFT JOIN latest_answer latest
        ON latest.question_id = question.question_id
       AND latest.row_rank = 1
     WHERE example.source_type = 'CUSTOMER_QA_BENCHMARK'
       AND example.reference_status = 'DRAFT'
  ) LOOP
    IF item.support_level = 'SUPPORTED'
       AND item.judgment_status = 'PASS'
       AND item.execution_status = 'COMPLETED'
       AND item.generated_sql IS NOT NULL
       AND DBMS_LOB.GETLENGTH(TRIM(item.generated_sql)) > 0 THEN
      v_target_type := REGEXP_SUBSTR(
        DBMS_LOB.SUBSTR(item.result_json, 32767, 1),
        '"targetType"[[:space:]]*:[[:space:]]*"([A-Z]+)"',
        1, 1, NULL, 1
      );
      IF v_target_type NOT IN ('NONE', 'SINGLE', 'MULTI', 'ALL', 'ANY') THEN
        v_target_type := 'ANY';
      END IF;
      v_answer_text := TO_CLOB('Expected focus: ') || item.expected_focus
        || CASE WHEN item.live_answer IS NULL THEN NULL
                ELSE TO_CLOB(CHR(10) || 'Verified live answer: ') || item.live_answer END;
      v_input := TO_CLOB('Customer QA question: ') || item.question_text
        || TO_CLOB(CHR(10) || 'Expected focus: ') || item.expected_focus
        || TO_CLOB(CHR(10) || 'Verified SQL template: ') || item.generated_sql;
      v_embedding := DBMS_VECTOR.UTL_TO_EMBEDDING(
        v_input,
        JSON(sg_qa_vector_params('search_document'))
      );
      UPDATE sg_qa_vector_example
         SET answer_sql = item.generated_sql,
             answer_text = v_answer_text,
             embedding_input = v_input,
             embedding = v_embedding,
             reference_status = 'APPROVED',
             reference_kind = 'SQL_TEMPLATE',
             target_type = v_target_type,
             inspection_status = 'VERIFIED',
             inspection_note = 'Promoted only after the latest Portal ReAct run completed with PASS for this customer benchmark case.',
             verified_at = SYSTIMESTAMP,
             verified_by = 'SGMP_POC_BENCHMARK_REVIEW'
       WHERE example_id = item.example_id;
      v_approved := v_approved + 1;
    ELSE
      UPDATE sg_qa_vector_example
         SET inspection_status = 'REVIEW',
             inspection_note = 'Not retrievable: latest customer benchmark execution is unsupported, incomplete, WARN, FAIL, or lacks executable SQL.'
       WHERE example_id = item.example_id;
    END IF;
  END LOOP;
  COMMIT;
  RETURN v_approved;
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,
           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 (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_case_id VARCHAR2(30);
  v_source  VARCHAR2(30);
  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_case_id, v_source, 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
      || CASE WHEN v_case_id IS NULL THEN NULL ELSE ', source_case_id=' || v_case_id END
      || ', 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.source_case_id IS
  'Customer QA benchmark case identifier, such as STD-01 or CZN-01.';
COMMENT ON COLUMN sg_qa_vector_example.source_type IS
  'Candidate provenance. CUSTOMER_QA_BENCHMARK rows remain DRAFT until reviewed.';
