-- =============================================================================
-- KI-Kostenverfolgung für Dokumenten-Check
-- Tabelle:  dc_ai_cost_log
-- Package:  DC_COSTS_PKG
-- =============================================================================
-- Deployment:
--   sqlplus user/pass@db @"Scripts/KI-Kostenverfolgung.sql"
--
-- Skript ist idempotent (DROP IF EXISTS vor jedem CREATE).
-- =============================================================================


-- =============================================================================
-- Tabelle: dc_ai_cost_log
-- =============================================================================
BEGIN
  EXECUTE IMMEDIATE 'DROP TABLE dc_ai_cost_log CASCADE CONSTRAINTS';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/

CREATE TABLE dc_ai_cost_log (
  id                NUMBER         GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  called_at         TIMESTAMP      DEFAULT SYSTIMESTAMP                   NOT NULL,
  provider          VARCHAR2(30)                                           NOT NULL, -- mistral | ollama
  model_name        VARCHAR2(100)                                          NOT NULL,
  operation         VARCHAR2(30)                                           NOT NULL, -- TRANSLATE | EVALUATE | OCR | CATALOG
  project_id        NUMBER,
  catalog_id        NUMBER,
  prompt_tokens     NUMBER         DEFAULT 0                               NOT NULL,
  completion_tokens NUMBER         DEFAULT 0                               NOT NULL,
  total_tokens      NUMBER         DEFAULT 0                               NOT NULL,
  cost_eur          NUMBER(14, 8)  DEFAULT 0                               NOT NULL,
  created_at        TIMESTAMP      DEFAULT SYSTIMESTAMP                    NOT NULL,
  created_by        VARCHAR2(200)  DEFAULT 'SYSTEM'                        NOT NULL
);

COMMENT ON TABLE  dc_ai_cost_log                  IS 'Protokoll aller KI-API-Aufrufe mit Token-Verbrauch und Kosten';
COMMENT ON COLUMN dc_ai_cost_log.operation        IS 'TRANSLATE, EVALUATE, OCR, CATALOG';
COMMENT ON COLUMN dc_ai_cost_log.cost_eur         IS 'Berechnete Kosten in EUR basierend auf konfigurierten Preisen';

CREATE INDEX idx_ai_cost_called_at   ON dc_ai_cost_log (called_at);
CREATE INDEX idx_ai_cost_project_id  ON dc_ai_cost_log (project_id);
CREATE INDEX idx_ai_cost_catalog_id  ON dc_ai_cost_log (catalog_id);
CREATE INDEX idx_ai_cost_ym          ON dc_ai_cost_log (TO_CHAR(called_at, 'YYYY-MM'));


-- =============================================================================
-- PL/SQL Package: DC_COSTS_PKG
-- =============================================================================
CREATE OR REPLACE PACKAGE DC_COSTS_PKG AS

  -- -------------------------------------------------------------------------
  -- Gesamtkosten + Kosten des laufenden Monats
  -- -------------------------------------------------------------------------
  PROCEDURE get_summary(
    p_total_eur         OUT NUMBER,
    p_total_tokens      OUT NUMBER,
    p_total_calls       OUT NUMBER,
    p_month_eur         OUT NUMBER,
    p_month_tokens      OUT NUMBER,
    p_month_calls       OUT NUMBER
  );

  -- -------------------------------------------------------------------------
  -- Kosten pro Monat + Modell (für APEX-Reports / direkte Abfragen)
  -- Gibt einen REF CURSOR zurück (Spalten: month, provider, model_name,
  -- operation, call_count, prompt_tokens, completion_tokens, total_tokens, cost_eur)
  -- -------------------------------------------------------------------------
  FUNCTION get_monthly_detail RETURN SYS_REFCURSOR;

END DC_COSTS_PKG;
/

CREATE OR REPLACE PACKAGE BODY DC_COSTS_PKG AS

  PROCEDURE get_summary(
    p_total_eur         OUT NUMBER,
    p_total_tokens      OUT NUMBER,
    p_total_calls       OUT NUMBER,
    p_month_eur         OUT NUMBER,
    p_month_tokens      OUT NUMBER,
    p_month_calls       OUT NUMBER
  ) IS
  BEGIN
    -- Gesamtkosten (all time)
    SELECT NVL(SUM(cost_eur), 0),
           NVL(SUM(total_tokens), 0),
           COUNT(*)
    INTO   p_total_eur, p_total_tokens, p_total_calls
    FROM   dc_ai_cost_log;

    -- Laufender Monat
    SELECT NVL(SUM(cost_eur), 0),
           NVL(SUM(total_tokens), 0),
           COUNT(*)
    INTO   p_month_eur, p_month_tokens, p_month_calls
    FROM   dc_ai_cost_log
    WHERE  called_at >= TRUNC(SYSDATE, 'MM');

  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      p_total_eur    := 0; p_total_tokens := 0; p_total_calls := 0;
      p_month_eur    := 0; p_month_tokens := 0; p_month_calls := 0;
  END get_summary;


  FUNCTION get_monthly_detail RETURN SYS_REFCURSOR IS
    v_cur SYS_REFCURSOR;
  BEGIN
    OPEN v_cur FOR
      SELECT
        TO_CHAR(called_at, 'YYYY-MM')  AS month,
        provider,
        model_name,
        operation,
        COUNT(*)                        AS call_count,
        SUM(prompt_tokens)              AS prompt_tokens,
        SUM(completion_tokens)          AS completion_tokens,
        SUM(total_tokens)               AS total_tokens,
        ROUND(SUM(cost_eur), 6)         AS cost_eur
      FROM  dc_ai_cost_log
      WHERE called_at >= ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -11)
      GROUP BY TO_CHAR(called_at, 'YYYY-MM'), provider, model_name, operation
      ORDER BY month DESC, cost_eur DESC;
    RETURN v_cur;
  END get_monthly_detail;

END DC_COSTS_PKG;
/

-- =============================================================================
-- Kurztest (optionale Verifikation nach Deployment)
-- =============================================================================
-- DECLARE
--   v_te NUMBER; v_tt NUMBER; v_tc NUMBER;
--   v_me NUMBER; v_mt NUMBER; v_mc NUMBER;
-- BEGIN
--   DC_COSTS_PKG.get_summary(v_te,v_tt,v_tc,v_me,v_mt,v_mc);
--   DBMS_OUTPUT.PUT_LINE('Total EUR: ' || v_te || ', Calls: ' || v_tc);
--   DBMS_OUTPUT.PUT_LINE('Month EUR: ' || v_me || ', Calls: ' || v_mc);
-- END;
-- /
