package service

import (
	"encoding/json"
	"errors"
	"fmt"
	"gadmin/config"
	"gadmin/internal/admin/consts"
	"gadmin/internal/admin/data"
	"gadmin/internal/admin/forms"
	"gadmin/internal/gorm/model"
	"gadmin/internal/gorm/query"
	"gadmin/package/gmdata"
	"gadmin/utility"
	"gadmin/utility/player"
	"gadmin/utility/serializer"
	"github.com/gin-gonic/gin"
	"github.com/jinzhu/now"
	"github.com/sirupsen/logrus"
	"github.com/xuri/excelize/v2"
	"math"
	"sync"
	"time"
)

var Order = new(sOrder)

type sOrder struct{}

func (s *sOrder) List(ctx *gin.Context, req forms.OrderListReq) serializer.Response {
	type OrderLstModel struct {
		model.Order
		NickName        string `json:"nickName"`
		PayAtFormat     string `json:"pay_at"`     // 支付时间
		CreatedAtFormat string `json:"created_at"` // 创建时间
	}

	var (
		c            = query.Use(config.DB).PlayerChannel
		o            = query.Use(config.DB).Order
		m            = o.WithContext(ctx)
		m2           = o.WithContext(ctx).Where(o.Status.Eq(consts.OrderStatusSuccess))
		offset int64 = 0
		models forms.OrderListRes
		lists  []OrderLstModel
	)

	if len(req.Time) == 2 {
		m = m.Where(o.CreatedAt.Between(req.Time[0], req.Time[1]))
		m2 = m2.Where(o.CreatedAt.Between(req.Time[0], req.Time[1]))
	}

	if req.Platform > 0 {
		m = m.Where(o.Platform.Eq(req.Platform))
		m2 = m2.Where(o.Platform.Eq(req.Platform))
	}

	if req.PlayerID > 0 {
		m = m.Where(o.PlayerID.Eq(int64(req.PlayerID)))
		m2 = m2.Where(o.PlayerID.Eq(int64(req.PlayerID)))
	}

	if req.GoodsID > 0 {
		m = m.Where(o.GoodsID.Eq(req.GoodsID))
		m2 = m2.Where(o.GoodsID.Eq(req.GoodsID))
	}

	if req.Status > 0 {
		m = m.Where(o.Status.Eq(req.Status))
		m2 = m2.Where(o.Status.Eq(req.Status))
	}

	if req.ServerId > 0 {
		m = m.Where(o.ServerID.Eq(req.ServerId))
		m2 = m2.Where(o.ServerID.Eq(req.ServerId))
	}

	if req.Flag > -1 {
		m = m.Where(o.Flag.Eq(req.Flag))
		m2 = m2.Where(o.Flag.Eq(req.Flag))
	}

	if req.OrderSn != "" {
		m = m.Where(o.OrderSn.Like("%" + req.OrderSn + "%"))
		m2 = m2.Where(o.OrderSn.Like("%" + req.OrderSn + "%"))
	}

	if req.OutTradeNo != "" {
		m = m.Where(o.OutTradeNo.Like("%" + req.OutTradeNo + "%"))
		m2 = m2.Where(o.OutTradeNo.Like("%" + req.OutTradeNo + "%"))
	}

	switch req.ChannelId {
	case consts.ChannelIdNone:
		// 不选择渠道
	case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
		// 所有的广告渠道
		m = m.Where(o.Columns(o.PlayerID).In(c.WithContext(ctx).Select(c.Playerid).Where(c.ChannelID.In(Channel.GetIdsByType(req.ChannelId)...))))
		m2 = m2.Where(o.Columns(o.PlayerID).In(c.WithContext(ctx).Select(c.Playerid).Where(c.ChannelID.In(Channel.GetIdsByType(req.ChannelId)...))))
	default:
		// 指定渠道
		m = m.Where(o.Columns(o.PlayerID).In(c.WithContext(ctx).Select(c.Playerid).Where(c.ChannelID.Eq(req.ChannelId))))
		m2 = m2.Where(o.Columns(o.PlayerID).In(c.WithContext(ctx).Select(c.Playerid).Where(c.ChannelID.Eq(req.ChannelId))))
	}

	m = m.Order(o.CreatedAt.Desc())

	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)

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

	// 导出
	if req.IsExport == 1 {
		if err = m.Scan(&lists); err != nil {
			return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
		}
		f := excelize.NewFile()
		sheetNum := 500
		pageCount := int(math.Ceil(float64(len(lists)) / float64(sheetNum)))
		wg := sync.WaitGroup{}
		wg.Add(pageCount)
		for i := 1; i <= pageCount; i++ {
			sheetName := fmt.Sprintf("Sheet%d", i)
			subList := make([]OrderLstModel, 0)
			if i == pageCount {
				subList = lists[(i-1)*sheetNum:]
			} else {
				subList = lists[(i-1)*sheetNum : i*sheetNum]
			}
			f.NewSheet(sheetName)
			f.SetColWidth(sheetName, "A", "A", 15)
			f.SetColWidth(sheetName, "B", "B", 15)
			f.SetColWidth(sheetName, "C", "C", 15)
			f.SetColWidth(sheetName, "D", "D", 25)
			f.SetColWidth(sheetName, "E", "E", 25)
			f.SetColWidth(sheetName, "F", "F", 30)
			f.SetColWidth(sheetName, "G", "G", 30)
			f.SetColWidth(sheetName, "H", "H", 15)
			f.SetColWidth(sheetName, "I", "I", 15)
			f.SetColWidth(sheetName, "J", "J", 25)
			f.SetColWidth(sheetName, "K", "K", 25)
			// 创建一个工作表
			f.SetCellValue(sheetName, "A1", "序号")
			f.SetCellValue(sheetName, "B1", "下单渠道")
			f.SetCellValue(sheetName, "C1", "玩家ID")
			f.SetCellValue(sheetName, "D1", "玩家昵称")
			f.SetCellValue(sheetName, "E1", "购买商品")
			f.SetCellValue(sheetName, "F1", "订单号")
			f.SetCellValue(sheetName, "G1", "外部订单号")
			f.SetCellValue(sheetName, "H1", "支付金额(元)")
			f.SetCellValue(sheetName, "I1", "支付状态")
			f.SetCellValue(sheetName, "J1", "支付时间")
			f.SetCellValue(sheetName, "K1", "创建时间")
			go func(subList []OrderLstModel) {
				defer wg.Done()
				for i, v := range subList {
					f.SetCellValue(sheetName, fmt.Sprintf("A%d", i+2), v.ID)
					if v.Platform == consts.OrderPlatformAndroid {
						f.SetCellValue(sheetName, fmt.Sprintf("B%d", i+2), "安卓")
					} else {
						f.SetCellValue(sheetName, fmt.Sprintf("B%d", i+2), "苹果")
					}
					f.SetCellValue(sheetName, fmt.Sprintf("C%d", i+2), v.PlayerID)
					user := data.GetUserToSyncMap(v.PlayerID)
					nickName := ""
					if user != nil {
						nickName = user.NickName
					}
					f.SetCellValue(sheetName, fmt.Sprintf("D%d", i+2), nickName)
					f.SetCellValue(sheetName, fmt.Sprintf("E%d", i+2), gmdata.GetGoodLabel(v.GoodsID))
					f.SetCellValue(sheetName, fmt.Sprintf("F%d", i+2), v.OrderSn)
					f.SetCellValue(sheetName, fmt.Sprintf("G%d", i+2), v.OutTradeNo)
					f.SetCellValue(sheetName, fmt.Sprintf("H%d", i+2), utility.Round(v.Money))
					f.SetCellValue(sheetName, fmt.Sprintf("I%d", i+2), consts.GetOrderStatusTag(v.Status))

					payAtFormat, createdAtFormat := "", ""
					if v.PayAt.Unix() > consts.FormsMinInvalidTimestamp {
						payAtFormat = utility.FormatSecond(v.PayAt)
					}

					if v.CreatedAt.Unix() > consts.FormsMinInvalidTimestamp {
						createdAtFormat = utility.FormatSecond(v.CreatedAt)
					}
					f.SetCellValue(sheetName, fmt.Sprintf("J%d", i+2), payAtFormat)
					f.SetCellValue(sheetName, fmt.Sprintf("K%d", i+2), createdAtFormat)
				}
			}(subList)
		}
		wg.Wait()
		// 设置工作簿的默认工作表
		f.SetActiveSheet(0)
		ctx.Header("Content-Type", "application/vnd.ms-excel")
		ctx.Header("Content-Disposition", fmt.Sprintf("attachment;filename=订单记录导出%s.xlsx", time.Now().Format("20060102150405")))
		f.WriteTo(ctx.Writer)
		return serializer.Response{}
	}

	if count > 0 {
		// 列表展示
		if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil {
			return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
		}

		for k, _ := range lists {
			user := data.GetUser(int64(lists[k].PlayerID))
			if user != nil {
				lists[k].NickName = user.NickName
			}

			if lists[k].PayAt.Unix() > consts.FormsMinInvalidTimestamp {
				lists[k].PayAtFormat = utility.FormatSecond(lists[k].PayAt)
			}

			if lists[k].CreatedAt.Unix() > consts.FormsMinInvalidTimestamp {
				lists[k].CreatedAtFormat = utility.FormatSecond(lists[k].CreatedAt)
			}

		}

		// 在存在成功订单时，查询统计
		if req.Status <= consts.OrderStatusNo || req.Status == consts.OrderStatusSuccess {
			// 交易金额
			transactionMoney, err := m2.Select(o.Money.Sum().As("money")).First()
			if err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 Money Sum", err)
			}
			models.TransactionMoney = transactionMoney.Money

			// 已支付订单数量
			if models.SuccessfulOrder, err = m2.Count(); err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 order Count", err)
			}
		}
	}

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

	return serializer.Suc(models)
}

