package phase

import (
	"context"

	"github.com/tidbcloud/devops/entity"
	rmapi "github.com/tidbcloud/devops/pkg/service/remediationticket/api"
)

// The package is based on `State` design pattern

type Phase interface {
	TransferToNext(Context) *Phase
	PhaseName() string
	PhaseNo() uint
	Successors() []*Phase
	Predecessors() []*Phase
	IsFinalized() bool
	RequiresInput() bool
	AutoAdvance() bool
	Validate(Context) error
	ValidateAndUpdateTicket(origin *entity.RemediationTicket, patch rmapi.TransferTicketParam) error
	Next(Context) (Phase, error)
}

type Context struct {
	context.Context
	TicketInstance entity.RemediationTicket
}

type basePhase struct {
	phaseName   string
	phaseNum    uint
	isFinalized bool
}

// Should be overidden
func (*basePhase) TransferToNext(context Context) *Phase {
	return nil
}

// Should be overidden
func (p *basePhase) PhaseName() string {
	return p.phaseName
}

func (p *basePhase) PhaseNo() uint {
	return p.phaseNum
}

func (*basePhase) Successors() []*Phase {
	return nil
}

func (*basePhase) Predecessors() []*Phase {
	return nil
}

func (p *basePhase) IsFinalized() bool {
	return p.isFinalized
}

func (*basePhase) RequiresInput() bool {
	return false
}

func (*basePhase) AutoAdvance() bool {
	return false
}

func (*basePhase) Validate() error {
	return nil
}

var phases []Phase
var phaseMap map[string]Phase

func init() {
	phaseMap = make(map[string]Phase)

	// Created
	phaseCreated := &PhaseCreated{&basePhase{
		phaseName:   entity.RemediationTicketPhaseCreated,
		isFinalized: false,
	}}
	phases = append(phases, phaseCreated)
	phaseMap[entity.RemediationTicketPhaseCreated] = phaseCreated

	// Region TSE Leader
	phaseRegionTSELeader := &PhaseRegionTSELeader{&basePhase{
		phaseName:   entity.RemediationTicketPhaseRegionTSELeader,
		isFinalized: false,
	}}
	phases = append(phases, phaseRegionTSELeader)
	phaseMap[entity.RemediationTicketPhaseRegionTSELeader] = phaseRegionTSELeader

	// RDG SLA Owner
	phaseRDGSLAOwner := &PhaseRDGSLAOwner{&basePhase{
		phaseName:   entity.RemediationTicketPhaseRDGSLAOwner,
		isFinalized: false,
	}}
	phases = append(phases, phaseRDGSLAOwner)
	phaseMap[entity.RemediationTicketPhaseRDGSLAOwner] = phaseRDGSLAOwner

	// RDG Final Decision Maker
	phaseRDGFinalDecisionMaker := &PhaseRDGFinalDecisionMaker{&basePhase{
		phaseName:   entity.RemediationTicketPhaseRDGFinalDecisionMaker,
		isFinalized: false,
	}}
	phases = append(phases, phaseRDGFinalDecisionMaker)
	phaseMap[entity.RemediationTicketPhaseRDGFinalDecisionMaker] = phaseRDGFinalDecisionMaker

	// Global Deal Desk
	phaseGlobalDealDesk := &PhaseGlobalDealDesk{&basePhase{
		phaseName:   entity.RemediationTicketPhaseGlobalDealDesk,
		isFinalized: false,
	}}
	phases = append(phases, phaseGlobalDealDesk)
	phaseMap[entity.RemediationTicketPhaseGlobalDealDesk] = phaseGlobalDealDesk

	// Regional GM
	phaseRegionalGM := &PhaseRegionalGM{&basePhase{
		phaseName:   entity.RemediationTicketPhaseRegionalGM,
		isFinalized: false,
	}}
	phases = append(phases, phaseRegionalGM)
	phaseMap[entity.RemediationTicketPhaseRegionalGM] = phaseRegionalGM

	// Commercial Operation
	phaseCommercialOperation := &PhaseCommercialOperation{&basePhase{
		phaseName:   entity.RemediationTicketPhaseCommercialOperation,
		isFinalized: false,
	}}
	phases = append(phases, phaseCommercialOperation)
	phaseMap[entity.RemediationTicketPhaseCommercialOperation] = phaseCommercialOperation

	// Succeed
	phaseSucceed := &PhaseSucceed{&basePhase{
		phaseName:   entity.RemediationTicketPhaseSucceed,
		isFinalized: true,
	}}
	phases = append(phases, phaseSucceed)
	phaseMap[entity.RemediationTicketPhaseSucceed] = phaseSucceed

	// Closed
	phaseClosed := &PhaseClosed{&basePhase{
		phaseName:   entity.RemediationTicketPhaseClosed,
		isFinalized: true,
	}}
	phases = append(phases, phaseClosed)
	phaseMap[entity.RemediationTicketPhaseClosed] = phaseClosed

	refreshWorkflowDefinitionPhaseMetadata()
}
