module Fastlane
  class Git
    def self.root
      `git rev-parse --show-toplevel`.strip
    end

    def self.current_branch
      `git rev-parse --abbrev-ref HEAD`.strip
    end

    def self.default_remote
      "origin"
    end

    def self.default_branch(remote_name: default_remote)
      `git remote show #{remote_name} | sed -n '/HEAD branch/s/.*: //p'`.strip
    end

    def self.default_branch_ref(remote_name: default_remote)
      "#{remote_name}/#{default_branch(remote_name: remote_name)}"
    end

    def self.current_sha(short: false)
      `git rev-parse #{short ? "--short" : ""} HEAD`.strip
    end

    def self.previous_sha(short: false)
      `git rev-parse #{short ? "--short" : ""} HEAD^`.strip
    end

    def self.relative_commit_date(sha: "")
      `git log -1 --relative-date --format='%cd' #{sha}`.strip
    end

    def self.last_merge_commit(subdir: nil)
      last_merge_sha = Actions.sh("git log -1 --merges --grep='Merge commit.*' --format='%H' #{subdir ? "#{subdir}/" : ""}", log: true).strip
      unless last_merge_sha
        return nil
      end
      message = Actions.sh("git log -1 --format='%s' #{last_merge_sha}", log: true).strip
      match = message.match(/Merge commit '([0-9a-f]{40})'/)
      unless match
        UI.crash!("Failed to parse merge commit message: #{message}")
      end
      {
        sha: last_merge_sha,
        merged_sha: match.captures.first,
        merged_at: relative_commit_date(sha: last_merge_sha)
      }
    end

    def self.summarize_changes(sha:, previous_sha: nil, max_commits: nil)
      range = [previous_sha, sha].compact.join("..")
      Actions.sh "git log --oneline #{range}", log: true do |status, result, command|
        unless status.success?
          UI.user_error!("Command #{command} (pid #{status.pid}) failed with status #{status.exitstatus}")
        end

        commits = result.strip.split("\n").reject(&:empty?)
        [
          "Summary of changes:",
          "",
          *commits[0..(max_commits || commits.length) - 1].map do |commit|
            "• #{commit.split(" ").drop(1).join(" ")} #{Github.commit_link(commit.split(" ")[0])}"
          end,
          commits.length > (max_commits || commits.length) ? "+ #{commits.length - (max_commits || commits.length)} more commits..." : nil
        ].compact.join("\n")
      rescue => e
        UI.user_error!("Failed to summarize changes for range #{range}: #{e.message}")
      end
    end
  end
end
