require 'mixlib/shellout'

require_relative 'log'

class SugarJar
  module Util
    # a mixin to hold stuff that Commands and RepoConfig both use
    def self.which(cmd)
      path = which_nofail(cmd)
      return path if path

      SugarJar::Log.fatal("Could not find #{cmd} in your path")
      exit(1)
    end

    # Finds the first entry in the path for a binary and checks
    # to make sure it's not us. Warn if it is us as that won't work in 2.x
    def self.which_nofail(cmd)
      ENV['PATH'].split(File::PATH_SEPARATOR).each do |dir|
        p = File.join(dir, cmd)
        next unless File.exist?(p) && File.executable?(p)

        if File.basename(File.realpath(p)) == 'sj'
          SugarJar::Log.error(
            "'#{cmd}' is linked to 'sj' which is no longer supported.",
          )
          next
        end
        return p
      end
      false
    end

    def self.git_nofail(*args, color: true)
      if %w{diff log grep branch}.include?(args[0]) &&
         args.none? { |x| x.include?('color') }
        args << (color ? '--color' : '--no-color')
      end
      SugarJar::Log.trace("Running: git #{args.join(' ')}")
      Mixlib::ShellOut.new([which('git')] + args).run_command
    end

    def self.git(*, color: true)
      s = git_nofail(*, :color => color)
      s.error!
      s
    end

    def self.ghcli_nofail(*)
      forge_nofail('gh', *)
    end

    def self.ghcli(*)
      s = ghcli_nofail(*)
      s.error!
      s
    end

    def self.glcli_nofail(*)
      forge_nofail('glab', *)
    end

    def self.glcli(*)
      s = glcli_nofail(*)
      s.error!
      s
    end

    def self.forge_nofail(cli, *args)
      SugarJar::Log.trace("Running: #{cli} #{args.join(' ')}")
      bin = which(cli)
      s = Mixlib::ShellOut.new([bin] + args).run_command
      if s.error? && s.stderr.include?("#{cli} auth")
        SugarJar::Log.info(
          'glab was run but no gitlab token exists. Will run ' +
          '"glab auth login" to force\ngh to authenticate...',
        )
        unless system(bin, 'auth', 'login', '-p', 'ssh')
          SugarJar::Log.fatal(
            'That failed, I will bail out. Hub needs to get a github ' +
            'token. Try running "gh auth login" (will list info about ' +
            'your account) and try this again when that works.',
          )
          exit(1)
        end
      end
      s
    end

    def self.in_repo?
      s = git_nofail('rev-parse', '--is-inside-work-tree')
      !s.error? && s.stdout.strip == 'true'
    end

    def self.repo_root
      git('rev-parse', '--show-toplevel').stdout.strip
    end
  end
end
