-- Resource URI mapper for authz
-- Maps request paths to resource URIs and generates req_uri with actual parameter values

local ResourceMapper = {}

-- Mapping table from request path patterns to resource URI templates
-- Pattern uses Lua pattern matching syntax
-- Resource URI uses {param_name} for parameter placeholders
local RESOURCE_MAPPINGS = {
  -- Metrics API (BYOC org-scoped; must precede the nextgen entry)
  {
    pattern = "^/[^/]+/metrics/",
    biz_type = {"byoc"},
    resource_uri = "o11y/orgs/{org_id}/byoc/metrics",
  },
  {
    pattern = "^/[^/]+/metrics/",
    biz_type = {".*nextgen"},
    resource_uri = "o11y/orgs/{org_id}/tidbs/{cluster_id}/metrics",
  },
  {
    pattern = "^/[^/]+/metrics/",
    biz_type = {".*tidbcloud",".*devtier"},
    resource_uri = "o11y/orgs/{org_id}/projects/{project_id}/tidbs/{cluster_id}/metrics",
  },
  -- Diagnosis API (BYOC org-scoped; must precede the nextgen entry)
  {
    pattern = "^/[^/]+/diagnosis/",
    biz_type = {"byoc"},
    resource_uri = "o11y/orgs/{org_id}/byoc/diagnosis",
  },
  {
    pattern = "^/[^/]+/diagnosis/",
    biz_type = {".*nextgen"},
    resource_uri = "o11y/orgs/{org_id}/tidbs/{cluster_id}/diagnosis",
  },
  {
    pattern = "^/[^/]+/diagnosis/",
    biz_type = {".*tidbcloud",".*devtier"},
    resource_uri = "o11y/orgs/{org_id}/projects/{project_id}/tidbs/{cluster_id}/diagnosis",
  },
}

-- Replace placeholders in resource URI template with actual values
-- Example: "o11y/orgs/{org_id}/tidbs/{cluster_id}/metrics"
--       -> "o11y/orgs/12345/tidbs/67890/metrics"
local function fill_resource_uri_params(resource_uri_template, params)
  local result = resource_uri_template

  for key, value in pairs(params) do
    local placeholder = "{" .. key .. "}"
    if value then
      result = result:gsub(placeholder, function() return value end)
    end
  end

  return result
end

-- Map request path to resource URI template
-- Returns: resource_uri_template or nil if no mapping found
function ResourceMapper.get_resource_uri_template(request_path, biz_type)
  for _, mapping in ipairs(RESOURCE_MAPPINGS) do
    if request_path:match(mapping.pattern) then
      for _, biz_pattern in ipairs(mapping.biz_type) do
        if biz_type:match(biz_pattern) then
          return mapping.resource_uri
        end
      end
    end
  end
  return nil
end

-- Get resource URI and req_uri for authz check
-- Parameters:
--   request_path: The request path after removing Kong's route prefix (from get_request_path_without_prefix)
--   org_id: Organization ID from X-Org-Id header
--   project_id: Project ID from X-Project-Id header
--   cluster_id: Cluster ID from X-Application-Id header
-- Returns:
--   resource_uri: The resource URI template for authz registration
--   req_uri: The resource URI filled with actual parameter values for authz check
function ResourceMapper.get_authz_uris(request_path, biz_type, org_id, project_id, cluster_id)
  -- Get resource URI template
  local resource_uri_template = ResourceMapper.get_resource_uri_template(request_path, biz_type)

  if not resource_uri_template then
    -- No mapping found, use request path as both resource_uri and req_uri
    -- NOTE: This will often be denied by authz service
    kong.log.warn("No resource URI mapping found for request path: ", request_path,
      ", biz_type: ", biz_type, ", trace_id: ",
        kong.ctx.shared.trace_id or "-")
    return request_path, request_path
  end

  if not org_id or not cluster_id then
    kong.log.warn("Missing org_id or cluster_id for request path: ", request_path, ", trace_id: ",
        kong.ctx.shared.trace_id or "-")
  end

  local params = {
    org_id = org_id or "",
    project_id = project_id or "",
    cluster_id = cluster_id or "",
  }
  local req_uri = fill_resource_uri_params(resource_uri_template, params)

  return resource_uri_template, req_uri
end

return ResourceMapper
