using Dates
# using GitCommand
using GitHub
using JSON
using Pkg
using Printf
using RegistryCI
using Test
using TimeZones

const AutoMerge = RegistryCI.AutoMerge

include("automerge-integration-utils.jl")

AUTOMERGE_INTEGRATION_TEST_REPO = ENV["AUTOMERGE_INTEGRATION_TEST_REPO"]::String
TEST_USER_GITHUB_TOKEN = ENV["BCBI_TEST_USER_GITHUB_TOKEN"]::String
INTEGRATION_TEST_READ_ONLY_TOKEN = ENV["INTEGRATION_TEST_READ_ONLY_TOKEN"]::String
GIT = "git"
auth = GitHub.authenticate(TEST_USER_GITHUB_TOKEN)
whoami = RegistryCI.AutoMerge.username(GitHub.DEFAULT_API, auth)
repo_url_without_auth = "https://github.com/$(AUTOMERGE_INTEGRATION_TEST_REPO)"
repo_url_with_auth = "https://$(whoami):$(TEST_USER_GITHUB_TOKEN)@github.com/$(AUTOMERGE_INTEGRATION_TEST_REPO)"
repo = GitHub.repo(AUTOMERGE_INTEGRATION_TEST_REPO; auth = auth)
@test success(`$(GIT) --version`)
@info("Authenticated to GitHub as \"$(whoami)\"")

_delete_branches_older_than = Dates.Hour(3)
delete_old_pull_request_branches(
    repo_url_with_auth,
    _delete_branches_older_than;
    GIT = GIT,
)

requires_commit = "1c843ed4d4d568345ca557fea48f43efdcd0271f"
hello_world_commit1 = "197e0e03f3f840f830cb5095ab6407d00fbee61c"
hello_world_commit2 = "57b0aec49622faa962c6752d4bc39a62b91fe37c"

