package wxbroadcastv2

import (
	"active/internal/model/goldbrick"
	"active/tools"
	"crypto/aes"
	"crypto/cipher"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"runtime/debug"
	"strings"
	"time"

	"git.jiaxianghudong.com/go/logs"
	"git.jiaxianghudong.com/webs/pkg/rds"
	"git.jiaxianghudong.com/webs/pkg/xgorm"
	"gorm.io/gorm/clause"
)

// 直播数据的一些参数
const (
	LiveWatcherMin           = 1 // 场观人数小于此数，算不合格开播
	LiveOpenBelowStandardMax = 3 //开播多少次不合格，关闭一键直播推荐
)

type WxBroadcastInfo struct {
	TaskMap     map[int64]bool `json:"task_map"`
	StartTime   int64          `json:"start_time"`
	StartNumber int64          `json:"start_number"`
	Time        int64          `json:"time"`
	Number      int64          `json:"number"` //游戏局数
	First       bool           `json:"first"`
	WatchCount  int64          `json:"watch_count"` //观看人数
}

type Wxbroadcast struct {
	Id             int64 `json:"id" gorm:"column:id"`
	Daily3         int64 `json:"daily_3" gorm:"column:daily_3"`
	Daily7         int64 `json:"daily_7" gorm:"column:daily_7"`
	UpdateTime     int64 `json:"update_time" gorm:"column:update_time"`
	FirstBroadcast int64 `json:"first_broadcast" gorm:"column:first_broadcast"`
	LiveLessCount  int64 `json:"live_less_count" gorm:"column:live_less_count"` //场观人数小于等于1的开播次数
}

// 直播数据
type GameLiveDetails struct {
	FeedId                int64  `json:"feedId"`                // 直播id
	Description           string `json:"description"`           // 直播主题
	StartTime             int64  `json:"startTime"`             // 开播时间戳
	EndTime               int64  `json:"endTime"`               // 关播时间戳
	TotalCheerCount       int64  `json:"totalCheerCount"`       // 主播收到的喝彩总数
	TotalAudienceCount    int64  `json:"totalAudienceCount"`    // 直播间总观众人数
	LiveDurationInSeconds int64  `json:"liveDurationInSeconds"` // 直播总时长
	Watermark             struct {
		Timestamp int64  `json:"timestamp"`
		AppID     string `json:"appid"`
	} `json:"watermark"`
}

func (w Wxbroadcast) TableName() string {
	return "wxbroadcast"
}

func (w *Wxbroadcast) Save() error {
	xdb := xgorm.NewConn(goldbrick.GoldBrickGorm)
	return xdb.Clauses(clause.OnConflict{
		Columns:   []clause.Column{{Name: "id"}},
		UpdateAll: true,
	}).Save(w).Error
}

func (w *Wxbroadcast) One() error {
	id := w.Id
	xdb := xgorm.NewConn(goldbrick.GoldBrickGorm)
	err := xdb.Where("id = ?", w.Id).Find(w).Error
	w.Id = id
	return err
}

func (w *WxBroadcastInfo) Get(userId string, tm string) {
	data := rds.Redis.HGet(fmt.Sprintf(WXBROADCASTDAY, tm), userId).Val()
	if data != "" {
		err := json.Unmarshal([]byte(data), w)
		if err != nil {
			logs.Errorf("redpacket[%s] WxBroadcastInfo json err:%v", userId, err)
		}
	}
	if w.TaskMap == nil {
		w.TaskMap = make(map[int64]bool)
	}
}

func (w *WxBroadcastInfo) Set(userId string, tm string) bool {
	data, _ := json.Marshal(w)
	rds.Redis.HSet(fmt.Sprintf(WXBROADCASTDAY, tm), userId, string(data)).Err()
	end, _ := time.Parse("2006-01-02", tm)
	expireAt := end.Add(48 * time.Hour)
	rds.Redis.ExpireAt(fmt.Sprintf(WXBROADCASTDAY, tm), expireAt)
	return true
}

func Init() {
	tools.ReloadYaml("wxbroadcastv2.yaml", &confv2)
	for i := 0; i < len(confv2.AwardList); i++ {
		fmt.Printf("AwardList %+v \n", confv2.AwardList[i])
	}
	for i := 0; i < len(confv2.AwardListV1); i++ {
		fmt.Printf("AwardListV1 %+v \n", confv2.AwardListV1[i])
	}
	tools.ReloadYaml("wxbroadcastv2.yaml", &upListConf)
	fmt.Printf("upddd %v \n", upListConf)
}

// 获取小游戏用户的已结束的直播数据
func EncryptedGameLiveDetails(userid uint32, encryptedData, iv string) *GameLiveDetails {
	sessionKey := rds.Redis2.HGet(fmt.Sprintf("user_%d", userid), "min_session_key").Val()
	if sessionKey == "" {
		logs.Errorf("userid %d min_session_key is not find:", userid)
		return nil
	}
	aesKey, _ := base64.StdEncoding.DecodeString(fmt.Sprintf("%s", sessionKey))
	encryptedStr, _ := base64.StdEncoding.DecodeString(strings.Replace(encryptedData, " ", "+", -1))
	IV, err := base64.StdEncoding.DecodeString(strings.Replace(iv, " ", "+", -1))
	if err != nil {
		logs.Errorf("iv decodeString[%v] err=%v", encryptedStr, iv)
		return nil
	}
	liveDetail, err := WxAESDecode(encryptedStr, aesKey, IV, userid)
	if err != nil {
		logs.Errorf("WxAESDecode|wechat_data decrypt err:userid:%v,encryptedStr=%v,iv=%v,err=%v", userid, encryptedStr, IV, err)
		return nil
	}
	logs.Infof("encryptedData=%v,iv=%v,userid:%v,GameLiveDetails=%+v", encryptedData, iv, userid, liveDetail)
	return liveDetail
}

// WxAESDecode 微信aes解码
func WxAESDecode(encryptedData []byte, sessionKey []byte, iv []byte, userid uint32) (*GameLiveDetails, error) {
	var err error
	var info GameLiveDetails
	defer func() { // 必须要先声明defer，否则不能捕获到panic异常
		if err1 := recover(); err1 != nil {
			logs.Error(fmt.Sprintf("[WxAESDecode] | sessionKey: %s | iv: %s | err: %v | userid: %d", string(sessionKey), string(iv), err1, userid))
			debug.PrintStack()
		}
	}()
	var aesBlockDecrypter cipher.Block
	aesBlockDecrypter, err = aes.NewCipher(sessionKey)
	if err != nil {
		return &info, err
	}
	decrypted := make([]byte, len(encryptedData))
	aesDecrypter := cipher.NewCBCDecrypter(aesBlockDecrypter, iv)
	aesDecrypter.CryptBlocks(decrypted, encryptedData)
	aesPlantText := PKCS7UnPadding(decrypted)
	err = json.Unmarshal(aesPlantText, &info)
	return &info, err
}

func PKCS7UnPadding(plantText []byte) []byte {
	length := len(plantText)
	if length > 0 {
		unPadding := int(plantText[length-1])
		return plantText[:(length - unPadding)]
	}
	return plantText
}
