package card_redeem_order

import (
	"context"
	"fmt"
	"kami/api/commonApi"
	"kami/internal/consts"
	"kami/internal/dao"
	"kami/internal/model"
	"kami/internal/model/entity"
	"kami/utility/config"
	"kami/utility/utils"
	"sort"
	"time"

	"github.com/duke-git/lancet/v2/slice"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/os/gtime"
)

func (h *sCardRedeemOrder) Summary(ctx context.Context, page commonApi.CommonPageReq, category consts.CardRedeemAccountCategory, username string, date *gtime.Time, tx gdb.TX) (output []*model.RedeemCardSummaryOutput, err error) {
	output = make([]*model.RedeemCardSummaryOutput, 0)
	m := dao.V1CardRedeemOrderInfo.Ctx(ctx).DB(config.GetDatabaseV1()).Unscoped()
	if tx != nil {
		m = m.TX(tx)
	}
	if date != nil {
		m = m.WhereBetween(dao.V1CardRedeemOrderInfo.Columns().CreatedAt, date.StartOfDay(), date.EndOfDay())
	}
	if username != "" {
		m = m.WhereIn(utils.OrmTable(dao.V1CardRedeemAccountInfo.Table(), dao.V1CardRedeemAccountInfo.Columns().Name), username)
	}
	err = m.FieldSum(utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().ActualAmount), "amount").
		FieldCount(utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().OrderNo), "count").
		Fields(
			utils.OrmAs(utils.OrmTable(dao.V1CardRedeemAccountInfo.Table(), dao.V1CardRedeemAccountInfo.Columns().AmountTotalSum), "amount_total_sum"),
			utils.OrmAs(utils.OrmTable(dao.V1CardRedeemAccountInfo.Table(), dao.V1CardRedeemAccountInfo.Columns().AmountTotalCount), "amount_total_count"),
			utils.OrmAs(utils.OrmTable(dao.V1CardRedeemAccountInfo.Table(), dao.V1CardRedeemAccountInfo.Columns().Name), "name"),
			utils.OrmAs(utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().AccountId), "account_id"),
			utils.OrmAs(utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().Category), "category"),
			utils.OrmAs(fmt.Sprintf("DATE(%s)", utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().CreatedAt)), "date"),
		).
		LeftJoinOnFields(dao.V1CardRedeemAccountInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().AccountId, "=", dao.V1CardRedeemAccountInfo.Columns().Id).
		Group(
			fmt.Sprintf("DATE(%s)", utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().CreatedAt)),
			dao.V1CardRedeemOrderInfo.Columns().AccountId,
			dao.V1CardRedeemOrderInfo.Columns().Category,
		).
		Page(page.Current, page.PageSize).
		OrderDesc(fmt.Sprintf("DATE(%s)", utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().CreatedAt))).
		WhereIn(dao.V1CardRedeemOrderInfo.Columns().Category, category).
		WhereIn(dao.V1CardRedeemOrderInfo.Columns().OrderStatus, []consts.RedeemOrderStatus{consts.RedeemOrderSuccess, consts.RedeemOrderSuccessWithDifferentAmount}).
		Scan(&output)
	return
}

