package v1

import (
	"designs/app/common/request"
	"designs/app/common/response"
	"designs/global"
	"designs/model"
	"designs/utils"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
)

func UserActionList(c *gin.Context) {
	form := request.Check(c, &struct {
		Gid       string   `form:"gid" binding:"required"`
		Pf        []string `form:"pf" binding:""`
		StartTime string   `form:"startTime" binding:"required"`
		EndTime   string   `form:"endTime" binding:"required"`
	}{})

	form.EndTime = form.EndTime + " 23:59:59"

	//查询出所有的事件
	var actionList []model.GameAction

	query := global.App.DB.Table("game_action")

	err := query.
		Where("gid", form.Gid).
		Select("id", "actionId", "actionName").
		Order("id desc").Scan(&actionList).Error
	if err != nil {
		response.Fail(c, 1003, err.Error())
		return
	}
	//查询出时间段内的活跃用户,登录次数
	var userLogin []model.UserLogin
	query1 := global.App.DB.Table("user_login")
	if len(form.Pf) > 0 {

		query1 = query1.WhereIn("pf", form.Pf)
	}
	err = query1.
		Where("gid", form.Gid).
		Where("loginTime", ">=", form.StartTime).
		Where("loginTime", "<=", form.EndTime).
		Select("userId", "loginTime").
		Scan(&userLogin).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}
	userLoginCount := len(userLogin)

	//查询出时间段内事件触发数量，以及触发人的ID
	var userAction []model.UserAction
	query2 := global.App.DB.Table("user_action")
	if len(form.Pf) > 0 {
		query2 = query2.WhereIn("pf", form.Pf)
	}
	err = query2.
		Where("gid", form.Gid).
		Where("createdAt", ">=", form.StartTime).
		Where("createdAt", "<=", form.EndTime).
		Select("id", "actionId", "userId", "createdAt").
		Scan(&userAction).Error
	if err != nil {
		response.Fail(c, 1002, err.Error())
		return
	}
	//计算事件的触发总数和触发用户数
	actionSumMap := make(map[string]int)
	actionUserSumMap := make(map[string][]int)
	//fmt.Println(userAction)
	for _, action := range userAction {
		actionSumMap[action.ActionId]++
		actionUserSumMap[action.ActionId] = append(actionUserSumMap[action.ActionId], action.UserId)
	}

	//根据事件触发和活跃用户数量进行比对得出其他数据
	activeUser := make(map[int]bool)
	var activeUserSlice []int
	for _, users := range userLogin {
		activeUser[users.UserId] = true
	}
	for k := range activeUser {
		activeUserSlice = append(activeUserSlice, k)
	}

	type responses struct {
		Id              int     `json:"id"`
		ActionId        string  `json:"actionId"`
		ActionName      string  `json:"actionName"`
		ActionCount     int     `json:"actionCount"`
		ActionUserCount int     `json:"actionUserCount"`
		ActiveUserRate  float64 `json:"activeUserRate"`
		LoginActiveRate float64 `json:"loginActiveRate"`
	}

	var res []responses

	for _, v := range actionList {
		var ActiveUserRate float64
		var LoginActiveRate float64
		if userLoginCount > 0 {
			ActiveUserRate = float64(actionSumMap[v.ActionId] / userLoginCount)
			LoginActiveRate = float64(len(actionUserSumMap[v.ActionId]) / userLoginCount)
		}

		res = append(res, responses{
			Id:              v.ID,
			ActionId:        v.ActionId,
			ActionName:      v.ActionName,
			ActionCount:     actionSumMap[v.ActionId],
			ActionUserCount: len(actionUserSumMap[v.ActionId]),
			ActiveUserRate:  ActiveUserRate,
			LoginActiveRate: LoginActiveRate,
		})
	}

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

func UserActionDetail(c *gin.Context) {
	form := request.Check(c, &struct {
		Id        int      `form:"id" binding:"required"`
		Pf        []string `form:"pf" binding:""`
		StartTime string   `form:"startTime" binding:"required"`
		EndTime   string   `form:"endTime" binding:"required"`
	}{})

	//查询启动次数
	var action model.GameAction
	err := global.App.DB.Table("game_action").
		Where("id", form.Id).Find(&action).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}
	var userAction []struct {
		UserId    int    `json:"userId" gorm:"not null;column:userId;"`
		CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"`
	}
	err = global.App.DB.Table("user_action").
		Where("gid", action.Gid).
		Where("actionId", action.ActionId).
		Select("userId", "DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt").
		Scan(&userAction).Error
	if err != nil {
		response.Fail(c, 1002, err.Error())
		return
	}

	//查询出时间段内的活跃用户,登录次数
	var userLogin []struct {
		UserId    int    `json:"userId" gorm:"not null;column:userId;"`
		CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"`
	}
	err = global.App.DB.Table("user_login").
		Where("gid", action.Gid).
		Where("loginTime", ">=", form.StartTime).
		Where("loginTime", "<=", form.EndTime).
		Select("userId", "DATE_FORMAT(loginTime, '%Y-%m-%d') as createdAt").
		Scan(&userLogin).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}
	//userLoginCount := len(userLogin)

	activeCount := make(map[string]int)
	activeCountUser := make(map[string]map[int]bool)

	//根据日期进行分组
	for _, v := range userAction {
		activeCount[v.CreatedAt]++

		if activeCountUser[v.CreatedAt] == nil {
			activeCountUser[v.CreatedAt] = make(map[int]bool)
		}
		activeCountUser[v.CreatedAt][v.UserId] = true

	}

	days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime)

	type responses struct {
		Date            string  `json:"date"`
		ActiveCount     int     `json:"activeCount"`
		ActiveUserCount int     `json:"activeUserCount"`
		ActiveCountRate float64 `json:"activeCountRate"`
		ActiveCountUser float64 `json:"activeCountUser"`
	}
	var res []responses
	//输出格式
	for _, v := range days {
		res = append(res, responses{
			Date:            v,
			ActiveCount:     activeCount[v],
			ActiveUserCount: len(activeCountUser[v]),
			ActiveCountRate: float64(activeCount[v] / 1),
			ActiveCountUser: float64(len(activeCountUser[v]) / 1),
		})
	}

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