// SevenStatisticsList 七日付费统计
func (s *sOrder) SevenStatisticsList(ctx *gin.Context, req forms.OrderSevenStatisticsListReq) serializer.Response {
	type Result struct {
		Date string  `json:"date"`
		C1   int64   `json:"c1"`
		M1   float64 `json:"m1"`
		C2   int64   `json:"c2"`
		M2   float64 `json:"m2"`
		C3   int64   `json:"c3"`
		M3   float64 `json:"m3"`
		C4   int64   `json:"c4"`
		M4   float64 `json:"m4"`
		C5   int64   `json:"c5"`
		M5   float64 `json:"m5"`
		C6   int64   `json:"c6"`
		M6   float64 `json:"m6"`
		C7   int64   `json:"c7"`
		M7   float64 `json:"m7"`
		U7   int64   `json:"u7"`
		C30  int64   `json:"c30"`
		M30  float64 `json:"m30"`
	}

	var (
		q            = query.Use(config.DB).Order
		m            = q.WithContext(ctx).Where(q.Status.Eq(consts.OrderStatusSuccess))
		offset int64 = 0
		models forms.UserAccountListRes
		lists  []Result
	)

	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)

	if len(req.Time) == 2 {
		m = m.Where(q.CreatedAt.Between(req.Time[0], req.Time[1]))
	}

	if req.ServerId > 0 {
		m = m.Where(q.ServerID.Eq(req.ServerId))
	}

	if req.Flag > -1 {
		m = m.Where(q.Flag.Eq(req.Flag))
	}

	switch req.ChannelId {
	case consts.ChannelIdNone:
		// 不选择渠道
	case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
		// 所有的广告渠道
		m = m.Where(q.ChannelID.In(Channel.GetIdsByType(req.ChannelId)...))
	default:
		// 指定渠道
		m = m.Where(q.ChannelID.Eq(req.ChannelId))
	}

	m = m.Select(q.Date).Order(q.Date.Desc()).Group(q.Date)
	count, err := m.Count()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
	}

	if count > 0 {
		if req.IsExport == 1 {
			if err = m.Scan(&lists); err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
			}
		} else {
			if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
			}
		}
	}

	stat := func(date time.Time, old time.Time) (count int64, total float64, err error) {
		o1 := now.With(old)
		b1, e1 := o1.BeginningOfDay().Unix(), o1.EndOfDay().Unix() // 当日起始时间戳
		qw := q.WithContext(ctx).Where(q.UserCreatedAt.Gte(int32(b1)), q.UserCreatedAt.Lte(int32(e1)))
		switch req.ChannelId {
		case consts.ChannelIdNone:
			// 不选择渠道
		case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
			// 所有的广告渠道
			qw = qw.Where(q.ChannelID.In(Channel.GetIdsByType(req.ChannelId)...))
		default:
			// 指定渠道
			qw = qw.Where(q.ChannelID.Eq(req.ChannelId))
		}

		if req.Platform > 0 {
			qw = qw.Where(q.Platform.Eq(req.Platform))
		}

		if req.ServerId > 0 {
			qw = qw.Where(q.ServerID.Eq(req.ServerId))
		}

		if req.Flag > -1 {
			qw = qw.Where(q.Flag.Eq(req.Flag))
		}

		var counter forms.CounterF
		err = qw.Select(q.Money.Sum().As("total")).
			Where(q.Status.Eq(consts.OrderStateSuccess), q.Date.Eq(date.Format("2006-01-02"))).Scan(&counter)
		if err != nil {
			return
		}

		total = counter.Total

		count, err = qw.Distinct(q.PlayerID).Where(q.Status.Eq(consts.OrderStateSuccess), q.Date.Eq(date.Format("2006-01-02"))).Count()
		if err != nil {
			return
		}

		return
	}

	stat2 := func(date time.Time, old time.Time) (count int64, total float64, err error) {
		o1 := now.With(old)
		b1, e1 := o1.BeginningOfDay().Unix(), o1.EndOfDay().Unix() // 当日起始时间戳
		qw := q.WithContext(ctx).Where(q.UserCreatedAt.Gte(int32(b1)), q.UserCreatedAt.Lte(int32(e1)))
		switch req.ChannelId {
		case consts.ChannelIdNone:
		// 不选择渠道
		case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
			// 所有的广告渠道
			qw = qw.Where(q.ChannelID.In(Channel.GetIdsByType(req.ChannelId)...))
		default:
			// 指定渠道
			qw = qw.Where(q.ChannelID.Eq(req.ChannelId))
		}

		if req.Platform > 0 {
			qw = qw.Where(q.Platform.Eq(req.Platform))
		}

		if req.ServerId > 0 {
			qw = qw.Where(q.ServerID.Eq(req.ServerId))
		}

		if req.Flag > -1 {
			qw = qw.Where(q.Flag.Eq(req.Flag))
		}

		var counter forms.CounterF
		err = qw.Select(q.Money.Sum().As("total")).
			Where(q.Status.Eq(consts.OrderStateSuccess),
				q.Date.Between(
					old.Format("2006-01-02"),
					date.Format("2006-01-02"),
				),
			).
			Scan(&counter)
		if err != nil {
			return
		}

		total = counter.Total

		count, err = qw.Distinct(q.PlayerID).Where(q.Status.Eq(consts.OrderStateSuccess),
			q.Date.Between(
				old.Format("2006-01-02"),
				date.Format("2006-01-02"),
			),
		).Count()
		if err != nil {
			return
		}

		return
	}

	if len(lists) > 0 {
		for k, _ := range lists {
			date, _ := now.ParseInLocation(time.Local, lists[k].Date)
			lists[k].Date = date.Format("2006-01-02")

			c1, m1, err := stat(date.AddDate(0, 0, 0), date)
			if err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 stat1", err)
			}

			c2, m2, err := stat(date.AddDate(0, 0, 1), date)
			if err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 stat2", err)
			}

			c3, m3, err := stat(date.AddDate(0, 0, 2), date)
			if err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 stat3", err)
			}

			c4, m4, err := stat(date.AddDate(0, 0, 3), date)
			if err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 stat4", err)
			}

			c5, m5, err := stat(date.AddDate(0, 0, 4), date)
			if err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 stat5", err)
			}

			c6, m6, err := stat(date.AddDate(0, 0, 5), date)
			if err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 stat6", err)
			}

			c7, m7, err := stat(date.AddDate(0, 0, 6), date)
			if err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 stat7", err)
			}

			c30, m30, err := stat2(date.AddDate(0, 0, 29), date)
			if err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 stat30", err)
			}

			lists[k].C1 = c1
			lists[k].M1 = m1

			lists[k].C2 = c2
			lists[k].M2 = m2

			lists[k].C3 = c3
			lists[k].M3 = m3

			lists[k].C4 = c4
			lists[k].M4 = m4

			lists[k].C5 = c5
			lists[k].M5 = m5

			lists[k].C6 = c6
			lists[k].M6 = m6

			lists[k].C7 = c7
			lists[k].M7 = m7

			lists[k].C30 = c30
			lists[k].M30 = m30

			// 7日唯一人数
			d1 := now.With(date)
			b1, e1 := d1.BeginningOfDay().Unix(), d1.EndOfDay().Unix() // 当日起始时间戳
			qw := q.WithContext(ctx).Where(q.UserCreatedAt.Gte(int32(b1)), q.UserCreatedAt.Lte(int32(e1)))
			switch req.ChannelId {
			case consts.ChannelIdNone:
				// 不选择渠道
			case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
				// 所有的广告渠道
				qw = qw.Where(q.ChannelID.In(Channel.GetIdsByType(req.ChannelId)...))
			default:
				// 指定渠道
				qw = qw.Where(q.ChannelID.Eq(req.ChannelId))
			}

			if req.Platform > 0 {
				qw = qw.Where(q.Platform.Eq(req.Platform))
			}

			if req.ServerId > 0 {
				qw = qw.Where(q.ServerID.Eq(req.ServerId))
			}

			if req.Flag > -1 {
				qw = qw.Where(q.Flag.Eq(req.Flag))
			}

			u7, err := qw.Distinct(q.PlayerID).Where(
				q.Status.Eq(consts.OrderStateSuccess),
				q.Date.Between(date.Format("2006-01-02"), date.AddDate(0, 0, 6).Format("2006-01-02"))).
				Count()
			if err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 Count", err)
			}

			lists[k].U7 = u7

		}
	}

	// 导出
	if req.IsExport == 1 {
		f := excelize.NewFile()
		f.SetColWidth("Sheet1", "A", "A", 15)
		f.SetColWidth("Sheet1", "B", "B", 20)
		f.SetColWidth("Sheet1", "C", "C", 20)
		f.SetColWidth("Sheet1", "D", "D", 20)
		f.SetColWidth("Sheet1", "E", "E", 20)
		f.SetColWidth("Sheet1", "F", "F", 20)
		f.SetColWidth("Sheet1", "G", "G", 20)
		f.SetColWidth("Sheet1", "H", "H", 20)
		f.SetColWidth("Sheet1", "I", "I", 20)
		f.SetColWidth("Sheet1", "J", "J", 20)
		f.SetColWidth("Sheet1", "K", "K", 20)
		f.SetColWidth("Sheet1", "L", "L", 20)
		f.SetColWidth("Sheet1", "M", "M", 20)
		f.SetColWidth("Sheet1", "N", "N", 20)
		f.SetColWidth("Sheet1", "O", "O", 20)
		f.SetColWidth("Sheet1", "P", "P", 15)
		f.SetColWidth("Sheet1", "Q", "Q", 15)
		f.SetColWidth("Sheet1", "R", "R", 15)

		// 创建一个工作表
		f.SetCellValue("Sheet1", "A1", "日期")
		f.SetCellValue("Sheet1", "B1", "当天注册付费人数")
		f.SetCellValue("Sheet1", "C1", "当天付费金额（元）")
		f.SetCellValue("Sheet1", "D1", "第2日注册付费人数")
		f.SetCellValue("Sheet1", "E1", "第2日付费金额（元）")
		f.SetCellValue("Sheet1", "F1", "第3日注册付费人数")
		f.SetCellValue("Sheet1", "G1", "第3日付费金额（元）")
		f.SetCellValue("Sheet1", "H1", "第4日注册付费人数")
		f.SetCellValue("Sheet1", "I1", "第4日付费金额（元）")
		f.SetCellValue("Sheet1", "J1", "第5日注册付费人数")
		f.SetCellValue("Sheet1", "K1", "第5日付费金额（元）")
		f.SetCellValue("Sheet1", "L1", "第6日注册付费人数")
		f.SetCellValue("Sheet1", "M1", "第6日付费金额（元）")
		f.SetCellValue("Sheet1", "N1", "第7日注册付费人数")
		f.SetCellValue("Sheet1", "O1", "第7日付费金额（元）")
		f.SetCellValue("Sheet1", "P1", "7日内人数")
		f.SetCellValue("Sheet1", "Q1", "30日内人数")
		f.SetCellValue("Sheet1", "R1", "30日内金额（元）")
		for i, v := range lists {
			f.SetCellValue("Sheet1", fmt.Sprintf("A%d", i+2), v.Date)
			f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i+2), v.C1)
			f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i+2), v.M1)
			f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i+2), v.C2)
			f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i+2), v.M2)
			f.SetCellValue("Sheet1", fmt.Sprintf("F%d", i+2), v.C3)
			f.SetCellValue("Sheet1", fmt.Sprintf("G%d", i+2), v.M3)
			f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i+2), v.C4)
			f.SetCellValue("Sheet1", fmt.Sprintf("I%d", i+2), v.M4)
			f.SetCellValue("Sheet1", fmt.Sprintf("J%d", i+2), v.C5)
			f.SetCellValue("Sheet1", fmt.Sprintf("K%d", i+2), v.M5)
			f.SetCellValue("Sheet1", fmt.Sprintf("L%d", i+2), v.C6)
			f.SetCellValue("Sheet1", fmt.Sprintf("M%d", i+2), v.M6)
			f.SetCellValue("Sheet1", fmt.Sprintf("N%d", i+2), v.C7)
			f.SetCellValue("Sheet1", fmt.Sprintf("O%d", i+2), v.M7)
			f.SetCellValue("Sheet1", fmt.Sprintf("P%d", i+2), v.U7)

			f.SetCellValue("Sheet1", fmt.Sprintf("Q%d", i+2), v.C30)
			f.SetCellValue("Sheet1", fmt.Sprintf("R%d", i+2), v.M30)
		}

		// 设置工作簿的默认工作表
		f.SetActiveSheet(1)
		ctx.Header("Content-Type", "application/vnd.ms-excel")
		ctx.Header("Content-Disposition", fmt.Sprintf("attachment;filename=新注册玩家付费统计导出%s.xlsx", time.Now().Format("20060102150405")))
		f.WriteTo(ctx.Writer)
		return serializer.Response{}
	}

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

	return serializer.Suc(models)
}

