package gitea

import (
	"fmt"
	"net/http"
	"net/http/httptest"
	"os"
	"testing"

	log "github.com/sirupsen/logrus"

	"github.com/Masterminds/semver"

	"github.com/Nightapes/go-semantic-release/internal/shared"
	"github.com/Nightapes/go-semantic-release/pkg/config"
	"github.com/stretchr/testify/assert"
)

type testHelperMethodStruct struct {
	config config.GiteaProvider
	valid  bool
}

type testReleaseStruct struct {
	config              config.GiteaProvider
	releaseVersion      *shared.ReleaseVersion
	generatedChangelog  *shared.GeneratedChangelog
	requestResponseBody string
	requestResponseCode int
	valid               bool
}

var testNewClient = []testHelperMethodStruct{
	{config: config.GiteaProvider{
		Repo: "foo",
		User: "bar",
		URL:  "https://hub.cybercinch.nz",
	},
		valid: true,
	},
}

var lastVersion, _ = semver.NewVersion("1.0.0")
var newVersion, _ = semver.NewVersion("2.0.0")

var testReleases = []testReleaseStruct{
	{
		config: config.GiteaProvider{
			Repo: "foo",
			User: "bar",
		},
		releaseVersion: &shared.ReleaseVersion{
			Last: shared.ReleaseVersionEntry{
				Version: lastVersion,
				Commit:  "foo",
			},
			Next: shared.ReleaseVersionEntry{
				Version: newVersion,
				Commit:  "bar",
			},
			Branch: "master",
		},
		generatedChangelog: &shared.GeneratedChangelog{
			Title:   "title",
			Content: "content",
		},
		requestResponseBody: "{  \"url\": \"https://api.github.com/repos/octocat/Hello-World/releases/1\",  \"html_url\": \"https://github.com/octocat/Hello-World/releases/v1.0.0\",  \"assets_url\": \"https://api.github.com/repos/octocat/Hello-World/releases/1/assets\",  \"upload_url\": \"https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}\",  \"tarball_url\": \"https://api.github.com/repos/octocat/Hello-World/tarball/v1.0.0\",  \"zipball_url\": \"https://api.github.com/repos/octocat/Hello-World/zipball/v1.0.0\",  \"id\": 1,  \"node_id\": \"MDc6UmVsZWFzZTE=\",  \"tag_name\": \"v1.0.0\",  \"target_commitish\": \"master\",  \"name\": \"v1.0.0\",  \"body\": \"Description of the release\",  \"draft\": false,  \"prerelease\": false,  \"created_at\": \"2013-02-27T19:35:32Z\",  \"published_at\": \"2013-02-27T19:35:32Z\",  \"author\": {    \"login\": \"octocat\",    \"id\": 1,    \"node_id\": \"MDQ6VXNlcjE=\",    \"avatar_url\": \"https://github.com/images/error/octocat_happy.gif\",    \"gravatar_id\": \"\",    \"url\": \"https://api.github.com/users/octocat\",    \"html_url\": \"https://github.com/octocat\",    \"followers_url\": \"https://api.github.com/users/octocat/followers\",    \"following_url\": \"https://api.github.com/users/octocat/following{/other_user}\",    \"gists_url\": \"https://api.github.com/users/octocat/gists{/gist_id}\",    \"starred_url\": \"https://api.github.com/users/octocat/starred{/owner}{/repo}\",    \"subscriptions_url\": \"https://api.github.com/users/octocat/subscriptions\",    \"organizations_url\": \"https://api.github.com/users/octocat/orgs\",    \"repos_url\": \"https://api.github.com/users/octocat/repos\",    \"events_url\": \"https://api.github.com/users/octocat/events{/privacy}\",    \"received_events_url\": \"https://api.github.com/users/octocat/received_events\",    \"type\": \"User\",    \"site_admin\": false  },  \"assets\": [  ]}",
		requestResponseCode: 200,
		valid:               true,
	},
	{
		config: config.GiteaProvider{
			Repo: "foo",
			User: "bar",
		},
		releaseVersion: &shared.ReleaseVersion{
			Last: shared.ReleaseVersionEntry{
				Version: lastVersion,
				Commit:  "foo",
			},
			Next: shared.ReleaseVersionEntry{
				Version: newVersion,
				Commit:  "bar",
			},
			Branch: "master",
		},
		generatedChangelog: &shared.GeneratedChangelog{
			Title:   "title",
			Content: "content",
		},
		requestResponseCode: 400,
		valid:               false,
	},
}

