# ──────────────────────────────────────────────
# cursor-api-proxy — 設定與建置
# 編輯下方變數，然後執行 make env 產生 .env 檔
# ──────────────────────────────────────────────

# ── 伺服器設定 ─────────────────────────────────
HOST               ?= 127.0.0.1
PORT               ?= 8766
API_KEY            ?=
TIMEOUT_MS         ?= 3600000
MULTI_PORT         ?= false
VERBOSE            ?= false

# ── Agent / 模型設定 ──────────────────────────
AGENT_BIN          ?= agent
AGENT_NODE         ?=
AGENT_SCRIPT       ?=
DEFAULT_MODEL      ?= auto
STRICT_MODEL       ?= true
MAX_MODE           ?= false
FORCE              ?= false
APPROVE_MCPS       ?= false

# ── 工作區與帳號 ──────────────────────────────
WORKSPACE          ?=
CHAT_ONLY_WORKSPACE ?= true
CONFIG_DIRS        ?=

# ── OpenCode 模型設定 ────────────────────
OPENCODE_MODEL       ?= cursor/claude-4.6-sonnet-medium
OPENCODE_SMALL_MODEL ?= cursor/gpt-5.4-nano-medium

# ── Cursor / Claude Code（~/.claude）────────────────
CLAUDE_SETTINGS                ?= $(HOME)/.claude/settings.json
CLAUDE_JSON                    ?= $(HOME)/.claude.json
ANTHROPIC_AUTH_TOKEN           ?=
ANTHROPIC_DEFAULT_SONNET_MODEL ?= claude-4.6-sonnet-medium
ANTHROPIC_DEFAULT_OPUS_MODEL   ?= claude-4.6-opus-max
ANTHROPIC_DEFAULT_HAIKU_MODEL  ?= gemini-3-flash
ANTHROPIC_BASE_HOST          ?= $(HOST)

# ── TLS / HTTPS ───────────────────────────────
TLS_CERT           ?=
TLS_KEY            ?=

# ── Gemini Web Provider ───────────────────────
PROVIDER           ?= cursor
GEMINI_ACCOUNT_DIR ?=
GEMINI_BROWSER_VISIBLE ?= false
GEMINI_MAX_SESSIONS ?= 3

# ── 記錄 ──────────────────────────────────────
SESSIONS_LOG       ?=

# ──────────────────────────────────────────────

ENV_FILE ?= .env

OPENCODE_CONFIG ?= $(HOME)/.config/opencode/opencode.json

# ── Docker 設定 ───────────────────────────────
DOCKER_IMAGE    ?= cursor-api-proxy
DOCKER_TAG      ?= latest
DOCKER_COMPOSE  ?= docker compose

.PHONY: env run build clean help opencode opencode-models pm2 pm2-stop pm2-logs claude-code pm2-claude-code \
	claude-settings claude-onboarding claude-cursor-setup \
	docker-build docker-up docker-down docker-logs docker-restart docker-shell docker-env docker-setup