func UserActionDetailDistribution(c *gin.Context) {
	form := request.Check(c, &struct {
		Id        int      `form:"id" binding:"required"`
		Pf        []string `form:"pf" binding:""`
		StartTime string   `form:"startTime" binding:"required"`
		EndTime   string   `form:"endTime" binding:"required"`
		Type      int      `form:"type" binding:"required"`
	}{})

	var action model.GameAction
	err := global.App.DB.Table("game_action").
		Where("id", form.Id).Find(&action).Error
	if err != nil {
		response.Fail(c, 1001, err.Error())
		return
	}

	res := make(map[string]interface{})
	if form.Type == 1 {
		var userAction []struct {
			UserId    int    `json:"userId" gorm:"not null;column:userId;"`
			CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"`
		}
		query := global.App.DB.Table("user_action")
		if len(form.Pf) > 0 {
			query = query.WhereIn("pf", form.Pf)
		}
		err = query.
			Where("gid", action.Gid).
			Where("actionId", action.ActionId).
			Select("userId", "DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt").
			Scan(&userAction).Error
		if err != nil {
			response.Fail(c, 1002, err.Error())
			return
		}

		activeCount := make(map[string]int)
		for _, v := range userAction {
			activeCount[v.CreatedAt]++
		}

		days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime)
		for _, v := range days {
			res[v] = activeCount[v]
		}

		response.Success(c, gin.H{
			"data": map[string]interface{}{
				"avg":  fmt.Sprintf("%.2f", float64(len(userAction))/float64(len(days))),
				"list": res,
			},
		})

	} else if form.Type == 2 {
		var userAction []struct {
			UserId    int    `json:"userId" gorm:"not null;column:userId;"`
			CreatedAt string `json:"createdAt" gorm:"not null;column:createdAt;"`
		}
		query := global.App.DB.Table("user_action")
		if len(form.Pf) > 0 {
			query = query.WhereIn("gid", form.Pf)
		}
		err = query.
			Where("gid", action.Gid).
			Where("actionId", action.ActionId).
			Select("userId", "DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt").
			Scan(&userAction).Error
		if err != nil {
			response.Fail(c, 1002, err.Error())
			return
		}

		activeCount := make(map[string]map[int]bool)
		for _, v := range userAction {
			if activeCount[v.CreatedAt] == nil {
				activeCount[v.CreatedAt] = make(map[int]bool)
			}
			activeCount[v.CreatedAt][v.UserId] = true
		}

		days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime)
		for _, v := range days {
			res[v] = len(activeCount[v])
		}

		response.Success(c, gin.H{
			"data": map[string]interface{}{
				"avg":  fmt.Sprintf("%.2f", float64(len(userAction))/float64(len(days))),
				"list": res,
			},
		})
	} else if form.Type == 3 {
		//活跃设备发生率
		var userAction []string
		query := global.App.DB.Table("user_action")
		if len(form.Pf) > 0 {
			query = query.WhereIn("pf", form.Pf)
		}
		err = query.
			Where("gid", action.Gid).
			Where("actionId", action.ActionId).
			Pluck("DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt", &userAction).Error
		if err != nil {
			response.Fail(c, 1002, err.Error())
			return
		}
		actionCount := make(map[string]int)
		for _, v := range userAction {
			actionCount[v]++
		}

		//var userOnline model.UserOnline
		//query = global.App.DB.Table("user_online")
		//if len(form.Pf) > 0 {
		//	query = query.WhereIn("gid", form.Pf)
		//}
		//err = query.
		//	Where("gid", action.Gid).
		//	Error
		//if err != nil {
		//	response.Fail(c, 1002, err.Error())
		//	return
		//}
		//userCount := make(map[string]map[int]bool)
		//for _, v := range userOnline {
		//
		//}

	} else if form.Type == 4 {
		//每次启动发生率
		var userLogin []string
		query := global.App.DB.Table("user_login")
		if len(form.Pf) > 0 {
			query = query.WhereIn("pf", form.Pf)
		}
		err = query.
			Where("gid", action.Gid).
			Pluck("DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt", &userLogin).Error
		if err != nil {
			response.Fail(c, 1001, err.Error())
			return
		}
		loginCount := make(map[string]int)
		for _, v := range userLogin {
			loginCount[v]++
		}
		var userAction []string
		query = global.App.DB.Table("user_action")
		if len(form.Pf) > 0 {
			query = query.WhereIn("pf", form.Pf)
		}
		err = query.
			Where("gid", action.Gid).
			Where("actionId", action.ActionId).
			Pluck("DATE_FORMAT(createdAt, '%Y-%m-%d') as createdAt", &userAction).Error
		if err != nil {
			response.Fail(c, 1002, err.Error())
			return
		}
		actionCount := make(map[string]int)
		for _, v := range userAction {
			actionCount[v]++
		}
		days := utils.GetTimeDayDateFormat(form.StartTime, form.EndTime)
		for _, v := range days {
			if loginCount[v] > 0 {
				res[v] = float64(actionCount[v]) / float64(loginCount[v])
			} else {
				res[v] = 0
			}
		}

	} else {
		response.Fail(c, 1003, errors.New("type 错误"))
		return
	}
}