func (s *sOrder) DailyStatisticsList(ctx *gin.Context, req forms.OrderDailyStatisticsListReq) serializer.Response {

	type Result struct {
		Date             string  `json:"date"`
		TotalRecharge    float64 `json:"totalRecharge"`
		IosRecharge      float64 `json:"iosRecharge"`
		AndroidRecharge  float64 `json:"androidRecharge"`
		Players          int     `json:"players"`
		ARPU             string  `json:"arpu"`
		NewPlayers       int64   `json:"newPlayers"`
		NewTotalRecharge float64 `json:"newTotalRecharge"`
		NewARPU          string  `json:"newArpu"`
	}

	var (
		c            = query.Use(config.DB).PlayerChannel
		q            = query.Use(config.DB).Order
		m            = q.WithContext(ctx).Where(q.Status.Eq(consts.OrderStatusSuccess))
		offset int64 = 0
		models forms.UserAccountListRes
		lists  []Result
	)

	statNew := func(date time.Time, old time.Time) (count int64, total float64, err error) {
		o1 := now.With(old)
		b1, e1 := o1.BeginningOfDay().Unix(), o1.EndOfDay().Unix() // 当日起始时间戳
		qw := q.WithContext(ctx).Where(q.UserCreatedAt.Gte(int32(b1)), q.UserCreatedAt.Lte(int32(e1)))
		switch req.ChannelId {
		case consts.ChannelIdNone:
			// 不选择渠道
		case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
			// 所有的广告渠道
			qw = qw.Where(q.ChannelID.In(Channel.GetIdsByType(req.ChannelId)...))
		default:
			// 指定渠道
			qw = qw.Where(q.ChannelID.Eq(req.ChannelId))
		}

		if req.ServerId > 0 {
			qw = qw.Where(q.ServerID.Eq(req.ServerId))
		}

		if req.Flag > -1 {
			qw = qw.Where(q.Flag.Eq(req.Flag))
		}

		var counter forms.CounterF
		err = qw.Select(q.Money.Sum().As("total")).
			Where(q.Status.Eq(consts.OrderStateSuccess), q.Date.Eq(date.Format("2006-01-02"))).Scan(&counter)
		if err != nil {
			return
		}

		total = counter.Total

		count, err = qw.Distinct(q.PlayerID).Where(q.Status.Eq(consts.OrderStateSuccess), q.Date.Eq(date.Format("2006-01-02"))).Group(q.PlayerID).Count()
		if err != nil {
			return
		}

		return
	}

	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)

	if len(req.Time) == 2 {
		m = m.Where(q.CreatedAt.Between(req.Time[0], req.Time[1]))
	}

	if req.ServerId > 0 {
		m = m.Where(q.ServerID.Eq(req.ServerId))
	}

	if req.Flag > -1 {
		m = m.Where(q.Flag.Eq(req.Flag))
	}

	switch req.ChannelId {
	case consts.ChannelIdNone:
		// 不选择渠道
	case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
		// 所有的广告渠道
		m = m.Where(q.Columns(q.PlayerID).In(c.WithContext(ctx).Select(c.Playerid).Where(c.ChannelID.In(Channel.GetIdsByType(req.ChannelId)...))))
	default:
		// 指定渠道
		m = m.Where(q.Columns(q.PlayerID).In(c.WithContext(ctx).Select(c.Playerid).Where(c.ChannelID.Eq(req.ChannelId))))
	}

	m = m.Select(q.Date).Order(q.Date.Desc()).Group(q.Date)
	count, err := m.Count()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 count", err)
	}

	if count > 0 {
		if req.IsExport == 1 {
			if err = m.Scan(&lists); err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
			}
		} else {
			if err = m.Limit(int(req.PerPage)).Offset(int(offset)).Scan(&lists); err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
			}
		}
	}

	if len(lists) > 0 {
		for k, _ := range lists {
			date, _ := now.ParseInLocation(time.Local, lists[k].Date)
			lists[k].Date = date.Format("2006-01-02")

			qw := q.WithContext(ctx)
			qw2 := q.WithContext(ctx)
			switch req.ChannelId {
			case consts.ChannelIdNone:
				// 不选择渠道
			case consts.ChannelIdAllAdv, consts.ChannelIdAllWx, consts.ChannelIdAllTT:
				// 所有的广告渠道
				qw = qw.Where(q.Columns(q.PlayerID).In(c.WithContext(ctx).Select(c.Playerid).Where(c.ChannelID.In(Channel.GetIdsByType(req.ChannelId)...))))
				qw2 = qw2.Where(q.Columns(q.PlayerID).In(c.WithContext(ctx).Select(c.Playerid).Where(c.ChannelID.In(Channel.GetIdsByType(req.ChannelId)...))))
			default:
				// 指定渠道
				qw = qw.Where(q.Columns(q.PlayerID).In(c.WithContext(ctx).Select(c.Playerid).Where(c.ChannelID.Eq(req.ChannelId))))
				qw2 = qw2.Where(q.Columns(q.PlayerID).In(c.WithContext(ctx).Select(c.Playerid).Where(c.ChannelID.Eq(req.ChannelId))))
			}

			if req.ServerId > 0 {
				qw = qw.Where(q.ServerID.Eq(req.ServerId))
				qw2 = qw2.Where(q.ServerID.Eq(req.ServerId))
			}

			if req.Flag > -1 {
				qw = qw.Where(q.Flag.Eq(req.Flag))
				qw2 = qw2.Where(q.Flag.Eq(req.Flag))
			}

			var counter forms.CounterF
			if err = qw.Select(q.Money.Sum().As("total")).Where(q.Status.Eq(consts.OrderStateSuccess), q.Date.Eq(lists[k].Date)).Scan(&counter); err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 Money Sum", err)
			}
			lists[k].TotalRecharge = counter.Total

			playerCount, err := qw.Distinct(q.PlayerID).Where(q.Status.Eq(consts.OrderStateSuccess), q.Date.Eq(lists[k].Date)).Count()
			if err != nil {
				return serializer.Response{}
			}

			lists[k].Players = int(playerCount)
			if playerCount == 0 {
				playerCount = 1
			}

			var iosCounter forms.CounterF
			if err = qw2.Select(q.Money.Sum().As("total")).Where(q.Status.Eq(consts.OrderStateSuccess), q.Platform.Eq(consts.OrderPlatformIos), q.Date.Eq(lists[k].Date)).Scan(&iosCounter); err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 OrderPlatformIos Sum", err)
			}
			lists[k].IosRecharge = iosCounter.Total
			lists[k].AndroidRecharge = counter.Total - iosCounter.Total

			lists[k].ARPU = utility.Round(lists[k].TotalRecharge / float64(playerCount))

			// 统计新增
			lists[k].NewPlayers, lists[k].NewTotalRecharge, err = statNew(date, date)
			if err != nil {
				return serializer.Err(consts.CodeParamErr, "查询出错 statNew ", err)
			}

			if lists[k].NewTotalRecharge > 0 && lists[k].NewPlayers > 0 {
				lists[k].NewARPU = utility.Round(lists[k].NewTotalRecharge / float64(lists[k].NewPlayers))
			}

		}
	}

	// 导出
	if req.IsExport == 1 {
		//if err = m.Scan(&lists); err != nil {
		//	return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
		//}
		f := excelize.NewFile()
		f.SetColWidth("Sheet1", "A", "A", 15)
		f.SetColWidth("Sheet1", "B", "B", 20)
		f.SetColWidth("Sheet1", "C", "C", 20)
		f.SetColWidth("Sheet1", "D", "D", 20)
		f.SetColWidth("Sheet1", "E", "E", 20)
		f.SetColWidth("Sheet1", "F", "F", 20)
		f.SetColWidth("Sheet1", "G", "G", 20)
		f.SetColWidth("Sheet1", "H", "H", 20)
		f.SetColWidth("Sheet1", "I", "I", 20)

		// 创建一个工作表
		f.SetCellValue("Sheet1", "A1", "日期")
		f.SetCellValue("Sheet1", "B1", "总充值")
		f.SetCellValue("Sheet1", "C1", "安卓充值")
		f.SetCellValue("Sheet1", "D1", "苹果充值")
		f.SetCellValue("Sheet1", "E1", "付费人数")
		f.SetCellValue("Sheet1", "F1", "ARPU")
		f.SetCellValue("Sheet1", "G1", "日新增充值")
		f.SetCellValue("Sheet1", "H1", "日新增人数")
		f.SetCellValue("Sheet1", "I1", "日新增ARPU")

		for i, v := range lists {
			f.SetCellValue("Sheet1", fmt.Sprintf("A%d", i+2), v.Date)
			f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i+2), v.TotalRecharge)
			f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i+2), v.AndroidRecharge)
			f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i+2), v.IosRecharge)
			f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i+2), v.Players)
			f.SetCellValue("Sheet1", fmt.Sprintf("F%d", i+2), v.ARPU)
			f.SetCellValue("Sheet1", fmt.Sprintf("G%d", i+2), v.NewTotalRecharge)
			f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i+2), v.NewPlayers)
			f.SetCellValue("Sheet1", fmt.Sprintf("I%d", i+2), v.NewARPU)
		}

		// 设置工作簿的默认工作表
		f.SetActiveSheet(1)
		ctx.Header("Content-Type", "application/vnd.ms-excel")
		ctx.Header("Content-Disposition", fmt.Sprintf("attachment;filename=每日订单统计导出%s.xlsx", time.Now().Format("20060102150405")))
		f.WriteTo(ctx.Writer)
		return serializer.Response{}
	}

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

	return serializer.Suc(models)
}

