module RuboCop
  module Cop
    module Mirego
      class ExplicitReturnValue < Cop
        MESSAGE = 'Always specify a value with `return`'.freeze

        def on_def(node)
          _, _, body = *node
          check(node: body)
        end

        def on_defs(node)
          _, _, _, body = *node
          check(node: body)
        end

      protected

        def check(node:)
          expressions = *node
          return nil unless node

          if expressions.empty?
            validate_expression(expression: node)
          else
            expressions.compact.each { |expression| validate_expression(expression: expression) }
          end
        end

        def validate_expression(expression:)
          if return_node_type(node: expression)
            check_return_node(node: expression, children: expression.children)
          elsif expression.respond_to?(:children)
            children = expression.children.compact

            check_return_node(node: expression, children: children.last.to_a) if children.last && return_node_type(node: children.last)
          end
        end

        def check_return_node(node:, children:)
          return nil unless children.empty?

          add_offense(node, :expression, MESSAGE)
        end

        def return_node_type(node:)
          node.respond_to?(:type) && node.type == :return
        end
      end
    end
  end
end