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

# Signal AI Gateway — OpenAI Codex CLI 一键接入
# 用法: curl -fsSL <portal>/docs/scripts/codex.sh | GATEWAY_BASE_URL='https://...' bash -s -- sk-...
# 可选: GATEWAY_CODEX_MODEL=gpt-5.5  GATEWAY_CODEX_OR_MODEL=openrouter-free
#       GATEWAY_CODEX_CHAT_MODEL=openrouter-free  GATEWAY_CODEX_WIRE_API=responses|chat
#       GATEWAY_CODEX_EXTRA_MODELS=claude-opus-4-8,claude-opus-4-6

API_KEY="${1:-}"
GATEWAY_BASE="${GATEWAY_BASE_URL:-https://api.4stoken.cn}"
BASE_URL="${GATEWAY_BASE%/}/v1"
CODEX_MODEL="${GATEWAY_CODEX_MODEL:-gpt-5.5}"
OR_MODEL="${GATEWAY_CODEX_OR_MODEL:-openrouter-free}"
CHAT_MODEL="${GATEWAY_CODEX_CHAT_MODEL:-$OR_MODEL}"
CODEX_CLI_MODELS="gpt-5.5,gpt-5.4,gpt-5.4-mini,gpt-5.4-nano,gpt-5.3-codex,claude-sonnet-4-6,claude-opus-4-8,claude-opus-4-7,claude-opus-4-6,claude-haiku-4-5,openrouter-free"
DEFAULT_EXTRA_MODELS="claude-opus-4-8,claude-opus-4-6"
EXTRA_MODELS="${GATEWAY_CODEX_EXTRA_MODELS:-$DEFAULT_EXTRA_MODELS}"
WIRE_API="${GATEWAY_CODEX_WIRE_API:-responses}"
CONFIG_DIR="$HOME/.codex"
CONFIG_FILE="$CONFIG_DIR/config.toml"
AUTH_FILE="$CONFIG_DIR/auth.json"
CATALOG_FILE="$CONFIG_DIR/signal-model-catalog.json"
OR_PROFILE_FILE="$CONFIG_DIR/openrouter-free.config.toml"
CHAT_PROFILE_FILE="$CONFIG_DIR/chat.config.toml"

if [ -z "$API_KEY" ]; then
  printf '\033[1;31m错误：\033[0m请提供 Client Key\n'
  printf '用法: ... | bash -s -- sk-YOUR_KEY\n'
  exit 1
fi

case "$WIRE_API" in
  responses|chat) ;;
  *)
    printf '\033[1;31m错误：\033[0mGATEWAY_CODEX_WIRE_API 仅支持 responses 或 chat\n'
    exit 1
    ;;
esac

mkdir -p "$CONFIG_DIR"

for f in "$CONFIG_FILE" "$AUTH_FILE" "$CATALOG_FILE" "$OR_PROFILE_FILE" "$CHAT_PROFILE_FILE"; do
  if [ -f "$f" ]; then
    cp "$f" "$f.bak.$(date +%s)"
    printf '\033[0;36m已备份\033[0m %s\n' "$f"
  fi
done

write_model_catalog() {
  if command -v codex >/dev/null 2>&1 && command -v python3 >/dev/null 2>&1; then
    if codex debug models --bundled > "$CONFIG_DIR/.signal-bundled-models.json" 2>/dev/null; then
      CODEX_MODEL="$CODEX_MODEL" OR_MODEL="$OR_MODEL" CHAT_MODEL="$CHAT_MODEL" CODEX_CLI_MODELS="$CODEX_CLI_MODELS" EXTRA_MODELS="$EXTRA_MODELS" CATALOG_FILE="$CATALOG_FILE" python3 - <<'PY'
import json, os
from pathlib import Path
catalog_path = Path(os.environ["CATALOG_FILE"])
codex_model = os.environ["CODEX_MODEL"]
or_model = os.environ["OR_MODEL"]
chat_model = os.environ["CHAT_MODEL"]
codex_cli_models = [m.strip() for m in os.environ.get("CODEX_CLI_MODELS", "").split(",") if m.strip()]
extra_models = [m.strip() for m in os.environ.get("EXTRA_MODELS", "").split(",") if m.strip()]
bundled_path = catalog_path.parent / ".signal-bundled-models.json"
with bundled_path.open() as f:
    bundled = json.load(f)
models = bundled.get("models", [])
base = next((m for m in models if m.get("slug") == codex_model), None)
if base is None and models:
    base = models[0]
if base is None:
    raise SystemExit("no bundled models")
wanted = {codex_model, *codex_cli_models, or_model, chat_model, *extra_models}
out = [m for m in models if m.get("slug") in wanted]
seen = {m.get("slug") for m in out}

def add_gateway_model(slug, display_name, provider="signal"):
    if not slug or slug in seen:
        return
    entry = json.loads(json.dumps(base))
    entry["slug"] = slug
    entry["display_name"] = display_name
    entry["displayName"] = display_name
    entry["provider"] = provider
    entry["hidden"] = False
    entry["description"] = f"Signal Gateway catalog mapping (Portal modelCode={slug})."
    entry["supported_reasoning_levels"] = []
    entry["default_reasoning_level"] = None
    entry["supports_reasoning_summaries"] = False
    entry["shell_type"] = entry.get("shell_type") or "shell_command"
    out.append(entry)
    seen.add(slug)

add_gateway_model(or_model, "OpenRouter Free")
if chat_model != or_model:
    add_gateway_model(chat_model, f"Signal Chat {chat_model}", "signal-chat")
for slug in codex_cli_models:
    add_gateway_model(slug, f"Signal {slug}")
for slug in extra_models:
    add_gateway_model(slug, f"Signal {slug}")
catalog_path.write_text(json.dumps({"models": out}, indent=2) + "\n")
PY
      rm -f "$CONFIG_DIR/.signal-bundled-models.json"
      return 0
    fi
  fi
  return 1
}

