package console

import (
	"context"

	"github.com/tidbcloud/serverless-service/idl/pbgen/proto/console"
	"github.com/tidbcloud/serverless-service/internal/domain/entity"
	"github.com/tidbcloud/serverless-service/internal/service/console_auditlog"
	tidbmgmtservicev1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	"github.com/tidbcloud/tiinf/sdk/auditlog"
)

func recordCreateMigrationTaskAuditLog(
	ctx context.Context,
	req *console.CreateMigrationTaskReq,
	cluster *tidbmgmtservicev1.Cluster,
	task *entity.DMTask,
	err error,
) {
	details := buildCreateMigrationTaskDetails(req, cluster, task)
	console_auditlog.SubmitWithStringIDs(
		ctx,
		auditlog.EventCreateMigrationJob,
		req.GetOrgId(),
		req.GetProjectId(),
		req.GetClusterId(),
		details,
		err,
	)
}

func recordDeleteMigrationTaskAuditLog(
	ctx context.Context,
	req *console.DeleteMigrationTaskReq,
	task *entity.DMTask,
	err error,
) {
	details := auditlog.Details{
		auditlog.KeyMigrationId: req.GetId(),
	}
	if task != nil {
		if task.Name != "" {
			details[auditlog.KeyJobName] = task.Name
		}
	}
	console_auditlog.SubmitWithStringIDs(
		ctx,
		auditlog.EventDeleteMigrationJob,
		req.GetOrgId(),
		req.GetProjectId(),
		req.GetClusterId(),
		details,
		err,
	)
}

func recordPauseMigrationTaskAuditLog(
	ctx context.Context,
	req *console.PauseMigrationTaskReq,
	task *entity.DMTask,
	err error,
) {
	recordOperateMigrationTaskAuditLog(
		ctx,
		req.GetOrgId(),
		req.GetProjectId(),
		req.GetClusterId(),
		req.GetId(),
		task,
		auditlog.EventSuspendMigrationJob,
		err,
	)
}

func recordResumeMigrationTaskAuditLog(
	ctx context.Context,
	req *console.ResumeMigrationTaskReq,
	task *entity.DMTask,
	err error,
) {
	recordOperateMigrationTaskAuditLog(
		ctx,
		req.GetOrgId(),
		req.GetProjectId(),
		req.GetClusterId(),
		req.GetId(),
		task,
		auditlog.EventResumeMigrationJob,
		err,
	)
}

func recordOperateMigrationTaskAuditLog(
	ctx context.Context,
	orgID, projectID, clusterID, taskID string,
	task *entity.DMTask,
	event auditlog.EventType,
	err error,
) {
	details := auditlog.Details{
		auditlog.KeyMigrationId: taskID,
	}
	if task != nil && task.Name != "" {
		details[auditlog.KeyJobName] = task.Name
	}
	console_auditlog.SubmitWithStringIDs(ctx, event, orgID, projectID, clusterID, details, err)
}

func buildCreateMigrationTaskDetails(
	req *console.CreateMigrationTaskReq,
	cluster *tidbmgmtservicev1.Cluster,
	task *entity.DMTask,
) auditlog.Details {
	details := auditlog.Details{
		auditlog.KeyJobName:          req.GetName(),
		auditlog.KeyTargetUsername:   req.GetTarget().GetUser(),
		auditlog.KeyMigrationJobType: req.GetMode().String(),
	}
	if cluster != nil {
		details[auditlog.KeyTargetRegion] = cluster.GetRegion()
		details[auditlog.KeyTargetClusterId] = req.GetClusterId()
	}
	if task != nil && task.ID != "" {
		details[auditlog.KeyMigrationId] = task.ID
		if task.Mode != "" {
			details[auditlog.KeyMigrationJobType] = string(task.Mode)
		}
	}
	if len(req.GetSources()) > 0 {
		fillSourceDetails(details, req.GetSources()[0])
	} else if task != nil && len(task.DMSources) > 0 {
		fillEntitySourceDetails(details, &task.DMSources[0])
	}
	return details
}

func fillSourceDetails(details auditlog.Details, source *console.Source) {
	if source == nil {
		return
	}
	if source.GetSourceTypeId() != "" {
		details[auditlog.KeySourceDataSource] = source.GetSourceTypeId()
	}
	cp := source.GetConnProfile()
	if cp == nil {
		return
	}
	details[auditlog.KeySourceConnectivityMethod] = cp.GetConnType().String()
	if cp.GetHost() != "" {
		details[auditlog.KeySourceHostnameOrIpaddress] = cp.GetHost()
	} else if cp.GetEndpointId() != "" {
		details[auditlog.KeySourceHostnameOrIpaddress] = cp.GetEndpointId()
	}
	if cp.GetPort() != 0 {
		details[auditlog.KeySourcePort] = cp.GetPort()
	}
	if cp.GetUser() != "" {
		details[auditlog.KeySourceUsername] = cp.GetUser()
	}
	details[auditlog.KeySourceEnableTls] = hasTLSEnabled(cp.GetSecurity())
}

func fillEntitySourceDetails(details auditlog.Details, source *entity.DMSource) {
	if source == nil {
		return
	}
	if source.SourceType != "" {
		details[auditlog.KeySourceDataSource] = string(source.SourceType)
	}
	details[auditlog.KeySourceConnectivityMethod] = string(source.ConnProfile.Type)
	if source.ConnProfile.Target != "" {
		details[auditlog.KeySourceHostnameOrIpaddress] = source.ConnProfile.Target
	} else if source.EndpointID != "" {
		details[auditlog.KeySourceHostnameOrIpaddress] = source.EndpointID
	}
	if source.ConnProfile.Port != 0 {
		details[auditlog.KeySourcePort] = source.ConnProfile.Port
	}
	if source.ConnProfile.User != "" {
		details[auditlog.KeySourceUsername] = source.ConnProfile.User
	}
	if source.ConnProfile.Security != nil {
		details[auditlog.KeySourceEnableTls] = hasEntityTLSEnabled(source.ConnProfile.Security)
	}
}

func hasTLSEnabled(security *console.Security) bool {
	if security == nil {
		return false
	}
	return len(security.GetSslCaContent()) > 0 ||
		len(security.GetSslCertContent()) > 0 ||
		len(security.GetSslKeyContent()) > 0
}

func hasEntityTLSEnabled(security *entity.Security) bool {
	if security == nil {
		return false
	}
	return len(security.SslCaContent) > 0 ||
		len(security.SslCertContent) > 0 ||
		len(security.SslKeyContent) > 0
}
