# frozen_string_literal: true

module Plugin
  def self.initialization_guard(&block)
    block.call
  rescue => error
    plugins_directory = Rails.root + "plugins"

    if error.backtrace && error.backtrace_locations
      plugin_path =
        error
          .backtrace_locations
          .lazy
          .map do |location|
            resolved_path = location.absolute_path || location.path
            next if resolved_path.nil?
            Pathname.new(resolved_path).ascend.lazy.find { |path| path.parent == plugins_directory }
          end
          .next

      raise unless plugin_path

      stack_trace =
        error
          .backtrace
          .each_with_index
          .inject([]) do |messages, (line, index)|
            if index == 0
              messages << "#{line}: #{error} (#{error.class})"
            else
              messages << "\t#{index}: from #{line}"
            end
          end
          .reverse
          .join("\n")

      STDERR.puts <<~TEXT
          #{stack_trace}

          ** INCOMPATIBLE PLUGIN **

          You are unable to start Discourse due to errors in the plugin at
          #{plugin_path}

          Please try removing this plugin and rebuilding again!
        TEXT
    else
      STDERR.puts <<~TEXT
          ** PLUGIN FAILURE **

          You are unable to start Discourse due to this error during plugin
          initialization:

          #{error}

          #{error.backtrace.join("\n")}
        TEXT
    end
    exit 1
  end
end
