// 玩家登录时间列表，登录次数排行
package service

import (
	"context"
	"fmt"
	"gadmin/config"
	"gadmin/internal/admin/consts"
	"gadmin/internal/admin/data"
	"gadmin/internal/admin/forms"
	"gadmin/internal/elastic/docs"
	"gadmin/internal/elastic/eapi"
	"gadmin/internal/gorm/model"
	"gadmin/internal/gorm/query"
	"gadmin/utility/serializer"
	"os"
	"time"

	"github.com/gin-gonic/gin"
)

var LoginLog = new(sLoginLog)

type sLoginLog struct{}

func (s *sLoginLog) Ranking(ctx context.Context, req forms.LoginRankingReq) serializer.Response {
	type mods struct {
		ID       int64  `json:"id"`
		NickName string `json:"nickName"`
		UserId   int64  `json:"user_id"`
		Count    int64  `json:"count"`
		LastTime int64  `json:"lastTime"`
	}

	var (
		loginModel = &model.LoginLog{}
		logDB      = model.TableOfYearMonth(loginModel.TableName(), time.Now())(config.DB)
		q          = query.Use(logDB).LoginLog.Table(logDB.Statement.Table)
		m          = q.WithContext(ctx).Select(q.EventAt).Where(q.EventID.Eq(consts.LoginEventEntryPack))
		models     forms.ListRes
		where      eapi.M
		index      = fmt.Sprintf("%s%s", os.Getenv("ELASTIC_TOPIC"), logDB.Statement.Table)
		lists      []*mods
	)

	must := []eapi.M{
		{
			"term": eapi.M{
				"event_id": consts.LoginEventEntryPack,
			},
		},
		{
			"range": eapi.M{
				"event_at": eapi.M{
					"gte": req.Createtime[0],
					"lte": req.Createtime[1],
				},
			},
		},
	}

	if req.ServerId > 0 {
		must = append(must, eapi.M{
			"term": eapi.M{
				"server_id": req.ServerId,
			},
		})
	}

	where = eapi.M{
		"query": eapi.M{
			"bool": eapi.M{
				"must": must,
			},
		},
	}

	topList, err := eapi.TopList(ctx, index, where, "user_id", 100)
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 TopList", err)
	}

	for i := 0; i < len(topList); i++ {
		v := new(mods)
		v.ID = int64(i + 1)
		v.UserId = topList[i].Key
		v.Count = topList[i].DocCount
		user := data.GetUser(v.UserId)
		if user != nil {
			v.NickName = user.NickName
		}

		first, _ := m.Where(q.UserID.Eq(v.UserId)).Order(q.ID.Desc()).First()
		if first != nil {
			v.LastTime = int64(first.EventAt)
		}

		q2 := eapi.M{
			"query": eapi.M{
				"bool": eapi.M{
					"must": []eapi.M{
						{
							"term": eapi.M{
								"user_id": v.UserId,
							},
						},
						{
							"term": eapi.M{
								"event_id": consts.LoginEventEntryPack,
							},
						},
					},
				},
			},
		}

		var data2 *model.LoginLog
		if err = eapi.LastSan(ctx, index, q2, "id", &data2); err != nil {
			return serializer.Err(consts.CodeParamErr, "查询出错 LastSan", err)
		}

		if data2 != nil {
			v.LastTime = int64(data2.EventAt)
		}
		lists = append(lists, v)
	}

	models.List = lists
	models.Page = req.Page
	models.PerPage = req.PerPage
	models.PageCount = 0

	return serializer.Suc(models)
}

func (s *sLoginLog) List(ctx *gin.Context, req forms.LoginLogListReq) serializer.Response {
	type Model struct {
		UserId   int64 `json:"user_id"`
		CostTime int   `json:"cost_time"`
		Id       int64 `json:"id"`
		EventAt  int   `json:"event_at"`
	}

	var (
		where  eapi.M
		index  = fmt.Sprintf("%s%s_%s", os.Getenv("ELASTIC_TOPIC"), docs.LoginLog.GetIndex(), time.Now().Format("200601"))
		lists  []*Model
		models forms.ListRes
		offset int64 = 0
	)

	must := []eapi.M{
		{
			"term": eapi.M{
				"event_id": consts.LoginEventEntryPack,
			},
		},
	}

	if len(req.EventAt) == 2 {
		must = append(must, eapi.M{
			"range": eapi.M{
				"event_at": eapi.M{
					"gte": req.EventAt[0],
					"lte": req.EventAt[1],
				},
			},
		})
	}

	if req.UserId > 0 {
		must = append(must, eapi.M{
			"term": eapi.M{
				"user_id": req.UserId, //1477867521, //
			},
		})
	}

	if req.Id > 0 {
		must = append(must, eapi.M{
			"term": eapi.M{
				"id": req.Id,
			},
		})
	}

	where = eapi.M{
		"query": eapi.M{
			"bool": eapi.M{
				"must": must,
			},
		},
	}

	count, err := eapi.Count(ctx, index, where)
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
	}

	// 分页
	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)

	where["from"] = offset
	where["size"] = req.PerPage
	where["_source"] = []string{"id", "user_id", "event_at", "cost_time"}
	where["sort"] = eapi.M{
		"event_at": "desc",
	}

	sources, err := eapi.Search(ctx, index, where)
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
	}

	for _, source := range sources {
		var v *Model
		if err = source.Scan(&v); err != nil {
			return serializer.Err(consts.CodeParamErr, "查询出错 Scan", err)
		}
		lists = append(lists, v)
	}

	models.List = lists
	models.Page = req.Page
	models.PerPage = req.PerPage
	models.PageCount = (count + req.PerPage - 1) / req.PerPage
	return serializer.Suc(models)
}