func (s *sOrder) RechargeRankingIOS(ctx *gin.Context, req forms.RechargeRankingReq) serializer.Response {

	var (
		sql    = "SELECT `playerid`,sum(total) as t FROM `wxpay_iosorder` WHERE  `state` = 1 and total > 0 GROUP BY `playerid` ORDER BY t DESC  LIMIT 100"
		models forms.ListRes
	)

	type Result struct {
		ID       int64  `json:"id"`
		Playerid int64  `json:"playerid"`
		T        int64  `json:"total"`
		NickName string `json:"nickName"`
	}

	var result []Result

	if len(req.Time) == 2 {
		sql = fmt.Sprintf("SELECT `playerid`,sum(total) as t "+
			"FROM `wxpay_iosorder` "+
			"WHERE `state` = 1 and total > 0 and `create_time` BETWEEN '%v' AND '%v' GROUP BY `playerid` ORDER BY t DESC  LIMIT 100", req.Time[0], req.Time[1])
	}

	config.GDB1.Raw(sql).Scan(&result)

	for i := 0; i < len(result); i++ {
		result[i].ID = int64(i + 1)
		result[i].T = result[i].T / 100
		user := data.GetUser(result[i].Playerid)
		if user != nil {
			result[i].NickName = user.NickName
		}
	}

	// 计算分页
	req.Page, req.PerPage, _ = forms.CalculatePage(req.Page, req.PerPage)

	models.List = result
	models.Page = req.Page
	models.PerPage = req.PerPage
	models.PageCount = 1 //(int64(len(result)) + req.PerPage - 1) / req.PerPage

	return serializer.Suc(models)
}

