package routecatalog

import (
	"sort"
	"strings"
)

// RouteBodyPolicy controls request-body handling for sensitive routes.
type RouteBodyPolicy string

const (
	BodyPolicyDefault           RouteBodyPolicy = "default"
	BodyPolicyIntegrationConfig RouteBodyPolicy = "integration_config"
	BodyPolicyPaymentConfig     RouteBodyPolicy = "payment_config"
	BodyPolicyPaymentCallback   RouteBodyPolicy = "payment_callback"
)

// Descriptor is the shared HTTP contract consumed by service bootstrap,
// Swagger generation and audit middleware.
type Descriptor struct {
	Method      string
	Path        string
	Public      bool
	Audit       bool
	Group       string
	Description string
	BodyPolicy  RouteBodyPolicy
}

type routeValue struct {
	group       string
	description string
	public      bool
	audit       bool
	bodyPolicy  RouteBodyPolicy
}

// routes is the single declaration point for cross-cutting route policy.
// Gin router files still bind handlers; tests keep those registrations aligned
// with this catalog while public, audit and API metadata live only here.
var routes = map[string]routeValue{
	"DELETE /api/deleteApisByIds":                              {group: "api", description: "批量删除api", audit: true},
	"DELETE /dataAccessLog/deleteDataAccessLogByIds":           {group: "数据权限审计", description: "批量删除数据权限审计日志", audit: true},
	"DELETE /department/deleteDepartment":                      {group: "部门", description: "删除部门", audit: true},
	"DELETE /info/deleteInfo":                                  {group: "公告", description: "删除公告", audit: true},
	"DELETE /info/deleteInfoByIds":                             {group: "公告", description: "批量删除公告", audit: true},
	"DELETE /integration/configs/:kind/:provider":              {group: "集成配置", description: "删除集成配置", audit: true},
	"DELETE /mediaUpload/:uploadId":                            {group: "媒体上传", description: "取消大文件上传"},
	"DELETE /position/deletePosition":                          {group: "岗位", description: "删除岗位", audit: true},
	"DELETE /sysDictionary/deleteSysDictionary":                {group: "系统字典", description: "删除字典", audit: true},
	"DELETE /sysDictionaryDetail/deleteSysDictionaryDetail":    {group: "系统字典详情", description: "删除字典内容", audit: true},
	"DELETE /sysError/deleteSysError":                          {group: "错误日志", description: "删除错误日志", audit: true},
	"DELETE /sysError/deleteSysErrorByIds":                     {group: "错误日志", description: "批量删除错误日志", audit: true},
	"DELETE /sysExportTemplate/deleteSysExportTemplate":        {group: "导出模板", description: "删除导出模板", audit: true},
	"DELETE /sysExportTemplate/deleteSysExportTemplateByIds":   {group: "导出模板", description: "批量删除导出模板", audit: true},
	"DELETE /sysLoginLog/deleteLoginLog":                       {group: "登录日志", description: "删除登录日志", audit: true},
	"DELETE /sysLoginLog/deleteLoginLogByIds":                  {group: "登录日志", description: "批量删除登录日志", audit: true},
	"DELETE /sysOperationRecord/deleteSysOperationRecord":      {group: "操作记录", description: "删除操作记录"},
	"DELETE /sysOperationRecord/deleteSysOperationRecordByIds": {group: "操作记录", description: "批量删除操作历史"},
	"DELETE /sysParams/deleteSysParams":                        {group: "参数管理", description: "删除参数", audit: true},
	"DELETE /sysParams/deleteSysParamsByIds":                   {group: "参数管理", description: "批量删除参数", audit: true},
	"DELETE /sysVersion/deleteSysVersion":                      {group: "版本控制", description: "删除版本", audit: true},
	"DELETE /sysVersion/deleteSysVersionByIds":                 {group: "版本控制", description: "批量删除版本", audit: true},
	"DELETE /timedTask/deleteTimedTask":                        {group: "定时任务", description: "删除定时任务", audit: true},
	"DELETE /user/deleteUser":                                  {group: "系统用户", description: "删除用户", audit: true},
	"GET /api/getApiGroups":                                    {group: "api", description: "获取路由组", audit: true},
	"GET /api/getApiRoles":                                     {group: "api", description: "获取指定API关联角色列表"},
	"GET /api/syncApi":                                         {group: "api", description: "获取待同步API", audit: true},
	"GET /api/freshCasbin":                                     {group: "api", description: "刷新 Casbin 缓存"},
	"GET /attachmentCategory/getCategoryList":                  {group: "媒体库分类", description: "分类列表"},
	"GET /authority/getDataScopeDepts":                         {group: "角色", description: "获取角色自定义部门集"},
	"GET /authority/getUsersByAuthority":                       {group: "角色", description: "获取角色关联用户ID列表"},
	"GET /department/findDepartment":                           {group: "部门", description: "根据ID获取部门"},
	"GET /department/getDepartmentUsers":                       {group: "部门", description: "获取部门成员ID列表"},
	"GET /fileUploadAndDownload/findFile":                      {group: "文件上传与下载", description: "获取文件详情"},
	"GET /health":                                              {group: "base", description: "健康检查", public: true},
	"GET /info/findInfo":                                       {group: "公告", description: "根据ID获取公告"},
	"GET /info/getInfoDataSource":                              {group: "公告", description: "获取公告数据源"},
	"GET /info/getInfoList":                                    {group: "公告", description: "获取公告列表"},
	"GET /info/getInfoPublic":                                  {group: "公告", description: "获取公开公告", public: true},
	"GET /integration/configs/:kind":                           {group: "集成配置", description: "按类型获取集成配置"},
	"GET /integration/configs/:kind/:provider":                 {group: "集成配置", description: "获取指定集成配置"},
	"GET /logViewer/content":                                   {group: "文件日志", description: "分块读取日志文件内容"},
	"GET /logViewer/dates":                                     {group: "文件日志", description: "获取存在日志的日期"},
	"GET /logViewer/files":                                     {group: "文件日志", description: "获取日期下的日志文件"},
	"GET /menu/getMenuRoles":                                   {group: "菜单", description: "获取菜单关联角色列表"},
	"GET /payment/orders":                                      {group: "支付", description: "分页查询支付订单"},
	"GET /payment/orders/:provider/:tradeNo":                   {group: "支付", description: "按路径查询支付订单"},
	"GET /position/findPosition":                               {group: "岗位", description: "根据ID获取岗位"},
	"GET /position/getPositionUsers":                           {group: "岗位", description: "获取岗位成员ID列表"},
	"GET /securityConfig/getSecurityConfig":                    {group: "安全配置", description: "获取安全配置"},
	"GET /swagger/*any":                                        {group: "base", description: "Swagger 文档", public: true},
	"GET /sysDictionary/exportSysDictionary":                   {group: "系统字典", description: "导出字典JSON", audit: true},
	"GET /sysDictionary/findSysDictionary":                     {group: "系统字典", description: "根据ID获取字典（建议选择）"},
	"GET /sysDictionary/getSysDictionaryList":                  {group: "系统字典", description: "获取字典列表"},
	"GET /sysDictionary/getSysDictionaryListWithDetails":       {group: "系统字典", description: "获取字典列表(含明细)"},
	"GET /sysDictionaryDetail/findSysDictionaryDetail":         {group: "系统字典详情", description: "根据ID获取字典内容"},
	"GET /sysDictionaryDetail/getDictionaryDetailsByParent":    {group: "系统字典详情", description: "根据父级ID获取字典详情"},
	"GET /sysDictionaryDetail/getDictionaryPath":               {group: "系统字典详情", description: "获取字典详情的完整路径"},
	"GET /sysDictionaryDetail/getDictionaryTreeList":           {group: "系统字典详情", description: "获取字典数列表"},
	"GET /sysDictionaryDetail/getDictionaryTreeListByType":     {group: "系统字典详情", description: "根据分类获取字典数列表"},
	"GET /sysDictionaryDetail/getSysDictionaryDetailList":      {group: "系统字典详情", description: "获取字典内容列表"},
	"GET /sysError/findSysError":                               {group: "错误日志", description: "根据ID获取错误日志"},
	"GET /sysError/getSysErrorList":                            {group: "错误日志", description: "获取错误日志列表"},
	"GET /sysExportTemplate/exportExcel":                       {group: "导出模板", description: "导出Excel"},
	"GET /sysExportTemplate/exportExcelByToken":                {group: "导出模板", description: "按令牌导出Excel", public: true},
	"GET /sysExportTemplate/exportTemplate":                    {group: "导出模板", description: "下载模板"},
	"GET /sysExportTemplate/exportTemplateByToken":             {group: "导出模板", description: "按令牌下载模板", public: true},
	"GET /sysExportTemplate/findSysExportTemplate":             {group: "导出模板", description: "根据ID获取导出模板"},
	"GET /sysExportTemplate/getSysExportTemplateList":          {group: "导出模板", description: "获取导出模板列表"},
	"GET /sysExportTemplate/previewSQL":                        {group: "导出模板", description: "预览SQL"},
	"GET /sysLoginLog/findLoginLog":                            {group: "登录日志", description: "根据ID获取登录日志"},
	"GET /sysLoginLog/getLoginLogList":                         {group: "登录日志", description: "获取登录日志列表"},
	"GET /sysOperationRecord/findSysOperationRecord":           {group: "操作记录", description: "根据ID获取操作记录"},
	"GET /sysOperationRecord/getSysOperationRecordList":        {group: "操作记录", description: "获取操作记录列表"},
	"GET /sysParams/findSysParams":                             {group: "参数管理", description: "根据ID获取参数"},
	"GET /sysParams/getSysParam":                               {group: "参数管理", description: "获取参数列表"},
	"GET /sysParams/getSysParamsList":                          {group: "参数管理", description: "获取参数列表"},
	"GET /sysVersion/downloadVersionJson":                      {group: "版本控制", description: "下载版本json"},
	"GET /sysVersion/findSysVersion":                           {group: "版本控制", description: "获取单一版本"},
	"GET /sysVersion/getSysVersionList":                        {group: "版本控制", description: "获取版本列表"},
	"GET /timedTask/alertStream":                               {group: "定时任务", description: "订阅定时任务失败告警(SSE)"},
	"GET /timedTask/getRegisteredMethods":                      {group: "定时任务", description: "获取已注册方法列表"},
	"GET /timedTask/getTimedTaskList":                          {group: "定时任务", description: "获取定时任务列表"},
	"GET /timedTask/getTimedTaskLogList":                       {group: "定时任务", description: "获取定时任务执行日志"},
	"GET /user/getUserInfo":                                    {group: "系统用户", description: "获取自身信息(必选)"},
	"POST /api/createApi":                                      {group: "api", description: "创建api", audit: true},
	"POST /api/deleteApi":                                      {group: "api", description: "删除Api", audit: true},
	"POST /api/enterSyncApi":                                   {group: "api", description: "确认同步API", audit: true},
	"POST /api/getAllApis":                                     {group: "api", description: "获取所有api"},
	"POST /api/getApiById":                                     {group: "api", description: "获取api详细信息", audit: true},
	"POST /api/getApiList":                                     {group: "api", description: "获取api列表"},
	"POST /api/ignoreApi":                                      {group: "api", description: "忽略API", audit: true},
	"POST /api/setApiRoles":                                    {group: "api", description: "全量覆盖API关联角色列表", audit: true},
	"POST /api/updateApi":                                      {group: "api", description: "更新Api", audit: true},
	"POST /attachmentCategory/addCategory":                     {group: "媒体库分类", description: "添加/编辑分类"},
	"POST /attachmentCategory/deleteCategory":                  {group: "媒体库分类", description: "删除分类"},
	"POST /authority/copyAuthority":                            {group: "角色", description: "拷贝角色", audit: true},
	"POST /authority/createAuthority":                          {group: "角色", description: "创建角色", audit: true},
	"POST /authority/deleteAuthority":                          {group: "角色", description: "删除角色", audit: true},
	"POST /authority/getAuthorityList":                         {group: "角色", description: "获取角色列表"},
	"POST /authority/setDataScope":                             {group: "角色", description: "设置角色数据权限", audit: true},
	"POST /authority/setRoleUsers":                             {group: "角色", description: "全量覆盖角色关联用户", audit: true},
	"POST /authorityBtn/canRemoveAuthorityBtn":                 {group: "按钮权限", description: "删除按钮"},
	"POST /authorityBtn/getAuthorityBtn":                       {group: "按钮权限", description: "获取已有按钮权限"},
	"POST /authorityBtn/setAuthorityBtn":                       {group: "按钮权限", description: "设置按钮权限"},
	"POST /base/captcha":                                       {group: "base", description: "获取验证码", public: true},
	"POST /base/login":                                         {group: "base", description: "登录", public: true},
	"POST /casbin/getPolicyPathByAuthorityId":                  {group: "casbin", description: "获取权限列表"},
	"POST /casbin/updateCasbin":                                {group: "casbin", description: "更改角色api权限", audit: true},
	"POST /dataAccessLog/getDataAccessLogList":                 {group: "数据权限审计", description: "获取数据权限审计日志"},
	"POST /department/createDepartment":                        {group: "部门", description: "创建部门", audit: true},
	"POST /department/getDepartmentList":                       {group: "部门", description: "获取部门树"},
	"POST /department/setDepartmentUsers":                      {group: "部门", description: "设置部门成员(反向分配)", audit: true},
	"POST /email/emailTest":                                    {group: "email", description: "发送测试邮件", audit: true},
	"POST /email/sendEmail":                                    {group: "email", description: "发送邮件", audit: true},
	"POST /fileUploadAndDownload/deleteFile":                   {group: "文件上传与下载", description: "删除文件"},
	"POST /fileUploadAndDownload/deleteFiles":                  {group: "文件上传与下载", description: "批量删除文件"},
	"POST /fileUploadAndDownload/editFileName":                 {group: "文件上传与下载", description: "文件名或者备注编辑"},
	"POST /fileUploadAndDownload/getFileList":                  {group: "文件上传与下载", description: "获取上传文件列表"},
	"POST /fileUploadAndDownload/importURL":                    {group: "文件上传与下载", description: "导入URL"},
	"POST /fileUploadAndDownload/listOssFiles":                 {group: "文件上传与下载", description: "获取对象存储文件列表"},
	"POST /fileUploadAndDownload/upload":                       {group: "文件上传与下载", description: "文件上传（建议选择）"},
	"POST /info/createInfo":                                    {group: "公告", description: "新建公告", audit: true},
	"POST /init/checkdb":                                       {group: "初始化", description: "检查数据库", public: true},
	"POST /init/initdb":                                        {group: "初始化", description: "初始化数据库", public: true},
	"POST /integration/configs/:kind/:provider/test":           {group: "集成配置", description: "测试通信集成连接", audit: true},
	"POST /jwt/jsonInBlacklist":                                {group: "jwt", description: "jwt加入黑名单(退出，必选)"},
	"POST /mediaUpload/chunk":                                  {group: "媒体上传", description: "上传分片"},
	"POST /mediaUpload/complete":                               {group: "媒体上传", description: "完成大文件上传"},
	"POST /mediaUpload/init":                                   {group: "媒体上传", description: "初始化大文件上传"},
	"POST /menu/addBaseMenu":                                   {group: "菜单", description: "新增菜单", audit: true},
	"POST /menu/addMenuAuthority":                              {group: "菜单", description: "增加menu和角色关联关系", audit: true},
	"POST /menu/deleteBaseMenu":                                {group: "菜单", description: "删除菜单", audit: true},
	"POST /menu/getBaseMenuById":                               {group: "菜单", description: "根据id获取菜单"},
	"POST /menu/getBaseMenuTree":                               {group: "菜单", description: "获取用户动态路由"},
	"POST /menu/getMenu":                                       {group: "菜单", description: "获取菜单树(必选)"},
	"POST /menu/getMenuAuthority":                              {group: "菜单", description: "获取指定角色menu"},
	"POST /menu/getMenuList":                                   {group: "菜单", description: "分页获取基础menu列表"},
	"POST /menu/setMenuRoles":                                  {group: "菜单", description: "全量覆盖菜单关联角色列表", audit: true},
	"POST /menu/updateBaseMenu":                                {group: "菜单", description: "更新菜单", audit: true},
	"POST /payment/callback/:provider":                         {group: "支付", description: "处理支付回调", public: true, bodyPolicy: BodyPolicyPaymentCallback},
	"POST /payment/create":                                     {group: "支付", description: "创建支付订单", audit: true},
	"POST /payment/fulfill":                                    {group: "支付", description: "重试支付订单发货", audit: true},
	"POST /payment/order":                                      {group: "支付", description: "查询支付订单"},
	"POST /payment/orders/:provider/:tradeNo/fulfill":          {group: "支付", description: "按路径重试支付订单发货", audit: true},
	"POST /payment/orders/:provider/:tradeNo/refund":           {group: "支付", description: "按路径申请支付订单退款", audit: true},
	"POST /payment/providers/:provider/test":                   {group: "支付", description: "测试支付渠道配置与沙箱交易链路", audit: true},
	"POST /payment/query":                                      {group: "支付", description: "同步支付订单状态", audit: true},
	"POST /payment/refund":                                     {group: "支付", description: "申请支付订单退款", audit: true},
	"POST /position/createPosition":                            {group: "岗位", description: "创建岗位", audit: true},
	"POST /position/getPositionList":                           {group: "岗位", description: "获取岗位列表"},
	"POST /position/setPositionUsers":                          {group: "岗位", description: "设置岗位成员(反向分配)", audit: true},
	"POST /securityConfig/setSecurityConfig":                   {group: "安全配置", description: "设置安全配置", audit: true},
	"POST /sysApiToken/createApiToken":                         {group: "API Token", description: "签发API Token", audit: true},
	"POST /sysApiToken/deleteApiToken":                         {group: "API Token", description: "作废API Token", audit: true},
	"POST /sysApiToken/getApiTokenList":                        {group: "API Token", description: "获取API Token列表", audit: true},
	"POST /sysDictionary/createSysDictionary":                  {group: "系统字典", description: "新增字典", audit: true},
	"POST /sysDictionary/importSysDictionary":                  {group: "系统字典", description: "导入字典JSON", audit: true},
	"POST /sysDictionaryDetail/createSysDictionaryDetail":      {group: "系统字典详情", description: "新增字典内容", audit: true},
	"POST /sysError/createSysError":                            {group: "错误日志", description: "新建错误日志", public: true},
	"POST /sysExportTemplate/createSysExportTemplate":          {group: "导出模板", description: "新增导出模板", audit: true},
	"POST /sysExportTemplate/importExcel":                      {group: "导出模板", description: "导入Excel", audit: true},
	"POST /sysParams/createSysParams":                          {group: "参数管理", description: "新建参数", audit: true},
	"POST /system/getServerInfo":                               {group: "系统服务", description: "获取服务器信息"},
	"POST /system/getSystemConfig":                             {group: "系统服务", description: "获取配置文件内容"},
	"POST /system/reloadSystem":                                {group: "系统服务", description: "重载系统配置", audit: true},
	"POST /system/setSystemConfig":                             {group: "系统服务", description: "设置配置文件内容", audit: true},
	"POST /sysVersion/exportVersion":                           {group: "版本控制", description: "创建版本", audit: true},
	"POST /sysVersion/importVersion":                           {group: "版本控制", description: "同步版本", audit: true},
	"POST /timedTask/createTimedTask":                          {group: "定时任务", description: "创建定时任务", audit: true},
	"POST /timedTask/toggleTimedTask":                          {group: "定时任务", description: "启用/停用定时任务", audit: true},
	"POST /timedTask/triggerTimedTask":                         {group: "定时任务", description: "手动触发定时任务", audit: true},
	"POST /user/admin_register":                                {group: "系统用户", description: "用户注册", audit: true},
	"POST /user/changePassword":                                {group: "系统用户", description: "修改密码（建议选择)", audit: true},
	"POST /user/getUserList":                                   {group: "系统用户", description: "获取用户列表"},
	"POST /user/resetPassword":                                 {group: "系统用户", description: "重置用户密码", audit: true},
	"POST /user/setUserAuthorities":                            {group: "系统用户", description: "设置权限组", audit: true},
	"POST /user/setUserAuthority":                              {group: "系统用户", description: "修改用户角色(必选)", audit: true},
	"POST /user/setUserDepartments":                            {group: "系统用户", description: "设置用户归属部门", audit: true},
	"POST /user/setUserPositions":                              {group: "系统用户", description: "设置用户岗位", audit: true},
	"PUT /authority/updateAuthority":                           {group: "角色", description: "更新角色信息", audit: true},
	"PUT /department/updateDepartment":                         {group: "部门", description: "更新部门", audit: true},
	"PUT /info/updateInfo":                                     {group: "公告", description: "更新公告", audit: true},
	"PUT /integration/configs/:kind/:provider":                 {group: "集成配置", description: "保存集成配置", audit: true, bodyPolicy: BodyPolicyIntegrationConfig},
	"PUT /position/updatePosition":                             {group: "岗位", description: "更新岗位", audit: true},
	"PUT /sysDictionary/updateSysDictionary":                   {group: "系统字典", description: "更新字典", audit: true},
	"PUT /sysDictionaryDetail/updateSysDictionaryDetail":       {group: "系统字典详情", description: "更新字典内容", audit: true},
	"PUT /sysError/updateSysError":                             {group: "错误日志", description: "更新错误日志", audit: true},
	"PUT /sysExportTemplate/updateSysExportTemplate":           {group: "导出模板", description: "更新导出模板", audit: true},
	"PUT /sysParams/updateSysParams":                           {group: "参数管理", description: "更新参数", audit: true},
	"PUT /timedTask/updateTimedTask":                           {group: "定时任务", description: "更新定时任务", audit: true},
	"PUT /user/setSelfInfo":                                    {group: "系统用户", description: "设置自身信息(必选)", audit: true},
	"PUT /user/setSelfSetting":                                 {group: "系统用户", description: "用户界面配置", audit: true},
	"PUT /user/setUserInfo":                                    {group: "系统用户", description: "设置用户信息", audit: true},
}

