package v1

import (
	"context"
	"designs/app/common/request"
	"designs/app/common/response"
	"designs/config"
	"designs/global"
	"designs/model"
	"designs/utils"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/go-playground/validator/v10"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

func InitGidConfig(c *gin.Context) {
	gidKey := config.Get("app.gid") + "*"
	keys, _ := global.App.Redis.Keys(context.Background(), gidKey).Result()
	var gameData = []interface{}{}
	for _, val := range keys {
		res, _ := global.App.Redis.HGetAll(context.Background(), val).Result()
		gameData = append(gameData, res)
	}

	now := model.XTime{
		Time: time.Now(),
	}
	for _, v := range gameData {
		var game model.Game
		data, _ := json.Marshal(v)
		json.Unmarshal(data, &game)

		game.CreatedAt = now
		game.UpdatedAt = now

		err := global.App.DB.Table("game").Create(&game).Error
		if err != nil {
			response.Fail(c, 111, "数据插入错误"+err.Error())
			return
		}
	}

	response.Success(c, gin.H{
		"res": "gid写入数据库完成",
	})

}

/* 添加游戏配置 */
//http://127.0.0.1:8787/v1/user/AddGidConfig
func AddGidConfig(c *gin.Context) {
	var data GameConfig
	form := request.Check(c, &data)

	// 在这种情况下，将自动选择合适的绑定
	if data.AppSecret != config.Get("app.app_secret") {
		response.Fail(c, 1003, "密钥参数错误")
		return
	}

	now := time.Now()

	//更新数据库
	var game model.Game
	global.App.DB.Table("game").Where("gid", form.Gid).First(&game)

	if game.Gid == "" {
		//新增
		gameNew := model.Game{
			Gid:        form.Gid,
			Pid:        form.Pid,
			GameName:   form.GameName,
			WxAppid:    form.WxAppid,
			WxSecret:   form.WxSecret,
			TtAppid:    form.TtAppid,
			TtSecret:   form.TtSecret,
			TtTplId:    form.TtTplId,
			WxTplId:    form.WxTplId,
			CreatedAt:  model.XTime{Time: now},
			UpdatedAt:  model.XTime{Time: now},
			ConfigPath: form.ConfigPath,
		}

		err := global.App.DB.Table("game").Create(&gameNew).Error
		if err != nil {
			response.Fail(c, 1001, err.Error())
			return
		}
	} else {
		//更新
		err := global.App.DB.Table("game").Where("gid", form.Gid).Updates(&model.Game{
			Gid:        form.Gid,
			Pid:        form.Pid,
			GameName:   form.GameName,
			WxAppid:    form.WxAppid,
			WxSecret:   form.WxSecret,
			TtAppid:    form.TtAppid,
			TtSecret:   form.TtSecret,
			TtTplId:    form.TtTplId,
			WxTplId:    form.WxTplId,
			ConfigPath: form.ConfigPath,
			CreatedAt:  model.XTime{Time: now},
			UpdatedAt:  model.XTime{Time: now},
		}).Error
		if err != nil {
			response.Fail(c, 1001, err.Error())
			return
		}
	}

	//更新redis
	gameConfigData := make(map[string]interface{})
	gameConfigData["gid"] = form.Gid
	gameConfigData["gameName"] = form.GameName
	gameConfigData["wxAppid"] = form.WxAppid
	gameConfigData["wxSecret"] = form.WxSecret
	gameConfigData["ttAppid"] = form.TtAppid
	gameConfigData["ttSecret"] = form.TtSecret
	gameConfigData["ttTplId"] = form.TtTplId
	gameConfigData["wxTplId"] = form.WxTplId
	gameConfigData["configPath"] = form.ConfigPath
	gidKey := config.Get("app.gid") + form.Gid
	err := global.App.Redis.HMSet(context.Background(), gidKey, gameConfigData).Err()
	if err != nil {
		response.Fail(c, 1003, "配置错误")
		return
	}

	response.Success(c, gin.H{
		"data": gameConfigData,
	})
}

/* 获取配置 */
func GetGidConfig(c *gin.Context) {
	form := request.Check(c, &struct {
		Offset int    `form:"offset" binding:"" json:"offset"`
		Limit  int    `form:"limit" binding:"" json:"limit"`
		Search string `form:"search" binding:"" json:"search"`
	}{})

	var gameList []model.Game
	var count int64
	query := global.App.DB.Table("game")

	if form.Search != "" {
		query = query.Where("gid", "like", "%"+form.Search+"%").
			Or("pid LIKE ?", "%"+form.Search+"%").
			Or("gameName LIKE ?", "%"+form.Search+"%")
	}

	err := query.Count(&count).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}

	if form.Limit != 0 {
		query = query.Limit(form.Limit)
	}
	err = query.Offset(form.Offset).Scan(&gameList).Error
	if err != nil {
		response.Fail(c, 1002, err.Error())
		return
	}

	//gidKey := config.Get("app.gid") + "*"
	//keys, _ := global.App.Redis.Keys(context.Background(), gidKey).Result()
	//var gameData = []interface{}{}
	//for _, val := range keys {
	//	res, _ := global.App.Redis.HGetAll(context.Background(), val).Result()
	//	gameData = append(gameData, res)
	//}

	response.Success(c, gin.H{
		"data":  gameList,
		"count": count,
	})
}