func (s *sOrder) RechargeRankingAndroid(ctx *gin.Context, req forms.RechargeRankingReq) serializer.Response {
	var (
		sql    = " SELECT `wxpay_order`.`playerid`,sum((`virtualpayorder`.`balance`-`virtualpayorder`.`payedBalance`)) as t FROM `wxpay_order` LEFT JOIN `virtualpayorder` AS `virtualpayorder` ON `wxpay_order`.`orderId` = `virtualpayorder`.`billNo` WHERE `wxpay_order`.`state` = 1 and (`virtualpayorder`.`balance`-`virtualpayorder`.`payedBalance`) > 0 GROUP BY `wxpay_order`.`playerid` ORDER BY t DESC  LIMIT 100"
		models forms.ListRes
	)

	type Result struct {
		ID       int64  `json:"id"`
		Playerid int64  `json:"playerid"`
		T        int64  `json:"total"`
		NickName string `json:"nickName"`
	}

	var result []Result

	if len(req.Time) == 2 {
		sql = fmt.Sprintf("SELECT `wxpay_order`.`playerid`,sum((`virtualpayorder`.`balance`-`virtualpayorder`.`payedBalance`)) as t "+
			"FROM `wxpay_order` LEFT JOIN `virtualpayorder` AS `virtualpayorder` ON `wxpay_order`.`orderId` = `virtualpayorder`.`billNo` "+
			"WHERE `wxpay_order`.`state` = 1 and (`virtualpayorder`.`balance`-`virtualpayorder`.`payedBalance`) > 0 "+
			"and `wxpay_order`.`create_time` BETWEEN '%v' AND '%v' "+
			"GROUP BY `wxpay_order`.`playerid` ORDER BY t DESC LIMIT 100", req.Time[0], req.Time[1])
	}

	config.GDB1.Raw(sql).Scan(&result)

	for i := 0; i < len(result); i++ {
		result[i].ID = int64(i + 1)
		result[i].T = result[i].T / 100
		user := data.GetUser(result[i].Playerid)
		if user != nil {
			result[i].NickName = user.NickName
		}
	}

	req.Page, req.PerPage, _ = forms.CalculatePage(req.Page, req.PerPage)

	models.List = result
	models.Page = req.Page
	models.PerPage = req.PerPage
	models.PageCount = 1

	return serializer.Suc(models)
}

