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

require "rfix"
require "rubocop"
require "rfix/formatter"
require "cli/ui"

should_list_files = false
limit_files       = false
options           = RuboCop::Options.new
config            = RuboCop::ConfigStore.new
display_help      = ARGV.include?("--help")
is_dry            = ARGV.include?("--dry")
config_path       = false

extend Rfix::Log
Rfix.init!
CLI::UI::StdoutRouter.enable

say "Using RuboCop {{yellow:#{RuboCop::Version.version}}}"

options.on("--untracked", "Include untracked files") do
  Rfix.load_untracked!
end

options.on("--dry", "No auto correct") do
  say "Will run rfix in {{red:read-only}} mode"
  Rfix.no_auto_correct!
end

options.on("--list-files", "List files found by git") do
  should_list_files = true
end

options.on("--limit-files NUM", Integer, "Limit number of files") do |limit|
  limit_files = limit
end

options.on("--config PATH", "A configuration file") do |path|
  config_path = path
end

case cmd = ARGV.shift
when "info"
  say "Using Rfix {{yellow:#{Rfix::VERSION}}}"
  say "Using OS {{yellow:#{Rfix.current_os}}}"
  say "Using Git {{yellow:#{Rfix.git_version}}}"
  say "Using Ruby {{yellow:#{Rfix.ruby_version}}}"
  exit 0
when "lint"
  Rfix.lint_mode!
  reference = Rfix.ref_since_push
when "local"
  reference = Rfix.ref_since_push
when "origin"
  reference = Rfix.ref_since_origin
when "all"
  reference = false
  Rfix.global_enable!
when "branch"
  abort_message = "No branch passed as second argument"
  unless reference = ARGV.shift
    say_abort abort_message
  end

  # Catches:
  # NOT OK: branch --help
  # OK branch master --help
  say_abort abort_message if reference.start_with?("--")

  # Check if branch exists
  say_abort "Branch {{yellow:#{reference}}} does not exist" unless Rfix.has_branch?(reference)
else
  unless display_help
    say_error "Valid rfix commands are:"
    say_error_sub "\n"
    say_error_sub "\t{{bold:rfix branch <branch>}} -- {{italic:Fix changes made between HEAD and <branch>}}"
    say_error_sub "\t{{bold:rfix origin}}          -- {{italic:Fix changes made between HEAD and origin branch}}"
    say_error_sub "\t{{bold:rfix local}}           -- {{italic:Fix changes not yet pushed to upstream branch}}"
    say_error_sub "\t{{bold:rfix info}}            -- {{italic:Display runtime dependencies and their versions}}"
    say_error_sub "\t{{bold:rfix all}}             -- {{italic:Fix all files in this repository}} {{warning:(not recommended)}}"
    say_error_sub "\t{{bold:rfix lint}}            -- {{italic:Shortcut for 'local --dry --untracked'}}"
    say_error_sub "\n"
    say_error_sub "\t{{italic:Optional args: --dry --help --list-files --limit-files --config --untracked}}"
    exit 1
  end

  ARGV.unshift(cmd)
end

begin
  options, paths = options.parse(ARGV)
rescue OptionParser::MissingArgument => e
  say_abort "[Parser] #{e}"
end

if path = config_path
  Rfix.load_config do
    config.options_config = path
  end
else
  Rfix.load_config do
    config.for(Dir.pwd)
  end
end

if ref = reference
  say "Compare against {{yellow:#{ref}}}"

  Rfix.load_tracked!(ref)

  paths = Rfix.paths if paths.empty?

  say_exit "No files to run against" if paths.empty?
end

if limit = limit_files
  say "Limit number of files to {{yellow:#{limit}}}"
  paths = paths.take(limit)
end

if should_list_files
  say "Loaded {{yellow:#{paths.count}}} paths"
  paths.each do |path|
    say "\t" + Rfix.to_relative(path: path)
  end
end

env = RuboCop::CLI::Environment.new(
  Rfix.config.merge(options),
  config,
  paths
)

begin
  exit RuboCop::CLI::Command::ExecuteRunner.new(env).run
rescue RuboCop::Error => e
  say_abort e.message
end