## 產生 .env 檔（預設輸出至 .env，可用 ENV_FILE=xxx 覆寫）
env:
	@printf '# 由 make env 自動產生，請勿手動編輯\n' > $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_HOST=%s\n'              "$(HOST)"                >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_PORT=%s\n'              "$(PORT)"                >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_API_KEY=%s\n'           "$(API_KEY)"             >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_TIMEOUT_MS=%s\n'        "$(TIMEOUT_MS)"          >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_MULTI_PORT=%s\n'        "$(MULTI_PORT)"          >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_VERBOSE=%s\n'           "$(VERBOSE)"             >> $(ENV_FILE)
	@printf 'CURSOR_AGENT_BIN=%s\n'                "$(AGENT_BIN)"           >> $(ENV_FILE)
	@printf 'CURSOR_AGENT_NODE=%s\n'               "$(AGENT_NODE)"          >> $(ENV_FILE)
	@printf 'CURSOR_AGENT_SCRIPT=%s\n'             "$(AGENT_SCRIPT)"        >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_DEFAULT_MODEL=%s\n'     "$(DEFAULT_MODEL)"       >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_STRICT_MODEL=%s\n'      "$(STRICT_MODEL)"        >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_MAX_MODE=%s\n'          "$(MAX_MODE)"            >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_FORCE=%s\n'             "$(FORCE)"               >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_APPROVE_MCPS=%s\n'      "$(APPROVE_MCPS)"        >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_WORKSPACE=%s\n'         "$(WORKSPACE)"           >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_CHAT_ONLY_WORKSPACE=%s\n' "$(CHAT_ONLY_WORKSPACE)" >> $(ENV_FILE)
	@printf 'CURSOR_CONFIG_DIRS=%s\n'              "$(CONFIG_DIRS)"         >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_TLS_CERT=%s\n'          "$(TLS_CERT)"            >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_TLS_KEY=%s\n'           "$(TLS_KEY)"             >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_SESSIONS_LOG=%s\n'      "$(SESSIONS_LOG)"        >> $(ENV_FILE)
	@printf '# ── Provider 設定 ───────────────────────────\n'                    >> $(ENV_FILE)
	@printf 'CURSOR_BRIDGE_PROVIDER=%s\n'          "$(PROVIDER)"            >> $(ENV_FILE)
	@printf '# Gemini Web Provider 設定（當 PROVIDER=gemini-web 時使用）\n'       >> $(ENV_FILE)
	@printf 'GEMINI_ACCOUNT_DIR=%s\n'              "$(GEMINI_ACCOUNT_DIR)"  >> $(ENV_FILE)
	@printf 'GEMINI_BROWSER_VISIBLE=%s\n'          "$(GEMINI_BROWSER_VISIBLE)" >> $(ENV_FILE)
	@printf 'GEMINI_MAX_SESSIONS=%s\n'             "$(GEMINI_MAX_SESSIONS)" >> $(ENV_FILE)
	@echo "已產生 $(ENV_FILE)"

## 編譯二進位檔
build:
	go build -o cursor-api-proxy .

## 載入 .env 後直接執行（需先執行 make env 或已有 .env）
run: build
	@if [ -f $(ENV_FILE) ]; then \
		set -a && . ./$(ENV_FILE) && set +a && ./cursor-api-proxy; \
	else \
		echo "找不到 $(ENV_FILE)，請先執行 make env"; exit 1; \
	fi

## 清除產出物
clean:
	rm -f cursor-api-proxy $(ENV_FILE)

## 設定 OpenCode 使用此代理（更新 opencode.json 的 cursor 與 gemini-web provider）
opencode: build
	@if [ ! -f "$(OPENCODE_CONFIG)" ]; then \
		echo "找不到 $(OPENCODE_CONFIG)，建立新設定檔"; \
		mkdir -p $$(dirname "$(OPENCODE_CONFIG)"); \
		printf '{\n  "model": "$(OPENCODE_MODEL)",\n  "small_model": "$(OPENCODE_SMALL_MODEL)",\n  "provider": {\n    "cursor": {\n      "npm": "@ai-sdk/openai-compatible",\n      "name": "Cursor Agent",\n      "options": {\n        "baseURL": "http://$(HOST):$(PORT)/v1",\n        "apiKey": "unused"\n      },\n      "models": { "auto": { "name": "Cursor Auto" } }\n    },\n    "gemini-web": {\n      "npm": "@ai-sdk/openai-compatible",\n      "name": "Gemini Web",\n      "options": {\n        "baseURL": "http://$(HOST):$(PORT)/v1",\n        "apiKey": "unused"\n      },\n      "models": {\n        "gemini-2.0-flash": { "name": "Gemini 2.0 Flash" },\n        "gemini-2.5-pro": { "name": "Gemini 2.5 Pro" },\n        "gemini-2.5-pro-thinking": { "name": "Gemini 2.5 Pro Thinking" }\n      }\n    }\n  }\n}\n' > "$(OPENCODE_CONFIG)"; \
		echo "已建立 $(OPENCODE_CONFIG)（包含 cursor 與 gemini-web provider）"; \
	elif [ -n "$(API_KEY)" ]; then \
		jq --arg model "$(OPENCODE_MODEL)" --arg small "$(OPENCODE_SMALL_MODEL)" --arg base "http://$(HOST):$(PORT)/v1" --arg key "$(API_KEY)" '.model = $$model | .small_model = $$small | .provider.cursor.options.baseURL = $$base | .provider.cursor.options.apiKey = $$key | .provider["gemini-web"].options.baseURL = $$base | .provider["gemini-web"].options.apiKey = $$key' "$(OPENCODE_CONFIG)" > "$(OPENCODE_CONFIG).tmp" && mv "$(OPENCODE_CONFIG).tmp" "$(OPENCODE_CONFIG)"; \
		echo "已更新 $(OPENCODE_CONFIG)（model=$(OPENCODE_MODEL), small_model=$(OPENCODE_SMALL_MODEL), baseURL → http://$(HOST):$(PORT)/v1，apiKey 已設定）"; \
	else \
		jq --arg model "$(OPENCODE_MODEL)" --arg small "$(OPENCODE_SMALL_MODEL)" --arg base "http://$(HOST):$(PORT)/v1" '.model = $$model | .small_model = $$small | .provider.cursor.options.baseURL = $$base | .provider["gemini-web"].options.baseURL = $$base' "$(OPENCODE_CONFIG)" > "$(OPENCODE_CONFIG).tmp" && mv "$(OPENCODE_CONFIG).tmp" "$(OPENCODE_CONFIG)"; \
		echo "已更新 $(OPENCODE_CONFIG)（model=$(OPENCODE_MODEL), small_model=$(OPENCODE_SMALL_MODEL), baseURL → http://$(HOST):$(PORT)/v1）"; \
	fi