func GidList(c *gin.Context) {
	form := request.Check(c, &struct {
		Search string `form:"search" binding:"" json:"search"`
		Active bool   `form:"active" binding:"" json:"active"`
	}{})

	var gameList []struct {
		Id       int    `json:"id" gorm:"primary_key"`
		Pid      string `json:"pid" gorm:"column:pid; "`
		Gid      string `json:"gid" gorm:"column:gid; "`
		GameName string `json:"gameName" gorm:"column:gameName; "`
	}
	query := global.App.DB.Table("game")

	if form.Search != "" {
		query = query.Where("gid", "like", "%"+form.Search+"%").
			Or("pid LIKE ?", "%"+form.Search+"%").
			Or("gameName LIKE ?", "%"+form.Search+"%")
	}

	if form.Active == true {
		//获取近七天有数据的gid
		ActiveGid := GetActiveGid()
		query = query.WhereIn("gid", ActiveGid)
	}

	err := query.Select("id", "gid", "gameName").Where("id", ">", 0).Scan(&gameList).Error
	if err != nil {
		response.Fail(c, 1002, err.Error())
		return
	}

	response.Success(c, gin.H{
		"data":  gameList,
		"count": len(gameList),
	})

}

func GetActiveGid() []string {
	var activeGidList []string

	key := "activeGidList"
	activeGid, _ := global.App.Redis.Get(context.Background(), key).Result()

	activeGidList = strings.Split(activeGid, ",")

	if len(activeGidList) <= 2 {
		var gidList []string

		//重新读取数据
		var dir string
		if config.Get("app.local") == "local" {
			//url = "mongodb://localhost:27017"
			dir = "storage"
		} else {
			dir = "/www/wwwroot/chunhao_receive/storage"
		}

		now := time.Now()

		for i := 0; i <= 7; i++ {
			date := now.AddDate(0, 0, -i).Format("2006-01-02")
			//读取对应的文件夹
			dirPath := filepath.Join(dir, date)
			dateDir, _ := os.ReadDir(dirPath)
			//fmt.Println(dirPath, dateDir)

			for _, v := range dateDir {

				fileName := v.Name()

				fileNameSplit := strings.Split(fileName, "_")

				if len(fileNameSplit) < 2 {
					continue
				}
				last := fileNameSplit[len(fileNameSplit)-1]
				gid := strings.TrimRight(fileName, "_"+last)

				if !utils.InArray(gid, gidList) {
					gidList = append(gidList, gid)
				}
			}
		}

		if len(gidList) > 0 {

			var gidString string
			for _, gid := range gidList {
				gidString = gid + ","
			}
			global.App.Redis.Set(context.Background(), key, gidString, time.Second*3600)
			activeGidList = gidList
		}

	}

	return activeGidList
}

type ActionOption struct {
	OptionName   string `json:"optionName" form:"optionName" binding:"required"`
	OptionId     string `json:"optionId" form:"optionId" binding:"required"`
	OptionType   string `json:"optionType" form:"optionType" binding:"required"`
	OptionStatus int    `json:"optionStatus" form:"optionStatus" binding:""`
}

