#!/bin/bash
#
# Setup do CENARIO DE TESTE MULTI-TENANT do Contextia (Etapa 9).
#
# Cria, do zero, o tenant `erp-vitalis` -- um ERP ficticio de gestao de
# clinicas -- com DOIS clientes finais (dois projetos), a semantica da casa no
# nivel do TENANT, uma sobrescrita de projeto, os dois documentos indexados e
# as TRES chaves (uma por cliente + o admin geral).
#
#   tenant  erp-vitalis
#     +-- projeto clinica-aurora     chave do cliente A + documento so dele
#     +-- projeto clinica-bemestar   chave do cliente B
#     +-- semantica e manual no nivel do TENANT, herdados pelos dois
#     +-- chave de escopo TENANT: o admin geral
#
# REEXECUTAVEL: cada passo tolera "ja existe". Tenant, projetos, semantica e
# fontes convergem para o mesmo estado quando o script roda de novo. A UNICA
# excecao sao as CHAVES: o plaintext e mostrado uma unica vez e nao pode ser
# recuperado, entao o script NAO cria chave nova se ja houver chave no tenant
# (isso duplicaria credencial em vez de convergir). Para trocar uma chave,
# revogue a antiga com `bin/mcp apikey:revoke --id=<id>` e rode de novo.
#
# USO
#     tools/setup-multitenant.sh              # tudo: estrutura + contexto + dados
#     tools/setup-multitenant.sh --sem-dados  # sem a carga (so estrutura/contexto)
#
# Os dados sao carregados por `tools/cenario-multitenant.py`, que recebe as
# chaves dos projetos por variavel de ambiente. Se as chaves ja existiam (o
# script nao pode reexibi-las), exporte-as antes:
#
#     export CONTEXTIA_KEY_AURORA=ctx_...
#     export CONTEXTIA_KEY_BEMESTAR=ctx_...
#     tools/setup-multitenant.sh
#
# Documentacao completa do cenario: docs/CENARIO-MULTITENANT.md

set -u

L_RAIZ="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
L_MCP="$L_RAIZ/bin/mcp"
L_DOCS="$L_RAIZ/storage/demo-vitalis"
L_PYTHON="${PYTHON:-python3}"

L_TENANT="erp-vitalis"
L_PROJ_A="clinica-aurora"
L_PROJ_B="clinica-bemestar"

L_SEM_DADOS=0
[ "${1:-}" = "--sem-dados" ] && L_SEM_DADOS=1

# ---------------------------------------------------------------------------
# Executa um passo tolerando "ja existe": o objetivo do script e CONVERGIR
# para um estado, nao falhar porque parte dele ja estava la.
# ---------------------------------------------------------------------------
passo() {
  local loc_titulo="$1"; shift
  local loc_saida loc_status

  loc_saida="$("$@" 2>&1)"
  loc_status=$?

  if [ $loc_status -eq 0 ]; then
    printf '  [ok]     %s\n' "$loc_titulo"
    return 0
  fi

  if printf '%s' "$loc_saida" | grep -qi "already exists"; then
    printf '  [existe] %s\n' "$loc_titulo"
    return 0
  fi

  printf '  [FALHA]  %s\n' "$loc_titulo" >&2
  printf '%s\n' "$loc_saida" | sed 's/^/           /' >&2
  return 1
}

titulo() {
  printf '\n=== %s ===\n' "$1"
}

# ---------------------------------------------------------------------------
titulo "1. Tenant e projetos"

passo "tenant $L_TENANT" \
  "$L_MCP" tenant:create --name="ERP Vitalis" --slug="$L_TENANT"
passo "projeto $L_PROJ_A (cliente final A)" \
  "$L_MCP" project:create --tenant="$L_TENANT" --name="Clínica Aurora" --slug="$L_PROJ_A"
passo "projeto $L_PROJ_B (cliente final B)" \
  "$L_MCP" project:create --tenant="$L_TENANT" --name="Clínica Bem-Estar" --slug="$L_PROJ_B"