func (h *sCardRedeemOrder) SummaryWithOutAccount(ctx context.Context, groupId int64, category consts.CardRedeemAccountCategory, username string, dateRange []*gtime.Time, tx gdb.TX) (output []*model.RedeemCardSummaryWithOutAccountOutput, err error) {
	output = make([]*model.RedeemCardSummaryWithOutAccountOutput, 0)

	m := dao.V1CardRedeemOrderInfo.Ctx(ctx).DB(config.GetDatabaseV1()).Unscoped()
	if tx != nil {
		m = m.TX(tx)
	}

	startDate := gtime.Now().Add(-gtime.D * 15).StartOfDay()
	endDate := gtime.Now().EndOfDay()

	if dateRange != nil && len(dateRange) == 2 {
		startDate = dateRange[0]
		endDate = dateRange[1]
	}

	m = m.WhereBetween(dao.V1CardRedeemOrderInfo.Columns().CreatedAt, startDate, endDate)

	if username != "" {
		m = m.WhereIn(utils.OrmTable(dao.V1CardRedeemAccountInfo.Table(), dao.V1CardRedeemAccountInfo.Columns().Name), username)
	}

	if groupId != 0 {
		accountEntities := make([]*entity.V1CardRedeemAccountInfo, 0)
		if err = dao.V1CardRedeemAccountInfo.Ctx(ctx).DB(config.GetDatabaseV1()).Where(dao.V1CardRedeemAccountInfo.Columns().GroupId, groupId).Scan(&accountEntities); err != nil {
			return
		}
		accountIds := slice.Map(accountEntities, func(index int, item *entity.V1CardRedeemAccountInfo) string {
			return item.Id
		})
		m = m.WhereIn(dao.V1CardRedeemOrderInfo.Columns().AccountId, accountIds)
	}

	err = m.FieldSum(utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().ActualAmount), "amount").
		FieldCount(utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().OrderNo), "count").
		Fields(
			utils.OrmAs(utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().Category), "category"),
			utils.OrmAs(fmt.Sprintf("DATE(%s)", utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().CreatedAt)), "date"),
		).
		Group(
			fmt.Sprintf("DATE(%s)", utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().CreatedAt)),
			dao.V1CardRedeemOrderInfo.Columns().Category,
		).
		LeftJoinOnFields(dao.V1CardRedeemAccountInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().AccountId, "=", dao.V1CardRedeemAccountInfo.Columns().Id).
		Limit(15).
		OrderDesc(fmt.Sprintf("DATE(%s)", utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().CreatedAt))).
		WhereIn(dao.V1CardRedeemOrderInfo.Columns().Category, category).
		WhereIn(dao.V1CardRedeemOrderInfo.Columns().OrderStatus, []consts.RedeemOrderStatus{consts.RedeemOrderSuccess, consts.RedeemOrderSuccessWithDifferentAmount}).
		Scan(&output)

	for i := range int(endDate.Sub(startDate).Hours() / 24) {
		date := startDate.Add(gtime.D * time.Duration(i))
		if !slice.ContainBy(output, func(item *model.RedeemCardSummaryWithOutAccountOutput) bool {
			return item.Date.Equal(date)
		}) {
			output = append(output, &model.RedeemCardSummaryWithOutAccountOutput{
				Date:     date,
				Category: category,
				Amount:   0,
				Count:    0,
			})
		}
	}

	sort.Slice(output, func(i, j int) bool {
		return output[i].Date.Before(output[j].Date)
	})
	return
}

// DailySummary 查询某个用户当日的订单总额
func (h *sCardRedeemOrder) DailySummary(ctx context.Context, date *gtime.Time, tx gdb.TX) (output []*model.RedeemCardSummaryOutput, err error) {
	m := dao.V1CardRedeemOrderInfo.Ctx(ctx).DB(config.GetDatabaseV1())
	if tx != nil {
		m = m.TX(tx)
	}
	err = m.FieldSum(utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().ActualAmount), "amount").
		FieldCount(utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().OrderNo), "count").
		Fields(
			utils.OrmAs(utils.OrmTable(dao.V1CardRedeemAccountInfo.Table(), dao.V1CardRedeemAccountInfo.Columns().AmountTotalSum), "amount_total_sum"),
			utils.OrmAs(utils.OrmTable(dao.V1CardRedeemAccountInfo.Table(), dao.V1CardRedeemAccountInfo.Columns().AmountTotalCount), "amount_total_count"),
			utils.OrmAs(utils.OrmTable(dao.V1CardRedeemAccountInfo.Table(), dao.V1CardRedeemAccountInfo.Columns().Name), "name"),
			utils.OrmAs(utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().AccountId), "account_id"),
			utils.OrmAs(utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().Category), "category"),
			utils.OrmAs(fmt.Sprintf("DATE(%s)", utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().CreatedAt)), "date"),
		).
		LeftJoinOnFields(dao.V1CardRedeemAccountInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().AccountId, "=", dao.V1CardRedeemAccountInfo.Columns().Id).
		Group(
			fmt.Sprintf("DATE(%s)", utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().CreatedAt)),
			dao.V1CardRedeemOrderInfo.Columns().AccountId,
			dao.V1CardRedeemOrderInfo.Columns().Category,
		).Unscoped().
		WhereIn(dao.V1CardRedeemOrderInfo.Columns().OrderStatus, []consts.RedeemOrderStatus{consts.RedeemOrderSuccess, consts.RedeemOrderSuccessWithDifferentAmount}).
		Where(fmt.Sprintf("DATE(%s)=?", utils.OrmTable(dao.V1CardRedeemOrderInfo.Table(), dao.V1CardRedeemOrderInfo.Columns().CreatedAt)), date.Format("Y-m-d")).
		Scan(&output)
	return
}