// 设置游戏的打点
func SetGameAction(c *gin.Context) {
	form := request.Check(c, &struct {
		Gid        string         `form:"gid" json:"gid" binding:"required"`
		ActionId   string         `form:"actionId" json:"actionId" binding:"required"`
		ActionName string         `form:"actionName" json:"actionName" binding:"required"`
		Remark     string         `form:"remark" json:"remark" binding:""`
		Status     int            `form:"status" json:"status" binding:""`
		Options    []ActionOption `form:"options" json:"options" binding:""`
	}{})

	//验证一下option 内的参数
	validate := validator.New()
	for _, v := range form.Options {
		err := validate.Struct(&v)
		if err != nil {
			response.Fail(c, 1003, err.Error())
			return
		}
	}

	//存入数据库
	now := time.Now()
	err := global.App.DB.Transaction(func(tx *utils.WtDB) error {
		gameAction := model.GameAction{
			Gid:        form.Gid,
			ActionId:   form.ActionId,
			ActionName: form.ActionName,
			Remark:     form.Remark,
			Status:     form.Status,
			CreatedAt:  model.XTime{Time: now},
			UpdatedAt:  model.XTime{Time: now},
		}
		err := tx.Table("game_action").Save(&gameAction).Error
		if err != nil {
			return err
		}

		for _, option := range form.Options {
			gameActionOption := model.GameActionOption{
				OptionName: option.OptionName,
				OptionId:   option.OptionId,
				ActionId:   gameAction.ID,
				OptionType: option.OptionType,
				Status:     option.OptionStatus,
				CreatedAt:  model.XTime{Time: now},
				UpdatedAt:  model.XTime{Time: now},
			}
			err = tx.Table("game_action_option").Save(&gameActionOption).Error
			if err != nil {
				return err
			}
		}

		return nil
	})
	if err != nil {
		response.Fail(c, 1002, err.Error())
		return
	}

	response.Success(c, gin.H{})
}

// 更新游戏中的事件
func UpdateGameAction(c *gin.Context) {
	form := request.Check(c, &struct {
		Gid        string `form:"gid" json:"gid" binding:"required"`
		ActionId   string `form:"actionId" json:"actionId" binding:"required"`
		ActionName string `form:"actionName" json:"actionName" binding:"required"`
		Remark     string `form:"remark" json:"remark" binding:""`
		Status     int    `form:"status" json:"status" binding:""`
	}{})

	err := global.App.DB.Table("game_action").
		Where("gid", form.Gid).
		Where("actionId", form.ActionId).
		Updates(map[string]interface{}{
			"status":     form.Status,
			"remark":     form.Remark,
			"updatedAt":  time.Now(),
			"actionName": form.ActionName,
		}).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}

	response.Success(c, gin.H{})
}

// 更新事件中的选项
func UpdateGameActionOption(c *gin.Context) {
	form := request.Check(c, &struct {
		Id         int    `form:"id" json:"id" binding:"required"`
		OptionName string `json:"optionName" form:"optionName" binding:"required"`
		OptionId   string `json:"optionId" form:"optionId" binding:"required"`
		OptionType string `json:"optionType" form:"optionType" binding:"required"`
		Status     int    `form:"status" json:"status" binding:""`
	}{})

	err := global.App.DB.Table("game_action_option").Where("id", form.Id).Updates(map[string]interface{}{
		"optionName": form.OptionName,
		"optionId":   form.OptionId,
		"optionType": form.OptionType,
		"status":     form.Status,
		"updatedAt":  time.Now(),
	}).Error
	if err != nil {
		response.Fail(c, 1003, err.Error())
		return
	}

	response.Success(c, gin.H{})
}

