#!/usr/bin/env bash
set -uo pipefail

# CASAN_MANAGED_PROMPT_ENTRYPOINT
# Project-owned governed chat. The DevKit installer places the project identity
# in .casan/prompt-policy.json; this launcher refuses to run when that contract
# or its repository instruction boundary has drifted.

SELF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT="$(cd "$SELF_DIR/.." && pwd)"
CHAT="$ROOT/packages/casan-harness/scripts/bash/chat-turn.py"
VERIFY="$ROOT/packages/casan-harness/scripts/bash/prompt-enforcement-verify.sh"
POLICY="$ROOT/.casan/prompt-policy.json"

if [[ ! -f "$CHAT" || ! -f "$VERIFY" || ! -f "$POLICY" ]]; then
  echo "casan-chat: prompt enforcement runtime is incomplete; reinstall CASAN DevKit" >&2
  exit 1
fi
if ! command -v python3 >/dev/null 2>&1; then
  echo "casan-chat: python3 is required" >&2
  exit 1
fi

if ! bash "$VERIFY" --root "$ROOT" --quiet; then
  echo "casan-chat: prompt enforcement verification failed closed" >&2
  exit 1
fi

PROJECT="$(python3 - "$POLICY" <<'PY'
import json, sys
print(json.load(open(sys.argv[1], encoding="utf-8"))["project_id"])
PY
)"
DOMAIN_REL="$(python3 - "$POLICY" <<'PY'
import json, sys
print(json.load(open(sys.argv[1], encoding="utf-8"))["domain_root"])
PY
)"

export CASAN_APP_ROOT="$ROOT"
export CASAN_DOMAIN_ROOT="$ROOT/$DOMAIN_REL"
export CASAN_PROJECT_ID="$PROJECT"

ACTOR="${CASAN_CHAT_ACTOR:-${USER:-member}}"
ROLE="${CASAN_CHAT_ROLE:-viewer}"
AGENT="${CASAN_CHAT_AGENT:-}"
SKILL="${CASAN_CHAT_SKILL:-}"
MODEL_PROVIDER="${CASAN_CHAT_MODEL_PROVIDER:-}"
CHAT_ID="${CASAN_CHAT_ID:-$PROJECT-$(date +%Y%m%d-%H%M%S)-$$}"

usage() {
  cat <<'EOF'
Usage:
  bin/casan-chat "normal prompt"
  bin/casan-chat                    # interactive mode

Every accepted prompt is submitted to CASAN chat-turn and produces H1-H7
evidence. Direct Claude, ChatGPT, Codex or Copilot UI prompts are outside this
enforcement boundary and must not be described as CASAN-certified.

Optional environment variables:
  CASAN_CHAT_ACTOR
  CASAN_CHAT_ROLE
  CASAN_CHAT_AGENT
  CASAN_CHAT_SKILL
  CASAN_CHAT_MODEL_PROVIDER
  CASAN_CHAT_ID
EOF
}

run_turn() {
  local message="$1"
  local raw_file rc
  raw_file="$(mktemp)"

  local command=(python3 "$CHAT" ask
    --message "$message"
    --actor "$ACTOR"
    --role "$ROLE"
    --project "$PROJECT"
    --chat-id "$CHAT_ID")
  [[ -n "$AGENT" ]] && command+=(--agent "$AGENT")
  [[ -n "$SKILL" ]] && command+=(--skill "$SKILL")
  [[ -n "$MODEL_PROVIDER" ]] && command+=(--model-provider "$MODEL_PROVIDER")

  set +e
  "${command[@]}" >"$raw_file"
  rc=$?
  set -e

  python3 - "$raw_file" "$ROOT" <<'PY'
import json
import pathlib
import sys

raw_path = pathlib.Path(sys.argv[1])
root = pathlib.Path(sys.argv[2])
lines = [line for line in raw_path.read_text(encoding="utf-8", errors="replace").splitlines() if line.strip()]
try:
    result = json.loads(lines[-1])
except (IndexError, json.JSONDecodeError):
    print(raw_path.read_text(encoding="utf-8", errors="replace"))
    raise SystemExit(0)

answer = result.get("answer") or result.get("reason") or result.get("decision") or "No answer returned."
print(answer)
print()
trace_id = result.get("trace_id", "")
certified = result.get("certified", False)
decision = result.get("decision", "UNKNOWN")
mode = result.get("mode", "UNKNOWN")
print(f"CASAN decision={decision} mode={mode} certified={str(bool(certified)).lower()} trace_id={trace_id or 'n/a'}")
if trace_id:
    trace = root / ".specify" / "logs" / "trace-events" / f"{trace_id}.jsonl"
    print(f"CASAN evidence={trace}")
PY

  if [[ "$rc" -eq 0 ]]; then
    local certification trace_id certified
    certification="$(python3 - "$raw_file" <<'PY'
import json, pathlib, sys
lines = [line for line in pathlib.Path(sys.argv[1]).read_text(encoding="utf-8", errors="replace").splitlines() if line.strip()]
try:
    result = json.loads(lines[-1])
except (IndexError, json.JSONDecodeError):
    print("|false")
else:
    print(f"{result.get('trace_id', '')}|{str(bool(result.get('certified', False))).lower()}")
PY
)"
    trace_id="${certification%%|*}"
    certified="${certification#*|}"
    if [[ -z "$trace_id" || "$certified" != "true" ]]; then
      echo "casan-chat: runtime returned success without a certified trace" >&2
      rc=2
    elif ! bash "$VERIFY" --root "$ROOT" --project "$PROJECT" --trace-id "$trace_id"; then
      echo "casan-chat: per-prompt certification verification failed closed" >&2
      rc=2
    fi
  fi

  rm -f "$raw_file"
  return "$rc"
}

if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
  usage
  exit 0
fi

if [[ "$#" -gt 0 ]]; then
  run_turn "$*"
  exit $?
fi

echo "CASAN governed chat — project=$PROJECT role=$ROLE actor=$ACTOR"
echo "Every accepted turn writes H1-H7 evidence. Type /quit to exit."
while true; do
  printf 'casan> '
  IFS= read -r message || break
  case "$message" in
    /quit|/exit) break ;;
    '') continue ;;
  esac
  run_turn "$message" || true
done
