package connection

import (
	"context"
	"fmt"
	"framework/sqlAsyncMgr"
	"goutil/logUtilPlus"
	"time"

	goredis "github.com/go-redis/redis/v8"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"

	// _ "github.com/go-sql-driver/mysql"
	config "common/configsYaml"
	"goutil/mysqlUtil"
	"goutil/redisUtil"
)

var (
	adminDB         *gorm.DB                  //管理员数据库对象
	userDB          *gorm.DB                  //用户数据库对象
	payDB           *gorm.DB                  //充值数据库对象
	gameModelDB     *gorm.DB                  // 游戏模型数据库对象
	gameDB          *gorm.DB                  // 游戏数据库
	gamePlayerDB    *gorm.DB                  // 玩家库
	redisDB         *goredis.Client           // 游戏redis连接客户端
	syncMgr         *sqlAsyncMgr.SqlAsyncUtil // 同步管理对象
	syncFileSize    = 1024 * 1024             // 同步文件大小
	fileMaxSaveTime = 24 * 7                  // 保留7天的sql文件
)

var excuteSqlFunc func(*gorm.DB, ITable, string) error
var loghandle func(s string, is ...interface{})
var defaultType = SyncSql

type ITable interface {
	TableName() string
}

type SqlExecuteType int32

const (
	SyncSql SqlExecuteType = iota
	ASyncSql
	Name = "BaseDal"
)

// init
// @description: init
// parameter:
// return:
func init() {

	//管理中心数据库配置
	adminDB = initMysql(config.GetDbConfig().GetAdminConfig())
	userDB = initMysql(config.GetDbConfig().GetUserConfig())
	payDB = initMysql(config.GetDbConfig().GetPayConfig())

	// 初始化游戏模型数据库
	gameModelDBConfig := config.GetDbConfig().GetGameModelConfig()
	gameModelDB = initMysql(gameModelDBConfig)

	// 初始化crossSever 游戏数据库
	gameDBConfig := config.GetDbConfig().GetGameConfig()
	gameDB = initMysql(gameDBConfig)
	gamePlayerDB = initMysql(config.GetDbConfig().GetPlayerConfig())

	// 初始化redis-client
	excuteSqlFunc = func(gdb *gorm.DB, table ITable, sql string) error {
		db := gdb.Exec(sql)
		if db.Error != nil {
			loghandle("sql执行错误:%s;错误信息:%v", sql, db.Error.Error())
			return db.Error
		}

		return nil
	}

	redisDB = initRedis(config.GetDbConfig().GetRedisConfig())
}

// 初始化Mysql
// initMysql
// @description: 初始化Mysql
// parameter:
// @dbConfig: dbConfig
// return:
// @*gorm.DB: DB
func initMysql(dbConfig *mysqlUtil.DBConfig) *gorm.DB {

	//不存在配置
	if dbConfig == nil || dbConfig.ConnectionString == "" {
		return nil
	}
	logUtilPlus.DebugLog("开始连接mysql:%s", dbConfig.ConnectionString)
	dbObj, err := gorm.Open(mysql.Open(dbConfig.ConnectionString), &gorm.Config{PrepareStmt: true})
	if err != nil {
		panic(fmt.Errorf("初始化数据库:%s失败，错误信息为：%s", dbConfig.ConnectionString, err))
	}
	logUtilPlus.DebugLog("连接mysql:%s成功", dbConfig.ConnectionString)

	return dbObj
}

// initRedis
// @description: 初始化redis客户端
// parameter:
// @redisConfig: redisConfig
// return:
// @*goredis.Client: Client
func initRedis(redisConfig *redisUtil.RedisConfig) *goredis.Client {

	client := goredis.NewClient(&goredis.Options{
		Addr:        redisConfig.ConnectionString,
		Password:    redisConfig.Password,
		DB:          redisConfig.Database,
		IdleTimeout: redisConfig.IdleTimeout,
		DialTimeout: redisConfig.DialConnectTimeout,
	})

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()

	ping, err := client.Ping(ctx).Result()
	if err != nil {
		panic(fmt.Errorf("ping->redis:%s失败,DB:%s，错误信息为：%s", redisConfig.ConnectionString, redisConfig.Database, err))
	}

	logUtilPlus.DebugLog("ping->redis:%s成功，信息为：%s", redisConfig.ConnectionString, ping)
	return client
}

// GetAdminDB
// @description: 获取admin库db实例
// parameter:
// return:
// @*gorm.DB:admin库db实例
func GetAdminDB() *gorm.DB {
	return adminDB
}

// GetUserDB
// @description: 获取user库db实例
// parameter:
// return:
// @*gorm.DB:user库db实例
func GetUserDB() *gorm.DB {
	return userDB
}

// GetPayDB
// @description: 获取pay库db实例
// parameter:
// return:
// @*gorm.DB:pay库db实例
func GetPayDB() *gorm.DB {
	return payDB
}

// GetGameDB
// @description: 获取game库db实例
// parameter:
// return:
// @*gorm.DB:game库db实例
func GetGameDB() *gorm.DB {
	return gameDB
}

// GetPlayerDB
// @description: 获取玩家库db实例
// parameter:
// return:
// @*gorm.DB:玩家库db实例
func GetPlayerDB() *gorm.DB {
	return gamePlayerDB
}

// GetGameModelDB
// @description: 获取model库db实例
// parameter:
// return:
// @*gorm.DB:model库db实例
func GetGameModelDB() *gorm.DB {
	return gameModelDB
}

// GetRedisClient
// @description: 获取redisdb实例
// parameter:
// return:
// @*goredis.Client:redisdb实例
func GetRedisClient() *goredis.Client {
	return redisDB
}

// GetAll
// @description: 获取model数据
// parameter:
// @dataList:数据列表
// return:
// @error:错误信息
func GetAll(dataList interface{}) error {
	mysqlObj := GetGameModelDB()
	if mysqlObj = mysqlObj.Find(dataList); mysqlObj.Error != nil {
		WriteLog("dal.GetAll", mysqlObj.Error)
		return mysqlObj.Error
	}

	return nil
}

// GetGameModelData
// @description: 获取GameModel数据
// parameter:
// @moduleName:模块名称
// @dataList:数据列表
// return:
// @error:错误信息
func GetGameModelData(moduleName string, dataList interface{}) error {
	if result := gameModelDB.Find(dataList); result.Error != nil {
		WriteLog(moduleName+"GetGameModelData", result.Error)
		return result.Error
	}

	return nil
}

// WriteLog
// @description: 记录错误日志
// parameter:
// @command:命令
// @err:错误信息
// return:
func WriteLog(command string, err error) {
	logUtilPlus.ErrorLog(fmt.Sprintf("Scan失败，错误信息：%s，command:%s", err, command))
}
