package options

import (
	"encoding/json"

	genericoptions "github.com/pingcap-inc/pingcat/internal/pkg/option"
	"github.com/pingcap-inc/pingcat/internal/pkg/server"

	"github.com/pingcap-inc/pchub/pkg/app"
	"github.com/pingcap-inc/pchub/pkg/log"
)

type Options struct {
	GenericServerRunOptions *genericoptions.ServerRunOptions       `json:"server"   mapstructure:"server"`
	InsecureServing         *genericoptions.InsecureServingOptions `json:"insecure" mapstructure:"insecure"`
	MySQLOptions            *genericoptions.MySQLOptions           `json:"mysql"    mapstructure:"mysql"`
	Log                     *log.Options                           `json:"log"      mapstructure:"log"`
	RedisOptions            *genericoptions.RedisOptions           `json:"redis"    mapstructure:"redis"`
}

func NewOptions() *Options {
	o := Options{
		GenericServerRunOptions: genericoptions.NewServerRunOptions(),
		InsecureServing:         genericoptions.NewInsecureServingOptions(),
		Log:                     log.NewOptions(),
		RedisOptions:            genericoptions.NewRedisOptions(),
	}

	return &o
}

func (o *Options) ApplyTo(c *server.Config) error {
	return nil
}

func (o *Options) LoggerConfigs() *log.Options {
	return o.Log
}

// Flags returns flags for a specific APIServer by section name.
func (o *Options) Flags() (fss app.NamedFlagSets) {
	o.GenericServerRunOptions.AddFlags(fss.FlagSet("generic"))
	o.InsecureServing.AddFlags(fss.FlagSet("insecure serving"))
	o.Log.AddFlags(fss.FlagSet("log"))
	o.RedisOptions.AddFlags(fss.FlagSet("redis"))

	return fss
}

// Validate checks Options and return a slice of found errs.
func (o *Options) Validate() []error {
	var errs []error

	errs = append(errs, o.GenericServerRunOptions.Validate()...)
	errs = append(errs, o.InsecureServing.Validate()...)
	errs = append(errs, o.Log.Validate()...)
	errs = append(errs, o.RedisOptions.Validate()...)

	return errs
}

func (o *Options) String() string {
	data, err := json.Marshal(o)
	if err != nil {
		return ""
	}

	return string(data)
}

func (o *Options) Complete() error {
	return nil
}
