package model

import (
	"encoding/json"
	"sync"

	"git.jiaxianghudong.com/go/logs"
	"git.jiaxianghudong.com/go/utils"
	"git.jiaxianghudong.com/webs/pkg/dbx"
)

type AwardInfo struct {
	Awards      map[int32]int64         // 普通奖励
	AwardsByNum map[int]map[int32]int64 //按次数发不同奖励
	LimitNum    int
	AwardsType  int
	Remark      string
	DayLimit    int
	LimitType   int
}

var funcMap map[string]*AwardInfo
var rwlock sync.RWMutex //读写锁

var ShareAwardConf = &ShareAwardConfig{}

type ShareAwardConfig struct {
	FhBasicBeans     int64     `json:"fh_basic_beans" yaml:"fh_basic_beans"`
	FhBeansMax       int64     `json:"fh_beans_max" yaml:"fh_beans_max"`
	BxpNewguideAward [][]int64 `json:"bxp_newguide_award" yaml:"bxp_newguide_award"`
}

type FuncAward struct {
	ID         int    `sql:"id" json:"id"`
	Func       string `sql:"func" json:"func"`
	MchID      string `sql:"mch_id" json:"mch_id"`
	Awards     string `sql:"awards" json:"awards"`
	LimitNum   int    `sql:"limit_num" json:"limit_num"`
	AwardsType int    `sql:"awards_type" json:"awards_type"`
	LimitType  int    `sql:"limit_type" json:"limit_type"`
	Remark     string `sql:"remark" json:"remark"`
	DayLimit   int    `sql:"day_limit" json:"day_limit"`
}

func GetAllFuncAwards() []FuncAward {
	sql := `select func,mch_id,awards,limit_num,awards_type,remark,limit_type from func_award `
	var funcAwards []FuncAward
	rows, err := dbx.MySQL.Query(sql)
	defer rows.Close()
	if err != nil {
		return nil
	}
	for rows.Next() {
		tmp := FuncAward{}
		if err = rows.Scan(&tmp.Func, &tmp.MchID, &tmp.Awards, &tmp.LimitNum, &tmp.AwardsType, &tmp.Remark, &tmp.LimitType); err != nil {
			return nil
		}
		funcAwards = append(funcAwards, tmp)
	}
	return funcAwards
}

func InsertFuncAwards(funcAward *FuncAward) (int64, error) {
	sql := "INSERT INTO func_award (`func`, `mch_id`, `awards`, `limit_num`, `awards_type`, `remark`) VALUES (?, ?, ?, ?, ?, ?)"
	res, err := dbx.MySQL.Exec(sql,
		funcAward.Func,
		funcAward.MchID,
		funcAward.Awards,
		funcAward.LimitNum,
		funcAward.AwardsType,
		funcAward.Remark)
	if err != nil {
		return 0, err
	}
	lastId, _ := res.LastInsertId()
	return lastId, nil
}

func UpdateFuncAwards(funcAward *FuncAward) error {
	sql := "UPDATE func_award set func = ?,mch_id=?,awards=?,limit_num=?,awards_type=?,remark=?,utime=now() where func=? and mch_id=? "
	res, err := dbx.MySQL.Exec(sql,
		funcAward.Func,
		funcAward.MchID,
		funcAward.Awards,
		funcAward.LimitNum,
		funcAward.AwardsType,
		funcAward.Remark,
		funcAward.Func,
		funcAward.MchID)
	if err != nil {
		return err
	}
	affect, _ := res.RowsAffected()
	if affect == 0 {
		InsertFuncAwards(funcAward)
		return nil
	}
	return nil
}

func DeleteFuncAwards(funcName, mchID string) error {
	sql := "delete from func_award where func=? and mch_id=?"
	_, err := dbx.MySQL.Exec(sql, funcName, mchID)
	if err != nil {
		return err
	}
	return nil
}

func InitAwards() {

	logs.Info("开始加载配置...")
	rwlock.Lock()
	defer rwlock.Unlock()
	funcMap = make(map[string]*AwardInfo)
	awards := GetAllFuncAwards()
	for _, v := range awards {
		if v.AwardsType == 1 {
			jsonAwards := make(map[string]map[string]int64)
			awardsMap := make(map[int]map[int32]int64)
			_ = json.Unmarshal([]byte(v.Awards), &jsonAwards)
			for ka, va := range jsonAwards {
				tmp := make(map[int32]int64)
				for kb, vb := range va {
					tmp[int32(utils.Atoi(kb))] = vb
				}
				awardsMap[utils.Atoi(ka)] = tmp
			}
			funcMap[v.Func+"_"+v.MchID] = &AwardInfo{LimitNum: v.LimitNum,
				AwardsType:  v.AwardsType,
				Remark:      v.Remark,
				DayLimit:    v.DayLimit,
				LimitType:   v.LimitType,
				AwardsByNum: awardsMap}
		} else {
			jsonAwards := make(map[string]int64)
			awardsMap := make(map[int32]int64)
			err := json.Unmarshal([]byte(v.Awards), &jsonAwards)
			if err != nil {
				logs.Error(err, " param:", v.Awards)
			}
			for ka, va := range jsonAwards {
				awardsMap[int32(utils.Atoi(ka))] = va
			}
			funcMap[v.Func+"_"+v.MchID] = &AwardInfo{LimitNum: v.LimitNum,
				AwardsType: v.AwardsType,
				Remark:     v.Remark,
				DayLimit:   v.DayLimit,
				LimitType:  v.LimitType,
				Awards:     awardsMap}
		}
	}
	for k, v := range funcMap {
		logs.Infof("funcMap Init:%s, value:%+v", k, v)
	}
	logs.Info("funcMap init complete")
}

func GetFuncMap(key string) *AwardInfo {
	rwlock.RLock()
	defer rwlock.RUnlock()
	return funcMap[key]
}
