package privatelink_svc

import (
	"context"
	"strings"

	"github.com/tidbcloud/serverless-service/idl/pbgen/proto/console"
	"github.com/tidbcloud/serverless-service/internal/domain/constant"
	"github.com/tidbcloud/serverless-service/internal/domain/entity"
	"github.com/tidbcloud/serverless-service/internal/service/console_auditlog"
	"github.com/tidbcloud/tiinf/sdk/auditlog"
)

func recordCreatePrivateEndpointForExternalServiceAuditLog(
	ctx context.Context,
	req *console.CreatePrivateLinkConnectionRequest,
	created *entity.PrivateLinkConnection,
	err error,
) {
	details := buildPrivateEndpointForExternalServiceDetails(req.GetPrivateLinkConnection(), created)
	console_auditlog.SubmitWithStringIDs(
		ctx,
		auditlog.EventCreatePrivateEndpointForExternalService,
		req.GetOrgId(),
		req.GetProjectId(),
		req.GetClusterId(),
		details,
		err,
	)
}

func recordDeletePrivateEndpointForExternalServiceAuditLog(
	ctx context.Context,
	req *console.DeletePrivateLinkConnectionRequest,
	deleted *entity.PrivateLinkConnection,
	err error,
) {
	details := auditlog.Details{
		auditlog.KeyPrivateEndpointForExternalServiceId: req.GetPrivateLinkConnectionId(),
	}
	if deleted != nil {
		if deleted.DisplayName != "" {
			details[auditlog.KeyDisplayName] = deleted.DisplayName
		}
		fillPrivateEndpointForExternalServiceTypeDetails(details, deleted)
	}
	console_auditlog.SubmitWithStringIDs(
		ctx,
		auditlog.EventDeletePrivateEndpointForExternalService,
		req.GetOrgId(),
		req.GetProjectId(),
		req.GetClusterId(),
		details,
		err,
	)
}

func recordAttachPrivateEndpointForExternalServiceDomainsAuditLog(
	ctx context.Context,
	req *console.AttachDomainsRequest,
	attach *entity.PLCAttachDomain,
	err error,
) {
	details := auditlog.Details{
		auditlog.KeyPrivateEndpointForExternalServiceId: req.GetPrivateLinkConnectionId(),
	}
	if attach != nil {
		if attach.ID != "" {
			details[auditlog.KeyAttachDomainId] = attach.ID
		}
		details[auditlog.KeyIntegrationType] = string(attach.Type)
		if attach.UniqueID != "" {
			details[auditlog.KeyEndpointName] = attach.UniqueID
		}
	}
	if ad := req.GetAttachDomain(); ad != nil {
		details[auditlog.KeyIntegrationType] = ad.GetType().String()
		if ad.GetUniqueName() != "" {
			details[auditlog.KeyEndpointName] = ad.GetUniqueName()
		}
	}
	console_auditlog.SubmitWithStringIDs(
		ctx,
		auditlog.EventAttachPrivateEndpointForExternalServiceDomains,
		req.GetOrgId(),
		req.GetProjectId(),
		req.GetClusterId(),
		details,
		err,
	)
}

func recordDetachPrivateEndpointForExternalServiceDomainsAuditLog(
	ctx context.Context,
	req *console.DetachDomainsRequest,
	attach *entity.PLCAttachDomain,
	err error,
) {
	details := auditlog.Details{
		auditlog.KeyPrivateEndpointForExternalServiceId: req.GetPrivateLinkConnectionId(),
		auditlog.KeyAttachDomainId:                      req.GetAttachDomainId(),
	}
	if attach != nil {
		details[auditlog.KeyIntegrationType] = string(attach.Type)
		if attach.UniqueID != "" {
			details[auditlog.KeyEndpointName] = attach.UniqueID
		}
	}
	console_auditlog.SubmitWithStringIDs(
		ctx,
		auditlog.EventDetachPrivateEndpointForExternalServiceDomains,
		req.GetOrgId(),
		req.GetProjectId(),
		req.GetClusterId(),
		details,
		err,
	)
}

func buildPrivateEndpointForExternalServiceDetails(
	reqPL *console.PrivateLinkConnection,
	created *entity.PrivateLinkConnection,
) auditlog.Details {
	details := auditlog.Details{}
	if reqPL != nil {
		if reqPL.GetDisplayName() != "" {
			details[auditlog.KeyDisplayName] = reqPL.GetDisplayName()
		}
		details[auditlog.KeyIntegrationType] = reqPL.GetType().String()
		switch reqPL.GetType() {
		case console.PrivateLinkConnectionType_AWS_ENDPOINT_SERVICE:
			if aws := reqPL.GetAwsEndpointService(); aws != nil {
				details[auditlog.KeyEndpointService] = aws.GetName()
				details[auditlog.KeyRegion] = aws.GetRegion()
			}
		case console.PrivateLinkConnectionType_ALICLOUD_ENDPOINT_SERVICE:
			if ali := reqPL.GetAlicloudEndpointService(); ali != nil {
				details[auditlog.KeyEndpointService] = ali.GetName()
			}
		case console.PrivateLinkConnectionType_AMAZON_MSK_PROVISIONED:
			if msk := reqPL.GetAmazonMskProvisioned(); msk != nil {
				details[auditlog.KeyMskArn] = msk.GetMskArn()
			}
		}
	}
	if created != nil {
		if created.ID != "" {
			details[auditlog.KeyPrivateEndpointForExternalServiceId] = created.ID
		}
		fillPrivateEndpointForExternalServiceTypeDetails(details, created)
	}
	return details
}

func fillPrivateEndpointForExternalServiceTypeDetails(
	details auditlog.Details,
	pl *entity.PrivateLinkConnection,
) {
	details[auditlog.KeyIntegrationType] = string(pl.Type)
	switch pl.Type {
	case constant.PrivateLinkConnectionAWSEndpointService:
		if pl.AWSEndpointService != nil {
			details[auditlog.KeyEndpointService] = pl.AWSEndpointService.EndpointServiceName
			details[auditlog.KeyRegion] = pl.AWSEndpointService.EndpointServiceRegion
			details[auditlog.KeyEndpointID] = pl.AWSEndpointService.EndpointID
			if len(pl.AWSEndpointService.EndpointAzIdToName) > 0 {
				azs := make([]string, 0, len(pl.AWSEndpointService.EndpointAzIdToName))
				for az := range pl.AWSEndpointService.EndpointAzIdToName {
					azs = append(azs, az)
				}
				details[auditlog.KeyEndpointZones] = strings.Join(azs, ",")
			}
		}
	case constant.PrivateLinkConnectionAlicloudEndpointService:
		if pl.AlicloudEndpointService != nil {
			details[auditlog.KeyEndpointService] = pl.AlicloudEndpointService.EndpointServiceName
			details[auditlog.KeyEndpointID] = pl.AlicloudEndpointService.EndpointID
		}
	case constant.PrivateLinkConnectionAmazonMSKProvisioned:
		if pl.AmazonMSKProvisioned != nil {
			details[auditlog.KeyMskArn] = pl.AmazonMSKProvisioned.MSKArn
		}
	}
}
