package redis_data

import (
	"encoding/json"
	"fmt"
	"github.com/gomodule/redigo/redis"
	log "github.com/sirupsen/logrus"
	"miads/adslib"
	"miads/adslib/ads_redis"
	"strconv"
	"strings"
	"time"
)

type ChannelFlag struct {
	Weigth      int `json:"weigth"`
	ChannelFlag int `json:"channel_flag"`
}

type FreqControlConfItem struct {
	BeginHour int `json:"begin_hour"`
	EndHour   int `json:"end_hour"`
	FreqTime  int `json:"freq_time"`
}

type FreqControlConf struct {
	confs []FreqControlConfItem
}

func (self *FreqControlConf) GetControlTime(hour int) (int, bool) {
	if self.confs == nil {
		return 0, false
	}
	for _, v := range self.confs {
		if v.BeginHour <= hour && hour <= v.EndHour {
			return v.FreqTime, true
		}
	}
	return 0, false
}

// 获取渠道的标记
func GetChannelFlag(reqSource string, business string) (ChannelFlag, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	redisKey := fmt.Sprintf("acfv2_%s_%s", reqSource, business)
	rsp, err := conn.Do("GET", redisKey)
	if err != nil {
		return ChannelFlag{}, err
	}

	if rsp == nil {
		return ChannelFlag{}, nil
	}

	rspBytes, _ := redis.Bytes(rsp, err)
	rspStr := strings.ReplaceAll(string(rspBytes), "'", "\"")
	rspStr = strings.ReplaceAll(rspStr, "L", "")
	log.Info(rspStr)

	channelFlag := ChannelFlag{}
	err = json.Unmarshal([]byte(rspStr), &channelFlag)
	if err != nil {
		return ChannelFlag{}, err
	}

	return channelFlag, nil
}

// 获取渠道频率信息
func GetFreqControlConf(reqSource string) (FreqControlConf, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	redisKey := "rsfreq_" + reqSource

	rsp, err := conn.Do("GET", redisKey)
	if err != nil {
		return FreqControlConf{}, err
	}

	if rsp == nil {
		return FreqControlConf{}, nil
	}

	rspBytes, _ := redis.Bytes(rsp, err)

	f := FreqControlConf{}
	err = json.Unmarshal(rspBytes, &f.confs)
	if err != nil {
		return FreqControlConf{}, err
	}

	return f, nil
}

// 获取该广告的总请求次数
func GetAdsRequestNum(advertiser string, adsBannerId int) (int, error) {
	if advertiser == "" {
		return 0, nil
	}

	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	redisKey := fmt.Sprintf("adsv2_%s_%d", advertiser, adsBannerId)
	rsp, err := conn.Do("GET", redisKey)
	if err != nil {
		return 0, err
	}

	if rsp == nil {
		return 0, nil
	}

	number, err := redis.Int(rsp, err)
	return number, nil
}

// 获取回调广告的动作请求次数
func GetAdsFeedbackNum(advertiser string, action string, bannerid int) (int, error) {
	if advertiser == "" {
		return 0, nil
	}

	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	redisKey := fmt.Sprintf("adsv3_%s_%s_%d", advertiser, action, bannerid)
	if time.Now().Unix()%100 == 0 {
		_, _ = conn.Do("DELETE", redisKey)
	}

	rsp, err := conn.Do("GET", redisKey)
	if err != nil {
		return 0, err
	}

	if rsp == nil {
		return 0, nil
	}

	number, _ := redis.Int(rsp, err)
	return number, nil
}

// 获取流量百分比
func GetFlowPercentDuration(advertiser string, action string) *adslib.FlogControlItem {
	config := adslib.GetConf()
	flowConf, ok := config.FlowPercent[advertiser]
	if !ok {
		return nil
	}

	actionConf, ok := flowConf[action]
	if !ok {
		return nil
	}
	return &actionConf
}

// 设置回调回来的广告动作的次数
func SetDistributeActionNum(advertiser string, action string, bannerid int) {
	if advertiser == "" {
		return
	}

	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	redisKey := fmt.Sprintf("adsv3_%s_%s_%d", advertiser, action, bannerid)
	curTime := int(time.Now().Unix())
	if curTime%100 == 0 {
		_, _ = conn.Do("delete", redisKey)
	}
	_, _ = conn.Do("INCR", redisKey)
}

