package it

import (
	"encoding/base64"
	"net/http"
	"net/http/httptest"

	gapi "gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/gitlab/api"
	"gitlab.com/gitlab-org/cluster-integration/gitlab-agent/v18/internal/tool/testing/testhelpers"
	"go.uber.org/mock/gomock"
)

func (s *integrationSuite) startGitLab() *httptest.Server {
	mux := http.NewServeMux()
	mux.Handle("GET "+gapi.AgentkInfoAPIPath, http.HandlerFunc(s.gitLabM.GetAgentInfo))
	mux.Handle("POST "+gapi.AgentConfigurationAPIPath, http.HandlerFunc(s.gitLabM.PostAgentConfiguration))
	mux.Handle("GET "+gapi.AllowedAgentsAPIPath, http.HandlerFunc(s.gitLabM.GetAllowedAgents))
	mux.Handle("GET "+gapi.ReceptiveAgentsAPIPath, http.HandlerFunc(s.gitLabM.GetReceptiveAgents))
	mux.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.WriteHeader(http.StatusInternalServerError)
		s.Failf("Missing handler for GitLab request", "%s %s", r.Method, r.URL)
	}))
	server := httptest.NewServer(mux)
	s.cleanup(func() {
		s.T().Log("Stopping GitLab")
		server.Close()
		s.T().Log("Stopped GitLab")
	})
	s.T().Log("GitLab running on", server.URL)
	return server
}

// We don't test any credentials here because we have comprehensive unit tests for that.
func (s *integrationSuite) setupGitLabMocks(gitalySrv *gitalyHolder, emptyReceptive bool) {
	gitalyInfo, gitalyRepository := gitalyFields(gitalySrv)
	s.gitLabM.EXPECT().
		GetAgentInfo(gomock.Any(), gomock.Any()).
		Do(func(w http.ResponseWriter, r *http.Request) {
			testhelpers.RespondWithJSON(s.T(), w, &gapi.GetAgentkInfoResponse{
				ProjectId:        testhelpers.ProjectID,
				AgentId:          testhelpers.AgentkKey1.ID,
				AgentName:        agentName,
				GitalyInfo:       gitalyInfo,
				GitalyRepository: gitalyRepository,
				DefaultBranch:    "main",
			})
		}).
		MinTimes(1)
	s.gitLabM.EXPECT().
		PostAgentConfiguration(gomock.Any(), gomock.Any()).
		AnyTimes()
	s.gitLabM.EXPECT().
		GetAllowedAgents(gomock.Any(), gomock.Any()).
		Do(func(w http.ResponseWriter, r *http.Request) {
			testhelpers.RespondWithJSON(s.T(), w, &gapi.AllowedAgentsForJobAPIResponse{
				AllowedAgents: []*gapi.AllowedAgent{
					{
						Id: testhelpers.AgentkKey1.ID,
						ConfigProject: &gapi.ConfigProject{
							Id: testhelpers.ProjectID,
						},
					},
				},
				Job: &gapi.Job{
					Id: 123,
				},
				Pipeline: &gapi.Pipeline{
					Id: 234,
				},
				Project: &gapi.Project{
					Id: testhelpers.ProjectID,
				},
				User: &gapi.User{
					Id:       testhelpers.UserID,
					Username: "user234",
				},
			})
		}).
		AnyTimes()
	if emptyReceptive {
		s.gitLabM.EXPECT().
			GetReceptiveAgents(gomock.Any(), gomock.Any()).
			Do(func(w http.ResponseWriter, r *http.Request) {
				testhelpers.RespondWithJSON(s.T(), w, &gapi.GetReceptiveAgentsResponse{})
			}).
			AnyTimes() // test might finish before the endpoint is called.
	}
}

func (s *integrationSuite) setupGitLabMocksForReceptiveAgents(agentk *agentkHolder) {
	s.gitLabM.EXPECT().
		GetReceptiveAgents(gomock.Any(), gomock.Any()).
		Do(func(w http.ResponseWriter, r *http.Request) {
			testhelpers.RespondWithJSON(s.T(), w, &gapi.GetReceptiveAgentsResponse{
				Agents: []*gapi.ReceptiveAgent{
					{
						Id:  testhelpers.AgentkKey1.ID,
						Url: agentk.receptiveURL,
						AuthConfig: &gapi.ReceptiveAgent_Jwt{
							Jwt: &gapi.ReceptiveAgentJWTAuth{
								PrivateKey: base64.StdEncoding.EncodeToString(agentk.receptivePrivateKey.Seed()),
							},
						},
					},
				},
			})
		}).
		MinTimes(1)
}
