//go:build integration
// +build integration

// Copyright 2025 Cloudbase Solutions SRL
//
//	Licensed under the Apache License, Version 2.0 (the "License"); you may
//	not use this file except in compliance with the License. You may obtain
//	a copy of the License at
//
//	     http://www.apache.org/licenses/LICENSE-2.0
//
//	Unless required by applicable law or agreed to in writing, software
//	distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
//	WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
//	License for the specific language governing permissions and limitations
//	under the License.

package integration

import (
	"github.com/cloudbase/garm/params"
)

func (suite *GarmSuite) TestGithubEndpointOperations() {
	t := suite.T()
	t.Log("Testing endpoint operations")
	suite.MustDefaultGithubEndpoint()

	caBundle, err := getTestFileContents("certs/srv-pub.pem")
	suite.NoError(err)

	endpointParams := params.CreateGithubEndpointParams{
		Name:          "test-endpoint",
		Description:   "Test endpoint",
		BaseURL:       "https://ghes.example.com",
		APIBaseURL:    "https://api.ghes.example.com/",
		UploadBaseURL: "https://uploads.ghes.example.com/",
		CACertBundle:  caBundle,
	}

	endpoint, err := suite.CreateGithubEndpoint(endpointParams)
	suite.NoError(err)
	suite.Equal(endpoint.Name, endpointParams.Name, "Endpoint name mismatch")
	suite.Equal(endpoint.Description, endpointParams.Description, "Endpoint description mismatch")
	suite.Equal(endpoint.BaseURL, endpointParams.BaseURL, "Endpoint base URL mismatch")
	suite.Equal(endpoint.APIBaseURL, endpointParams.APIBaseURL, "Endpoint API base URL mismatch")
	suite.Equal(endpoint.UploadBaseURL, endpointParams.UploadBaseURL, "Endpoint upload base URL mismatch")
	suite.Equal(string(endpoint.CACertBundle), string(caBundle), "Endpoint CA cert bundle mismatch")

	endpoint2 := suite.GetGithubEndpoint(endpointParams.Name)
	suite.NotNil(endpoint, "endpoint is nil")
	suite.NotNil(endpoint2, "endpoint2 is nil")

	err = checkEndpointParamsAreEqual(*endpoint, *endpoint2)
	suite.NoError(err, "endpoint params are not equal")
	endpoints := suite.ListGithubEndpoints()
	suite.NoError(err, "error listing github endpoints")
	var found bool
	for _, ep := range endpoints {
		if ep.Name == endpointParams.Name {
			checkEndpointParamsAreEqual(*endpoint, ep)
			found = true
			break
		}
	}
	suite.Equal(found, true, "endpoint not found in list")

	err = suite.DeleteGithubEndpoint(endpoint.Name)
	suite.NoError(err, "error deleting github endpoint")
}

func (suite *GarmSuite) TestGithubEndpointMustFailToDeleteDefaultGithubEndpoint() {
	t := suite.T()
	t.Log("Testing error when deleting default github.com endpoint")
	err := deleteGithubEndpoint(suite.cli, suite.authToken, "github.com")
	suite.Error(err, "expected error when attempting to delete the default github.com endpoint")
}

func (suite *GarmSuite) TestGithubEndpointFailsOnInvalidCABundle() {
	t := suite.T()
	t.Log("Testing endpoint creation with invalid CA cert bundle")
	badCABundle, err := getTestFileContents("certs/srv-key.pem")
	suite.NoError(err, "error reading CA cert bundle")

	endpointParams := params.CreateGithubEndpointParams{
		Name:          "dummy",
		Description:   "Dummy endpoint",
		BaseURL:       "https://ghes.example.com",
		APIBaseURL:    "https://api.ghes.example.com/",
		UploadBaseURL: "https://uploads.ghes.example.com/",
		CACertBundle:  badCABundle,
	}

	_, err = createGithubEndpoint(suite.cli, suite.authToken, endpointParams)
	suite.Error(err, "expected error when creating endpoint with invalid CA cert bundle")
}

func (suite *GarmSuite) TestGithubEndpointDeletionFailsWhenCredentialsExist() {
	t := suite.T()
	t.Log("Testing endpoint deletion when credentials exist")
	endpointParams := params.CreateGithubEndpointParams{
		Name:          "dummy",
		Description:   "Dummy endpoint",
		BaseURL:       "https://ghes.example.com",
		APIBaseURL:    "https://api.ghes.example.com/",
		UploadBaseURL: "https://uploads.ghes.example.com/",
	}

	endpoint, err := suite.CreateGithubEndpoint(endpointParams)
	suite.NoError(err, "error creating github endpoint")
	creds, err := suite.createDummyCredentials("test-creds", endpoint.Name)
	suite.NoError(err, "error creating dummy credentials")

	err = deleteGithubEndpoint(suite.cli, suite.authToken, endpoint.Name)
	suite.Error(err, "expected error when deleting endpoint with credentials")

	err = suite.DeleteGithubCredential(int64(creds.ID)) //nolint:gosec
	suite.NoError(err, "error deleting credentials")
	err = suite.DeleteGithubEndpoint(endpoint.Name)
	suite.NoError(err, "error deleting endpoint")
}

