package apidef

// 统一 API 目录：代码注册与文档同源，禁止另起一套重复路径。
// 约定：
//   GET    读
//   POST   创建 / 触发无幂等动作（login、import、publish、generate）
//   PUT    更新（整资源或按约定部分字段）
//   DELETE 删除
// 动态业务行数据仅通过 /api/v1/apps/{slug}/{resource}[/{id}] 传输，不按行业写死字段。

type Entry struct {
	Method      string `json:"method"`
	Path        string `json:"path"`
	OperationID string `json:"operation_id"`
	Summary     string `json:"summary"`
	Public      bool   `json:"public"` // 网关可不带 JWT
	Group       string `json:"group"`
}

// Catalog 为平台对外唯一路由清单（动态 CRUD 形状固定，不因业务变化而增删行业接口）。
var Catalog = []Entry{
	{Method: "POST", Path: "/api/v1/auth/register", OperationID: "authRegister", Summary: "注册（默认 pending，无租户）", Public: true, Group: "auth"},
	{Method: "POST", Path: "/api/v1/auth/login", OperationID: "authLogin", Summary: "登录：用户名/手机+密码，或手机+短信验证码", Public: true, Group: "auth"},
	{Method: "POST", Path: "/api/v1/auth/sms/send", OperationID: "sendLoginSMS", Summary: "发送登录短信验证码（手机须已绑定）", Public: true, Group: "auth"},
	{Method: "POST", Path: "/api/v1/auth/password", OperationID: "changePassword", Summary: "登录用户修改自己的密码", Group: "auth"},
	{Method: "GET", Path: "/api/v1/auth/me", OperationID: "authMe", Summary: "当前登录用户资料", Group: "auth"},
	{Method: "PUT", Path: "/api/v1/auth/phone", OperationID: "bindPhone", Summary: "绑定或更换手机号", Group: "auth"},
	{Method: "POST", Path: "/api/v1/auth/token", OperationID: "authToken", Summary: "服务/智能体签发 JWT（含 client_credentials）", Public: true, Group: "auth"},
	{Method: "POST", Path: "/api/v1/auth/agent/register", OperationID: "agentSelfRegister", Summary: "宿主自注册；已 sync_bound 则复用并轮换密钥（Z28）", Public: true, Group: "auth"},
	{Method: "POST", Path: "/api/v1/auth/bind-code/redeem", OperationID: "redeemBindCode", Summary: "绑定码兑换（host_key+code）", Public: true, Group: "auth"},
	{Method: "POST", Path: "/api/v1/auth/bind/phone-lookup", OperationID: "bindPhoneLookup", Summary: "同号探测（不绑定）", Public: true, Group: "auth"},
	{Method: "POST", Path: "/api/v1/auth/bind/phone-confirm", OperationID: "bindPhoneConfirm", Summary: "同号确认后绑定", Public: true, Group: "auth"},
	{Method: "GET", Path: "/api/v1/auth/bind/policy", OperationID: "bindPolicy", Summary: "绑定策略（试运行/短信/凭票开关）", Public: true, Group: "auth"},
	{Method: "POST", Path: "/api/v1/auth/yuheng/ticket-exchange", OperationID: "yuhengTicketExchange", Summary: "宇恒凭票免登录换票（仅宇恒）", Public: true, Group: "auth"},
	{Method: "POST", Path: "/api/v1/auth/yuheng/restore-by-host", OperationID: "yuhengRestoreByHost", Summary: "按宇恒 host_key 恢复同步绑定（Z34b，phone 可空）", Public: true, Group: "auth"},
	{Method: "POST", Path: "/api/v1/auth/invites/accept", OperationID: "acceptInvite", Summary: "接受邀请加入租户", Group: "auth"},
	{Method: "POST", Path: "/api/v1/tenants", OperationID: "createTenant", Summary: "pending 用户创建自己的公司", Group: "auth"},

	{Method: "GET", Path: "/api/v1/meta/apis", OperationID: "listApis", Summary: "API 目录（防重复约定）", Public: true, Group: "meta"},
	{Method: "GET", Path: "/api/v1/meta/openapi.yaml", OperationID: "getOpenAPI", Summary: "OpenAPI 契约原文", Public: true, Group: "meta"},

	{Method: "GET", Path: "/api/v1/agents/me", OperationID: "agentMe", Summary: "智能体自查绑定落点", Group: "agent"},
	{Method: "GET", Path: "/api/v1/admin/bind-codes", OperationID: "listBindCodes", Summary: "列出公司绑定码", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/bind-codes", OperationID: "createBindCode", Summary: "生成绑定码", Group: "admin"},
	{Method: "DELETE", Path: "/api/v1/admin/bind-codes/{code}", OperationID: "revokeBindCode", Summary: "撤销绑定码", Group: "admin"},

	{Method: "GET", Path: "/api/v1/admin/agents", OperationID: "listAgents", Summary: "列出智能体账号", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/agents", OperationID: "createAgent", Summary: "创建智能体账号", Group: "admin"},
	{Method: "GET", Path: "/api/v1/admin/agents/{id}", OperationID: "getAgent", Summary: "智能体详情", Group: "admin"},
	{Method: "PUT", Path: "/api/v1/admin/agents/{id}", OperationID: "updateAgent", Summary: "更新智能体", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/agents/{id}/rotate-secret", OperationID: "rotateAgentSecret", Summary: "轮换 client_secret", Group: "admin"},
	{Method: "DELETE", Path: "/api/v1/admin/agents/{id}", OperationID: "deleteAgent", Summary: "删除智能体", Group: "admin"},

	{Method: "GET", Path: "/api/v1/admin/roles", OperationID: "listRoles", Summary: "列出角色", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/roles", OperationID: "createRole", Summary: "创建角色", Group: "admin"},
	{Method: "GET", Path: "/api/v1/admin/roles/{id}", OperationID: "getRole", Summary: "角色详情", Group: "admin"},
	{Method: "PUT", Path: "/api/v1/admin/roles/{id}", OperationID: "updateRole", Summary: "更新角色", Group: "admin"},
	{Method: "DELETE", Path: "/api/v1/admin/roles/{id}", OperationID: "deleteRole", Summary: "删除角色", Group: "admin"},

	{Method: "GET", Path: "/api/v1/admin/invites", OperationID: "listInvites", Summary: "列出租户邀请码", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/invites", OperationID: "createInvite", Summary: "创建租户邀请码", Group: "admin"},
	{Method: "DELETE", Path: "/api/v1/admin/invites/{id}", OperationID: "revokeInvite", Summary: "撤销邀请码", Group: "admin"},

	{Method: "GET", Path: "/api/v1/admin/org-units", OperationID: "listOrgUnits", Summary: "组织树列表", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/org-units", OperationID: "createOrgUnit", Summary: "创建组织节点", Group: "admin"},
	{Method: "PUT", Path: "/api/v1/admin/org-units/{id}", OperationID: "updateOrgUnit", Summary: "更新组织节点", Group: "admin"},
	{Method: "DELETE", Path: "/api/v1/admin/org-units/{id}", OperationID: "deleteOrgUnit", Summary: "删除组织节点", Group: "admin"},

	{Method: "GET", Path: "/api/v1/admin/sync/channels", OperationID: "listSyncChannels", Summary: "列出跨库同步通道", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/sync/channels", OperationID: "createSyncChannel", Summary: "创建同步通道（可配线上 DSN）", Group: "admin"},
	{Method: "PUT", Path: "/api/v1/admin/sync/channels/{id}", OperationID: "updateSyncChannel", Summary: "更新同步通道", Group: "admin"},
	{Method: "DELETE", Path: "/api/v1/admin/sync/channels/{id}", OperationID: "deleteSyncChannel", Summary: "删除同步通道", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/sync/test", OperationID: "testSyncEndpoints", Summary: "测试本地/线上库连接", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/sync/channels/{id}/prepare", OperationID: "prepareSyncChannel", Summary: "准备同步（建 outbox/触发器）", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/sync/channels/{id}/start", OperationID: "startSyncChannel", Summary: "启动近实时同步", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/sync/channels/{id}/stop", OperationID: "stopSyncChannel", Summary: "停止同步", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/sync/channels/{id}/reconcile", OperationID: "reconcileSyncChannel", Summary: "主键对账（同步修复，有限流）", Group: "admin"},
	{Method: "GET", Path: "/api/v1/admin/sync/channels/{id}/checkpoint", OperationID: "getSyncCheckpoint", Summary: "线上库同步快照摘要（latest/previous）", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/sync/channels/{id}/restore", OperationID: "restoreSyncChannel", Summary: "按上次同步快照恢复线上库", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/sync/channels/{id}/ingest", OperationID: "ingestSyncRows", Summary: "外部行写入通道 local", Group: "admin"},
	{Method: "GET", Path: "/api/v1/admin/sync/bindings", OperationID: "listSyncBindings", Summary: "列出本机库↔线上库绑定（用户仅本人）", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/sync/bindings", OperationID: "ensureSyncBinding", Summary: "登记/更新绑定（用户可自助）", Group: "admin"},
	{Method: "GET", Path: "/api/v1/admin/sync/conflicts", OperationID: "listSyncConflicts", Summary: "已废弃：公司侧 403，改用超管 LWW 审计", Group: "admin"},
	{Method: "POST", Path: "/api/v1/admin/sync/conflicts/{id}/resolve", OperationID: "resolveSyncConflict", Summary: "已废弃：公司侧 403", Group: "admin"},
	{Method: "GET", Path: "/api/v1/agent/sync/channels/{id}/whitelist", OperationID: "agentSyncWhitelist", Summary: "拉取表白名单（管理员或用户+Binding）", Group: "agent"},
	{Method: "POST", Path: "/api/v1/agent/sync/channels/{id}/push", OperationID: "agentSyncPush", Summary: "推变更到线上 A（用户须 online_db_id）", Group: "agent"},
	{Method: "POST", Path: "/api/v1/agent/sync/channels/{id}/push/batch", OperationID: "agentSyncPushBatch", Summary: "批量推送（同上鉴权）", Group: "agent"},
	{Method: "POST", Path: "/api/v1/agent/sync/channels/{id}/pull", OperationID: "agentSyncPull", Summary: "从线上 A 下行（bootstrap/rows/pks）", Group: "agent"},
	{Method: "POST", Path: "/api/v1/agent/sync/channels/{id}/bootstrap", OperationID: "agentSyncBootstrap", Summary: "全量灌库别名（mode=bootstrap）", Group: "agent"},
	{Method: "POST", Path: "/api/v1/agent/sync/channels/{id}/schema", OperationID: "agentSyncSchema", Summary: "拉线上表结构（含空表 columns）", Group: "agent"},
	{Method: "POST", Path: "/api/v1/agent/sync/channels/{id}/schema/ensure", OperationID: "agentSyncSchemaEnsure", Summary: "本机表结构推到线上（Z10/Z10d 可补列）", Group: "agent"},
	{Method: "POST", Path: "/api/v1/agent/sync/channels/{id}/schema/fingerprint", OperationID: "agentSyncSchemaFingerprint", Summary: "线上表级指纹 row_count+content_hash（Z14）", Group: "agent"},
	{Method: "GET", Path: "/api/v1/platform/dbsync/lww-overrides", OperationID: "platformLwwOverrides", Summary: "超管查看 LWW 覆盖审计", Group: "platform"},
	{Method: "POST", Path: "/api/v1/platform/dbsync/lww-overrides/{id}/rollback", OperationID: "platformLwwRollback", Summary: "超管按落败快照回滚线上单行", Group: "platform"},

	{Method: "GET", Path: "/api/v1/apps", OperationID: "listApps", Summary: "列出模块：管理账号看本租户全部（含在建）；智能体仅已授权", Group: "app"},
	{Method: "PUT", Path: "/api/v1/apps/{slug}/draft", OperationID: "saveDraft", Summary: "登记在建模块蓝图（不发布）", Group: "app"},
	{Method: "POST", Path: "/api/v1/apps/{slug}/publish", OperationID: "publishApp", Summary: "向建站平台发布模块；回执含按用户ID加密的访问路径", Group: "app"},
	{Method: "GET", Path: "/api/v1/apps/{slug}/blueprint", OperationID: "getBlueprint", Summary: "读取已发布模块蓝图", Group: "app"},
	{Method: "GET", Path: "/api/v1/apps/{slug}/agent-capsule", OperationID: "getAgentCapsule", Summary: "智能体加密契约", Group: "app"},
	{Method: "GET", Path: "/api/v1/public/m/{token}/blueprint", OperationID: "publicModulePathBlueprint", Summary: "经加密路径公开读取模块蓝图", Public: true, Group: "app"},

	{Method: "GET", Path: "/api/v1/apps/{slug}/{resource}", OperationID: "listRows", Summary: "列表", Group: "crud"},
	{Method: "POST", Path: "/api/v1/apps/{slug}/{resource}", OperationID: "createRow", Summary: "创建", Group: "crud"},
	{Method: "GET", Path: "/api/v1/apps/{slug}/{resource}/{id}", OperationID: "getRow", Summary: "详情", Group: "crud"},
	{Method: "PUT", Path: "/api/v1/apps/{slug}/{resource}/{id}", OperationID: "updateRow", Summary: "更新", Group: "crud"},
	{Method: "DELETE", Path: "/api/v1/apps/{slug}/{resource}/{id}", OperationID: "deleteRow", Summary: "删除", Group: "crud"},

	{Method: "POST", Path: "/api/v1/apps/{slug}/{resource}/import", OperationID: "importRows", Summary: "导入 Excel/CSV", Group: "crud"},
	{Method: "GET", Path: "/api/v1/apps/{slug}/{resource}/export", OperationID: "exportRows", Summary: "导出 Excel/CSV", Group: "crud"},
	{Method: "GET", Path: "/api/v1/apps/{slug}/{resource}/aggregate", OperationID: "aggregateRows", Summary: "聚合统计", Group: "crud"},

	{Method: "GET", Path: "/api/v1/audit/logs", OperationID: "listAuditLogs", Summary: "审计日志", Group: "audit"},
	{Method: "POST", Path: "/api/v1/storage", OperationID: "uploadObject", Summary: "上传对象", Group: "storage"},
	{Method: "GET", Path: "/api/v1/storage/{tenant}/{day}/{name}", OperationID: "downloadObject", Summary: "下载对象", Group: "storage"},
}

// AICatalog 由 AI 服务提供，经网关 /ai 前缀访问；不在 platform 重复实现。
var AICatalog = []Entry{
	{Method: "GET", Path: "/api/v1/llm/providers", OperationID: "listLlmProviders", Summary: "LLM 厂商列表", Public: true, Group: "ai"},
	{Method: "POST", Path: "/api/v1/apps/generate", OperationID: "generateBlueprint", Summary: "生成蓝图草稿", Public: true, Group: "ai"},
}

// ReservedResources 不可作为动态 resource 名，避免与固定路由冲突。
var ReservedResources = map[string]struct{}{
	"blueprint": {}, "publish": {}, "agent-capsule": {},
	"import": {}, "export": {}, "aggregate": {},
	"generate": {}, "meta": {},
}

func IsReservedResource(name string) bool {
	_, ok := ReservedResources[name]
	return ok
}
