# typed: strict
# frozen_string_literal: true

require "rubocops/extend/formula_cop"

module RuboCop
  module Cop
    module FormulaAudit
      # This cop audits Python formulae that include certain resources
      # to ensure that they also have the correct `uses_from_macos`
      # dependencies.
      class ResourceRequiresDependencies < FormulaCop
        sig { override.params(formula_nodes: FormulaNodes).void }
        def audit_formula(formula_nodes)
          return if (body_node = formula_nodes.body_node).nil?

          resource_nodes = find_every_method_call_by_name(body_node, :resource)
          return if resource_nodes.empty?

          %w[bcrypt lxml pynacl pyyaml].each do |resource_name|
            found = resource_nodes.find { |node| node.arguments&.first&.str_content == resource_name }
            next unless found

            uses_from_macos_nodes = find_every_method_call_by_name(body_node, :uses_from_macos)
            depends_on_nodes = find_every_method_call_by_name(body_node, :depends_on)
            uses_from_macos_or_depends_on = (uses_from_macos_nodes + depends_on_nodes).filter_map do |node|
              if (dep = node.arguments.first).hash_type?
                dep_types = dep.values.first
                dep_types = dep_types.array_type? ? dep_types.values : [dep_types]
                dep.keys.first.str_content if dep_types.select(&:sym_type?).map(&:value).include?(:build)
              else
                dep.str_content
              end
            end

            required_deps = case resource_name
            when "bcrypt"
              kind = "depends_on"
              ["pkgconf", "rust"]
            when "lxml"
              kind = depends_on?(:linux) ? "depends_on" : "uses_from_macos"
              ["libxml2", "libxslt"]
            when "pynacl"
              kind = "depends_on"
              ["libsodium"]
            when "pyyaml"
              kind = "depends_on"
              ["libyaml"]
            else
              []
            end
            next if required_deps.all? { |dep| uses_from_macos_or_depends_on.include?(dep) }

            @offensive_node = found
            problem "Add `#{kind}` lines above for #{required_deps.map { |req| "`\"#{req}\"`" }.join(" and ")}."
          end
        end
      end
    end
  end
end
