package card_apple_order

import (
	"context"
	"kami/api/commonApi"
	"kami/internal/consts"
	"kami/internal/dao"
	"kami/internal/errHandler"
	"kami/internal/model"
	"kami/internal/model/do"
	"kami/internal/model/entity"
	"kami/internal/service"
	"kami/utility/config"
	"kami/utility/utils"
	"slices"

	"github.com/gogf/gf/v2/os/gmlock"

	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/os/gtime"
)

// List 获取充值列表
func (h *sAppleOrder) List(ctx context.Context, input model.AppleCardRechargeParamsInput) (total int, data []entity.V1CardAppleRechargeInfo, err error) {
	data = make([]entity.V1CardAppleRechargeInfo, 0)
	m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
	if input.StartDate != nil {
		m = m.WhereGTE(dao.V1CardAppleRechargeInfo.Columns().CreatedAt, input.StartDate)
	}
	if input.EndDate != nil {
		input.EndDate = input.EndDate.AddDate(0, 0, 1)
		m = m.WhereLTE(dao.V1CardAppleRechargeInfo.Columns().CreatedAt, input.EndDate)
	}
	if input.AccountID != "" {
		m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().AccountId, utils.OrmLike(input.AccountID))
	}
	if input.OrderNo != "" {
		m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().OrderNo, utils.OrmLike(input.OrderNo))
	}
	if input.Attach != "" {
		m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().Attach, utils.OrmLike(input.Attach))
	}
	if input.CardNo != "" {
		m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().OrderNo, utils.OrmLike(input.CardNo))
	}
	if input.CardPass != "" {
		m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().CardPass, utils.OrmLike(input.CardPass))
	}
	if input.UserId != "" {
		m = m.Where(dao.V1CardAppleRechargeInfo.Columns().CreatedUserId, input.UserId)
	}
	if input.MerchantId != "" {
		m = m.Where(dao.V1CardAppleRechargeInfo.Columns().MerchantId, input.MerchantId)
	}
	if input.Account != "" {
		m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().AccountName, utils.OrmLike(input.Account))
	}
	err2 := m.Page(input.Current, input.PageSize).
		OrderDesc(dao.V1CardAppleRechargeInfo.Columns().CreatedAt).
		ScanAndCount(&data, &total, false)
	if err2 != nil {
		total = 0
		err = gerror.Wrap(err2, "获取充值订单列表(分页)失败")
	}
	return
}

// ListWithAccount 获取充值列表（包含账号信息）
func (h *sAppleOrder) ListWithAccount(ctx context.Context, input model.AppleCardRechargeParamsInput) (total int, data []model.AppleCardRechargeListOutput, err error) {
	data = make([]model.AppleCardRechargeListOutput, 0)
	m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
	if input.AccountID != "" {
		accountEntity, _ := service.AppleAccount().GetDetailById(ctx, input.AccountID)
		if accountEntity.Id != "" {
			m = m.Where(dao.V1CardAppleRechargeInfo.Columns().AccountId, accountEntity.Account)
		}
	}
	if input.OrderNo != "" {
		m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().OrderNo, utils.OrmLike(input.OrderNo))
	}
	if input.Attach != "" {
		m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().Attach, utils.OrmLike(input.Attach))
	}
	if input.CardNo != "" {
		m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().OrderNo, utils.OrmLike(input.CardNo))
	}
	if input.CardPass != "" {
		m = m.WhereLike(dao.V1CardAppleRechargeInfo.Columns().CardPass, utils.OrmLike(input.CardPass))
	}
	err2 := m.Page(input.Current, input.PageSize).WithAll().
		OrderDesc(dao.V1CardAppleRechargeInfo.Columns().CreatedAt).
		ScanAndCount(&data, &total, true)
	if err2 != nil {
		total = 0
		err = gerror.Wrap(err2, "获取充值订单列表失败")
	}
	return
}

