package jobs

import (
	"encoding/json"
	"gadmin/config"
	"gadmin/utility"
	"gadmin/utility/compress"
	"os"
	"path"
	"path/filepath"
	"time"

	"github.com/sirupsen/logrus"
	"github.com/spf13/cast"
)

var BackupRedis = new(jBackupRedis)

const RedisBackupPath = "/redisHistoryKeys/" // 备份二级路径

type jBackupRedis struct{}

func (j *jBackupRedis) Run() {
	//logrus.Info("BackupRedis Run.....")
	//
	//if os.Getenv("GIN_MODE") == "release" {
	//	j.createDir()
	//	j.cleanDateType()
	//	j.cleanWeekType()
	//	j.refreshDownloadList()
	//} else {
	//	logrus.Warn("非正式环境无需进行备份，跳过..")
	//}

}

// cleanDateType 清理日期类型
func (j *jBackupRedis) cleanDateType() {
	now := time.Now()
	firstDay := time.Date(now.Year(), time.January, 1, 0, 0, 0, 0, now.Location()).Unix()
	lastDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).Unix() - 86400*21 // 3周前
	for i := firstDay; i <= lastDay; i += 86400 {

		format1 := time.Unix(i, 0).Format("2006-01-02")
		j.cleanString("luck_draw_v2:" + format1)
		j.cleanString("day_task_v2:" + format1)

		format2 := time.Unix(i, 0).Format("20060102")
		j.cleanZSet("curio_ranking:" + format2)
	}
}

// cleanWeekType 清理周类型
func (j *jBackupRedis) cleanWeekType() {
	var (
		start = utility.WeekByDate(time.Now()) - 4 // -4是从3周前截止
	)

	for i := 1; i <= start; i++ {
		j.cleanHash("pvpplayers:" + cast.ToString(i))
		j.cleanHash("pvphistorys:" + cast.ToString(i))
		j.cleanHash("pvpmode:" + cast.ToString(i))

		j.cleanZSet("ranking_pvp:" + cast.ToString(i))
		j.cleanZSet("ranking_list:" + cast.ToString(i))
	}
}

func (j *jBackupRedis) cleanString(key string) {
	logrus.Info("cleanString 正在清理: ", key)
	models := config.GameRedis.Get(key).Val()
	if models == "" {
		logrus.Info(key, "不存在已跳过..")
		return
	}

	j.compression(key, models)

	//config.Redis.Del(key)
}

func (j *jBackupRedis) cleanHash(key string) {
	logrus.Info("cleanHash 正在清理: ", key)
	type Models struct {
		Member string `json:"member"`
		Score  string `json:"score"`
	}

	var (
		err    error
		cursor uint64 = 0
		match         = ""
		count  int64  = 20000
		models []Models
	)

	keys, cursor, err := config.GameRedis.HScan(key, cursor, match, count).Result()
	if len(keys) == 0 {
		logrus.Info(key, "不存在已跳过..")
		return
	}
	if err != nil {
		logrus.Info("HScan err:", key, err)
		return
	}

	for i := 0; i < len(keys); i++ {
		if utility.IsEven(i) {
			models = append(models, Models{Member: keys[i], Score: keys[i+1]})
		}
	}

	j.compression(key, models)

	//config.Redis.Del(key)
}

func (j *jBackupRedis) cleanZSet(key string) {
	logrus.Info("cleanZSet 正在清理: ", key)
	type Models struct {
		Member string `json:"member"`
		Score  string `json:"score"`
	}

	var (
		err    error
		cursor uint64 = 0
		match         = ""
		count  int64  = 20000
		models []Models
	)

	keys, cursor, err := config.GameRedis.ZScan(key, cursor, match, count).Result()
	if len(keys) == 0 {
		logrus.Info(key, "不存在已跳过..")
		return
	}

	if err != nil {
		logrus.Info("ZScan err:", key, err)
		return
	}

	for i := 0; i < len(keys); i++ {
		if utility.IsEven(i) {
			models = append(models, Models{Member: keys[i], Score: keys[i+1]})
		}
	}

	j.compression(key, models)

	//config.Redis.Del(key)
}

// compression 统一压缩处理
func (j *jBackupRedis) compression(key string, models interface{}) {
	bytes, err := json.Marshal(models)
	if err != nil {
		logrus.Infof("json.Marshal err:%v", err)
		return
	}

	fileName, gzFilePath := j.getCompressPath(key)
	if err = compress.DoGzip(bytes, gzFilePath, fileName); err != nil {
		logrus.Infof("compress.DoGzip err:%v", err)
		return
	}
}

func (j *jBackupRedis) createDir() {
	utility.CreateDir(os.Getenv("BACKUP_PATH") + RedisBackupPath)
}

// getCompressPath 获取压缩路径
func (j *jBackupRedis) getCompressPath(key string) (fileName, gzFilePath string) {
	fileName = key + ".json"
	gzFilePath = os.Getenv("BACKUP_PATH") + RedisBackupPath + key + ".gz"
	return
}

// refreshDownloadList 刷新下载列表
func (j *jBackupRedis) refreshDownloadList() {
	var (
		downloadJsonPath = os.Getenv("BACKUP_PATH") + RedisBackupPath + "download.json"
		files            []string
	)
	file, err := os.OpenFile(downloadJsonPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
	if err != nil {
		logrus.Errorf("文件错误,错误为:%v\n", err)
		return
	}
	defer file.Close()

	err = filepath.Walk(os.Getenv("BACKUP_PATH"), func(pat string, info os.FileInfo, err error) error {
		if path.Ext(info.Name()) == ".gz" {
			files = append(files, info.Name())
		}
		return nil
	})
	if err != nil {
		logrus.Errorf("filepath.Walk err:%v\n", err)
		return
	}

	bytes, err := json.Marshal(files)
	if err != nil {
		logrus.Errorf("json.Marshal err:%v\n", err)
		return
	}

	if _, err = file.Write(bytes); err != nil {
		logrus.Errorf("file.Write err:%v\n", err)
		return
	}
	logrus.Infof("刷新下载列表:%+v", files)
}