# ---------------------------------------------------------------------------
titulo "2. Chaves (uma por cliente + admin geral do tenant)"

# `apikey:list --tenant` sem `--project` traz as chaves dos projetos E as de
# tenant. Se ja ha qualquer uma, nao criamos outra: o plaintext nao volta, e
# criar de novo so acumularia credencial ativa.
L_CHAVES_EXISTENTES="$("$L_MCP" apikey:list --tenant="$L_TENANT" 2>/dev/null | tail -n +2 | grep -c 'ctx_')"

if [ "${L_CHAVES_EXISTENTES:-0}" -gt 0 ]; then
  printf '  [existe] %s chave(s) no tenant -- criacao PULADA (o plaintext so aparece uma vez).\n' "$L_CHAVES_EXISTENTES"
  printf '           As chaves em vigor estao em docs/CENARIO-MULTITENANT.md.\n'
  printf '           Para trocar uma: bin/mcp apikey:revoke --id=<id> e rode este script de novo.\n\n'
  "$L_MCP" apikey:list --tenant="$L_TENANT" | sed 's/^/           /'
else
  printf '\n--- chave do CLIENTE A (projeto %s) ---\n' "$L_PROJ_A"
  "$L_MCP" apikey:create --tenant="$L_TENANT" --project="$L_PROJ_A" --name="Agente Clinica Aurora"

  printf '\n--- chave do CLIENTE B (projeto %s) ---\n' "$L_PROJ_B"
  "$L_MCP" apikey:create --tenant="$L_TENANT" --project="$L_PROJ_B" --name="Agente Clinica Bem-Estar"

  printf '\n--- chave do ADMIN GERAL (escopo TENANT) ---\n'
  "$L_MCP" apikey:create --scope=tenant --tenant="$L_TENANT" --name="Admin geral ERP Vitalis"

  printf '\nANOTE AS TRES CHAVES ACIMA -- elas nao serao exibidas de novo.\n'
fi

# ---------------------------------------------------------------------------
titulo "3. Semantica do TENANT (a regra da casa, herdada pelos dois projetos)"

# STATUS_ID e opaco nos dados de proposito: o significado de cada codigo vive
# AQUI, definido UMA vez para o ERP inteiro. Num ERP com mil clientes, esta e a
# diferenca entre cadastrar a tabela de status uma vez e cadastra-la mil vezes.
#
# Os subjects NAO usam a forma `<dataset>.<campo>`: essa forma e ocupada
# automaticamente pelo intake (definicoes `client`, no nivel do PROJETO), que
# sobrescreveria a regra da casa sem querer.

passo "status_id.1" "$L_MCP" semantic:define --scope=tenant --tenant="$L_TENANT" \
  --subject=status_id.1 --author=setup-vitalis \
  --definition="Guia EM ABERTO: emitida e enviada ao convênio, repasse ainda não recebido. O SALDO é maior que zero e compõe o faturamento em aberto."

passo "status_id.2" "$L_MCP" semantic:define --scope=tenant --tenant="$L_TENANT" \
  --subject=status_id.2 --author=setup-vitalis \
  --definition="Guia RECEBIDA: valor integralmente creditado pelo convênio ou pago pelo paciente. O SALDO é sempre zero e a guia não entra no faturamento em aberto."

passo "status_id.3" "$L_MCP" semantic:define --scope=tenant --tenant="$L_TENANT" \
  --subject=status_id.3 --author=setup-vitalis \
  --definition="Guia GLOSADA: o convênio recusou o pagamento, total ou parcialmente. O SALDO continua em aberto até o recurso ser julgado, e o recurso tem prazo de 90 dias contados do atendimento."

