package taskruns

import (
	"fmt"
	"time"

	"github.com/pingcap/test-infra/common/model"
)

const (
	KindTestbedSetup     = "TestbedSetup"
	KindTestbedSetupList = "TestbedSetupList"
)

type TestbedSetup struct {
	GeneralHeader
	MetaData GeneralMetaData    `json:"metadata"`
	Spec     TestbedSetupSpec   `json:"spec"`
	Status   TestbedSetupStatus `json:"status"`
}

func (s TestbedSetup) Validate() error {
	if s.GeneralHeader != HeaderTestbedSetup {
		return fmt.Errorf("model Mismatch: %s", s.GeneralHeader.Kind)
	}
	return nil
}

type TestbedSetupList struct {
	GeneralHeader
	Items []TestbedSetup `json:"items"`
	Total *int           `json:"total,omitempty"`
}

var (
	HeaderTestbedSetup = GeneralHeader{
		ApiVersion: CurrentApiVersion,
		Kind:       KindTestbedSetup,
	}
	HeaderTestbedSetupList = GeneralHeader{
		ApiVersion: CurrentApiVersion,
		Kind:       KindTestbedSetupList,
	}
)

func NewTestbedSetup() TestbedSetup {
	return TestbedSetup{
		GeneralHeader: HeaderTestbedSetup,
	}
}

func NewTestbedSetupList() TestbedSetupList {
	return TestbedSetupList{
		GeneralHeader: HeaderTestbedSetupList,
	}
}

type TestbedSetupSpec struct {
	TaskRunSpec
	PlanExecID  *model.ID      `json:"planExecID,omitempty"`
	TestbedSpec *model.TestBed `json:"testbedSpec,omitempty"`
	TestbedRef  *TestbedRef    `json:"testbedRef,omitempty"`
	OutPuts     []OutputParam  `json:"outPuts,omitempty"`
}

type OutputParam struct {
	Name      string `json:"name"`
	Type      string `json:"type"`
	Value     string `json:"value"`
	ValueExpr string `json:"valueExpr"`
}

type TestbedRef struct {
	PlanID *model.ID `json:"planID"`
}

type ScheduleReason struct {
	SchedulerName   string     `json:"schedulerName"`
	Message         string     `json:"message"`
	RelatedSetupIds []model.ID `json:"relatedSetupIds,omitempty"`
}

type Schedule struct {
	ScheduleStatus   ScheduleStatus `json:"scheduleStatus"`
	LastScheduleTime time.Time      `json:"lastScheduleTime"`
	ScheduleReason   ScheduleReason `json:"scheduleReason"`
	TestbedSpec      *model.TestBed `json:"testbedSpec,omitempty"`
}

type TestbedSetupReport struct {
	RetryCnt       int               `json:"retryCnt"`
	TestbedSpec    *model.TestBed    `json:"testbedSpec,omitempty"`
	Status         SetupWorkerStatus `json:"status"`
	LastReportTime time.Time         `json:"LastReportTime"`
}

type SetupWorkerStatus string

const (
	SetupWorkerStatusUnknown   SetupWorkerStatus = ""
	SetupWorkerStatusPolling   SetupWorkerStatus = "polling"
	SetupWorkerStatusDeploying SetupWorkerStatus = "deploying"
	SetupWorkerStatusDone      SetupWorkerStatus = "done"
)

type TestbedSetupStatus struct {
	Schedule *Schedule           `json:"schedule,omitempty"`
	Report   *TestbedSetupReport `json:"report,omitempty"`
	TaskRun  *TaskRunStatus      `json:"run,omitempty"`
}

type ScheduleStatus string

const (
	ScheduleStatusUnknown  ScheduleStatus = ""
	ScheduleStatusPending  ScheduleStatus = "pending"
	ScheduleStatusApproved ScheduleStatus = "approved"
	ScheduleStatusRefused  ScheduleStatus = "refused"
	ScheduleStatusDone     ScheduleStatus = "done"
)

type ListTestbedSetupOpts struct {
	GeneralListOpts
	RunPhase       *string         `schema:"runPhase,omitempty"`
	ScheduleStatus *ScheduleStatus `schema:"scheduleStatus,omitempty"`
	PlanExecIDs    []model.ID      `schema:"planExecIDs,omitempty"`
	IDs            []model.ID      `schema:"IDs,omitempty"`
}

type GetTestbedSetupOpts struct {
	GeneralGetOpts
}

type CreateTestbedSetupOpts struct {
	GeneralCreateOpts
}
