You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: update_environment_settings.go
    path of file: ./repos/porter/api/server/handlers/environment
    
    the code of the file until where you have to start completion: package environment

import (
	"context"
	"errors"
	"fmt"
	"net/http"
	"reflect"
	"strings"

	"github.com/porter-dev/porter/internal/telemetry"

	"github.com/porter-dev/porter/api/server/authz"
	"github.com/porter-dev/porter/api/server/handlers"
	"github.com/porter-dev/porter/api/server/shared"
	"github.com/porter-dev/porter/api/server/shared/apierrors"
	"github.com/porter-dev/porter/api/server/shared/config"
	"github.com/porter-dev/porter/api/server/shared/requestutils"
	"github.com/porter-dev/porter/api/types"
	"github.com/porter-dev/porter/internal/models"
	"gorm.io/gorm"
)

type UpdateEnvironmentSettingsHandler struct {
	handlers.PorterHandlerReadWriter
	authz.KubernetesAgentGetter
}

func NewUpdateEnvironmentSettingsHandler(
	config *config.Config,
	decoderValidator shared.RequestDecoderValidator,
	writer shared.ResultWriter,
) *UpdateEnvironmentSettingsHandler {
	return &UpdateEnvironmentSettingsHandler{
		PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
		KubernetesAgentGetter:   authz.NewOutOfClusterAgentGetter(config),
	}
}

func (c *UpdateEnvironmentSettingsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ctx, span := telemetry.NewSpan(r.Context(), "serve-update-environment-settings")
	defer span.End()

	project, _ := ctx.Value(types.ProjectScope).(*models.Project)
	cluster, _ := ctx.Value(types.ClusterScope).(*models.Cluster)

	telemetry.WithAttributes(span,
		telemetry.AttributeKV{Key: "project-id", Value: project.ID},
		telemetry.AttributeKV{Key: "cluster-id", Value: cluster.ID},
	)

	envID, reqErr := requestutils.GetURLParamUint(r, "environment_id")

	if reqErr != nil {
		_ = telemetry.Error(ctx, span, reqErr, "could not get environment id from url")
		c.HandleAPIError(w, r, reqErr)
		return
	}

	telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "environment-id", Value: envID})

	request := &types.UpdateEnvironmentSettingsRequest{}

	if ok := c.DecodeAndValidate(w, r, request); !ok {
		_ = telemetry.Error(ctx, span, nil, "could not decode and validate request")
		return
	}

	telemetry.WithAttributes(span,
		telemetry.
    
func (c *UpdateEnvironmentSettingsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ctx, span := telemetry.NewSpan(r.Context(), "serve-update-environment-settings")
	defer span.End()

	project, _ := ctx.Value(types.ProjectScope).(*models.Project)
	cluster, _ := ctx.Value(types.ClusterScope).(*models.Cluster)

	telemetry.WithAttributes(span,
		telemetry.AttributeKV{Key: "project-id", Value: project.ID},
		telemetry.AttributeKV{Key: "cluster-id", Value: cluster.ID},
	)

	envID, reqErr := requestutils.GetURLParamUint(r, "environment_id")

	if reqErr != nil {
		_ = telemetry.Error(ctx, span, reqErr, "could not get environment id from url")
		c.HandleAPIError(w, r, reqErr)
		return
	}

	telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "environment-id", Value: envID})

	request := &types.UpdateEnvironmentSettingsRequest{}

	if ok := c.DecodeAndValidate(w, r, request); !ok {
		_ = telemetry.Error(ctx, span, nil, "could not decode and validate request")
		return
	}

	telemetry.WithAttributes(span,
		telemetry.AttributeKV{Key: "mode", Value: request.Mode},
		telemetry.AttributeKV{Key: "git-repo-branches", Value: request.GitRepoBranches},
		telemetry.AttributeKV{Key: "git-deploy-branches", Value: request.GitDeployBranches},
	)

	env, err := c.Repo().Environment().ReadEnvironmentByID(project.ID, cluster.ID, envID)
	if err != nil {
		err = telemetry.Error(ctx, span, err, "could not read environment by id")

		if errors.Is(err, gorm.ErrRecordNotFound) {
			c.HandleAPIError(w, r, apierrors.NewErrNotFound(fmt.Errorf("no such environment with ID: %d", envID)))
			return
		}

		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
		return
	}

	var newBranches []string

	for _, br := range request.GitRepoBranches {
		name := strings.TrimSpace(br)

		if len(name) > 0 {
			newBranches = append(newBranches, name)
		}
	}

	changed := !reflect.DeepEqual(env.ToEnvironmentType().GitRepoBranches, newBranches)

	if changed {
		env.GitRepoBranches = strings.Join(request.GitRepoBranches, ",")
	}

	newBranches = []string{}

	for _, br := range request.GitDeployBranches {
		name := strings.TrimSpace(br)

		if len(name) > 0 {
			newBranches = append(newBranches, name)
		}
	}

	changed = !reflect.DeepEqual(env.ToEnvironmentType().GitDeployBranches, newBranches)

	telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "changed", Value: changed})

	if changed {
		// let us check if the webhook has access to the "push" event
		client, err := getGithubClientFromEnvironment(c.Config(), env)
		if err != nil {
			err = telemetry.Error(ctx, span, err, "could not get github client")
			c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
			return
		}

		hook, _, err := client.Repositories.GetHook(
			context.Background(), env.GitRepoOwner, env.GitRepoName, env.GithubWebhookID,
		)
		if err != nil {
			err = telemetry.Error(ctx, span, err, "could not get hook")
			c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
			return
		}

		found := false

		for _, ev := range hook.Events {
			if ev == "push" {
				found = true
				break
			}
		}

		telemetry.WithAttributes(span, telemetry.AttributeKV{Key: "found", Value: found})

		if !found {
			webhookURL := getGithubWebhookURLFromUID(c.Config().ServerConf.ServerURL, string(env.WebhookID))

			hook.Events = append(hook.Events, "push")
			hook.Config = map[string]interface{}{
				"url":          webhookURL,
				"content_type": "json",
				"secret":       c.Config().ServerConf.GithubIncomingWebhookSecret,
			}

			_, _, err := client.Repositories.EditHook(
				context.Background(), env.GitRepoOwner, env.GitRepoName, env.GithubWebhookID, hook,
			)
			if err != nil {
				err = telemetry.Error(ctx, span, err, "could not edit hook")
				c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
				return
			}
		}

		env.GitDeployBranches = strings.Join(request.GitDeployBranches, ",")

		if len(request.GitDeployBranches) > 0 && c.Config().ServerConf.EnableAutoPreviewBranchDeploy {
			errs := autoDeployBranch(env, c.Config(), request.GitDeployBranches, true)

			if len(errs) > 0 {
				errString := errs[0].Error()

				for _, e := range errs {
					errString += ": " + e.Error()
				}

				_ = telemetry.Error(ctx, span, errors.New(errString), "could not auto deploy branch")
				c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(
					fmt.Errorf("error auto deploying preview branches: %s", errString), http.StatusConflict),
				)
				return
			}
		}
	}

	if request.DisableNewComments != env.NewCommentsDisabled {
		env.NewCommentsDisabled = request.DisableNewComments
		changed = true
	}

	if request.Mode != env.Mode {
		env.Mode = request.Mode
		changed = true
	}

	if len(request.NamespaceLabels) > 0 {
		var labels []string

		for k, v := range request.NamespaceLabels {
			labels = append(labels, fmt.Sprintf("%s=%s", k, v))
		}

		env.NamespaceLabels = []byte(strings.Join(labels, ","))

		changed = true
	} else {
		env.NamespaceLabels = []byte{}

		changed = true
	}

	if changed {
		env, err = c.Repo().Environment().UpdateEnvironment(env)

		if err != nil {
			err = telemetry.Error(ctx, span, err, "could not update environment")
			c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
			return
		}
	}

	c.WriteResult(w, r, env.ToEnvironmentType())
}