func (s *sOrder) RechargeRanking(ctx *gin.Context, req forms.RechargeRankingReq) serializer.Response {
	type RankingModels struct {
		Ranking           int32   `json:"ranking"`
		Total             float64 `json:"total"`
		PlayerID          int64   `json:"player_id"`
		NickName          string  `json:"nickName"`
		Platform          int32   `json:"platform"`
		LastLogin         string  `json:"lastLogin"`
		LastLoginValue    int64   `json:"lastLoginValue"`
		LastLoginTag      string  `json:"lastLoginTag"`
		LastRecharge      string  `json:"lastRecharge"`
		LastRechargeValue int64   `json:"lastRechargeValue"`
		LastRechargeTag   string  `json:"lastRechargeTag"`
		Diamond           int32   `json:"diamond"`
		Level             int32   `json:"level"`
		MaxPass           string  `json:"maxPass"`
		MaxPassValue      int32   `json:"maxPassValue"`
	}

	var (
		models forms.ListRes
		offset int64 = 0
		list   []RankingModels
		count  int64 = 0
		err    error
	)

	formatTime := func(t int64) (string, string) {
		n := time.Now().Unix()

		var ys int64 = 31536000
		var ds int64 = 86400
		var hs int64 = 3600
		var ms int64 = 60
		var ss int64 = 1

		var rs string
		var tag = "success"

		d := n - t
		switch {
		case d > ys:
			tag = "error"
			rs = fmt.Sprintf("%d年前", int(d/ys))
		case d > ds:
			if int(d/ds) > 6 {
				tag = "warning"
			} else {
				tag = "info"
			}
			rs = fmt.Sprintf("%d天前", int(d/ds))
		case d > hs:
			rs = fmt.Sprintf("%d小时前", int(d/hs))
		case d > ms:
			rs = fmt.Sprintf("%d分钟前", int(d/ms))
		case d > ss:
			rs = fmt.Sprintf("%d秒前", int(d/ss))
		default:
			rs = "刚刚"
		}

		return rs, tag
	}

	getPlayerMaterial := func(playerId int64) (diamond int32, maxPassName string, maxPassValue int32, err error) {
		type Pass struct {
			Id         int  `json:"id"`
			Count      int  `json:"count"`
			Difficulty int  `json:"difficulty"`
			Pass       bool `json:"pass"`
			IsActivity bool `json:"isActivity"`
		}

		DB, err := player.GetDBByUserId(int64(playerId))
		if err != nil {
			return 0, "", 0, err
		}

		var (
			models1 *model.PlayerMaterial
			q       = query.Use(config.GDBGroup[DB]).PlayerMaterial
			m       = q.WithContext(ctx).Select(q.Diamond, q.PassRoom).Where(q.Playerid.Eq(int64(playerId)))
			pass    []*Pass
			maxPass int
		)

		if err = m.Scan(&models1); err != nil {
			return
		}

		if models1 == nil {
			return 0, "", 0, nil
		}

		if err = json.Unmarshal([]byte(models1.PassRoom), &pass); err != nil {
			return 0, "", 0, err
		}

		if len(pass) > 0 {
			for _, p := range pass {
				if p.Id < 100 && p.Id > maxPass {
					maxPass = p.Id
				}
			}
		}

		ca := gmdata.GetChapterById(int32(maxPass))
		if ca != nil {
			maxPassName = ca.Name
			maxPassValue = int32(ca.Uid)
		}

		return models1.Diamond, maxPassName, maxPassValue, nil
	}

	getLoginTime := func(playerId int64) (l int32, s, t string, v int64, err error) {
		DB, err := player.GetDBByUserId(int64(playerId))
		if err != nil {
			return
		}
		var (
			models1 *model.PlayerAttr
			q       = query.Use(config.GDBGroup[DB]).PlayerAttr
			m       = q.WithContext(ctx).Select(q.Lastlogintick, q.Level).Where(q.Playerid.Eq(int64(playerId)))
		)

		if err = m.Scan(&models1); err != nil {
			return
		}

		if models1 == nil {
			return 0, "", "default", 0, nil
		}

		s, t = formatTime(models1.Lastlogintick)
		l = models1.Level
		v = models1.Lastlogintick
		return
	}

	getRechargeTime := func(playerId int64) (s, t string, v int64, err error) {
		var (
			models1 *model.Order
			q       = query.Use(config.DB).Order
			m       = q.WithContext(ctx).Select(q.CreatedAt).Where(q.PlayerID.Eq(playerId))
		)

		if err = m.Order(q.CreatedAt.Desc()).Scan(&models1); err != nil {
			return
		}

		if models1 == nil {
			return "", "default", 0, nil
		}

		s, t = formatTime(models1.CreatedAt.Unix())
		v = models1.CreatedAt.Unix()
		return
	}

	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)

	mod := config.DB.Model(&model.Order{}).
		Select("SUM(`money`) AS `total`,`player_id`,`platform`").
		Where("money > ? and status = ? ", 0, consts.OrderStatusSuccess).
		Group("player_id")

	if len(req.Time) == 2 {
		mod = mod.Where("created_at BETWEEN ? AND ?", req.Time[0], req.Time[1])
	}

	if req.Platform > 0 {
		mod = mod.Where("platform = ?", req.Platform)
	}

	if req.ServerId > 0 {
		mod = mod.Where("server_id = ?", req.ServerId)
	}

	mod.Count(&count)
	if count > 0 {
		mod.Limit(int(req.PerPage)).Offset(int(offset)).Order("total desc").Find(&list)
	}

	if len(list) > 0 {
		for k, _ := range list {
			list[k].Ranking = int32(offset + int64(k) + 1)
			user := data.GetUser(int64(list[k].PlayerID))
			if user != nil {
				list[k].NickName = user.NickName
			}

			list[k].Diamond, list[k].MaxPass, list[k].MaxPassValue, err = getPlayerMaterial(list[k].PlayerID)
			if err != nil {
				logrus.Warnf("查询出错 getPlayerMaterial:%+v", err)
			}

			list[k].Level, list[k].LastLogin, list[k].LastLoginTag, list[k].LastLoginValue, err = getLoginTime(list[k].PlayerID)
			if err != nil {
				logrus.Warnf("查询出错 getLoginTime:%+v", err)
			}

			list[k].LastRecharge, list[k].LastRechargeTag, list[k].LastRechargeValue, err = getRechargeTime(int64(list[k].PlayerID))
			if err != nil {
				logrus.Warnf("查询出错 getRechargeTime:%+v", err)
			}

		}
	}

	models.List = list
	models.Page = req.Page
	models.PerPage = req.PerPage
	models.PageCount = (count + req.PerPage - 1) / req.PerPage

	return serializer.Suc(models)
}

