-- EMBED: o agente do cliente na pagina dele, em uma linha de script.
--
-- DUAS TABELAS PORQUE SAO DUAS VIDAS DIFERENTES
--
--   embed_configs   uma vez por projeto. Provedor, modelo e a CHAVE DO MODELO
--                   (cifrada). Ninguem mexe depois de configurar.
--   embed_sessions  uma por carregamento do widget. Efemera, automatica,
--                   ninguem administra.
--
-- Misturar as duas e o que criava a sensacao de "mais uma chave para gerir": a
-- configuracao parece credencial (e e), a sessao nao (e descartavel).
--
-- POR QUE A SESSAO TEM LINHA, E NAO E UM TOKEN ASSINADO SEM ESTADO
--
-- Um token assinado verificaria mais barato e nao precisaria de tabela. Mas a
-- chave do modelo e DO CLIENTE: cada pergunta gasta dinheiro dele. Isso exige
-- contabilidade por sessao, e contabilidade exige linha. Com ela vem o que
-- protege a fatura -- teto de perguntas -- e o que torna o gasto visivel.
--
-- O QUE A SESSAO NUNCA E
--
-- Sempre de PROJETO. Uma chave de TENANT pode EMITIR (o backend do ERP tem uma
-- so e nao quer 33), mas a chamada e obrigada a nomear o projeto e o que sai
-- alcanca so ele. Alcance de tenant nao chega ao navegador em hipotese nenhuma:
-- e o unico segredo cujo vazamento expoe todos os clientes de uma vez.

CREATE TABLE embed_configs (
  id              BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  tenant_id       BIGINT UNSIGNED NOT NULL,
  project_id      BIGINT UNSIGNED NOT NULL,

  provider        VARCHAR(32)  NOT NULL,
  model           VARCHAR(128) NOT NULL,

  -- base64(nonce . secretbox(json)), mesmo formato de context_servers e
  -- database_connections. Nunca sai daqui em texto: nem por API, nem no painel.
  provider_key    TEXT NOT NULL,

  -- Origens permitidas, JSON array. O Origin do navegador e conferido contra
  -- esta lista na EMISSAO e de novo a cada pergunta -- um token levado para
  -- outro site nao responde.
  origins         JSON NULL,

  -- Tetos. Existem porque token publico + chave de LLM do cliente e uma conta
  -- aberta: sem limite, alguem copia o token e torra o cartao dele numa
  -- madrugada, e ele descobre pela fatura.
  max_questions_per_session INT UNSIGNED NOT NULL DEFAULT 30,
  max_sessions_per_minute   INT UNSIGNED NOT NULL DEFAULT 60,
  monthly_question_cap      INT UNSIGNED NULL,

  -- TTL padrao da sessao, em segundos. 30 min: 15 morre no meio de uma
  -- conversa; o teto existe porque sessao de 30 dias e chave permanente com
  -- outro nome.
  default_ttl     INT UNSIGNED NOT NULL DEFAULT 1800,

  status          VARCHAR(16) NOT NULL DEFAULT 'active',
  created_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  updated_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  PRIMARY KEY (id),
  -- Uma configuracao por projeto: duas seriam duas chaves de modelo para o
  -- mesmo lugar, e ninguem saberia qual esta gastando.
  UNIQUE KEY uq_embed_configs_project (project_id),
  KEY idx_embed_configs_tenant (tenant_id),
  CONSTRAINT fk_embed_configs_tenant  FOREIGN KEY (tenant_id)  REFERENCES tenants(id),
  CONSTRAINT fk_embed_configs_project FOREIGN KEY (project_id) REFERENCES projects(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE embed_sessions (
  id              BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  tenant_id       BIGINT UNSIGNED NOT NULL,
  project_id      BIGINT UNSIGNED NOT NULL,
  config_id       BIGINT UNSIGNED NOT NULL,

  -- O que vai para o navegador. Guardamos o HASH, como nas api_keys: um dump
  -- do banco nao entrega sessao viva. O prefixo serve para achar a linha no
  -- log sem revelar o resto.
  token_hash      CHAR(64)    NOT NULL,
  token_prefix    VARCHAR(16) NOT NULL,

  -- A origem desta sessao, congelada na emissao. Conferida a cada pergunta.
  origin          VARCHAR(255) NULL,

  -- Quem e o usuario final, do ponto de vista do CLIENTE. Nao e nosso usuario:
  -- e o identificador que o backend dele mandou. Vira a autoria da correcao,
  -- para que o historico responda QUEM corrigiu e nao so o que mudou.
  end_user        VARCHAR(190) NULL,

  -- Corrigir contexto e ESCRITA a partir de um token publico. Opt-in, padrao
  -- NAO: so o backend do cliente sabe se quem esta logado e o gerente
  -- financeiro ou um visitante do portal. Adivinhar isso seria errado.
  can_correct     TINYINT(1) NOT NULL DEFAULT 0,

  questions_used  INT UNSIGNED NOT NULL DEFAULT 0,
  max_questions   INT UNSIGNED NOT NULL,

  expires_at      DATETIME NOT NULL,
  revoked_at      DATETIME NULL,
  last_used_at    DATETIME NULL,
  created_at      DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,

  PRIMARY KEY (id),
  UNIQUE KEY uq_embed_sessions_token (token_hash),
  KEY idx_embed_sessions_project (project_id),
  KEY idx_embed_sessions_expira (expires_at),
  CONSTRAINT fk_embed_sessions_tenant  FOREIGN KEY (tenant_id)  REFERENCES tenants(id),
  CONSTRAINT fk_embed_sessions_project FOREIGN KEY (project_id) REFERENCES projects(id),
  CONSTRAINT fk_embed_sessions_config  FOREIGN KEY (config_id)  REFERENCES embed_configs(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
