package dm

import (
	"os"

	"gopkg.in/yaml.v3"

	"github.com/pingcap/test-infra/caselib/pkg/utils"
)

type (
	OperateSourceType int
	OperateRelayType  int
	operateSchemaType int
	handleErrorType   int
	OperateTaskType   int
)

const (
	Create OperateSourceType = iota
	Update
	Stop
	Show
)

func (o OperateSourceType) String() string {
	switch o {
	case Create:
		return "create"
	case Update:
		return "update"
	case Stop:
		return "stop"
	case Show:
		return "show"
	default:
		panic("unsupported operate source type")
	}
}

const (
	StartRelay OperateRelayType = iota
	PauseRelay
	ResumeRelay
	StopRelay
)

func (o OperateRelayType) String() string {
	switch o {
	case StartRelay:
		return "start-relay"
	case PauseRelay:
		return "pause-relay"
	case ResumeRelay:
		return "resume-relay"
	case StopRelay:
		return "stop-relay"
	default:
		panic("unsupported operate relay type")
	}
}

const (
	StartTask OperateTaskType = iota
	PauseTask
	ResumeTask
	StopTask
)

func (o OperateTaskType) String() string {
	switch o {
	case StartTask:
		return "start-task"
	case PauseTask:
		return "pause-task"
	case ResumeTask:
		return "resume-task"
	case StopTask:
		return "stop-task"
	default:
		panic("unsupported operate task type")
	}
}

const (
	Get operateSchemaType = iota
	Set
	Remove
)

func (o operateSchemaType) String() string {
	switch o {
	case Get:
		return "get"
	case Set:
		return "set"
	case Remove:
		return "remove"
	default:
		panic("unsupported operate schema type")
	}
}

const (
	skip handleErrorType = iota
	replace
	revert
)

func (h handleErrorType) String() string {
	switch h {
	case skip:
		return "skip"
	case replace:
		return "replace"
	case revert:
		return "revert"
	default:
		panic("unsupported handle error type")
	}
}

type SourceOption struct {
	ConfigPath  string
	OperateType OperateSourceType
}

func (opt *SourceOption) String() string {
	return opt.OperateType.String() + " " + utils.TempPath(opt.ConfigPath)
}

type Path struct {
	SourcePaths []string `yaml:"source-paths" validate:"required"`
	TaskPaths   []string `yaml:"task-paths" validate:"required"`
	DiffPaths   []string `yaml:"diff-paths" validate:"required"`
}

// ParseYaml read yaml content from `file` and unmarshal it to `p`
func ParseYaml(filePath string, p *Path) error {
	content, err := os.ReadFile(filePath)
	if err != nil {
		return err
	}

	if err := yaml.Unmarshal(content, p); err != nil {
		return err
	}
	return nil
}

type TaskOption struct {
	ConfigPath  string
	OperateType OperateTaskType
}

// operate task just support `xxxxx-task <config-file>`.
func (opt *TaskOption) String() string {
	return opt.OperateType.String() + " " + utils.TempPath(opt.ConfigPath)
}

type RelayOption struct {
	SourceName  *string
	OperateType OperateRelayType
}

// operate relay just support `xxx-relay <sourcename> + xxx`.
func (opt *RelayOption) String() string {
	return opt.OperateType.String() + " -s " + *opt.SourceName
}