// 获取设备+ip上报是否可以
func GetDeviceIpReport(deviceId string, ip string) (bool, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	redisKey := fmt.Sprintf("dim2_%s_'%s'", deviceId, ip)
	rsp, err := conn.Do("GET", redisKey)
	if err != nil {
		return false, err
	}
	lastReportTime := int64(0)
	if rsp != nil {
		lastReportTime, _ = redis.Int64(rsp, err)
	}

	if time.Now().Unix()-lastReportTime >= 3*86400 {
		return true, nil
	}
	return false, nil
}

// 设置设备+ip上报的时间点
func SetDeviceIpReport(deviceid string, ip string) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	redisKey := fmt.Sprintf("dim2_%s_'%s'", deviceid, ip)
	_, _ = conn.Do("SET", redisKey, time.Now().Unix(), 3*86400)
}

// 设置总请求到广告的次数
func SetAdsRequestNum(advertiser string, bannerId int) {
	if advertiser == "" {
		return
	}

	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	redisKey := fmt.Sprintf("adsv2_%s_%d", advertiser, bannerId)
	if time.Now().Unix()%100 == 0 {
		_, _ = conn.Do("delete", redisKey)
	}
	_, _ = conn.Do("incr", redisKey)
}

func SetAdsRealRequestNum(advertiser string) {
	if advertiser == "" {
		return
	}

	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	redisKey := fmt.Sprintf("adsv2_request_%s", advertiser)
	_, _ = conn.Do("incr", redisKey)
}

// 设置skip redis
func SetSkipInfo(md5Skip string, skipUrl string) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	redisKey := "su_" + md5Skip
	_, _ = conn.Do("set", redisKey, skipUrl, 300)
}

// 通过advertiser获取最小的script_order
func GetMinScriptOrderByAdv(advertiser string) (int64, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	redisKey := "adv_script_" + advertiser
	rsp, err := conn.Do("GET", redisKey)
	if err != nil {
		return 0, err
	}

	if rsp == nil {
		return 0, err
	}
	scriptOrder, _ := redis.Int64(rsp, err)
	return scriptOrder, nil
}

// 设置来源的曝光次数
func SetReqSourceView(adv string, reqSource string, source string) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	dateInt, _ := strconv.Atoi(time.Now().Format("20060102"))
	key := fmt.Sprintf("view3_%s_%s_%d_%s", adv, reqSource, dateInt, source)
	_, _ = conn.Do("incr", key)
}

// 获取剩余总投放量
func GetRemainDispatchCount(key string) (int, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	rsp, err := conn.Do("GET", key)
	if err != nil {
		return 0, err
	}

	if rsp == nil {
		return 0, nil
	}

	count, _ := redis.Int(rsp, err)
	return count, nil
}

// 获取已经投放的量
// dispatchType: "click", "show"
func GetFinishedDispatchCount(orderId int64, dispatchType string, curTime time.Time) (int, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	key := fmt.Sprintf("order_kpi_%d_%d%d%d_%s_kpi", orderId, curTime.Year(), curTime.Month(), curTime.Day(), dispatchType)
	rsp, err := conn.Do("GET", key)
	if err != nil {
		return 0, err
	}

	if rsp == nil {
		return 0, nil
	}

	count, _ := redis.Int(rsp, err)
	return count, nil
}

// 增加已经投放的量
// dispatchType: "click", "show"
func IncrFinishedDispatchCount(orderId int64, dispatchType string, curTime time.Time) (int, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	key := fmt.Sprintf("order_kpi_%d_%d%d%d_%s_kpi", orderId, curTime.Year(), curTime.Month(), curTime.Day(), dispatchType)
	rsp, err := conn.Do("INCR", key)
	if err != nil {
		return 0, err
	}

	count, _ := redis.Int(rsp, err)
	return count, nil
}

// 获取当前分钟已经投放的量
// dispatchType: "click", "show"
func GetPreMinuteFinishedDispatchCount(orderId int64, dispatchType string, curTime time.Time) (int, string, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	curMinutes := curTime.Hour()*60 + curTime.Minute()
	key := fmt.Sprintf("order_kpi_%d_%d%d%d_%d_%s_kpi", orderId, curTime.Year(), curTime.Month(), curTime.Day(), curMinutes, dispatchType)
	rsp, err := conn.Do("GET", key)
	if err != nil {
		return 0, key, err
	}

	if rsp == nil {
		return 0, key, nil
	}

	count, _ := redis.Int(rsp, err)
	return count, key, nil
}