// 新增事件中的选项
func AddGameActionOption(c *gin.Context) {
	form := request.Check(c, &struct {
		ActionId   int    `form:"actionId" json:"actionId" binding:"required"`
		OptionName string `json:"optionName" form:"optionName" binding:"required"`
		OptionId   string `json:"optionId" form:"optionId" binding:"required"`
		OptionType string `json:"optionType" form:"optionType" binding:"required"`
		Status     int    `json:"status" form:"status" binding:""`
	}{})

	now := time.Now()
	gameActionOption := model.GameActionOption{
		OptionName: form.OptionName,
		OptionId:   form.OptionId,
		ActionId:   form.ActionId,
		OptionType: form.OptionType,
		Status:     form.Status,
		CreatedAt:  model.XTime{Time: now},
		UpdatedAt:  model.XTime{Time: now},
	}
	err := global.App.DB.Table("game_action_option").Save(&gameActionOption).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}

	response.Success(c, gin.H{})
}

// 删除事件中的选项
func DeleteGameActionOption(c *gin.Context) {
	form := request.Check(c, &struct {
		Id int `form:"id" json:"id" binding:"required"`
	}{})

	var d interface{}
	err := global.App.DB.Table("game_action_option").Where("id", form.Id).Delete(d).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}

	response.Success(c, gin.H{})
}

// 列表 事件列表
func GameActionList(c *gin.Context) {
	form := request.Check(c, &struct {
		Offset int    `form:"offset" json:"offset" binding:""`
		Limit  int    `form:"limit" json:"limit" binding:"required"`
		Search string `form:"search" json:"search" binding:""`
		Status string `form:"status" json:"status" binding:""`
		Order  string `form:"order" json:"order" binding:""`
		Gid    string `form:"gid" json:"gid" binding:"required"`
	}{})

	query := global.App.DB.Table("game_action").Where("gid", form.Gid)
	if form.Search != "" {
		query = query.WhereRaw(global.App.DB.Where("actionId", "like", "%"+form.Search+"%").Or("actionName like ?", "%"+form.Search+"%").SubQuery())
	}
	if form.Status != "" {
		status, _ := strconv.Atoi(form.Status)
		query = query.Where("status", status)
	}
	if form.Order != "" {
		query = query.Order("id " + form.Order)
	}

	var count int64
	err := query.Count(&count).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}

	var actionList []model.GameAction
	err = query.Offset(form.Offset).Limit(form.Limit).Scan(&actionList).Error
	if err != nil {
		response.Fail(c, 1002, err.Error())
		return
	}
	response.Success(c, gin.H{
		"data":  actionList,
		"count": count,
	})
}

// 事件详情
func GameActionDetail(c *gin.Context) {
	form := request.Check(c, &struct {
		Id int `form:"id" json:"id" binding:"required"`
	}{})

	var action model.GameAction
	err := global.App.DB.Table("game_action").Where("id", form.Id).First(&action).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}
	//var optionList []model.GameActionOption
	//err = global.App.DB.Table("game_action_option").Where("actionId", action.ActionId).Scan(&optionList).Error

	response.Success(c, gin.H{
		"data": action,
	})
}

// 事件 选项 列表
func GameActionOptionList(c *gin.Context) {
	form := request.Check(c, &struct {
		Offset   int    `form:"offset" json:"offset" binding:""`
		Limit    int    `form:"limit" json:"limit" binding:"required"`
		Search   string `form:"search" json:"search" binding:""`
		Status   string `form:"status" json:"status" binding:""`
		Order    string `form:"order" json:"order" binding:""`
		ActionId int    `form:"actionId" json:"actionId" binding:"required"`
	}{})
	query := global.App.DB.Table("game_action_option").Where("actionId", form.ActionId)
	if form.Search != "" {
		query = query.WhereRaw(global.App.DB.Where("optionId", "like", "%"+form.Search+"%").Where("optionName", "like", "%"+form.Search+"%").SubQuery())
	}
	if form.Status != "" {
		status, _ := strconv.Atoi(form.Status)
		query = query.Where("status", status)
	}
	if form.Order != "" {
		query = query.Order("id " + form.Order)
	}
	var count int64
	err := query.Count(&count).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}
	var optionList []model.GameActionOption
	err = query.Offset(form.Offset).Limit(form.Limit).Scan(&optionList).Error
	if err != nil {
		response.Fail(c, 1002, err.Error())
		return
	}

	response.Success(c, gin.H{
		"data":  optionList,
		"count": count,
	})
}