// AddRechargeOrder 添加一条充值记录
func (h *sAppleOrder) AddRechargeOrder(ctx context.Context, input *model.AppleCardRechargeInput) (orderNo string, err error) {
	orderNo = utils.GenerateRandomUUID()
	status := consts.AppleRechargeOrderWaiting
	operation := consts.AppleRechargeOperationCreated
	// 处理二次提交的订单
	if targetEntity, _ := h.QueryOneByCardPass(ctx, input.CardPass, nil); targetEntity.Id != 0 &&
		targetEntity.Status == int(consts.AppleRechargeOrderAmountDifferent) {
		status = consts.AppleRechargeOrderCardNoOrCardPassDuplicated
		operation = consts.AppleRechargeOperationDuplicatedOrder
		if targetEntity.ActualAmount != input.Amount {
			err = gerror.NewCode(errHandler.ErrAppleErrCardPass)
			return
		}
	}
	rechargeId, err := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
		InsertAndGetId(do.V1CardAppleRechargeInfo{
			OrderNo:     orderNo,
			AccountId:   input.AccountID,
			AccountName: input.AccountName,
			CardNo:      input.CardNo,
			CardPass:    input.CardPass,
			Balance:     input.Balance,
			CardAmount:  input.FaceValue,
			Status:      status,
			CallbackUrl: input.CallbackUrl,
			Attach:      input.Attach,
			MerchantId:  input.MerchantId,
		})
	if err != nil {
		err = gerror.WrapCode(gcode.CodeDbOperationError, err, "添加充值订单失败")
		return "", err
	}
	err = h.AddHistory(ctx, &model.AppleCardRechargeHistoryInput{
		RechargeId:  int(rechargeId),
		OrderNo:     orderNo,
		AccountName: input.AccountName,
		Operation:   operation,
	}, nil)
	if err != nil {
		err = gerror.WrapCode(gcode.CodeDbOperationError, err, "添加充值订单历史记录失败")
		return "", err
	}
	return orderNo, err
}

// DistributionAccordingAccount 给指定订单分配一个账户
func (h *sAppleOrder) DistributionAccordingAccount(ctx context.Context, account *entity.V1CardAppleAccountInfo, order *entity.V1CardAppleRechargeInfo) (err error) {
	if account == nil || order == nil {
		err = gerror.NewCode(gcode.CodeNil)
		return
	}
	m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).Where(dao.V1CardAppleRechargeInfo.Columns().OrderNo, order.OrderNo)
	err = m.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		_, err2 := m.TX(tx).Update(do.V1CardAppleRechargeInfo{
			AccountId:     account.Id,
			AccountName:   account.Account,
			CreatedUserId: account.CreatedUserId,
		})
		if err2 != nil {
			return err2
		}
		_, err2 = m.TX(tx).Increment(dao.V1CardAppleRechargeInfo.Columns().DistributionCount, 1)
		return err2
	})
	return err
}

// DecrementDistributionCount 减少分配次数
func (h *sAppleOrder) DecrementDistributionCount(ctx context.Context, orderNo string) (err error) {
	_, err = dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
		Where(dao.V1CardAppleRechargeInfo.Columns().OrderNo, orderNo).
		Decrement(dao.V1CardAppleRechargeInfo.Columns().DistributionCount, 1)
	return err
}

// UpdateActualAmount 修改订单实际金额
func (h *sAppleOrder) UpdateActualAmount(ctx context.Context, data *model.AppleAccountUpdateAmountRecord, tx gdb.TX) (err error) {
	m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
	if tx != nil {
		m = m.TX(tx)
	}
	_, err = m.Where(dao.V1CardAppleRechargeInfo.Columns().OrderNo, data.OrderNo).
		Update(do.V1CardAppleRechargeInfo{
			ActualAmount: data.Amount,
			Status:       data.Status,
			Remark:       data.Remark,
		})
	return err
}

// UpdateActualAmountAndHistory 添加充值记录
func (h *sAppleOrder) UpdateActualAmountAndHistory(ctx context.Context, record *model.AppleAccountUpdateAmountAndHistoryRecord, tx gdb.TX) (err error) {
	m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
	if tx != nil {
		m = m.TX(tx)
	}
	err = m.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		orderEntity, err2 := h.GetOneByOrderNo(ctx, record.OrderInfo.OrderNo, tx)
		if err2 != nil {
			return err2
		}
		if orderEntity.Id == 0 {
			return gerror.NewCode(gcode.CodeNil)
		}
		err2 = h.UpdateActualAmount(ctx, record.OrderInfo, tx)
		if err != nil {
			return err2
		}
		err = h.AddHistory(ctx, &model.AppleCardRechargeHistoryInput{
			RechargeId:  int(orderEntity.Id),
			OrderNo:     orderEntity.OrderNo,
			AccountID:   orderEntity.AccountId,
			AccountName: orderEntity.AccountName,
			Operation:   record.HistoryOperation,
			Remark:      record.HistoryRemark,
		}, tx)
		return err
	})
	return
}

func (h *sAppleOrder) UpdateActualAmountAndHistoryAndWallet(ctx context.Context, m *model.AppleAccountUpdateAmountAndHistoryRecord) (err error) {
	err = config.GetDatabaseV1().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
		if err = h.UpdateActualAmountAndHistory(ctx, m, tx); err != nil {
			return err
		}
		//往钱包里充值
		_, err = service.AppleAccount().AddWalletAmount(ctx, &model.AppleCardWalletInfo{
			CommonStrId:       commonApi.CommonStrId{ID: m.AccountId},
			OrderNo:           m.OrderInfo.OrderNo,
			Amount:            m.OrderInfo.Amount,
			BalanceFromItunes: m.BalanceFromItunes,
			Remark:            m.WalletRemark,
		}, tx)
		return err
	})
	//if err != nil {
	//	newPool := pool.New(pool.AppleAccountCheckWallet, 10)
	//	_ = newPool.Add(ctx, func(ctx context.Context) {
	//		orderEntity, err2 := h.GetOneByOrderNo(ctx, m.OrderInfo.OrderNo, nil)
	//		if err2 != nil {
	//			return
	//		}
	//		//检查余额是否正常
	//		service.AppleAccount().CheckWalletHistoryNormal(ctx, orderEntity.AccountId)
	//	})
	//}
	return
}

