package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"ems.agt/lib/global"
	"ems.agt/lib/log"

	"gopkg.in/yaml.v3"
)

// Yaml struct of config
type YamlConfig struct {
	Logger struct {
		File     string `yaml:"file"`
		Level    string `yaml:"level"`
		Duration int    `yaml:"duration"`
		Count    int    `yaml:"count"`
	} `yaml:"logger"`

	OMC struct {
		Name     string `yaml:"name"`
		HostUri  string `yaml:"hosturi"`
		HostNo   string `yaml:"hostno"`
		Province string `yaml:"province"`
		NetAbbr  string `yaml:"netabbr"`
		Vendor   string `yaml:"vendor"`
	} `yaml:"omc"`

	Database struct {
		Type     string `yaml:"type"`
		User     string `yaml:"user"`
		Password string `yaml:"password"`
		Host     string `yaml:"host"`
		Port     string `yaml:"port"`
		Name     string `yaml:"name"`
		Backup   string `yaml:"backup"`
	} `yaml:"database"`

	Tasks struct {
		File string `yaml:"file"`
	} `yaml:"tasks"`

	NBI struct {
		CM struct {
			CfgFileDir string `yaml:"cfgfiledir"`
			XmlFileDir string `yaml:"xmlfiledir"`
			Version    string `yaml:"version"`
		} `yaml:"cm"`
		PM struct {
			CfgFileDir string `yaml:"cfgfiledir"`
			XmlFileDir string `yaml:"xmlfiledir"`
			Version    string `yaml:"version"`
		} `yaml:"pm"`
	} `yaml:"nbi"`
}

var yamlConfig YamlConfig

func ReadConfig(configFile string) error {
	yamlFile, err := os.ReadFile(configFile)
	if err != nil {
		fmt.Println("Read yaml config file error:", err)
		return err
	}

	err = yaml.Unmarshal(yamlFile, &yamlConfig)
	if err != nil {
		fmt.Println("Unmarshal error:", err)
		return err
	}
	return nil
}

func GetYamlConfig() *YamlConfig {
	return &yamlConfig
}

func GetLogLevel() log.LogLevel {
	var logLevel log.LogLevel
	switch strings.ToLower(yamlConfig.Logger.Level) {
	case "trace":
		logLevel = log.LOG_TRACE
	case "info":
		logLevel = log.LOG_INFO
	case "debug":
		logLevel = log.LOG_DEBUG
	case "warn":
		logLevel = log.LOG_WARN
	case "error":
		logLevel = log.LOG_ERROR
	case "fatal":
		logLevel = log.LOG_FATAL
	case "off":
		logLevel = log.LOG_OFF
	default:
		logLevel = log.LOG_DEBUG
	}
	return logLevel
}

type Task struct {
	Name     string `yaml:"name"`
	Status   string `yaml:"status" default:"Active"`
	Uri      string `yaml:"uri"`
	Params   string `yaml:"params"`
	Body     string `yaml:"body"`
	Interval uint64 `yaml:"interval"`
	Unit     string `yaml:"unit"`
	At       string `yaml:"at"`
	From     int    `yaml:"from"`
	Do       string `yaml:"do"`
}

type Crontab struct {
	Name   string `yaml:"name"`
	Status string `yaml:"status" default:"Active"`
	Tab    string `yaml:"tab"`
	Do     string `yaml:"do"`
	Uri    string `yaml:"uri"`
	Params string `yaml:"params"`
	Body   string `yaml:"body"`
}

type Tasks struct {
	Tasks    []Task    `yaml:"tasks"`
	Crontabs []Crontab `yaml:"crontab"`
}

const (
	TaskStatusActive   = "active"
	TaskStatusInactive = "inactive"
)

var taskSet Tasks

func ReadTasksYaml(pfile string) (ret error) {
	log.Debug("pfile:", pfile)
	file, err := os.ReadFile(pfile)
	if err != nil {
		log.Error(err)
		return err
	}

	err = yaml.Unmarshal(file, &taskSet)
	if err != nil {
		log.Error(err)
		return err
	}

	log.Trace("tasks:", taskSet)
	return nil
}

func GetDefaultUserAgent() string {
	return "OMC-crontask/" + global.Version
}

const defaultConfigFile = "./etc/crontask.yaml"

var ConfigFile *string

func init() {
	ConfigFile = flag.String("c", defaultConfigFile, "config file")
	pv := flag.Bool("v", false, "print version")
	ph := flag.Bool("h", false, "print help")

	flag.Parse()
	if *pv {
		fmt.Printf("OMC crontask version: %s\n%s\n%s\n\n", global.Version, global.BuildTime, global.GoVer)
		os.Exit(0)
	}
	if *ph {
		flag.Usage()
		os.Exit(0)
	}

	err := ReadConfig(*ConfigFile)
	if err != nil {
		fmt.Println("Failed to ReadConfig:", err)
		os.Exit(3)
	}
}
