package user

import (
	"bindbox-game/internal/pkg/logger"
	"bindbox-game/internal/repository/mysql"
	"bindbox-game/internal/repository/mysql/dao"
	"bindbox-game/internal/repository/mysql/model"
	"context"
	"time"
)

type Service interface {
	UpdateProfile(ctx context.Context, userID int64, nickname *string, avatar *string) (*model.Users, error)
	GetProfile(ctx context.Context, userID int64) (*model.Users, error)
	ListOrders(ctx context.Context, userID int64, page, pageSize int) (items []*model.Orders, total int64, err error)
	ListOrdersWithItems(ctx context.Context, userID int64, status int32, isConsumed *int32, page, pageSize int) (items []*OrderWithItems, total int64, err error)
	ListInventoryWithProduct(ctx context.Context, userID int64, page, pageSize int) (items []*InventoryWithProduct, total int64, err error)
	ListInventoryWithProductActive(ctx context.Context, userID int64, page, pageSize int, status int32) (items []*InventoryWithProduct, total int64, err error)
	ListInventoryAggregated(ctx context.Context, userID int64, page, pageSize int, status int32) (items []*AggregatedInventory, total int64, err error)
	ListCoupons(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserCoupons, total int64, err error)
	ListCouponsByStatus(ctx context.Context, userID int64, status int32, page, pageSize int) (items []*model.UserCoupons, total int64, err error)
	ListPointsLedger(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserPointsLedger, total int64, err error)
	GetPointsBalance(ctx context.Context, userID int64) (int64, error)
	LoginWeixin(ctx context.Context, in LoginWeixinInput) (*LoginWeixinOutput, error)
	LoginDouyin(ctx context.Context, in LoginDouyinInput) (*LoginDouyinOutput, error)
	ListInvites(ctx context.Context, userID int64, page, pageSize int) (items []*model.Users, total int64, err error)
	AddPoints(ctx context.Context, userID int64, points int64, kind string, remark string, validStart *time.Time, validEnd *time.Time) error
	AddPointsWithAction(ctx context.Context, userID int64, points int64, kind string, remark string, action string, validStart *time.Time, validEnd *time.Time) error
	AddCoupon(ctx context.Context, userID int64, couponID int64) error
	VoidUserCoupon(ctx context.Context, adminID int64, userID int64, userCouponID int64) error
	GrantReward(ctx context.Context, userID int64, req GrantRewardRequest) (*GrantRewardResponse, error)
	GrantRewardToOrder(ctx context.Context, userID int64, req GrantRewardToOrderRequest) (*GrantRewardToOrderResponse, error)
	BatchGrantRewardsToOrder(ctx context.Context, userID int64, orderID int64, items []BatchRewardItem) ([]int64, error)
	AddItemCard(ctx context.Context, userID int64, cardID int64, quantity int) error
	VoidUserItemCard(ctx context.Context, adminID int64, userID int64, userItemCardID int64) error
	RedeemItemCard(ctx context.Context, userID int64, cardID int64, quantity int) (ledgerID int64, err error)
	ListUserItemCards(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserItemCards, total int64, err error)
	ListUserItemCardsWithTemplate(ctx context.Context, userID int64, page, pageSize int) (items []*ItemCardWithTemplate, total int64, err error)
	ListUserItemCardsWithTemplateUsable(ctx context.Context, userID int64, page, pageSize int) (items []*ItemCardWithTemplate, total int64, err error)
	ListUserItemCardsWithTemplateByStatus(ctx context.Context, userID int64, status int32, page, pageSize int) (items []*ItemCardWithTemplate, total int64, err error)
	ListAggregatedUserItemCards(ctx context.Context, userID int64, status int32, page, pageSize int) (items []*ItemCardWithTemplate, total int64, err error)
	ListUserItemCardUses(ctx context.Context, userID int64, page, pageSize int) (items []*model.ActivityDrawEffects, total int64, err error)
	GetUserStats(ctx context.Context, userID int64) (*UserStats, error)
	AddAddress(ctx context.Context, userID int64, in AddAddressInput) (*model.UserAddresses, error)
	ListAddresses(ctx context.Context, userID int64, page, pageSize int) (items []*model.UserAddresses, total int64, err error)
	SetDefaultAddress(ctx context.Context, userID int64, addressID int64) error
	UpdateAddress(ctx context.Context, userID int64, addressID int64, in UpdateAddressInput) error
	DeleteAddress(ctx context.Context, userID int64, addressID int64) error
	CreateUser(ctx context.Context, in CreateUserInput) (*model.Users, error)
	DeleteUser(ctx context.Context, userID int64) error
	ConsumePoints(ctx context.Context, userID int64, points int64, orderNo string) (int64, error)
	ConsumePointsFor(ctx context.Context, userID int64, points int64, refTable string, refID string, remark string, action string) (int64, error)
	RefundPoints(ctx context.Context, userID int64, points int64, orderNo string, reason string) (int64, error)
	CreateAddressShare(ctx context.Context, userID int64, inventoryID int64, expiresAt time.Time) (string, string, time.Time, error)
	RevokeAddressShare(ctx context.Context, userID int64, inventoryID int64) error
	SubmitAddressShare(ctx context.Context, shareToken string, name string, mobile string, province string, city string, district string, address string, submittedByUserID *int64, submittedIP *string) (int64, error)
	RequestShipping(ctx context.Context, userID int64, inventoryID int64) (int64, error)
	CancelShipping(ctx context.Context, userID int64, inventoryID int64, batchNo string) (int64, error)
	RequestShippings(ctx context.Context, userID int64, inventoryIDs []int64, addressID *int64) (addrID int64, batchNo string, success []int64, skipped []struct {
		ID     int64
		Reason string
	}, failed []struct {
		ID     int64
		Reason string
	}, err error)
	VoidUserInventory(ctx context.Context, adminID int64, userID int64, inventoryID int64) error
	RedeemInventoryToPoints(ctx context.Context, userID int64, inventoryID int64) (int64, error)
	RedeemInventoriesToPoints(ctx context.Context, userID int64, inventoryIDs []int64) (int64, error)
	RecordOrderCouponUsage(ctx context.Context, orderID int64, userCouponID int64, appliedAmount int64) error
	DeductCouponsForPaidOrder(ctx context.Context, tx *dao.Query, userID int64, orderID int64, paidAt time.Time) error
	GetOrderWithItems(ctx context.Context, userID, orderID int64) (*OrderWithItems, error)
	CancelOrder(ctx context.Context, userID, orderID int64, reason string) (*model.Orders, error)
	CentsToPoints(ctx context.Context, cents int64) (int64, error)
	ListUserShipmentGroups(ctx context.Context, userID int64, page, pageSize int) (items []*ShipmentGroup, total int64, err error)
	ConsumePointsForRefund(ctx context.Context, userID int64, points int64, refTable string, refID string, remark string) (int64, int64, error)
	// 短信登录
	SendSmsCode(ctx context.Context, mobile string) error
	LoginByCode(ctx context.Context, in SmsLoginInput) (*SmsLoginOutput, error)
	GrantGamePass(ctx context.Context, userID int64, packageID int64, count int32, orderNo string) error
}

type service struct {
	logger  logger.CustomLogger
	readDB  *dao.Query
	writeDB *dao.Query
	repo    mysql.Repo
}

func New(l logger.CustomLogger, db mysql.Repo) Service {
	return &service{logger: l, readDB: dao.Use(db.GetDbR()), writeDB: dao.Use(db.GetDbW()), repo: db}
}
