package config

import (
	"context"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"game/common/testHelper"
	"github.com/fox/fox/log"
	"github.com/go-redis/redis/v8"
)

const (
	//ModeDev     = "dev" // 开发服
	etcdKey     = "etcd_config"
	etcdAddress = "114.132.124.145:2379"
	natsKey     = "nats_config"
	natsAddress = "nats://114.132.124.145:4222"

	redisKey      = "redis_config"
	redisAddress  = testHelper.Host
	redisPort     = testHelper.RedisPort
	redisPassword = testHelper.RedisPassword

	mysqlKey     = "mysql_config"
	mysqlAddress = "114.132.124.145"
	mysqlPort    = "3306"
	mysqlUser    = "game"
	mysqlPasswd  = "fox379@@zyxi"
	mysqlDBName  = "game"

	clickhouseKey     = "clickhouse_config"
	clickhouseAddress = "81.71.140.178"
	clickhousePort    = "9000"
	clickhouseUser    = "game"
	clickhousePasswd  = "fox379@@zyxi"
	clickhouseDBName  = "game_log"
)

func LoadGameConfig(rd *redis.Client, specialKey string, comm *Common) error {
	s, err := rd.Get(context.Background(), specialKey).Result()
	if err != nil && !errors.Is(err, redis.Nil) {
		log.ErrorF("init config:%v", err)
		return err
	}
	if s == "" {
		return fmt.Errorf("config:%s not found from redis", specialKey)
	}
	comm.GameJson = s
	return nil
}

func LoadCommonConfig(rd *redis.Client, GitCommit, GitBranch, BuildDate string) (*Common, error) {
	var comm Common
	comm.GitCommit = GitCommit
	comm.GitBranch = GitBranch
	comm.BuildDate = BuildDate
	// 初始化etcd
	s, err := rd.Get(context.Background(), etcdKey).Result()
	if err != nil && !errors.Is(err, redis.Nil) {
		log.FatalF("init config:%v", err)
		return nil, err
	}
	if s == "" {
		log.DebugF("load config:empty etcd key")
		comm.Etcd = Etcd{
			Address:  []string{etcdAddress},
			Username: "",
			Password: "",
		}
		if bs, err := json.Marshal(&comm.Etcd); err == nil {
			err = rd.Set(context.Background(), etcdKey, string(bs), 0).Err()
		}
	} else {
		err = json.Unmarshal([]byte(s), &comm.Etcd)
	}

	// 初始化nats
	s, err = rd.Get(context.Background(), natsKey).Result()
	if err != nil && !errors.Is(err, redis.Nil) {
		log.FatalF("init config:%v", err)
		return nil, err
	}
	if s == "" {
		log.DebugF("load config:empty nats key")
		comm.Nats = Nats{Address: []string{natsAddress}}
		if bs, err := json.Marshal(&comm.Nats); err == nil {
			err = rd.Set(context.Background(), natsKey, string(bs), 0).Err()
		}
	} else {
		err = json.Unmarshal([]byte(s), &comm.Nats)
	}

	// 初始化redis
	s, err = rd.Get(context.Background(), redisKey).Result()
	if err != nil && !errors.Is(err, redis.Nil) {
		log.FatalF("init config:%v", err)
		return nil, err
	}
	if s == "" {
		log.DebugF("load config:empty redis key")
		comm.Redis = Redis{Host: redisAddress, Port: redisPort, Password: redisPassword}
		if bs, err := json.Marshal(&comm.Redis); err == nil {
			err = rd.Set(context.Background(), redisKey, string(bs), 0).Err()
		}
	} else {
		err = json.Unmarshal([]byte(s), &comm.Redis)
	}

	// 初始化mysql
	s, err = rd.Get(context.Background(), mysqlKey).Result()
	if err != nil && !errors.Is(err, redis.Nil) {
		log.FatalF("init config:%v", err)
		return nil, err
	}
	if s == "" {
		log.DebugF("load config:empty mysql key")
		comm.UserDb = Mysql{Host: mysqlAddress, Port: mysqlPort, Password: mysqlPasswd, Username: mysqlUser, DbName: mysqlDBName}
		if bs, err := json.Marshal(&comm.UserDb); err == nil {
			err = rd.Set(context.Background(), mysqlKey, string(bs), 0).Err()
		}
	} else {
		err = json.Unmarshal([]byte(s), &comm.UserDb)
	}

	// 初始化clickhouse
	s, err = rd.Get(context.Background(), clickhouseKey).Result()
	if err != nil && !errors.Is(err, redis.Nil) {
		log.FatalF("init config:%v", err)
		return nil, err
	}
	if s == "" {
		log.DebugF("load config:empty mysql key")
		comm.LogDb = ClickHouse{Host: clickhouseAddress, Port: clickhousePort, Password: clickhousePasswd,
			Username: clickhouseUser, DbName: clickhouseDBName}
		if bs, err := json.Marshal(&comm.LogDb); err == nil {
			err = rd.Set(context.Background(), clickhouseKey, string(bs), 0).Err()
		}
	} else {
		err = json.Unmarshal([]byte(s), &comm.LogDb)
	}
	return &comm, nil
}

/*
所有配置信息都存放在redis中，程序启动会给配置信息的redis地址，
连上后从该redis中读取所有其它的配置信息如mysql，etcd，nats，以及玩法相关的如房间配置等信息
*/
type Command struct {
	RedisHost     string
	RedisPort     string
	RedisPassword string
	ServiceId     int    // 起始服务id
	ServiceNum    int    // 服务数量
	VMod          string // 区分测试服，开发服
}

func ParseCommand() *Command {
	var Cmd Command
	flag.StringVar(&Cmd.RedisHost, "redis_host", "114.132.124.145", "redis host")
	flag.StringVar(&Cmd.RedisPort, "redis_port", "6379", "redis port")
	flag.StringVar(&Cmd.RedisPassword, "redis_password", "fox379@@zyxi", "redis password")
	flag.IntVar(&Cmd.ServiceId, "sid", 0, "service id")
	flag.IntVar(&Cmd.ServiceNum, "num", 1, "service num")
	flag.StringVar(&Cmd.VMod, "v_mod", "dev", "dev|release|test|prod")
	flag.Parse()
	return &Cmd
}