if ! write_model_catalog; then
  printf '\033[1;33m警告：\033[0m未检测到 codex CLI，跳过 model_catalog 自动生成。\n'
  printf '  安装 codex 后请重新运行本脚本。\n'
fi

GATEWAY_BLOCK=$(cat <<EOF
model_provider = "signal"
model = "$CODEX_MODEL"
model_catalog_json = "$CATALOG_FILE"

[model_providers.signal]
name = "Signal Gateway"
base_url = "$BASE_URL"
wire_api = "responses"
env_key = "OPENAI_API_KEY"
requires_openai_auth = false

EOF
)

GATEWAY_BLOCK="${GATEWAY_BLOCK/wire_api = \"responses\"/wire_api = \"$WIRE_API\"}"

if [ -f "$CONFIG_FILE" ]; then
  GATEWAY_BLOCK="$GATEWAY_BLOCK" CONFIG_FILE="$CONFIG_FILE" python3 - <<'PY'
import os
from pathlib import Path
path = Path(os.environ["CONFIG_FILE"])
gateway = os.environ["GATEWAY_BLOCK"]
if not gateway.endswith("\n"):
    gateway += "\n"
lines = path.read_text().splitlines()
skip = False
kept = []
for line in lines:
    s = line.strip()
    if s in ('model_provider = "OpenAI"', 'model_provider = "signal"'):
        continue
    if s.startswith('model = '):
        continue
    if s.startswith('model_catalog_json = '):
        continue
    if s in ('[model_providers.OpenAI]', '[model_providers.signal]'):
        skip = True
        continue
    if skip:
        if s.startswith('[') and not s.startswith('[model_providers.'):
            skip = False
        else:
            continue
    kept.append(line)
path.write_text(gateway + '\n'.join(kept).lstrip() + ('\n' if kept else ''))
PY
else
  printf '%s' "$GATEWAY_BLOCK" > "$CONFIG_FILE"
fi

cat > "$OR_PROFILE_FILE" <<EOF
model = "$OR_MODEL"
model_provider = "signal"
EOF

cat > "$CHAT_PROFILE_FILE" <<EOF
model = "$CHAT_MODEL"
model_provider = "signal-chat"
model_catalog_json = "$CATALOG_FILE"

[model_providers.signal-chat]
name = "Signal Gateway Chat"
base_url = "$BASE_URL"
wire_api = "chat"
env_key = "OPENAI_API_KEY"
requires_openai_auth = false
EOF

cat > "$AUTH_FILE" <<EOF
{
  "auth_mode": "apikey",
  "OPENAI_API_KEY": "$API_KEY"
}
EOF

SHELL_RC=""
if [ -f "$HOME/.zshrc" ]; then
  SHELL_RC="$HOME/.zshrc"
elif [ -f "$HOME/.bashrc" ]; then
  SHELL_RC="$HOME/.bashrc"
elif [ "$(uname)" = "Darwin" ]; then
  SHELL_RC="$HOME/.zshrc"
else
  SHELL_RC="$HOME/.bashrc"
fi

if [ -f "$SHELL_RC" ]; then
  sed -i.bak '/# Signal AI Gateway - Codex/d; /OPENAI_API_KEY.*signal\|OPENAI_BASE_URL.*signal/d' "$SHELL_RC" 2>/dev/null || true
fi

cat >> "$SHELL_RC" <<EOF
export OPENAI_API_KEY="$API_KEY"  # Signal AI Gateway - Codex
export OPENAI_BASE_URL="$BASE_URL"  # Signal AI Gateway - Codex
EOF

export OPENAI_API_KEY="$API_KEY"
export OPENAI_BASE_URL="$BASE_URL"

printf '\n\033[1;32m✓ Codex 配置完成\033[0m\n'
printf '  config: %s\n' "$CONFIG_FILE"
printf '  catalog: %s\n' "$CATALOG_FILE"
printf '  profile: %s\n' "$OR_PROFILE_FILE"
printf '  chat profile: %s\n' "$CHAT_PROFILE_FILE"
printf '  默认模型: %s | wire_api: %s | OpenRouter: %s | Chat 模型: %s\n' "$CODEX_MODEL" "$WIRE_API" "$OR_MODEL" "$CHAT_MODEL"
printf '  Codex CLI 支持模型: %s\n' "$CODEX_CLI_MODELS"
printf '  Codex catalog 追加模型: %s\n' "$EXTRA_MODELS"
printf '  验证: \033[1mcodex debug models\033[0m 应含 gpt-5.5 / claude-opus-4-8 / openrouter-free 等\n'
printf '  Responses: \033[1mcodex\033[0m 或 \033[1mcodex --profile openrouter-free\033[0m\n'
printf '  Chat-only 上游: \033[1mcodex --profile chat\033[0m\n'
printf '\n  \033[1;33m请运行：\033[0m \033[1msource %s\033[0m 并重启 Codex 会话\n' "$SHELL_RC"