## 啟動代理並用 curl 同步模型列表到 opencode.json
opencode-models: opencode
	@echo "啟動代理以取得模型列表..."
	@set -a && . ./$(ENV_FILE) 2>/dev/null; set +a; \
	./cursor-api-proxy & PID=$$!; \
	sleep 2; \
	MODELS=$$(curl -s http://$(HOST):$(PORT)/v1/models | jq '[.data[].id]'); \
	kill $$PID 2>/dev/null; wait $$PID 2>/dev/null; \
	if [ -n "$$MODELS" ] && [ "$$MODELS" != "null" ]; then \
		jq --argjson ids "$$MODELS" 'reduce $ids[] as $id (.; .provider.cursor.models[$id] = { name: $id } | .provider["gemini-web"].models[$id] = { name: $id })' "$(OPENCODE_CONFIG)" > "$(OPENCODE_CONFIG).tmp" && mv "$(OPENCODE_CONFIG).tmp" "$(OPENCODE_CONFIG)"; \
		echo "已同步模型列表到 $(OPENCODE_CONFIG)（cursor 與 gemini-web）"; \
	else \
		echo "無法取得模型列表，請確認代理已啟動"; \
	fi

## 編譯並用 pm2 啟動
pm2: build
	@if [ -f "$(ENV_FILE)" ]; then \
		env $$(cat $(ENV_FILE) | grep -v '^#' | xargs) CURSOR_BRIDGE_HOST=$(HOST) CURSOR_BRIDGE_PORT=$(PORT) pm2 start ./cursor-api-proxy --name cursor-api-proxy --update-env; \
	else \
		CURSOR_BRIDGE_HOST=$(HOST) CURSOR_BRIDGE_PORT=$(PORT) pm2 start ./cursor-api-proxy --name cursor-api-proxy; \
	fi
	@pm2 save
	@echo "pm2 已啟動 cursor-api-proxy（http://$(HOST):$(PORT)）"

## 用 pm2 啟動 OpenCode 代理（設定 + 啟動一步完成）
pm2-opencode: opencode pm2
	@echo "OpenCode 設定已更新並用 pm2 啟動代理"

## 寫入 ~/.claude/settings.json（ANTHROPIC_BASE_URL、三個 DEFAULT_* 模型；需 jq）
claude-settings:
	@command -v jq >/dev/null 2>&1 || { echo "需要 jq"; exit 1; }
	@mkdir -p $$(dirname "$(CLAUDE_SETTINGS)")
	@jq -n \
		--arg base "http://$(ANTHROPIC_BASE_HOST):$(PORT)" \
		--arg token "$(ANTHROPIC_AUTH_TOKEN)" \
		--arg sonnet "$(ANTHROPIC_DEFAULT_SONNET_MODEL)" \
		--arg opus "$(ANTHROPIC_DEFAULT_OPUS_MODEL)" \
		--arg haiku "$(ANTHROPIC_DEFAULT_HAIKU_MODEL)" \
		'{ env: { ANTHROPIC_BASE_URL: $$base, ANTHROPIC_AUTH_TOKEN: $$token, ANTHROPIC_DEFAULT_SONNET_MODEL: $$sonnet, ANTHROPIC_DEFAULT_OPUS_MODEL: $$opus, ANTHROPIC_DEFAULT_HAIKU_MODEL: $$haiku } }' \
		> "$(CLAUDE_SETTINGS).tmp" && mv "$(CLAUDE_SETTINGS).tmp" "$(CLAUDE_SETTINGS)"
	@echo "已寫入 $(CLAUDE_SETTINGS)（BASE_URL=http://$(ANTHROPIC_BASE_HOST):$(PORT)）"

## 將 ~/.claude.json 的 hasCompletedOnboarding 設為 true（繞過初次引導；需 jq）
claude-onboarding:
	@command -v jq >/dev/null 2>&1 || { echo "需要 jq"; exit 1; }
	@test -f "$(CLAUDE_JSON)" || { echo "找不到 $(CLAUDE_JSON)"; exit 1; }
	@jq '.hasCompletedOnboarding = true' "$(CLAUDE_JSON)" > "$(CLAUDE_JSON).tmp" && mv "$(CLAUDE_JSON).tmp" "$(CLAUDE_JSON)"
	@echo "已設定 $(CLAUDE_JSON) hasCompletedOnboarding=true"

## 一次執行 claude-settings + claude-onboarding
claude-cursor-setup: claude-settings claude-onboarding
	@echo "Cursor/Claude Code 本機設定已套用"

## 編譯並用 pm2 啟動 + 設定 Claude Code 環境變數
pm2-claude-code: pm2
	@echo ""
	@echo "Claude Code 設定：將以下指令加入你的 shell 啟動檔（~/.bashrc 或 ~/.zshrc）："
	@echo ""
	@echo "  export ANTHROPIC_BASE_URL=http://$(HOST):$(PORT)"
	@echo "  export ANTHROPIC_API_KEY=$(if $(API_KEY),$(API_KEY),dummy-key)"
	@echo ""
	@echo "或在當前 shell 執行："
	@echo ""
	@echo "  export ANTHROPIC_BASE_URL=http://$(HOST):$(PORT)"
	@echo "  export ANTHROPIC_API_KEY=$(if $(API_KEY),$(API_KEY),dummy-key)"
	@echo "  claude"
	@echo ""

## 停止 pm2 中的代理
pm2-stop:
	pm2 stop cursor-api-proxy 2>/dev/null || echo "cursor-api-proxy 未在執行"

## 查看 pm2 日誌
pm2-logs:
	pm2 logs cursor-api-proxy


## ──────────────────────────────────────────────────
## Docker Compose 指令
## ──────────────────────────────────────────────────

## 複製 .env.example 為 .env 並自動偵測本機 agent 路徑（首次設定）
docker-env:
	@if [ -f .env ]; then \
		echo ".env 已存在，若要重置請手動刪除後再執行"; \
	else \
		cp .env.example .env; \
		DETECTED_AGENT=$$(which agent 2>/dev/null || echo ""); \
		if [ -n "$$DETECTED_AGENT" ]; then \
			REAL_AGENT=$$(readlink -f "$$DETECTED_AGENT"); \
			sed -i "s|^CURSOR_AGENT_HOST_BIN=.*|CURSOR_AGENT_HOST_BIN=$$REAL_AGENT|" .env; \
			echo "  已偵測 agent: $$REAL_AGENT"; \
		else \
			echo "  警告：找不到 agent，請手動設定 CURSOR_AGENT_HOST_BIN"; \
		fi; \
		echo "已建立 .env，請確認設定後執行 make docker-up"; \
	fi

## 建置 Docker 映像檔
docker-build:
	$(DOCKER_COMPOSE) build

## 啟動 Docker Compose（背景執行）
docker-up:
	@if [ ! -f .env ]; then \
		echo "找不到 .env，請先執行：make docker-env"; exit 1; \
	fi
	$(DOCKER_COMPOSE) up -d
	@echo "cursor-api-proxy 已啟動（http://0.0.0.0:$(PORT)）"

## 首次設定並啟動（複製 .env + build + up，一步完成）
docker-setup:
	@if [ ! -f .env ]; then \
		cp .env.example .env; \
		echo "已建立 .env，請先編輯填入必要設定（CURSOR_AGENT_HOST_BIN、CURSOR_ACCOUNTS_DIR），然後重新執行 make docker-setup"; \
		exit 1; \
	fi
	$(DOCKER_COMPOSE) build
	$(DOCKER_COMPOSE) up -d
	@echo "cursor-api-proxy 已啟動（http://0.0.0.0:$(PORT)）"
	@echo "查看日誌：make docker-logs"

## 停止並移除容器
docker-down:
	$(DOCKER_COMPOSE) down

## 查看容器日誌（即時跟蹤）
docker-logs:
	$(DOCKER_COMPOSE) logs -f cursor-api-proxy

## 重新建置並啟動容器
docker-restart:
	$(DOCKER_COMPOSE) down
	$(DOCKER_COMPOSE) build
	$(DOCKER_COMPOSE) up -d
	@echo "cursor-api-proxy 已重新啟動"

## 進入容器 shell（除錯用）
docker-shell:
	$(DOCKER_COMPOSE) exec cursor-api-proxy sh

## 顯示說明
help:
	@echo "可用目標："
	@echo "  make env                產生 .env（先在 Makefile 頂端填好變數）"
	@echo "  make build              編譯 cursor-api-proxy 二進位檔"
	@echo "  make run                編譯並載入 .env 執行"
	@echo "  make pm2                編譯並用 pm2 啟動代理"
	@echo "  make pm2-stop           停止 pm2 中的代理"
	@echo "  make pm2-logs           查看 pm2 日誌"
	@echo "  make pm2-claude-code    啟動代理 + 輸出 Claude Code 設定指令"
	@echo "  make opencode           編譯並設定 OpenCode（更新 opencode.json）"
	@echo "  make pm2-opencode       設定 OpenCode + 啟動代理"
	@echo "  make opencode-models    編譯、設定 OpenCode 並同步模型列表"
	@echo "  make claude-settings    寫入 ~/.claude/settings.json（模型與 BASE_URL）"
	@echo "  make claude-onboarding  設定 ~/.claude.json hasCompletedOnboarding=true"
	@echo "  make claude-cursor-setup  同上兩步一次完成"
	@echo "  make clean              刪除二進位檔與 .env"
	@echo ""
	@echo "Docker Compose 指令："
	@echo "  make docker-env         複製 .env.example 為 .env（首次設定）"
	@echo "  make docker-setup       首次設定並啟動（自動複製 .env + build + up）"
	@echo "  make docker-build       建置 Docker 映像檔"
	@echo "  make docker-up          啟動容器（背景執行，需已有 .env）"
	@echo "  make docker-down        停止並移除容器"
	@echo "  make docker-logs        查看容器即時日誌"
	@echo "  make docker-restart     重新建置並啟動容器"
	@echo "  make docker-shell       進入容器 shell（除錯用）"
	@echo ""
	@echo "Provider 設定範例："
	@echo "  make env PROVIDER=cursor                                    # 使用 Cursor（預設）"
	@echo "  make env PROVIDER=gemini-web                                # 使用 Gemini Web"
	@echo "  make env PROVIDER=gemini-web GEMINI_ACCOUNT_DIR=/path/to/sessions"
	@echo "  make env PROVIDER=gemini-web GEMINI_BROWSER_VISIBLE=true"
	@echo "  make opencode                                               # 設定 OpenCode（含 cursor 與 gemini-web provider）"
	@echo ""
	@echo "覆寫範例："
	@echo "  make env PORT=9000 API_KEY=mysecret TIMEOUT_MS=60000"
	@echo "  make pm2-claude-code PORT=8765 API_KEY=mykey"
	@echo "  make pm2-opencode PORT=8765"
	@echo "  make claude-settings PORT=8766 ANTHROPIC_BASE_HOST=localhost ANTHROPIC_DEFAULT_OPUS_MODEL=claude-4.6-opus-high"
	@echo ""
	@echo "使用 Gemini Web Provider："
	@echo "  1. make env PROVIDER=gemini-web"
	@echo "  2. gemini-login my-session                                  # 登入並儲存 session"
	@echo "  3. make run                                                 # 啟動代理"
	@echo "  4. 在 OpenCode 設定 model: gemini/gemini-2.5-pro"