func (s *sOrder) UserStatistics(ctx *gin.Context, req forms.OrderUserStatisticsReq) serializer.Response {
	type Counter struct {
		Total float64 `json:"total"`
	}
	type Counter2 struct {
		Total int64 `json:"total"`
	}

	DB, err := player.GetDBByUserId(req.Playerid)
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "GetDBByUserId err", err)
	}

	var (
		androidQuery          = query.Use(config.GDBGroup[DB]).WxpayOrder
		iosQuery              = query.Use(config.GDBGroup[DB]).PayOrderIos
		orderQuery            = query.Use(config.DB).Order
		changedQuery          = query.Use(config.DB).ChangedLog
		models                forms.OrderUserStatisticsRes
		rechargeAmountCounter Counter
	)

	models.Playerid = req.Playerid
	models.OrderPlatform = consts.OrderPlatformAndroid

	err = orderQuery.WithContext(ctx).Select(orderQuery.Money.Sum().As("total")).Where(orderQuery.PlayerID.Eq(req.Playerid), orderQuery.Status.Eq(consts.OrderStateSuccess)).Scan(&rechargeAmountCounter)
	if err != nil {
		return serializer.Err(
			consts.CodeParamErr,
			"查询出错 RechargeAmount count",
			err,
		)
	}
	models.RechargeAmount = rechargeAmountCounter.Total

	models.RechargeCount, err = androidQuery.WithContext(ctx).Where(androidQuery.Playerid.Eq(req.Playerid), androidQuery.State.Eq(consts.OrderStateSuccess)).Count()
	if err != nil {
		return serializer.Err(
			consts.CodeParamErr,
			"查询出错 androidQuery count",
			err,
		)
	}
	if models.RechargeCount == 0 {
		models.RechargeCount, err = iosQuery.WithContext(ctx).Where(iosQuery.PlayerID.Eq(req.Playerid), iosQuery.State.Eq(consts.OrderStateSuccess), iosQuery.TradeState.Eq("SUCESS")).Count()
		if err != nil {
			return serializer.Err(
				consts.CodeParamErr,
				"查询出错 iosQuery count",
				err,
			)
		}

		if models.RechargeCount > 0 {
			models.OrderPlatform = consts.OrderPlatformIos
		}
	}

	if models.RechargeCount > 0 {
		if models.OrderPlatform == consts.OrderPlatformAndroid {
			models.RechargeDiamondCount, err = androidQuery.WithContext(ctx).
				Where(androidQuery.Playerid.Eq(req.Playerid), androidQuery.State.Eq(consts.OrderStateSuccess), androidQuery.GoodsID.In(config.DiamondGoodIds...)).
				Count()
			if err != nil {
				return serializer.Err(
					consts.CodeParamErr,
					"查询出错 androidQuery RechargeDiamondCount count",
					err,
				)
			}

			first, err := androidQuery.WithContext(ctx).
				Select(androidQuery.CreateTime).
				Where(androidQuery.Playerid.Eq(req.Playerid), androidQuery.State.Eq(consts.OrderStateSuccess)).
				First()

			if err != nil {
				return serializer.Err(
					consts.CodeParamErr,
					"查询出错 androidQuery First count",
					err,
				)
			}
			models.FirstChargeAt = first.CreateTime.Unix()

			last, err := androidQuery.WithContext(ctx).
				Select(androidQuery.CreateTime).
				Where(androidQuery.Playerid.Eq(req.Playerid), androidQuery.State.Eq(consts.OrderStateSuccess)).
				Last()

			if err != nil {
				return serializer.Err(
					consts.CodeParamErr,
					"查询出错 androidQuery last count",
					err,
				)
			}
			models.LastChargeAt = last.CreateTime.Unix()

		} else {
			models.RechargeDiamondCount, err = iosQuery.WithContext(ctx).
				Where(iosQuery.PlayerID.Eq(req.Playerid), iosQuery.TradeState.Eq("SUCESS"), iosQuery.State.Eq(consts.OrderStateSuccess), iosQuery.GoodsID.In(config.DiamondGoodIds...)).
				Count()
			if err != nil {
				return serializer.Err(
					consts.CodeParamErr,
					"查询出错 iosQuery RechargeDiamondCount count",
					err,
				)
			}

			first, err := iosQuery.WithContext(ctx).
				Select(iosQuery.CreateTime).
				Where(iosQuery.PlayerID.Eq(req.Playerid), iosQuery.State.Eq(consts.OrderStateSuccess)).
				First()

			if err != nil {
				return serializer.Err(
					consts.CodeParamErr,
					"查询出错 iosQuery First count",
					err,
				)
			}
			models.FirstChargeAt = first.CreateTime.Unix()

			last, err := iosQuery.WithContext(ctx).
				Select(iosQuery.CreateTime).
				Where(iosQuery.PlayerID.Eq(req.Playerid), iosQuery.State.Eq(consts.OrderStateSuccess), iosQuery.TradeState.Eq("SUCESS")).
				Last()

			if err != nil {
				return serializer.Err(
					consts.CodeParamErr,
					"查询出错 iosQuery last count",
					err,
				)
			}
			models.LastChargeAt = last.CreateTime.Unix()

		}
	}

	// 消费金币
	var consumptionCoinCountCounter Counter2
	err = changedQuery.WithContext(ctx).
		Select(changedQuery.Coin.Sum().As("total")).
		Where(changedQuery.UserID.Eq(req.Playerid), changedQuery.Coin.Lt(0)).
		Scan(&consumptionCoinCountCounter)
	if err != nil {
		return serializer.Err(
			consts.CodeParamErr,
			"查询出错 ConsumptionCoinCount count",
			err,
		)
	}
	models.ConsumptionCoinCount = consumptionCoinCountCounter.Total * -1

	// 消费钻石
	var ConsumptionDiamondCountCounter Counter2
	err = changedQuery.WithContext(ctx).
		Select(changedQuery.Diamond.Sum().As("total")).
		Where(changedQuery.UserID.Eq(req.Playerid), changedQuery.Diamond.Lt(0)).
		Scan(&ConsumptionDiamondCountCounter)
	if err != nil {
		return serializer.Err(
			consts.CodeParamErr,
			"查询出错 ConsumptionDiamondCount count",
			err,
		)
	}
	models.ConsumptionDiamondCount = ConsumptionDiamondCountCounter.Total * -1

	return serializer.Suc(models)
}

