package migrate

import (
	"context"
	"strconv"

	apprent "github.com/tidbcloud/devops/entity/approval"
	jumpent "github.com/tidbcloud/devops/entity/jump"
	"github.com/tidbcloud/devops/pkg/infra/errs"
	apprrepo "github.com/tidbcloud/devops/pkg/service/approval/repo"
	jumpsvcactor "github.com/tidbcloud/devops/pkg/service/jump/authactor"
	"github.com/tidbcloud/devops/pkg/service/jump/repo"
	oprepo "github.com/tidbcloud/devops/pkg/service/operation/repo"
	"github.com/tidbcloud/pkgv2/db"
	"gorm.io/gorm"
)

// migration for jump service to use approval service
var _ = AddMigrateRecord(
	"202407021400",
	func(raw *gorm.DB) error {
		db := db.NewProvider(raw)
		jmpRepo := repo.NewJumpRepo(db)
		opRepo := oprepo.NewOperationRepo(db)
		apprRepo := apprrepo.NewApprovalRepo(db)

		return db.Transaction(context.Background(), func(ctx context.Context) error {
			auths, err := jmpRepo.ListAuthorizations(ctx)
			if err != nil {
				return err
			}

			for _, auth := range auths {
				if auth.ApprovalID == nil {
					continue
				}

				op, err := opRepo.GetInstance(ctx, *auth.ApprovalID)
				if err != nil && !errs.IsNotFound(err) {
					return err
				}

				if errs.IsNotFound(err) {
					continue
				}

				newAppr := apprent.Approval{
					Name:       jumpsvcactor.ApprovalName,
					Applicant:  auth.Applicant,
					StartAt:    &op.CreatedAt,
					EndAt:      op.ClosedAt,
					Status:     apprent.ApprovalStatusApproved,
					DetailLink: "",
					Parameters: map[string]string{
						jumpsvcactor.ApprovalParamAuthID:     strconv.FormatUint(auth.ID, 10),
						"reason":                             auth.Reason,
						jumpsvcactor.ApprovalParamPrivilege:  string(auth.Privilege),
						jumpsvcactor.ApprovalParamExpiration: string(auth.Expiration),
					},
					Levels:  nil, // Approval nodes are not needed now
					CCTasks: nil, // Approval nodes are not needed now
				}
				appr, err := apprRepo.CreateApproval(ctx, &newAppr)
				if err != nil {
					return err
				}

				err = jmpRepo.PatchAuthorization(ctx, auth, func(current *jumpent.Authorization) error {
					auth.ApprovalID = &appr.ID
					return nil
				})
				if err != nil {
					return err
				}
			}

			return nil
		})

	},
)
