package gateway

import (
	"fmt"
	"strconv"

	"github.com/tidbcloud/pov-service/internal/client/tcms"
	"github.com/tidbcloud/pov-service/internal/model"
)

type tiWorkloadFormProvider interface {
	GetTrafficForm(name string) ([]model.WorkloadField, error)
	GetPrepareForm(name string) ([]model.WorkloadField, error)
}

type paramHelper struct {
	forms  tiWorkloadFormProvider
	isProd bool
}

func newParamHelper(
	provider tiWorkloadFormProvider,
	isProd bool) paramHelper {
	return paramHelper{
		forms:  provider,
		isProd: isProd,
	}
}

func (h paramHelper) mergeWithDefaults(
	defaultForms []model.WorkloadField,
	params model.WorkloadParams,
) (map[string]any, error) {
	workloadParams := make(map[string]any, len(defaultForms))

	for _, form := range defaultForms {
		workloadParams[form.Key] = form.Value
	}
	for _, param := range params {
		if _, ok := workloadParams[param.Name]; ok {
			workloadParams[param.Name] = param.Value
		}
	}
	for k, v := range workloadParams {
		switch vv := v.(type) {
		case nil:
			delete(workloadParams, k)
		case string:
			if vv == "" {
				delete(workloadParams, k)
			}
		case int:
			if vv == 0 {
				delete(workloadParams, k)
			}
		}
	}

	for _, form := range defaultForms {
		current, ok := workloadParams[form.Key]
		if !ok {
			continue
		}
		strVal, ok := current.(string)
		if !ok {
			continue
		}
		switch form.Type {
		case "int":
			if i, err := strconv.ParseInt(strVal, 10, 64); err == nil {
				workloadParams[form.Key] = i
			}
		case "checkbox":
			if b, err := strconv.ParseBool(strVal); err == nil {
				workloadParams[form.Key] = b
			}
		case "decimal":
			if f, err := strconv.ParseFloat(strVal, 64); err == nil {
				workloadParams[form.Key] = f
			}
		}
	}

	return workloadParams, nil
}

func (h paramHelper) trafficParams(
	workloadName string,
	params model.WorkloadParams,
) (map[string]any, error) {
	defaultForms, err := h.forms.GetTrafficForm(workloadName)
	if err != nil {
		return nil, err
	}

	return h.mergeWithDefaults(defaultForms, params)
}

func (h paramHelper) prepareParams(
	workloadName string,
	params model.WorkloadParams,
) (map[string]any, error) {
	defaultForms, err := h.forms.GetPrepareForm(workloadName)
	if err != nil {
		return nil, err
	}
	return h.mergeWithDefaults(defaultForms, params.GetPrepareParams())
}

func (h paramHelper) clusterWorkflowID(
	params model.WorkloadParams,
) (int, error) {
	clusterType, err := params.GetClusterType()
	if err != nil {
		return 0, err
	}
	if clusterType == model.ClusterTypeTiDBCloudEssential {
		if h.isProd {
			return 0, fmt.Errorf("essential cluster is not supported in prod env")
		}
		return tcmsCreateEssentialClusterWorkflowID, nil
	}

	if h.isProd {
		return tcmsCreateNGProdClusterWorkflowID, nil
	}
	return tcmsCreateNGClusterWorkflowID, nil
}

func (h paramHelper) tcmsRunnerID(
	params model.WorkloadParams,
) (int64, error) {
	clusterType, err := params.GetClusterType()
	if err != nil {
		return 0, err
	}
	switch clusterType {
	case model.ClusterTypeTiDBCloudEssential:
		return tcms.AWSUsEast1RunnerID, nil
	case model.ClusterTypeTiDBCloudPremium:
		return tcms.AWSUsWest2RunnerID, nil
	}
	return 0, fmt.Errorf("unknown cluster type: %s", clusterType)
}
