package log

import (
	"context"
	"encoding/json"
	"fmt"
	"go.uber.org/zap"
	"log-server/global"
	"log-server/model/log"
	"log-server/model/log/request"
	"log-server/model/log/response"
	loging2 "log-server/service/log/loging"
	"strconv"
	"time"
)

type ServiceLogList struct {
	ServiceLogCoding
	logical loging2.LogicalLog
}

func (s *ServiceLogList) GetCodeLogList(ctx context.Context, api log.Loging, info request.PageInfo, order string, desc bool, code int) (list interface{}, total int64, err error) {
	limit := info.PageSize
	offset := info.PageSize * (info.Page - 1)
	db := global.GVA_DB.Model(&log.Loging{})

	var apiList []log.Loging
	var createDate string
	if api.CreateDate == "" {
		createDate = time.Now().Format("2006-01-02")
	} else {
		createDate = api.CreateDate
	}
	db = db.Where("create_date = ?", createDate)
	if api.Coding != 0 {
		db = db.Where("coding = ?", api.Coding)
	}
	if api.GameId != 0 {
		db = db.Where("game_id = ?", api.GameId)
	} else {
		return
	}
	if api.PcCode != "" {
		db = db.Where("pc_code = ?", api.PcCode)
	}
	if api.Account != "" {
		db = db.Where("account = ?", api.Account)
	}
	if api.LogUuid != "" {
		db = db.Where("log_uuid = ?", api.LogUuid)
	}

	if code != 0 {
		db = db.Where("type_coding = ?", code)
	}
	if api.Status != 0 {
		if api.Status == 2 {
			db = db.Where("status = ?", 0)
		} else {
			db = db.Where("status = ?", 1)
		}
	}
	err = db.Count(&total).Error
	if err != nil {
		return apiList, total, err
	} else {
		db = db.Limit(limit).Offset(offset)
		if order != "" {
			var OrderStr string
			// 设置有效排序key 防止sql注入
			// 感谢 Tom4t0 提交漏洞信息
			orderMap := make(map[string]bool, 4)
			orderMap["id"] = true
			orderMap["log_uuid"] = true
			orderMap["account"] = true
			orderMap["game_id"] = true
			if orderMap[order] {
				if desc {
					OrderStr = order + " desc"
				} else {
					OrderStr = order
				}
			} else { // didn't matched any order key in `orderMap`
				global.GVA_LOG.Error("获取失败!", zap.Error(err))
				return apiList, total, err
			}

			err = db.Order(OrderStr).Find(&apiList).Error
		} else {
			err = db.Order("id").Find(&apiList).Error
		}
	}
	fmt.Println(time.Now().Unix())
	var apisReply []*response.GetLogReply
	if total != 0 {
		for _, apiInfo := range apiList {
			apiReply := new(response.GetLogReply)
			apiReply.Id = apiInfo.Id
			apiReply.Coding = strconv.Itoa(apiInfo.Coding)
			apiReply.GameId = apiInfo.GameId
			apiReply.Status = apiInfo.Status
			apiReply.Account = apiInfo.Account
			apiReply.DeviceId = apiInfo.DeviceId
			apiReply.ComputerType = apiInfo.ComputerType
			apiReply.EnvCode = apiInfo.EnvCode
			apiReply.LogUuid = apiInfo.LogUuid
			apiReply.Operator = apiInfo.Operator
			apiReply.PcCode = apiInfo.PcCode
			apiReply.PcIp = apiInfo.PcIp
			apiReply.SimulatorIp = apiInfo.SimulatorIp
			apiReply.SimulatorMac = apiInfo.SimulatorMac
			apiReply.PcMac = apiInfo.PcMac
			apiReply.AccountType = apiInfo.AccountType
			apiReply.CreateDate = apiInfo.CreateDate[:10]
			apiReply.CreateTime = apiInfo.CreateTime
			apiReply.Remarks = apiInfo.Remarks
			apiReply.TaskType = apiInfo.TaskType
			describe, _ := s.CodeListCache(ctx, apiReply.Coding)
			apiReply.Describe = describe
			apiReply.ScriptType = apiInfo.ScriptType
			apisReply = append(apisReply, apiReply)
		}

	}
	fmt.Println(time.Now().Unix())
	return apisReply, total, err
}