func splitKey(key string) (string, string) {
	parts := strings.SplitN(key, " ", 2)
	if len(parts) != 2 {
		return "", key
	}
	return strings.ToUpper(parts[0]), normalizePath(parts[1])
}

func descriptorKey(method, path string) string {
	return strings.ToUpper(strings.TrimSpace(method)) + " " + normalizePath(path)
}

func normalizePath(path string) string {
	path = strings.TrimSpace(path)
	if path == "" {
		return "/"
	}
	return "/" + strings.Trim(path, "/")
}

func descriptorFrom(key string, value routeValue) Descriptor {
	method, path := splitKey(key)
	group := value.group
	if group == "" {
		group = RouteGroup(path)
	}
	return Descriptor{
		Method: method, Path: path, Public: value.public, Audit: value.audit,
		Group: group, Description: value.description, BodyPolicy: value.bodyPolicy,
	}
}

func pathMatches(pattern, path string) bool {
	patternParts := strings.Split(strings.Trim(normalizePath(pattern), "/"), "/")
	pathParts := strings.Split(strings.Trim(normalizePath(path), "/"), "/")
	if len(patternParts) == 1 && patternParts[0] == "" {
		return len(pathParts) == 1 && pathParts[0] == ""
	}
	if len(pathParts) < len(patternParts) {
		return false
	}
	offset := len(pathParts) - len(patternParts)
	for index, patternPart := range patternParts {
		if strings.HasPrefix(patternPart, "*") {
			return true
		}
		actual := pathParts[offset+index]
		if strings.HasPrefix(patternPart, ":") {
			if actual == "" {
				return false
			}
			continue
		}
		if patternPart != actual {
			return false
		}
	}
	return true
}