func initHTTPServerMux() *httptest.Server {
	// Take the request entries and return http mux
	mux := http.NewServeMux()
	mux.HandleFunc("/api/v1/version", func(rw http.ResponseWriter, req *http.Request) {
		log.Infof("Got call from %s %s", req.Method, req.URL.String())
		rw.WriteHeader(200)
		rw.Header().Set("Content-Type", "application/json")
		body := `{
			"version": "1.21.10"
		}`
		if _, err := rw.Write([]byte(body)); err != nil {
			log.Info(err)
		}
	})
	mux.HandleFunc("/api/v1/repos/bar/foo/releases", func(rw http.ResponseWriter, req *http.Request) {
		log.Infof("Got call from %s %s", req.Method, req.URL.String())

		rw.WriteHeader(200)
		body := `{
			"url": "https://api.github.com/repos/octocat/Hello-World/releases/1",
			"html_url": "https://github.com/octocat/Hello-World/releases/v1.0.0",
			"assets_url": "https://api.github.com/repos/octocat/Hello-World/releases/1/assets",
			"upload_url": "https://uploads.github.com/repos/octocat/Hello-World/releases/1/assets{?name,label}",
			"tarball_url": "https://api.github.com/repos/octocat/Hello-World/tarball/v1.0.0",
			"zipball_url": "https://api.github.com/repos/octocat/Hello-World/zipball/v1.0.0",
			"id": 1,
			"node_id": "MDc6UmVsZWFzZTE=",
			"tag_name": "v1.0.0",
			"target_commitish": "master",
			"name": "v1.0.0",
			"body": "Description of the release",
			"draft": false,
			"prerelease": false,
			"created_at": "2013-02-27T19:35:32Z",
			"published_at": "2013-02-27T19:35:32Z",
			"author": {
				"login": "octocat",
				"id": 1,
				"node_id": "MDQ6VXNlcjE=",
				"avatar_url": "https://github.com/images/error/octocat_happy.gif",
				"gravatar_id": "",
				"url": "https://api.github.com/users/octocat",
				"html_url": "https://github.com/octocat",
				"followers_url": "https://api.github.com/users/octocat/followers",
				"following_url": "https://api.github.com/users/octocat/following{/other_user}",
				"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
				"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
				"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
				"organizations_url": "https://api.github.com/users/octocat/orgs",
				"repos_url": "https://api.github.com/users/octocat/repos",
				"events_url": "https://api.github.com/users/octocat/events{/privacy}",
				"received_events_url": "https://api.github.com/users/octocat/received_events",
				"type": "User",
				"site_admin": false
			},
			"assets": []
		}`
		rw.Header().Set("Content-Type", "application/json")

		if _, err := rw.Write([]byte(body)); err != nil {
			log.Info(err)
		}
	})
	server := httptest.NewServer(mux)
	return server
}

func TestNewGitea(t *testing.T) {
	for _, testOject := range testNewClient {
		if testOject.valid {
			os.Setenv("GITEA_TOKEN", "XXX")
		}
		server := initHTTPServerMux()
		defer server.Close()
		testOject.config.URL = server.URL
		_, err := New(&testOject.config, true)

		assert.Equal(t, testOject.valid, err == nil)

		os.Unsetenv("GITEA_TOKEN")

	}
}

func TestGetCommitURLGitea(t *testing.T) {
	os.Setenv("GITEA_TOKEN", "XX")
	for _, testOject := range testNewClient {
		server := initHTTPServerMux()
		defer server.Close()
		testOject.config.URL = server.URL
		client, _ := New(&testOject.config, false)
		actualURL := client.GetCommitURL()
		expectedURL := fmt.Sprintf("%s/%s/%s/commit/{{hash}}", testOject.config.URL, testOject.config.User, testOject.config.Repo)
		assert.EqualValues(t, expectedURL, actualURL)
	}
	os.Unsetenv("GITEA_TOKEN")

}

func TestGetCompareURLGitea(t *testing.T) {
	os.Setenv("GITEA_TOKEN", "XX")
	for _, testOject := range testNewClient {
		server := initHTTPServerMux()
		defer server.Close()
		testOject.config.URL = server.URL
		client, _ := New(&testOject.config, false)
		actualURL := client.GetCompareURL("1", "2")
		expectedURL := fmt.Sprintf("%s/%s/%s/compare/%s...%s", testOject.config.URL, testOject.config.User, testOject.config.Repo, "1", "2")
		assert.EqualValues(t, expectedURL, actualURL)
	}
	os.Unsetenv("GITEA_TOKEN")

}

func TestCreateReleaseGitea(t *testing.T) {
	os.Setenv("GITEA_TOKEN", "XX")

	for _, testObject := range testReleases {
		if testObject.valid {
			server := initHTTPServerMux()
			defer server.Close()
			testObject.config.URL = server.URL
			client, _ := New(&testObject.config, false)
			err := client.makeRelease(testObject.releaseVersion, testObject.generatedChangelog)
			if err != nil {
				t.Log(err)
			}
			assert.Equal(t, testObject.valid, err == nil)
		} else {
			server := initHTTPServerMux()
			defer server.Close()
			testObject.config.URL = server.URL
			client, _ := New(&testObject.config, false)
			server.Close() // Simulate error response
			err := client.makeRelease(testObject.releaseVersion, testObject.generatedChangelog)
			if err != nil {
				t.Log(err)
			}
			assert.Error(t, err)
		}
	}
	os.Unsetenv("GITEA_TOKEN")

}