func (suite *GarmSuite) TestGithubEndpointFailsOnDuplicateName() {
	t := suite.T()
	t.Log("Testing endpoint creation with duplicate name")
	endpointParams := params.CreateGithubEndpointParams{
		Name:          "github.com",
		Description:   "Dummy endpoint",
		BaseURL:       "https://ghes.example.com",
		APIBaseURL:    "https://api.ghes.example.com/",
		UploadBaseURL: "https://uploads.ghes.example.com/",
	}

	_, err := createGithubEndpoint(suite.cli, suite.authToken, endpointParams)
	suite.Error(err, "expected error when creating endpoint with duplicate name")
}

func (suite *GarmSuite) TestGithubEndpointUpdateEndpoint() {
	t := suite.T()
	t.Log("Testing endpoint update")
	endpoint, err := suite.createDummyEndpoint("dummy")
	suite.NoError(err, "error creating dummy endpoint")
	t.Cleanup(func() {
		suite.DeleteGithubEndpoint(endpoint.Name)
	})

	newDescription := "Updated description"
	newBaseURL := "https://ghes2.example.com"
	newAPIBaseURL := "https://api.ghes2.example.com/"
	newUploadBaseURL := "https://uploads.ghes2.example.com/"
	newCABundle, err := getTestFileContents("certs/srv-pub.pem")
	suite.NoError(err, "error reading CA cert bundle")

	updateParams := params.UpdateGithubEndpointParams{
		Description:   &newDescription,
		BaseURL:       &newBaseURL,
		APIBaseURL:    &newAPIBaseURL,
		UploadBaseURL: &newUploadBaseURL,
		CACertBundle:  newCABundle,
	}

	updated, err := updateGithubEndpoint(suite.cli, suite.authToken, endpoint.Name, updateParams)
	suite.NoError(err, "error updating github endpoint")

	suite.Equal(updated.Name, endpoint.Name, "Endpoint name mismatch")
	suite.Equal(updated.Description, newDescription, "Endpoint description mismatch")
	suite.Equal(updated.BaseURL, newBaseURL, "Endpoint base URL mismatch")
	suite.Equal(updated.APIBaseURL, newAPIBaseURL, "Endpoint API base URL mismatch")
	suite.Equal(updated.UploadBaseURL, newUploadBaseURL, "Endpoint upload base URL mismatch")
	suite.Equal(string(updated.CACertBundle), string(newCABundle), "Endpoint CA cert bundle mismatch")
}

func (suite *GarmSuite) MustDefaultGithubEndpoint() {
	ep := suite.GetGithubEndpoint("github.com")

	suite.NotNil(ep, "default GitHub endpoint not found")
	suite.Equal(ep.Name, "github.com", "default GitHub endpoint name mismatch")
}

func (suite *GarmSuite) GetGithubEndpoint(name string) *params.ForgeEndpoint {
	t := suite.T()
	t.Log("Get GitHub endpoint")
	endpoint, err := getGithubEndpoint(suite.cli, suite.authToken, name)
	suite.NoError(err, "error getting GitHub endpoint")

	return endpoint
}

func (suite *GarmSuite) CreateGithubEndpoint(params params.CreateGithubEndpointParams) (*params.ForgeEndpoint, error) {
	t := suite.T()
	t.Log("Create GitHub endpoint")
	endpoint, err := createGithubEndpoint(suite.cli, suite.authToken, params)
	suite.NoError(err, "error creating GitHub endpoint")

	return endpoint, nil
}

func (suite *GarmSuite) DeleteGithubEndpoint(name string) error {
	t := suite.T()
	t.Log("Delete GitHub endpoint")
	err := deleteGithubEndpoint(suite.cli, suite.authToken, name)
	suite.NoError(err, "error deleting GitHub endpoint")

	return nil
}

func (suite *GarmSuite) ListGithubEndpoints() params.ForgeEndpoints {
	t := suite.T()
	t.Log("List GitHub endpoints")
	endpoints, err := listGithubEndpoints(suite.cli, suite.authToken)
	suite.NoError(err, "error listing GitHub endpoints")

	return endpoints
}

func (suite *GarmSuite) createDummyEndpoint(name string) (*params.ForgeEndpoint, error) {
	endpointParams := params.CreateGithubEndpointParams{
		Name:          name,
		Description:   "Dummy endpoint",
		BaseURL:       "https://ghes.example.com",
		APIBaseURL:    "https://api.ghes.example.com/",
		UploadBaseURL: "https://uploads.ghes.example.com/",
	}

	return suite.CreateGithubEndpoint(endpointParams)
}