/*var loging1 = map[string]ServiceLoging{
	"410":new(loging2.PullAccountLog),
	"430":new(loging2.SimulatorStartLog),
	//"450":new(loging2.ScriptStartLog),
	"450":new(loging2.GameStartLog),
	"460":new(loging2.LoginLog),
	//"470":new(loging2.EnterGameLog),
	"470":new(loging2.EnterMainLog),
	"480":new(loging2.FeeLog),
	"490":new(loging2.TaskEndLog),
	"other":new(loging2.OtherLog),
}*/

var failCacheKey = "%s:fail:list"

func (s *ServiceLogList) CreateLog(c context.Context, request request.AddLogRequest, logical ServiceLoging, status, noLogStatus string) {
	var err error
	if status == "99" {
		err = logical.SuccessLog(c, request)
	} else if noLogStatus == "99" {
		err = logical.NoLogStatusData(c, request)
	} else {
		err = logical.FailLog(c, request)
	}
	if err != nil {
		body, _ := json.Marshal(request)
		current := time.Now().Format("2006-01-02")
		key := fmt.Sprintf(failCacheKey, current)
		global.GVA_REDIS.LPush(c, key, body)
		global.GVA_LOG.Error("创建失败!: "+string(body), zap.Error(err))
		return
	}
	global.GVA_LOG.Info("创建成功!: " + request.LogUuid + " code: " + strconv.Itoa(request.Coding))
}

func (s *ServiceLogList) CreateFailLog() {
	c := context.Background()
	current := time.Now().Format("2006-01-02")
	key := fmt.Sprintf(failCacheKey, current)
	n, err := global.GVA_REDIS.LLen(c, key).Result()
	if err != nil {
		global.GVA_LOG.Error("corn 获取队列长度失败!"+key, zap.Error(err))
		return
	}
	if n == 0 {
		global.GVA_LOG.Info("corn 获取队列长度为0!")
		return
	}

	if n > 300 {
		n = 300
	}
	for i := 0; i < int(n); i++ {
		str, err := global.GVA_REDIS.RPop(c, key).Result()
		if err != nil {
			global.GVA_LOG.Error("rpop获取数据失败!", zap.Error(err))
			return
		}
		var data request.AddLogRequest
		err = json.Unmarshal([]byte(str), &data)
		if err != nil {
			global.GVA_LOG.Error("rpop获取数据失败!", zap.Error(err))
			continue
		}
		l, err := s.logical.GetLogByUuidCoding(data.LogUuid, data.Coding, data.ScriptType)
		if err != nil {
			global.GVA_LOG.Error("GetLogByUuidCoding获取数据失败!", zap.Error(err))
			continue
		}
		if l.GameId != 0 {
			global.GVA_LOG.Info("数据已存在!: " + data.LogUuid + " code: " + strconv.Itoa(data.Coding))
			continue
		}
		coding := strconv.Itoa(data.Coding)
		nodeCoding := coding[:3]
		status := coding[5:]
		noLogStatus := coding[3:5]
		var logical ServiceLoging
		switch nodeCoding {
		case "410":
			logical = new(loging2.PullAccountLog)
			break
		case "430":
			logical = new(loging2.SimulatorStartLog)
			break
		case "450":
			logical = new(loging2.GameStartLog)
			break
		case "460":
			logical = new(loging2.LoginLog)
			break
		case "470":
			logical = new(loging2.EnterMainLog)
			break
		case "480":
			logical = new(loging2.FeeLog)
			break
		default:
			logical = new(loging2.OtherLog)
			break
		}
		s.CreateLog(c, data, logical, status, noLogStatus)
		global.GVA_LOG.Info("重试!: " + data.LogUuid + " code: " + strconv.Itoa(data.Coding))
	}

}
