package alicloud

import (
	"context"
	"errors"

	openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client"
	privatelink20200415 "github.com/alibabacloud-go/privatelink-20200415/v5/client"
	"github.com/tidbcloud/observability/pkg/common/metrics"
)

const (
	vpcEndpointServiceClient = "vpc-endpoint-service-client"

	errGetVpcEndpointServiceFailed               = "get vpc endpoint service failed"
	ErrNotFoundEndpointService                   = "not found alicloud endpoint service with given service id"
	errAddVpcEndpointServicePermissionsFailed    = "add vpc endpoint service permission failed"
	errDeleteVpcEndpointServicePermissionsFailed = "delete vpc endpoint service permission failed"
)

type AliEndpointServiceClient struct {
	cli aliEndpointServiceClient
	cfg *openapi.Config
}

//type ssoLoginResponse struct {
//	Mode            string `json:"mode"`
//	AccessKeyId     string `json:"access_key_id"`
//	AccessKeySecret string `json:"access_key_secret"`
//	StsToken        string `json:"sts_token"`
//}

// use this function to get the STS token, when in local development
//func GetStSToken() (*ssoLoginResponse, error) {
//	// build the command for acs-sso login
//	cmd := exec.Command("acs-sso", "login", "--profile", "sso")
//
//	// get the output of the command
//	output, err := cmd.Output()
//	if err != nil {
//		return nil, errors.New("failed to execute command")
//	}
//
//	// parse the output as JSON
//	var response ssoLoginResponse
//	err = json.Unmarshal(output, &response)
//	if err != nil {
//		return nil, errors.New("failed to parse JSON")
//	}
//
//	return &response, nil
//}

func NewAliEndpointService(config *openapi.Config) (AliEndpointServiceClient, error) {
	c, err := privatelink20200415.NewClient(config)
	return AliEndpointServiceClient{
		cli: c,
		cfg: config,
	}, err
}

func (aedpc AliEndpointServiceClient) GetAliEndpointService(ctx context.Context, serviceID string) (*privatelink20200415.GetVpcEndpointServiceAttributeResponseBody, error) {
	output, err := aedpc.cli.GetVpcEndpointServiceAttribute(&privatelink20200415.GetVpcEndpointServiceAttributeRequest{
		ServiceId: &serviceID,
	})
	if err != nil {
		metrics.HandleAliCloudAPIRequestMetrics(*aedpc.cfg.RegionId, vpcEndpointServiceClient, "GetVpcEndpointServiceAttribute", serviceID, errGetVpcEndpointServiceFailed)
		return nil, err
	}
	if output == nil || output.Body == nil || *output.StatusCode == 400 {
		// something nil pointer in the following func HandleAliCloudAPIRequestMetrics
		metrics.HandleAliCloudAPIRequestMetrics(*aedpc.cfg.RegionId, vpcEndpointServiceClient, "DescribeVpcEndpointServiceConfigurations", serviceID, ErrNotFoundEndpointService)
		return nil, errors.New(ErrNotFoundEndpointService)
	}
	return output.Body, err
}

func (aedpc AliEndpointServiceClient) AddUserPermissions(ctx context.Context, serviceID string, userARNs []string) error {
	for i := range userARNs {
		_, err := aedpc.cli.AddUserToVpcEndpointService(&privatelink20200415.AddUserToVpcEndpointServiceRequest{
			ServiceId: &serviceID,
			UserARN:   &userARNs[i],
		})
		if err != nil {
			metrics.HandleAliCloudAPIRequestMetrics(*aedpc.cfg.RegionId, vpcEndpointServiceClient, "AddUserToVpcEndpointService", serviceID, errAddVpcEndpointServicePermissionsFailed)
			return err
		}
	}
	return nil
}

func (aedpc AliEndpointServiceClient) DeleteUserPermissions(ctx context.Context, serviceID string, userARNs []string) error {
	for i := range userARNs {
		_, err := aedpc.cli.RemoveUserFromVpcEndpointService(&privatelink20200415.RemoveUserFromVpcEndpointServiceRequest{
			ServiceId: &serviceID,
			UserARN:   &userARNs[i],
		})
		if err != nil {
			metrics.HandleAliCloudAPIRequestMetrics(*aedpc.cfg.RegionId, vpcEndpointServiceClient, "RemoveUserFromVpcEndpointService", serviceID, errDeleteVpcEndpointServicePermissionsFailed)
			return err
		}
	}
	return nil
}
