package tiworkload

import (
	"time"

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

type FormElement struct {
	Key      string `json:"key,omitempty"`
	Name     string `json:"name,omitempty"`
	Type     string `json:"type,omitempty"`
	Required bool   `json:"required,omitempty"`
	Default  any    `json:"default,omitempty"`
	// There are several more fields here, but we don't need them for now
}

func (f FormElement) ToWorkloadField() model.WorkloadField {
	key := f.Key
	if key == "" {
		key = f.Name
	}
	return model.WorkloadField{
		Key:      key,
		Name:     f.Name,
		Type:     f.Type,
		Desc:     f.Name,
		Required: f.Required,
		Value:    f.Default,
	}
}

type FormElements []FormElement

func (f FormElements) ToWorkloadFields() []model.WorkloadField {
	var fields []model.WorkloadField
	for _, fe := range f {
		fields = append(fields, fe.ToWorkloadField())
	}
	return fields
}

type execForms struct {
	Clean    FormElements `json:"clean,omitempty"`
	Prepare  FormElements `json:"prepare,omitempty"`
	Workload FormElements `json:"workload,omitempty"`
	Backup   FormElements `json:"backup,omitempty"`
	Advance  FormElements `json:"advance,omitempty"`
}

type TaskParams struct {
	Params map[string]any `json:"params"`
}

type ExecuteBase struct {
	// Cluster Meta
	ClusterID string `json:"cluster_id"`
	// Type      string `json:"type"`
	DBHost   string `json:"db_host"`
	DBPort   int    `json:"db_port"`
	PDHost   string `json:"pd_host"`
	PDPort   int    `json:"pd_port"`
	User     string `json:"db_user,omitempty"`
	Password string `json:"db_password,omitempty"`

	// Workload Meta
	WorkloadName string `json:"workload_name"`
}

type WorkloadParams struct {
	ExecuteBase
	WorkloadParams TaskParams `json:"workload"`
}

type PrepareParams struct {
	ExecuteBase
	PrepareParams TaskParams `json:"prepare"`
}

type TrafficExec struct {
	ID        string     `json:"id,omitempty"`
	Workload  string     `json:"workload,omitempty"`
	ClusterId string     `json:"cluster_id,omitempty"`
	Tool      string     `json:"tool,omitempty"`
	StartedAt *time.Time `json:"started_at,omitempty"`
	UpdatedAt *time.Time `json:"updated_at,omitempty"`

	DBHost string `json:"db_host"`
	DBPort int    `json:"db_port"`
	PDHost string `json:"pd_host"`
	PDPort int    `json:"pd_port"`

	User     string `json:"db_user,omitempty"`
	Password string `json:"db_password,omitempty"`

	Status  string `json:"status,omitempty"`
	Message string `json:"message,omitempty"`
}

func (e TrafficExec) ToWorkloadTask() model.WorkloadTaskBase {
	var status model.ExecStatus
	message := e.Message
	switch e.Status {
	case "init", "pending", "ready":
		status = model.ExecStatusPending
	case "running", "terminating":
		status = model.ExecStatusRunning
	case "success":
		status = model.ExecStatusCompleted
	case "failure", "interrupted":
		status = model.ExecStatusFailed
	case "terminated":
		status = model.ExecStatusStopped
		message = "workload client was stopped by admin."
	default:
		status = model.ExecStatus(e.Status)
	}

	progress := 0.0
	// Determine phase based on status and whether we have a service ID
	if e.ID != "" && status == model.ExecStatusCompleted {
		progress = 1.0
	}

	// TODO: progress by exec time/duration
	return model.WorkloadTaskBase{
		RelatedServiceID: e.ID,
		ExecBase: model.ExecBase{
			StartedAt: e.StartedAt,
			UpdatedAt: e.UpdatedAt,
			Message:   message,
			Status:    status,
		},
		Progress: progress,
	}
}

type DBAccess struct {
	ClusterID  string `json:"cluster_id,omitempty"`
	DBUser     string `json:"db_user,omitempty"`
	DBPassword string `json:"db_password,omitempty"`
}

type OverProvisionResource struct {
	CPU    string `json:"cpu,omitempty"`
	Memory string `json:"memory,omitempty"`
}

type OverProvisionOption struct {
	Resource     OverProvisionResource `json:"resource"`
	WorkerImage  string                `json:"worker_image,omitempty"`
	ToolsetImage string                `json:"toolset_image,omitempty"`

	Name     string `json:"name"`
	Replicas int    `json:"replicas"`
}

type ClusterDetail struct {
	ID     string `json:"id"`
	Name   string `json:"name"`
	Handle string `json:"handle"`
	DBHost string `json:"db_host"`
	DBPort int    `json:"db_port"`
}

type ExecteSqlReq struct {
	ClusterID string `json:"cluster_id"`
	Query     string `json:"query"`
}

type ExecteSqlResp struct {
	RowsAffected int64      `json:"rows_affected,omitempty"`
	Columns      []string   `json:"columns,omitempty"`
	Rows         [][]string `json:"rows,omitempty"`
	Truncated    bool       `json:"truncated,omitempty"`
	RowLimit     int        `json:"row_limit,omitempty"`
}
