package phase

import (
	"fmt"
	"strconv"

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

type PhaseGlobalDealDesk struct {
	*basePhase
}

func (p *PhaseGlobalDealDesk) PhaseName() string {
	return p.basePhase.phaseName
}

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

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

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

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

func (*PhaseGlobalDealDesk) RequiresInput() bool {
	return true
}

func (p *PhaseGlobalDealDesk) Validate(context Context) error {
	ticket := context.TicketInstance
	// Check ExtraCompensation Value
	if len(ticket.ExtraPercent) == 0 {
		return fmt.Errorf("extra percent cannot be empty")
	}
	floatPercentage, err := strconv.ParseFloat(ticket.ExtraPercent, 32)
	if err != nil {
		return fmt.Errorf("parse monthly uptime percentage failed: %w", err)
	}
	if floatPercentage < 0.0 || floatPercentage > 100.0 {
		return fmt.Errorf("monthly uptime percentage %s is invalid", ticket.ExtraPercent)
	}
	return nil
}

func (p *PhaseGlobalDealDesk) ValidateAndUpdateTicket(origin *entity.RemediationTicket, patch rmapi.TransferTicketParam) error {
	if len(patch.ClusterBilling) == 0 {
		return fmt.Errorf("cluster billing cannot be empty")
	}
	floatBilling, err := strconv.ParseFloat(patch.ClusterBilling, 32)
	if err != nil {
		return fmt.Errorf("parse cluster billing failed: %w", err)
	}
	if floatBilling < 0.0 {
		return fmt.Errorf("cluster billing %s cannot be smaller than 0", patch.ClusterBilling)
	}
	origin.ClusterBilling = patch.ClusterBilling

	if len(patch.TotalCompensation) == 0 {
		return fmt.Errorf("total compensation cannot be empty")
	}
	floatBilling, err = strconv.ParseFloat(patch.TotalCompensation, 32)
	if err != nil {
		return fmt.Errorf("parse total compensation failed: %w", err)
	}
	if floatBilling < 0.0 {
		return fmt.Errorf("total compensation %s cannot be smaller than 0", patch.TotalCompensation)
	}
	origin.TotalCompensation = patch.TotalCompensation

	// DEPRECATED: will not use this two fields in the future. stay here for compatibility reasons.
	origin.PredefinedPercent = patch.PredefinedPercent
	origin.ExtraPercent = patch.ExtraPercent

	return nil
}

func (p *PhaseGlobalDealDesk) Next(context Context) (Phase, error) {
	err := p.Validate(context)
	if err != nil {
		return nil, fmt.Errorf("validation failed in %s: %w", p.basePhase.phaseName, err)
	}

	nextPhaseName, err := ResolveNextPhase(entity.RemediationTicketPhaseGlobalDealDesk, &context.TicketInstance)
	if err != nil {
		return nil, fmt.Errorf("resolve next phase failed for %s: %w", p.basePhase.phaseName, err)
	}

	nextPhase, err := GetPhaseByName(nextPhaseName)
	if err != nil {
		return nil, fmt.Errorf("get next phase failed for %s: %w", p.basePhase.phaseName, err)
	}

	return nextPhase, nil
}