passo "status_id.9" "$L_MCP" semantic:define --scope=tenant --tenant="$L_TENANT" \
  --subject=status_id.9 --author=setup-vitalis \
  --definition="Guia CANCELADA: atendimento não realizado ou guia anulada antes do envio. Não é receita, o SALDO é zero e ela não entra em nenhum total de faturamento."

passo "faturamento.regra_em_aberto" "$L_MCP" semantic:define --scope=tenant --tenant="$L_TENANT" \
  --subject=faturamento.regra_em_aberto --author=setup-vitalis \
  --definition="Faturamento em aberto é a SOMA DE SALDO das guias com STATUS_ID 1 ou 3. Guias 2 já foram pagas e guias 9 nunca foram receita. Somar VALOR em vez de SALDO infla o número sempre que houve repasse parcial."

passo "glosa" "$L_MCP" semantic:define --scope=tenant --tenant="$L_TENANT" \
  --subject=glosa --author=setup-vitalis \
  --definition="Recusa de pagamento pelo convênio, total ou parcial, sobre uma guia já enviada. No ERP Vitalis a guia glosada fica com STATUS_ID 3 até o recurso ser julgado."

passo "convenio.particular" "$L_MCP" semantic:define --scope=tenant --tenant="$L_TENANT" \
  --subject=convenio.particular --author=setup-vitalis \
  --definition="O valor 'Particular' no campo CONVENIO não é um convênio: marca o atendimento pago diretamente pelo paciente, sempre à vista (DATAVENCIMENTO igual à DATAATENDIMENTO) e sem recurso de glosa."

passo "prazo_repasse" "$L_MCP" semantic:define --scope=tenant --tenant="$L_TENANT" \
  --subject=prazo_repasse --author=setup-vitalis \
  --definition="Prazo entre o atendimento e o vencimento da guia: 60 dias corridos para qualquer convênio; à vista para Particular."

# ---------------------------------------------------------------------------
titulo "4. Sobrescrita do PROJETO clinica-aurora"

# A Aurora usa o codigo 3 para uma etapa que so existe nela. Definir o mesmo
# subject COM --project cria uma sobrescrita: a regra do tenant continua
# intacta e continua valendo para a Bem-Estar.

passo "status_id.3 (sobrescrita da Aurora)" "$L_MCP" semantic:define \
  --tenant="$L_TENANT" --project="$L_PROJ_A" \
  --subject=status_id.3 --author=setup-vitalis \
  --definition="Na Clínica Aurora o código 3 é EM AUDITORIA INTERNA: a guia está sendo conferida pelo próprio setor de faturamento (prontuário e autorização prévia) antes de qualquer contato com o convênio, em até 5 dias úteis. Não é, ainda, recusa do convênio — boa parte volta a ser recebida após a correção."

# ---------------------------------------------------------------------------
titulo "5. Grupos de dados (a taxonomia do ERP, no nivel do TENANT)"

# O grupo classifica DATASETS por assunto e vive no TENANT (migration 0020):
# a taxonomia e do ERP, nao do cliente final -- todo cliente tem `faturamento`
# e em todos ela e Financeiro.
#
# Vem ANTES da carga de dados de proposito, e isso e o ponto do desenho: a
# associacao e por NOME de dataset (dataset_group_members.dataset_name, sem FK
# para `datasets`), entao da para classificar `faturamento` antes de qualquer
# projeto ter ingerido esse dataset. Quando os dados chegam -- e quando um
# cliente NOVO chegar com os mesmos nomes --, eles ja nascem classificados.
#
# REEXECUTAVEL nas duas metades: group:create devolve "already exists" (que o
# passo() tolera) e group:assign e um ON DUPLICATE KEY sobre
# UNIQUE (tenant_id, dataset_name) -- reclassificar MOVE o dataset em vez de
# criar uma segunda linha.

passo "grupo clinico" "$L_MCP" group:create --tenant="$L_TENANT" \
  --name=clinico --label="Clínico" --position=1 \
  --description="Pacientes e procedimentos realizados"

