package tenantaction

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	opent "github.com/tidbcloud/devops/entity/operation"
	"github.com/tidbcloud/devops/pkg/infra/clients/billingcli"
	"github.com/tidbcloud/devops/pkg/service/operation/actions"
)

var (
	ActionCreateCredits opent.ActionMetadata = opent.ActionMetadata{
		Name:             "CreateCredits",
		Type:             opent.ActionTypeAuto,
		AllowAnyoneApply: true,
	}
)

type createCredits struct {
	actions.BaseAction
	comps *actions.Components
}

func NewCreateCredits(comps *actions.Components) actions.AutoAction {
	return &createCredits{comps: comps}
}

func (a *createCredits) Metadata() opent.ActionMetadata {
	return ActionCreateCredits
}

func (a *createCredits) PreCheck(ctx context.Context, instance *opent.Instance) error {
	_, err := a.getParam(instance)
	if err != nil {
		return err
	}

	tid, err := actions.GetTenantID(instance)
	if err != nil {
		return err
	}

	_, err = a.comps.TenantAPI.GetTenant(ctx, tid)
	if err != nil {
		return err
	}

	return nil
}

func (a *createCredits) Start(ctx context.Context, instance *opent.Instance) (*actions.ActionResult, error) {
	req, err := a.getParam(instance)
	if err != nil {
		return actions.FailedActionResult(err), nil
	}
	tid, err := actions.GetTenantID(instance)
	if err != nil {
		return actions.FailedActionResult(err), err
	}

	err = a.comps.BillingCli.CreateCredits(ctx, tid, req)
	if err != nil {
		return actions.FailedActionResult(err), nil
	}

	return actions.SucceededActionResult(nil), nil // return succeeded directly
}

func (a *createCredits) Result(ctx context.Context, instance *opent.Instance) (*actions.ActionResult, error) {
	return actions.SucceededActionResult(nil), nil
}

func (a *createCredits) getParam(instance *opent.Instance) (*billingcli.CreateCreditsPackageReq, error) {
	startTime := time.Now().UTC().Format("2006-01-02T15:04:05Z")
	expiredTime, _ := instance.GetParam(opent.ParamExpiredDate)
	usage, _ := instance.GetParam(opent.ParamUsage)
	credits, _ := instance.GetParam(opent.ParamTotalCredits)
	filters, _ := instance.GetParam(opent.ParamUnitFilters)
	discountEnabled, _ := instance.GetParam(opent.ParamDiscountEnabled)
	note := instance.Reason
	if startTime == "" || expiredTime == "" || usage == "" || credits == "" || filters == "" || discountEnabled == "" {
		return nil, fmt.Errorf("create credits param is required")
	}

	var unitFilters []*billingcli.UnitFilterSlim
	err := json.Unmarshal([]byte(filters), &unitFilters)
	if err != nil {
		return nil, err
	}

	reqs := &billingcli.CreateCreditsPackageReq{
		StartDate:       startTime,
		ExpiredDate:     expiredTime,
		TotalCredits:    credits,
		Usage:           usage,
		Note:            note,
		UnitFilters:     unitFilters,
		DiscountEnabled: discountEnabled == "true",
		UserEmail:       instance.Applicant,
		ForeignID:       fmt.Sprintf("%d", instance.ID),
	}

	return reqs, nil
}