// GetListByStatus 获取指定状态的订单
func (h *sAppleOrder) GetListByStatus(ctx context.Context, statusList []consts.AppleRechargeOrderStatus) (data entity.V1CardAppleRechargeInfo, err error) {
	// 切片
	err = dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
		WhereIn(dao.V1CardAppleRechargeInfo.Columns().Status, statusList).
		Scan(&data)
	return
}

// GetTodayRechargeAmountByAccountID 获取当前账户今日的充值金额
func (h *sAppleOrder) GetTodayRechargeAmountByAccountID(ctx context.Context, accountID string) (amount float64, err error) {
	amount, err = dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
		Where(dao.V1CardAppleRechargeInfo.Columns().AccountId, accountID).
		Where(dao.V1CardAppleRechargeInfo.Columns().Status, consts.AppleRechargeOrderProcessing).
		Where(dao.V1CardAppleRechargeInfo.Columns().Status, consts.AppleRechargeOrderSuccess).
		Where(dao.V1CardAppleRechargeInfo.Columns().Status, consts.AppleRechargeOrderAmountDifferent).
		WhereBetween(dao.V1CardAppleRechargeInfo.Columns().CreatedAt, gtime.Now().StartOfDay(), gtime.Now()).
		Sum(dao.V1CardAppleRechargeInfo.Columns().ActualAmount)
	return
}

// GetRechargeStatusByOrderNo 通过订单号查询当前订单充值状态
func (h *sAppleOrder) GetRechargeStatusByOrderNo(ctx context.Context, orderNo string) (status int, err error) {
	m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
	err = m.Where(dao.V1CardAppleRechargeInfo.Columns().OrderNo, orderNo).Scan(&status)
	return
}

// GetOneByOrderNo 通过订单号查询当前订单充值
func (h *sAppleOrder) GetOneByOrderNo(ctx context.Context, orderNo string, tx gdb.TX, id ...int64) (data entity.V1CardAppleRechargeInfo, err error) {
	m := dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1())
	if tx != nil {
		m = m.TX(tx)
	}
	if orderNo != "" {
		m = m.Where(dao.V1CardAppleRechargeInfo.Columns().OrderNo, orderNo)
	}
	if len(id) != 0 && id[0] != 0 {
		m = m.Where(dao.V1CardAppleRechargeInfo.Columns().Id, id[0])
	}
	err = m.Scan(&data)
	return
}

func (h *sAppleOrder) GetOneByMerchantId(ctx context.Context, merchantId string) (data *entity.V1CardAppleRechargeInfo, err error) {
	err = dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
		Where(dao.V1CardAppleRechargeInfo.Columns().MerchantId, merchantId).
		Scan(&data)
	return
}

// GetAccordingOrders 找到符合条件的订单
func (h *sAppleOrder) GetAccordingOrders(ctx context.Context) (list []*entity.V1CardAppleRechargeInfo, err error) {
	gmlock.Lock("sAppleOrder_GetAccordingOrders")
	defer gmlock.Unlock("sAppleOrder_GetAccordingOrders")
	_ = dao.V1CardAppleRechargeInfo.Ctx(ctx).DB(config.GetDatabaseV1()).
		Where(dao.V1CardAppleRechargeInfo.Columns().Status, consts.AppleRechargeOrderWaiting).
		OrderAsc(dao.V1CardAppleRechargeInfo.Columns().CreatedAt).Scan(&list)

	list = slices.DeleteFunc(list, func(v *entity.V1CardAppleRechargeInfo) bool {
		if v.Id == 0 {
			return true
		}
		if v.DistributionCount < consts.AppleOrderMaxDistributionCount {
			return false
		}
		err = config.GetDatabaseV1().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
			err = h.ModifyOrderStatus(ctx, v.OrderNo, consts.AppleRechargeOrderFreeze, "订单回调超过最大次数", tx)
			if err != nil {
				return err
			}
			err = h.AddHistory(ctx, &model.AppleCardRechargeHistoryInput{
				RechargeId:  int(v.Id),
				OrderNo:     v.OrderNo,
				AccountID:   v.AccountId,
				AccountName: v.AccountName,
				Operation:   consts.AppleRechargeOperationDistributionCountOverLimit,
				Remark:      "调用订单超过最大次数",
			}, tx)
			return err
		})
		return true
	})
	return
}