passo "grupo financeiro" "$L_MCP" group:create --tenant="$L_TENANT" \
  --name=financeiro --label="Financeiro" --position=2 \
  --description="Faturamento e contas"

passo "pacientes -> clinico" "$L_MCP" group:assign --tenant="$L_TENANT" \
  --dataset=pacientes --group=clinico
passo "procedimentos -> clinico" "$L_MCP" group:assign --tenant="$L_TENANT" \
  --dataset=procedimentos --group=clinico
passo "faturamento -> financeiro" "$L_MCP" group:assign --tenant="$L_TENANT" \
  --dataset=faturamento --group=financeiro

# ---------------------------------------------------------------------------
titulo "6. Documentos"

# O manual da casa e indexado com --scope=tenant: a FONTE pertence ao projeto
# clinica-aurora (e la que ela e administrada), mas cada item gerado nasce com
# project_id NULL -- indexado UMA vez, lido pelos dois projetos.
#
# O documento de convenios da Aurora e indexado no escopo padrao (projeto):
# ele nao pode aparecer para a Bem-Estar.

passo "fonte manual-operacional (scope=tenant)" "$L_MCP" source:add \
  --tenant="$L_TENANT" --project="$L_PROJ_A" --scope=tenant \
  --type=file --name=manual-erp --path="$L_DOCS/manual-operacional.md"

passo "fonte convenios-aurora (scope=project)" "$L_MCP" source:add \
  --tenant="$L_TENANT" --project="$L_PROJ_A" \
  --type=file --name=convenios-aurora --path="$L_DOCS/convenios-aurora.md"

titulo "7. Indexacao"

"$L_MCP" index --tenant="$L_TENANT" --project="$L_PROJ_A" || exit 1

# ---------------------------------------------------------------------------
if [ "$L_SEM_DADOS" -eq 1 ]; then
  titulo "8. Dados -- PULADO (--sem-dados)"
  printf '  Para carregar depois:\n'
  printf '    export CONTEXTIA_KEY_AURORA=ctx_...\n'
  printf '    export CONTEXTIA_KEY_BEMESTAR=ctx_...\n'
  printf '    %s %s/tools/cenario-multitenant.py\n' "$L_PYTHON" "$L_RAIZ"
else
  titulo "8. Dados das duas clinicas"

  if [ -z "${CONTEXTIA_KEY_AURORA:-}" ] || [ -z "${CONTEXTIA_KEY_BEMESTAR:-}" ]; then
    printf '  [PULADO] exporte CONTEXTIA_KEY_AURORA e CONTEXTIA_KEY_BEMESTAR com as\n'
    printf '           chaves dos projetos e rode:\n'
    printf '             %s %s/tools/cenario-multitenant.py\n' "$L_PYTHON" "$L_RAIZ"
  else
    "$L_PYTHON" "$L_RAIZ/tools/cenario-multitenant.py" || exit 1
  fi
fi

# ---------------------------------------------------------------------------
titulo "Estado final"

printf '\n-- semantica em vigor no projeto %s (ORIGIN diz a camada) --\n' "$L_PROJ_A"
"$L_MCP" semantic:list --tenant="$L_TENANT" --project="$L_PROJ_A"

printf '\n-- semantica em vigor no projeto %s --\n' "$L_PROJ_B"
"$L_MCP" semantic:list --tenant="$L_TENANT" --project="$L_PROJ_B"

printf '\n-- knowledge items visiveis por %s --\n' "$L_PROJ_A"
"$L_MCP" knowledge:list --tenant="$L_TENANT" --project="$L_PROJ_A"

printf '\n-- knowledge items visiveis por %s (nao deve ter nada da Aurora) --\n' "$L_PROJ_B"
"$L_MCP" knowledge:list --tenant="$L_TENANT" --project="$L_PROJ_B"

printf '\nPronto. Roteiro de perguntas e comandos `claude mcp add`: docs/CENARIO-MULTITENANT.md\n'
