package dbuser

import (
	"context"

	"github.com/tidbcloud/account/internel/svc/dbuser"

	"github.com/tidbcloud/account/commons/config"
	"go.opentelemetry.io/otel"

	dbUserDao "github.com/tidbcloud/account/internel/dao/dbuser"

	"github.com/tidbcloud/account/central/utils"
	"github.com/tidbcloud/account/internel/dao/entity"
	"github.com/tidbcloud/account/thirdparty/infra"

	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
)

// RunOrgKeyJob
//
//	@Description:create orgKey
//	@Author wangletian 2022-12-17 23:08:59
//	@param ctx
//	@param dbUserSrv
//	@return error
func RunOrgKeyJob(c context.Context, dbUserSrv dbuser.DBUserIface) error {
	ctx, span := otel.Tracer(config.TraceComponentNameWorker).Start(context.Background(), "RunOrgKeyJob")
	defer span.End()
	bm := utils.Begin(ctx, "RunOrgKeyJob")
	defer bm.OnExit(ctx)
	filter := dbUserDao.CommandOrgKeyFilter{
		Status:  []entity.CommandStatus{entity.CommandStatusWaiting, entity.CommandStatusFail},
		Actions: []entity.CommandAction{entity.CommandActionCreate, entity.CommandActionDelete},
	}
	orgKeys, err := dbUserSrv.ListCommandOrgKeys(ctx, filter)
	tilog.Info(ctx, "RunOrgKeyJob  query CommandOrgKeys", zap.Any("orgKeys", orgKeys))
	if err != nil {
		return err
	}
	for _, orgKey := range orgKeys {
		if !IsIgnore(ctx, orgKey.Status, orgKey.CreatedAt, orgKey) {
			// Create key
			if entity.CommandActionCreate == orgKey.Action {
				if err := dbUserSrv.CreateKmsKeyAndUpdateRecord(ctx, orgKey); err != nil {
					continue
				}

				orgKey.Status = entity.CommandStatusComplete
				// delete key
			} else if entity.CommandActionDelete == orgKey.Action {
				if err := dbUserSrv.DeleteKmsKeyAndUpdateRecord(ctx, orgKey.OrgID.Uint64()); err != nil {
					continue
				}

				orgKey.Status = entity.CommandStatusComplete
				// update key
			} else if entity.CommandActionUpdate == orgKey.Action {
				if err := dbUserSrv.DeleteKmsKeyAndUpdateRecord(ctx, orgKey.OrgID.Uint64()); err != nil {
					continue
				}

				if err = dbUserSrv.CreateKmsKeyAndUpdateRecord(ctx, orgKey); err != nil {
					continue
				}

				insertCommandClusterKey(ctx, dbUserSrv, &orgKey)

				// fail cluster Key
			} else if entity.CommandActionCreate == orgKey.Action && entity.CommandStatusFailClusterKey == orgKey.Status {
				insertCommandClusterKey(ctx, dbUserSrv, &orgKey)

			}

			return dbUserSrv.UpdateCommandOrgKey(ctx, orgKey.OrgID.Uint64(), orgKey.Status, orgKey.Action)
		}

	}
	return nil

}

// insertCommandClusterKey
//
//	@Description: save create/delete  org_key command
//	@Author wangletian 2022-12-25 23:07:50
//	@param ctx
//	@param dbUserSrv
//	@param orgKey
func insertCommandClusterKey(ctx context.Context, dbUserSrv dbuser.DBUserIface, orgKey *entity.CommandOrgKey) {

	clusters, err := infra.GetHandler().GetOrgClusterSupportDbUser(ctx, orgKey.OrgID.Uint64())
	if err != nil {
		orgKey.Status = entity.CommandStatusFailClusterKey
	}

	for i, c := range clusters {
		if !c.IsDevTier {
			err := dbUserSrv.CreateCommandClusterKey(ctx, orgKey.OrgID.Uint64(), c.Id, entity.CommandStatusWaiting, entity.CommandActionCreate)
			if err != nil {
				tilog.Error(ctx, "CreateCommandClusterKey error",
					zap.Any("len", len(clusters)),
					zap.Any("clusterId", c.Id),
					zap.Any("OrgId", orgKey.OrgID.Uint64()),
					zap.Any("orgKey.Status", orgKey.Status))
				orgKey.Status = entity.CommandStatusFailClusterKey
			}
			tilog.Info(ctx, "CreateCommandClusterKey",
				zap.Any("i", i),
				zap.Any("len", len(clusters)),
				zap.Any("clusterId", c.Id),
				zap.Any("OrgId", orgKey.OrgID.Uint64()),
				zap.Any("orgKey.Status", orgKey.Status))
		} else {
			tilog.Info(ctx, "this cluster isDevTier ,skip  ",
				zap.Any("clusterId", c.Id),
				zap.Any("OrgId", orgKey.OrgID.Uint64()))
		}

	}

}
