package authactor

import (
	"fmt"
	"time"

	apprent "github.com/tidbcloud/devops/entity/approval"
	jmpent "github.com/tidbcloud/devops/entity/jump"

	"github.com/tidbcloud/devops/pkg/infra/errs"
	"github.com/tidbcloud/devops/pkg/infra/utils/pointer"
	jmpsvcapi "github.com/tidbcloud/devops/pkg/service/jump/api"
)

type actorWhenApproving struct {
	*baseActor
}

func (a *actorWhenApproving) ContinueIfPodReady() error {
	return a.defaultErr
}

func (a *actorWhenApproving) ContinueIfApproved() error {
	ctx := a.Context
	ins := a.JumpAuthorization

	if ins.ApprovalID == nil {
		return fmt.Errorf("phase is approving but approval id is nil")
	}

	appr, err := a.ApprovalService.GetApproval(ctx, *ins.ApprovalID)
	if err != nil {
		return fmt.Errorf("get approval '%d' failed: %s", *ins.ApprovalID, err)
	}

	// record event detail
	/*a.EventDetail.FinshApproval = &event.OperationEventFinishApproval{
		Result: approval.Status,
	}*/

	switch appr.Status {
	case apprent.ApprovalStatusRejected, apprent.ApprovalStatusCancelled:
		return a.PatchAuthorization(ctx, func(current *jmpent.Authorization) error {
			current.Phase = jmpent.AuthorizationPhaseNotApproved
			current.ClosedAt = pointer.Pointer(time.Now().Unix())
			return nil
		})
	case apprent.ApprovalStatusApproved:
		// transition status to 'creating'
		err := a.PatchAuthorization(ctx, func(current *jmpent.Authorization) error {
			current.Phase = jmpent.AuthorizationPhaseCreating
			return nil
		})
		if err != nil {
			return err
		}
		_, err = a.JumpPodManager.SetUpJumpPod(ctx, EmailToJumpPodName(ins.Applicant))
		if err != nil {
			return err
		}
		return nil
	}

	return errs.RetriableErrorf("approval '%d' is still %s", *ins.ApprovalID, appr.Status)
}

func (a *actorWhenApproving) Cancel(param jmpsvcapi.CancelAuthorizaitonParam) error {
	return a.cancel(param)
}

// cancel transition status to 'Closed' and result is 'Cancel'.
func (a *actorWhenApproving) cancel(_ jmpsvcapi.CancelAuthorizaitonParam) error {
	ctx := a.Context

	apprID := ctx.Origin.ApprovalID
	if apprID != nil {
		err := a.GetContext().ApprovalService.CancelApproval(ctx, *apprID)
		if err != nil {
			return err
		}
	}

	// transition status to 'Cancel'
	return a.PatchAuthorization(ctx,
		func(current *jmpent.Authorization) error {
			current.Phase = jmpent.AuthorizationPhaseCanceled
			current.ClosedAt = pointer.Pointer(time.Now().Unix())
			return nil
		})
}