@testset "Integration tests" begin
    for (test_number, (master_dir, feature_dir, public_dir, title, check_license, pass, commit)) in enumerate([
            ("master_1", "feature_1", "", "New package: Requires v1.0.0", true, true, requires_commit), # OK: new package
            ("master_1", "feature_1", "", "New package: Requires v1.0.0", true, false, "659e09770ba9fda4a503f8bf281d446c9583ff3b"), # FAIL: wrong commit!
            ("master_2", "feature_2", "", "New version: Requires v2.0.0", false, true, requires_commit),            # OK: new version
            ("master_1", "feature_3", "", "New package: Req v1.0.0", false, false, requires_commit),                # FAIL: name too short
            ("master_2", "feature_4", "", "New version: Requires v2.0.1", false, false, requires_commit),           # FAIL: skips v2.0.0
            ("master_3", "feature_5", "", "New version: Requires v2.0.0", false, false, requires_commit),           # FAIL: modifies extra file
            ("master_1", "feature_6", "", "New package: HelloWorldC_jll v1.0.6+0", false, true, hello_world_commit1),   # OK: new JLL package
            ("master_4", "feature_7", "", "New version: HelloWorldC_jll v1.0.8+0", false, true, hello_world_commit2),   # OK: new JLL version
            ("master_1", "feature_8", "", "New package: HelloWorldC_jll v1.0.6+0", false, false, hello_world_commit1),  # FAIL: unallowed dependency
            ("master_1", "feature_1", "public_1", "New package: Requires v1.0.0", false, true, requires_commit),    # OK: no UUID conflict
            ("master_1", "feature_1", "public_2", "New package: Requires v1.0.0", false, false, requires_commit),  # FAIL: UUID conflict, name differs
            ("master_1", "feature_1", "public_3", "New package: Requires v1.0.0", false, false, requires_commit),  # FAIL: UUID conflict, repo differs
            ("master_1", "feature_1", "public_4", "New package: Requires v1.0.0", false, true, requires_commit),   # OK: UUID conflict but name and repo match
        ])
        @info "Performing integration tests with settings" test_number master_dir feature_dir title pass
        with_master_branch(templates(master_dir), "master"; GIT = GIT, repo_url = repo_url_with_auth) do master
            with_feature_branch(templates(feature_dir), master; GIT = GIT, repo_url = repo_url_with_auth) do feature
                public_registries = String[]
                if public_dir != ""
                    public_git_repo = generate_public_registry(public_dir, GIT)
                    push!(public_registries, "file://$(public_git_repo)/.git")
                end
                head = feature
                base = master
                body = """
                - Foo: Bar
                - Commit: $commit
                - Hello: World
                """
                params = Dict("title" => title,
                              "head" => head,
                              "base" => base,
                              "body" => body)

                sleep(1)
                pr = GitHub.create_pull_request(repo; auth = auth, params = params)
                pr = wait_pr_compute_mergeability(GitHub.DEFAULT_API, repo, pr; auth = auth)
                @test pr.mergeable
                sleep(1)
                with_pr_merge_commit(pr, repo_url_without_auth; GIT = GIT) do build_dir
                    withenv("AUTOMERGE_GITHUB_TOKEN" => TEST_USER_GITHUB_TOKEN,
                            "TRAVIS_BRANCH" => master,
                            "TRAVIS_BUILD_DIR" => build_dir,
                            "TRAVIS_EVENT_TYPE" => "pull_request",
                            "TRAVIS_PULL_REQUEST" => string(pr.number),
                            "TRAVIS_PULL_REQUEST_SHA" => string(AutoMerge.pull_request_head_sha(pr)),
                            "TRAVIS_REPO_SLUG" => AUTOMERGE_INTEGRATION_TEST_REPO) do
                        sleep(1)
                        run_thunk = () -> AutoMerge.run(;
                                      merge_new_packages = true,
                                      merge_new_versions = true,
                                      new_package_waiting_period = Minute(typemax(Int32)),
                                      new_jll_package_waiting_period = Minute(typemax(Int32)),
                                      new_version_waiting_period = Minute(typemax(Int32)),
                                      new_jll_version_waiting_period = Minute(typemax(Int32)),
                                      registry = AUTOMERGE_INTEGRATION_TEST_REPO,
                                      authorized_authors = String[whoami],
                                      authorized_authors_special_jll_exceptions = String[whoami],
                                      error_exit_if_automerge_not_applicable = true,
                                      master_branch = master,
                                      master_branch_is_default_branch = false,
                                      check_license = check_license,
                                      public_registries = public_registries)
                        @info "Running integration test for " test_number master_dir feature_dir public_dir title pass
                        if pass
                            run_thunk()
                        else
                            @test_throws(RegistryCI.AutoMerge.AutoMergeGuidelinesNotMet, run_thunk())
                        end

                    end
                    withenv("AUTOMERGE_GITHUB_TOKEN" => TEST_USER_GITHUB_TOKEN,
                            "TRAVIS_BRANCH" => master,
                            "TRAVIS_BUILD_DIR" => build_dir,
                            "TRAVIS_EVENT_TYPE" => "cron",
                            "TRAVIS_PULL_REQUEST" => "false",
                            "TRAVIS_PULL_REQUEST_SHA" => "",
                            "TRAVIS_REPO_SLUG" => AUTOMERGE_INTEGRATION_TEST_REPO) do
                        sleep(1)
                        AutoMerge.run(;
                                      merge_new_packages = true,
                                      merge_new_versions = true,
                                      new_package_waiting_period = Minute(typemax(Int32)),
                                      new_jll_package_waiting_period = Minute(typemax(Int32)),
                                      new_version_waiting_period = Minute(typemax(Int32)),
                                      new_jll_version_waiting_period = Minute(typemax(Int32)),
                                      registry = AUTOMERGE_INTEGRATION_TEST_REPO,
                                      authorized_authors = String[whoami],
                                      authorized_authors_special_jll_exceptions = String[whoami],
                                      error_exit_if_automerge_not_applicable = true,
                                      master_branch = master,
                                      master_branch_is_default_branch = false)
                        sleep(1)
                        AutoMerge.run(;
                                      merge_new_packages = true,
                                      merge_new_versions = true,
                                      new_package_waiting_period = Minute(0),
                                      new_jll_package_waiting_period = Minute(0),
                                      new_version_waiting_period = Minute(0),
                                      new_jll_version_waiting_period = Minute(0),
                                      registry = AUTOMERGE_INTEGRATION_TEST_REPO,
                                      authorized_authors = String[whoami],
                                      authorized_authors_special_jll_exceptions = String[whoami],
                                      error_exit_if_automerge_not_applicable = true,
                                      master_branch = master,
                                      master_branch_is_default_branch = false)
                    end
                end
            end
        end
    end
end