// Lookup accepts either a canonical Gin route template or an actual URL. A
// configured router prefix is tolerated by matching canonical paths by suffix.
func Lookup(method, path string) (Descriptor, bool) {
	key := descriptorKey(method, path)
	if value, ok := routes[key]; ok {
		return descriptorFrom(key, value), true
	}
	for key, value := range routes {
		descriptor := descriptorFrom(key, value)
		if strings.EqualFold(descriptor.Method, method) && pathMatches(descriptor.Path, path) {
			return descriptor, true
		}
	}
	return Descriptor{}, false
}

func Describe(method, path string) Descriptor {
	if descriptor, ok := Lookup(method, path); ok {
		return descriptor
	}
	return Descriptor{
		Method: strings.ToUpper(strings.TrimSpace(method)),
		Path:   normalizePath(path),
		Group:  RouteGroup(path),
	}
}

func ShouldAudit(method, path string) bool {
	descriptor, ok := Lookup(method, path)
	return ok && descriptor.Audit
}

func IsPublic(method, path string) bool {
	descriptor, ok := Lookup(method, path)
	return ok && descriptor.Public
}

// Descriptors returns an immutable, stable-order snapshot for startup and
// contract tests.
func Descriptors() []Descriptor {
	values := make([]Descriptor, 0, len(routes))
	for key, value := range routes {
		values = append(values, descriptorFrom(key, value))
	}
	sort.Slice(values, func(i, j int) bool {
		if values[i].Path == values[j].Path {
			return values[i].Method < values[j].Method
		}
		return values[i].Path < values[j].Path
	})
	return values
}

// BodyPolicyFor resolves generic integration configuration writes against the
// actual URL so only kind=payment receives the payment-config summary policy.
func BodyPolicyFor(method, path string) RouteBodyPolicy {
	descriptor, ok := Lookup(method, path)
	if !ok {
		return BodyPolicyDefault
	}
	if descriptor.BodyPolicy != BodyPolicyIntegrationConfig {
		return descriptor.BodyPolicy
	}
	parts := strings.Split(strings.Trim(normalizePath(path), "/"), "/")
	for index := 0; index+2 < len(parts); index++ {
		if parts[index] == "integration" && parts[index+1] == "configs" && parts[index+2] == "payment" {
			return BodyPolicyPaymentConfig
		}
	}
	return BodyPolicyDefault
}

func RouteGroup(path string) string {
	parts := strings.Split(strings.Trim(normalizePath(path), "/"), "/")
	if len(parts) > 0 && parts[0] != "" {
		return parts[0]
	}
	return "base"
}