func (s *sOrder) AbnormalList(ctx *gin.Context, req forms.AbnormalOrderListReq) serializer.Response {
	type AbnormalOrderListModel struct {
		model.WxpayOrder
		NickName  string `json:"nickName"`
		GoodsName string `json:"goodsName"`
		Money     int64  `json:"money"`
		ServerId  int    `json:"serverId"`
	}

	var (
		offset int64 = 0
		models forms.ListRes
		result []AbnormalOrderListModel
	)

	req.Page, req.PerPage, offset = forms.CalculatePage(req.Page, req.PerPage)
	//result
	models.List = result
	models.Page = req.Page
	models.PerPage = req.PerPage

	o := query.Use(config.GDBGroup[int(req.ServerId)]).WxpayOrder
	m := o.WithContext(ctx)

	if len(req.Time) == 2 {
		m = m.Where(o.CreateTime.Between(req.Time[0], req.Time[1]))
	} else {
		nowTime := time.Now()
		threeDaysAgo := time.Date(nowTime.Year(), nowTime.Month(), nowTime.Day()-3, 0, 0, 0, 0, time.Local)
		m = m.Where(o.CreateTime.Between(threeDaysAgo, time.Now()))
	}

	if req.PlayerID > 0 {
		m = m.Where(o.Playerid.Eq(req.PlayerID))
	}

	if req.GoodsID > 0 {
		m = m.Where(o.GoodsID.Eq(req.GoodsID))
	}

	if req.OrderID != "" {
		m = m.Where(o.OrderID.Like("%" + req.OrderID + "%"))
	}

	//只获取异常订单
	m = m.Where(o.State.Neq(1)).Where(o.State.Neq(3)).Order(o.CreateTime.Desc())

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

	if count == 0 {
		return serializer.Suc(models)
	}

	if req.IsExport != 1 {
		m = m.Limit(int(req.PerPage)).Offset(int(offset))
	}
	// 列表展示
	if err = m.Scan(&result); err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 lists", err)
	}

	playerIds := make([]int64, len(result))

	for i, item := range result {
		playerIds[i] = item.Playerid
	}
	users := data.GetUsers(playerIds, int(req.ServerId))

	uMap := make(map[int64]*model.PlayerAttr, len(users))

	for _, user := range users {
		uMap[user.ID] = user
	}

	//读取shop.json获取商品信息
	shopGoods := gmdata.GetShopGoods()
	for i, item := range result {
		if _, ok := shopGoods[int64(item.GoodsID)]; ok {
			result[i].Money = shopGoods[int64(item.GoodsID)].Cost[0].Count
			result[i].GoodsName = shopGoods[int64(item.GoodsID)].Name
		} else {
			result[i].Money = 0
			result[i].GoodsName = string(item.GoodsID)
		}
		if user, ok := uMap[item.Playerid]; ok {
			result[i].NickName = user.NickName
		}
		result[i].ServerId = int(req.ServerId)
	}

	// 导出
	if req.IsExport == 1 && len(result) != 0 {
		f := excelize.NewFile()
		f.SetColWidth("Sheet1", "A", "A", 15)
		f.SetColWidth("Sheet1", "B", "B", 15)
		f.SetColWidth("Sheet1", "C", "C", 15)
		f.SetColWidth("Sheet1", "D", "D", 25)
		f.SetColWidth("Sheet1", "E", "E", 25)
		f.SetColWidth("Sheet1", "F", "F", 30)
		f.SetColWidth("Sheet1", "G", "G", 30)
		f.SetColWidth("Sheet1", "H", "H", 15)
		f.SetColWidth("Sheet1", "J", "J", 15)
		f.SetColWidth("Sheet1", "K", "K", 25)
		f.SetColWidth("Sheet1", "L", "L", 25)
		// 创建一个工作表
		f.SetCellValue("Sheet1", "A1", "序号")
		f.SetCellValue("Sheet1", "B1", "下单渠道")
		f.SetCellValue("Sheet1", "C1", "玩家ID")
		f.SetCellValue("Sheet1", "D1", "玩家昵称")
		f.SetCellValue("Sheet1", "E1", "购买商品")
		f.SetCellValue("Sheet1", "F1", "订单号")
		f.SetCellValue("Sheet1", "G1", "外部订单号")
		f.SetCellValue("Sheet1", "H1", "支付金额(元)")
		f.SetCellValue("Sheet1", "J1", "支付状态")
		f.SetCellValue("Sheet1", "K1", "支付时间")
		f.SetCellValue("Sheet1", "L1", "创建时间")

		for i, v := range result {
			f.SetCellValue("Sheet1", fmt.Sprintf("A%d", i+2), v.ID)
			if v.Platform == consts.OrderPlatformAndroid {
				f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i+2), "安卓")
			} else {
				f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i+2), "苹果")
			}
			f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i+2), v.Playerid)
			f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i+2), v.NickName)
			f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i+2), gmdata.GetGoodLabel(v.GoodsID))
			f.SetCellValue("Sheet1", fmt.Sprintf("F%d", i+2), v.OrderID)
			f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i+2), v.GoodsName)                     //商品名
			f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i+2), utility.Round(float64(v.Money))) //商品价格
			f.SetCellValue("Sheet1", fmt.Sprintf("J%d", i+2), consts.GetOrderStatusTag(v.State))
			f.SetCellValue("Sheet1", fmt.Sprintf("L%d", i+2), v.CreateTime.Format("2006-01-02 15:04:05"))
		}

		// 设置工作簿的默认工作表
		f.SetActiveSheet(1)
		ctx.Header("Content-Type", "application/vnd.ms-excel")
		ctx.Header("Content-Disposition", fmt.Sprintf("attachment;filename=订单记录导出%s.xlsx", time.Now().Format("20060102150405")))
		f.WriteTo(ctx.Writer)
		return serializer.Response{}
	}
	models.List = result
	models.PageCount = (count + req.PerPage - 1) / req.PerPage
	return serializer.Suc(models)
}

func (s *sOrder) AbnormalReissue(ctx *gin.Context, req forms.AbnormalOrderReissueReq) serializer.Response {
	var (
		o = query.Use(config.GDBGroup[req.ServerId]).WxpayOrder
		m = o.WithContext(ctx)
	)
	//查询订单
	order, err := m.Where(o.OrderID.Eq(req.OrderId)).First()
	if err != nil {
		return serializer.Err(consts.CodeParamErr, "查询出错 order", err)
	}
	//是否已经补发
	if order.State == 1 {
		return serializer.Suc(nil)
	}
	// 更新
	if _, err = m.Where(o.OrderID.Eq(order.OrderID)).Update(o.State, 8); err != nil {
		return serializer.Err(consts.CodeNoRightErr, "更新出错 order", err)
	}
	//redis新增mdsWaitPayment:玩家id
	rdsClient := config.RedisGroup[req.ServerId]
	if rdsClient == nil {
		return serializer.Err(consts.CodeParamErr, "redis不存在", errors.New("redis不存在"))
	}
	rdsClient.HSet(fmt.Sprintf("mdsWaitPayment:%d", order.Playerid), order.OrderID, order.CreateTime.Unix())
	return serializer.Suc(nil)
}
