# Uncomment the line if you want fastlane to automatically update itself
#update_fastlane

desc "fl docweb - run local webserver on generated doc"
lane :docweb do
  Dir.chdir("../") do
    # open browser http://localhost:8080 and run local webserver
    sh("dart pub global run dhttpd --path doc/api & open http://localhost:8080")
  end
end

desc "fl doc - generate doc and run webserver"
lane :doc do
  Dir.chdir("../") do
    # generate doc
    sh("dart doc")
    # run local webserver
    docweb
  end
end

desc "fl test - Run tests"
lane :test do
  Dir.chdir("../") do
    sh("flutter test")
  end
end

desc "fl checkout [issue:<issue>] - checkout lastest branch created or create new branch on <issue>"
lane :checkout do|options|
  issue_number = options[:issue]
  forge = detect_forge 

  if issue_number == nil || issue_number == ""
    puts "show open issues in #{forge}"
    if forge == "github"
      sh("gh issue list")
    elsif forge == "forgejo"
      sh("fj issue search");
    end
    issue_number = UI.input("Enter the issue number (without #):")
  end  
  puts "check issue #{issue_number} exists in #{forge}"
  if forge == "github"
    sh("gh issue list")
    found_issues = sh("gh issue list --search \"state:open #{issue_number}\"").strip!;
    if found_issues.start_with?("no issues")
      puts "issue #{issue_number} not found in #{forge}"
      exit(1)
    end
  elsif forge == "forgejo"
    found_issues = sh("fj issue search #{issue_number}").strip!;
    if found_issues.start_with?("0")
      puts "issue #{issue_number} not found in #{forge}"
      exit(1)
    end
  end
  puts "issue #{issue_number} found in #{forge}"
  puts "create and checkout branch #{issue_number}"
  sh("git checkout -b #{issue_number}")
  puts "push branch #{issue_number} to origin"
  sh("git push --set-upstream origin #{issue_number}")
end

desc "fl forge_release - Creates a forge release and update CHANGELOG.md"
lane :forge_release do
  version = ""
  Dir.chdir("../") do
    version = sh("dart run flutter_heyteacher_meta:dartsemver show")
  end 
  create_forge_release(version)
end

desc "fl release [semver:major|minor|patch] [suffix:<version_suffix>] [merge:true|false] [forge:true|false] [publish:false|true]- Creates new release, merge branch into main and creates a forge release"
lane :release do|options|
  if options[:semver] != nil && !["major", "minor", "patch"].include?(options[:semver])
    puts "invalid semver. Must be major|minor|patch found #{options[:semver]}"
    exit(1)
  end
  currentBranch = sh("git branch --show-current").strip!  
  if currentBranch == "main"
    puts "current branch must not be \"main\""
    exit(1)
  end
  sh("git pull")
  test
  version = ""
  Dir.chdir("../") do
    if options[:semver] != nil
      version = sh("dart run flutter_heyteacher_meta:dartsemver #{options[:semver]}")
    elsif
      version = sh("git-cliff --bumped-version").lines.last.strip!.split("-").last.split("+").first
      confirm = UI.input("Version detected is #{version}, confirm? (Y/n):")
      if confirm != nil && confirm != "" && confirm.downcase != "y"
        exit(0)
      end
      version = sh("dart run flutter_heyteacher_meta:dartsemver set --version #{version}")
      puts "\"pubspec.yaml\" updated with new version #{version}"
    end  
    # append tag suffix if set
    if options[:suffix] != nil && options[:suffix] != ""
      version = "#{version}-#{options[:suffix]}"
    end
  end
  # commit bump and push remote
  puts "commit pubspec.yaml with new version #{version}"
  sh("git add ../pubspec.yaml")
  sh("git commit -m \"build: update `pubspec.yaml` version to #{version} which closes ##{currentBranch}\"")
  push_to_git_remote
  if options[:merge] == nil || options[:merge] == true
    forge_merge(currentBranch)
  end
  puts "make release #{version} release forge #{options[:forge]}"
  if options[:forge] == nil || options[:forge] == true
    puts "create forge release for #{version}"
    create_forge_release(version)
  end
  if options[:publish] == true
    puts "publish on pub.dev"
    sh("dart pub publish -f")
  end
  puts "run pub get to update dependencies"
  sh("dart pub get")
end

##
# Detects forge
# @return: [String]  `github`, `forgejo`
# @raise: Exception if no github or forgejo detected
def detect_forge()
  url_forge = sh("git remote get-url --push origin").strip!  
  if url_forge.include? "https://github.com/"
    return "github"
  elsif url_forge.start_with?("https://codeberg.org/") \
        || url_forge.start_with?("https://bolha.dev/") \
        || url_forge.start_with?("https://codefloe.com/") \
        || url_forge.start_with?("https://git.gay/") \
        || url_forge.start_with?("https://git.kaki87.net/") \
        || url_forge.start_with?("https://opencommit.eu/") \
        || url_forge.start_with?("https://git.pub.solar/")
    return "forgejo"
  else
    raise Exception.new('no github or forgejo detected')
  end
end

##
# Merge branch to main repo
# @param: [String, #currentBranch] the current branch
def forge_merge(currentBranch)
  forge = detect_forge 
  puts "create pull request on #{forge} for branch #{currentBranch}"
  if forge == "github"
    sh("gh pr create --fill-verbose")
  elsif forge == "forgejo"
    sh("fj pr create --autofill")
  end
  puts "wait 1 second in order new pull request will be available on #{forge}"
  sleep(1)
  puts "merge pull request on #{forge}"
  if forge == "github"
    sh("gh pr merge -m -d --auto")
  elsif forge == "forgejo"
    sh("fj pr merge --delete")
    sh("git checkout main")
    sh("git branch -d #{currentBranch}")
    sh("git pull")
  end
end

##
# Create a release on forge
# @param: [String, #version] the version to release
def create_forge_release(version)
  package_name = ""
  Dir.chdir("../") do
    package_name = sh("basename `pwd`").strip!
  end
  Dir.chdir("../") do
    puts "generate CHANGELOG.md with git-cliff"
    sh("git-cliff -t #{package_name}-#{version} -o CHANGELOG.md")
  end
  sh("git branch release")
  sh("git checkout release")
  puts "commit CHANGELOG.md generated for #{package_name}-#{version}"
  git_commit(
    path: "CHANGELOG.md", 
    message: "docs(#{package_name}): update `CHANGELOG.md` with #{package_name}-#{version}"
  )
  sh("git checkout main")
  sh("git merge release")
  sh("git branch release -d")
  push_to_git_remote
  # add tag and put remote
  puts "create tag #{package_name}-#{version}"
  add_git_tag(tag: "#{package_name}-#{version}")
  push_git_tags(tag: "#{package_name}-#{version}")
  # create release with notes
  forge = detect_forge 
  if forge == "github"
    puts "create forge release #{package_name}-#{version}"
    sh("gh release create #{package_name}-#{version} --generate-notes")
  elsif forge == "forgejo"
    puts "wait 2 second in order tag #{package_name}-#{version} will be available on #{forge}"
    sleep(2)
    puts "create forge release #{package_name}-#{version}"
    sh("fj release create --tag #{package_name}-#{version} #{package_name}-#{version}")
  end
end

##
## Increments build number
def increment_build
  Dir.chdir("../") do
    sh("dart run flutter_heyteacher_meta:dartsemver build")
  end
end