// 增加当前分钟已经投放的量
// dispatchType: "click", "show"
func IncrPreMinuteFinishedDispatchCount(orderId int64, dispatchType string, curTime time.Time) (int, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	curMinutes := curTime.Hour()*60 + curTime.Minute()
	key := fmt.Sprintf("order_kpi_%d_%d%d%d_%d_%s_kpi", orderId, curTime.Year(), curTime.Month(), curTime.Day(), curMinutes, dispatchType)
	rsp, err := conn.Do("INCR", key)
	if err != nil {
		return 0, err
	}
	count, _ := redis.Int(rsp, err)
	return count, nil
}

// 设置总计划投放数量
// dispatchType: "click", "show"
func SetPlanDispatchCount(orderId int64, dispatchType string, cnt int, curTime time.Time) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	key := fmt.Sprintf("plan_all_kpi_%d_%d%d%d_%s_kpi", orderId, curTime.Year(), curTime.Month(), curTime.Day(), dispatchType)
	_, _ = conn.Do("SET", key, cnt, 3600*24)
}

// 设置订单计划投放数量
// dispatchType: "click", "show"
func SetOrderPlanDispatchCount(orderId int64, dispatchType string, cnt int, curTime time.Time) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	curMinutes := curTime.Hour()*60 + curTime.Minute()
	key := fmt.Sprintf("plan_kpi_%d_%d%d%d_%d_%s_kpi", orderId, curTime.Year(), curTime.Month(), curTime.Day(), curMinutes, dispatchType)
	_, _ = conn.Do("SET", key, cnt, 3600*24)
}

// 获取总量每分钟要投放的量
func GetPerMinuteNeedDispatchCnt(curTime time.Time) (int, string, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	curMinutes := curTime.Minute() + (curTime.Hour() * 60)
	key := fmt.Sprintf("time_%d", curMinutes)
	rsp, err := conn.Do("GET", key)

	if err != nil {
		return 0, key, err
	}

	if rsp == nil {
		return 0, key, nil
	}

	count, _ := redis.Int(rsp, err)
	return count, key, nil
}

// 获取订单每分钟要投放的量
func GetOrderPerMinuteNeedDispatchCnt(orderId int64, curTime time.Time) (int, string, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	curMinutes := curTime.Minute() + (curTime.Hour() * 60)
	key := fmt.Sprintf("time_%d_%d", orderId, curMinutes)
	rsp, err := conn.Do("GET", key)

	if err != nil {
		return 0, key, err
	}

	if rsp == nil {
		return 0, key, nil
	}

	count, _ := redis.Int(rsp, err)
	return count, key, nil
}

// 获取ios的ua和imei
func GetIosUaImei(ip string) (string, string, error) {
	conn := ads_redis.RedisConn.Get()
	defer conn.Close()

	dateInt, _ := strconv.Atoi(time.Now().Format("20060102"))
	iosUaImeiRedisKey := fmt.Sprintf("ads_ios_%d_%s", dateInt, ip)

	// "{'imei': 'F389E3E1-5459-4B30-83A9-1AD504F6293F', 'ua': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_3_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML like Gecko) Mobile/15E148'}"
	rsp, err := conn.Do("GET", iosUaImeiRedisKey)
	if err != nil {
		return "", "", err
	}

	if rsp == nil {
		redisKey := fmt.Sprintf("new_ios_ua_v2_%d", dateInt)
		rsp, err = conn.Do("SRANDMEMBER", redisKey)
		if err != nil {
			return "", "", err
		}
		if rsp == nil {
			return "", "", nil
		}

		_, _ = conn.Do("SREM", redisKey, rsp)

		tomorrowDateInt, _ := strconv.Atoi(time.Unix(time.Now().Unix()+86400, 0).Format("20060102"))
		redisKey = fmt.Sprintf("new_ios_ua_v2_%d", tomorrowDateInt)
		_, _ = conn.Do("SADD", redisKey, rsp)
	}

	_, _ = conn.Do("SET", iosUaImeiRedisKey, rsp, 86520)

	var uaImeiInfo struct {
		Imei string
		Ua   string
	}

	rspBytes, _ := redis.Bytes(rsp, err)
	rspStr := strings.ReplaceAll(string(rspBytes), "'", "\"")

	err = json.Unmarshal([]byte(rspStr), &uaImeiInfo)
	if err != nil {
		return "", "", err
	}
	return uaImeiInfo.Imei, uaImeiInfo.Ua, nil
}