module JSONAPI::Routing

def build_controller_name(resource_name, namespace = nil)

def build_controller_name(resource_name, namespace = nil)
  base_name = "#{resource_name.pluralize.camelize}Controller"
  return base_name unless namespace
  "#{namespace.to_s.camelize}::#{base_name}"
end

def build_jsonapi_defaults(defaults, resource_name, namespace)

def build_jsonapi_defaults(defaults, resource_name, namespace)
  defaults.merge(format: :jsonapi, resource_type: resource_name, jsonapi_namespace: namespace)
end

def define_auto_sti_routes(resource, resource_name, defaults, namespace = nil)

def define_auto_sti_routes(resource, resource_name, defaults, namespace = nil)
  resource_class = JSONAPI::ResourceLoader.find(resource_name, namespace:)
  model_class = resource_class.model_class
  return unless model_class.respond_to?(:descendants)
  model_class.descendants.each do |subclass|
    sub_resource_name = subclass.name.demodulize.underscore.pluralize.to_sym
    next if sub_resource_name == resource.to_sym
    jsonapi_resources(sub_resource_name, defaults:)
  rescue NameError, JSONAPI::ResourceLoader::MissingResourceClass
    next
  end
end

def define_explicit_sti_routes(sti_resources, defaults)

def define_explicit_sti_routes(sti_resources, defaults)
  sti_resources.each do |entry|
    case entry
    in Hash
      entry.each { |sub_resource_name, options| jsonapi_resources(sub_resource_name, defaults:, **options) }
    else
      jsonapi_resources(entry, defaults:)
    end
  end
end

def define_relationship_routes

def define_relationship_routes
  member do
    get "relationships/:relationship_name", to: "json_api/relationships#show", as: :relationship
    patch "relationships/:relationship_name", to: "json_api/relationships#update"
    delete "relationships/:relationship_name", to: "json_api/relationships#destroy"
  end
end

def define_resource_routes(resource, controller, defaults, options, &block)

def define_resource_routes(resource, controller, defaults, options, &block)
  resources(resource, controller:, defaults:, **options) do
    define_relationship_routes
    instance_eval(&block) if block
  end
end

def define_sti_routes(resource, resource_name, defaults, sti, namespace = nil)

def define_sti_routes(resource, resource_name, defaults, sti, namespace = nil)
  return unless sti
  if sti.is_a?(Array)
    define_explicit_sti_routes(sti, defaults)
  else
    define_auto_sti_routes(resource, resource_name, defaults, namespace)
  end
end

def detect_controller(resource_name, namespace = nil)

def detect_controller(resource_name, namespace = nil)
  potential_controller_name = build_controller_name(resource_name, namespace)
  potential_controller_name.constantize
  nil
rescue NameError
  "json_api/resources"
end

def extract_namespace_from_scope

def extract_namespace_from_scope
  @scope[:module]&.to_s.presence
end

def jsonapi_resources(resource, controller: nil, defaults: {}, sti: false, **options, &)

def jsonapi_resources(resource, controller: nil, defaults: {}, sti: false, **options, &)
  resource_name = resource.to_s
  namespace = extract_namespace_from_scope
  controller ||= detect_controller(resource_name, namespace)
  defaults = build_jsonapi_defaults(defaults, resource_name, namespace)
  options[:only] = :index if sti
  JSONAPI::ResourceLoader.find(resource_name, namespace:)
  define_resource_routes(resource, controller, defaults, options, &)
  define_sti_routes(resource, resource_name, defaults, sti, namespace)
end