#!/usr/bin/env ruby
# frozen_string_literal: true

require 'optparse'
require 'dependency_checker'
require 'json'

options = {}
OptionParser.new do |opts|
  opts.on('-o module,version', '--override module,version', Array, 'Forge name of module and semantic version to override') do |override|
    options[:override] = override
  end

  opts.on('-c', '--current', 'Extract override version from metadata.json inside current working directory') do |current_override|
    options[:current_override] = current_override
  end

  opts.on('-n', '--namespace namespace', 'Check all modules in a given namespace (filter with endorsements).') do |namespace|
    options[:namespace] = namespace
  end

  opts.on('--endorsement endorsement', 'Filter a namespace search by endorsement (supported/approved/partner).') do |endorsement|
    raise 'You may only filter by one endorsement at a time' if options[:endorsement]

    options[:endorsement] = endorsement
  end

  opts.on('--es', '--supported', 'Shorthand for `--endorsement supported`') do
    raise 'You may only filter by one endorsement at a time' if options[:endorsement]

    options[:endorsement] = 'supported'
  end

  opts.on('--ea', '--approved', 'Shorthand for `--endorsement approved`') do
    raise 'You may only filter by one endorsement at a time' if options[:endorsement]

    options[:endorsement] = 'approved'
  end

  opts.on('--ep', '--partner', 'Shorthand for `--endorsement partner`') do
    raise 'You may only filter by one endorsement at a time' if options[:endorsement]

    options[:endorsement] = 'partner'
  end

  opts.on('--ft forge_token', '--forge-token forge_token', 'The API token to authenticate the Forge connection with') do |forge_token|
    options[:forge_token] = forge_token
  end

  opts.on('--fh forge_hostname', '--forge-hostname forge_hostname', 'Specify a specific Forge hostname to overwrite the default of https://forgeapi.puppet.com') do |forge_hostname|
    raise 'Forge host must be specified in the format https://your-own-api.url/' unless forge_hostname.start_with? 'http'

    options[:forge_hostname] = forge_hostname
  end

  opts.on('-v', '--[no-]verbose', 'Run verbosely') do
    options[:verbose] = true
  end

  opts.on('-h', '--help', 'Display help') do
    puts opts
    exit
  end
end.parse!

# Raise error if both :override and :current_override are specified
raise OptionParser::InvalidOption, 'You can not select both override and current override options' if options[:override] && options[:current_override]

# If :current_override is specified, retrieve name and version of module in current working directory
if options[:current_override]
  metadata_json = JSON.parse(File.read('metadata.json'))
  module_name = metadata_json['name'].sub('-', '/')
  module_version = metadata_json['version']

  override_check = metadata_json.is_a?(Hash) && !metadata_json.empty?
  options[:override] = [module_name, module_version] if override_check
  raise OptionParser::InvalidOption, 'Unable to find local metadata.json in current working directory' unless override_check
end

# Default :verbose to false
options[:verbose] ||= false

runner = DependencyChecker::Runner.new(options[:verbose], options[:forge_hostname], options[:forge_token])

if options[:namespace]
  runner.resolve_from_namespace(options[:namespace], options[:endorsement])

elsif ARGV.empty?
  puts "No module criteria specified. Defaulting to CAT supported modules.\n\n"
  runner.resolve_from_path('https://puppetlabs.github.io/content-and-tooling-team/modules/list.json')

elsif ARGV.map { |arg| File.basename arg } != ['metadata.json']
  runner.resolve_from_path(ARGV.first)

else
  runner.resolve_from_files(ARGV)
end

runner.override = options[:override]
runner.run

exit(runner.problems.zero? ? 0 : 1)
