package app

import (
	"fmt"
	"net/http"
	"time"

	"bindbox-game/internal/code"
	"bindbox-game/internal/pkg/core"
	"bindbox-game/internal/pkg/validation"
	"bindbox-game/internal/repository/mysql/model"
)

// ==================== 用户次数卡 API ====================

type getGamePassesRequest struct {
	ActivityID *int64 `form:"activity_id"`
}

type userGamePassItem struct {
	ID           int64  `json:"id"`
	ActivityID   int64  `json:"activity_id"`
	ActivityName string `json:"activity_name"`
	Remaining    int32  `json:"remaining"`
	ExpiredAt    string `json:"expired_at"`
	Source       string `json:"source"`
}

type getGamePassesResponse struct {
	TotalRemaining  int32              `json:"total_remaining"`
	GlobalRemaining int32              `json:"global_remaining"` // 全局通用次数
	Passes          []userGamePassItem `json:"passes"`
}

// GetGamePasses 获取用户可用的游戏次数卡
// @Summary 获取用户次数卡
// @Description 查询当前用户可用的游戏次数卡
// @Tags APP端.用户
// @Accept json
// @Produce json
// @Security LoginVerifyToken
// @Param activity_id query integer false "活动ID，不传返回所有可用次数卡"
// @Success 200 {object} getGamePassesResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/game-passes/available [get]
func (h *handler) GetGamePasses() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(getGamePassesRequest)
		res := new(getGamePassesResponse)
		if err := ctx.ShouldBindForm(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}

		userID := int64(ctx.SessionUserInfo().Id)
		now := time.Now()

		// 查询用户的次数卡（已过滤过期和剩余为0的）
		q := h.readDB.UserGamePasses.WithContext(ctx.RequestContext()).
			Where(h.readDB.UserGamePasses.UserID.Eq(userID)).
			Where(h.readDB.UserGamePasses.Remaining.Gt(0))

		passes, err := q.Find()
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error()))
			return
		}

		// 获取活动名称
		activityIDs := make([]int64, 0)
		for _, p := range passes {
			if p.ActivityID > 0 {
				activityIDs = append(activityIDs, p.ActivityID)
			}
		}
		activityMap := make(map[int64]string)
		if len(activityIDs) > 0 {
			activities, _ := h.readDB.Activities.WithContext(ctx.RequestContext()).
				Where(h.readDB.Activities.ID.In(activityIDs...)).Find()
			for _, a := range activities {
				activityMap[a.ID] = a.Name
			}
		}

		res.Passes = make([]userGamePassItem, 0)
		for _, p := range passes {
			// 检查是否过期
			if !p.ExpiredAt.IsZero() && p.ExpiredAt.Before(now) {
				continue
			}

			// 如果指定了活动ID，只返回全局通用的和该活动的
			if req.ActivityID != nil && *req.ActivityID > 0 {
				if p.ActivityID != 0 && p.ActivityID != *req.ActivityID {
					continue
				}
			}

			expiredAt := ""
			if !p.ExpiredAt.IsZero() {
				expiredAt = p.ExpiredAt.Format("2006-01-02 15:04:05")
			}

			item := userGamePassItem{
				ID:           p.ID,
				ActivityID:   p.ActivityID,
				ActivityName: activityMap[p.ActivityID],
				Remaining:    p.Remaining,
				ExpiredAt:    expiredAt,
				Source:       p.Source,
			}

			res.TotalRemaining += p.Remaining
			if p.ActivityID == 0 {
				res.GlobalRemaining += p.Remaining
			}
			res.Passes = append(res.Passes, item)
		}

		ctx.Payload(res)
	}
}

// ==================== 套餐列表 API ====================

type getPackagesRequest struct {
	ActivityID *int64 `form:"activity_id"`
}

type packageItem struct {
	ID            int64  `json:"id"`
	Name          string `json:"name"`
	PassCount     int32  `json:"pass_count"`
	Price         int64  `json:"price"`
	OriginalPrice int64  `json:"original_price"`
	ValidDays     int32  `json:"valid_days"`
	ActivityID    int64  `json:"activity_id"`
}

type getPackagesResponse struct {
	Packages []packageItem `json:"packages"`
}

// GetGamePassPackages 获取可购买的套餐列表
// @Summary 获取次数卡套餐
// @Description 获取可购买的次数卡套餐列表
// @Tags APP端.用户
// @Accept json
// @Produce json
// @Param activity_id query integer false "活动ID，不传返回全局套餐"
// @Success 200 {object} getPackagesResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/game-passes/packages [get]
func (h *handler) GetGamePassPackages() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(getPackagesRequest)
		res := new(getPackagesResponse)
		if err := ctx.ShouldBindForm(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}

		q := h.readDB.GamePassPackages.WithContext(ctx.RequestContext()).
			Where(h.readDB.GamePassPackages.Status.Eq(1)) // 只返回上架的

		// 如果指定了活动ID，返回全局套餐(activity_id=0)和该活动的专属套餐
		if req.ActivityID != nil && *req.ActivityID > 0 {
			q = q.Where(h.readDB.GamePassPackages.ActivityID.In(0, *req.ActivityID))
		} else {
			// 只返回全局套餐
			q = q.Where(h.readDB.GamePassPackages.ActivityID.Eq(0))
		}

		packages, err := q.Order(h.readDB.GamePassPackages.SortOrder.Desc(), h.readDB.GamePassPackages.ID.Asc()).Find()
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error()))
			return
		}

		res.Packages = make([]packageItem, len(packages))
		for i, p := range packages {
			res.Packages[i] = packageItem{
				ID:            p.ID,
				Name:          p.Name,
				PassCount:     p.PassCount,
				Price:         p.Price,
				OriginalPrice: p.OriginalPrice,
				ValidDays:     p.ValidDays,
				ActivityID:    p.ActivityID,
			}
		}

		ctx.Payload(res)
	}
}

// ==================== 购买套餐 API ====================

type purchasePackageRequest struct {
	PackageID int64 `json:"package_id" binding:"required"`
	Count     int32 `json:"count"` // 购买数量
}

type purchasePackageResponse struct {
	OrderNo string `json:"order_no"`
	Message string `json:"message"`
}

// PurchaseGamePassPackage 购买次数卡套餐（创建订单）
// @Summary 购买次数卡套餐
// @Description 购买次数卡套餐，创建订单等待支付
// @Tags APP端.用户
// @Accept json
// @Produce json
// @Security LoginVerifyToken
// @Param RequestBody body purchasePackageRequest true "请求参数"
// @Success 200 {object} purchasePackageResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/game-passes/purchase [post]
func (h *handler) PurchaseGamePassPackage() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(purchasePackageRequest)
		res := new(purchasePackageResponse)
		if err := ctx.ShouldBindJSON(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}

		if req.Count <= 0 {
			req.Count = 1
		}

		userID := int64(ctx.SessionUserInfo().Id)

		// 查询套餐信息
		pkg, err := h.readDB.GamePassPackages.WithContext(ctx.RequestContext()).
			Where(h.readDB.GamePassPackages.ID.Eq(req.PackageID)).
			Where(h.readDB.GamePassPackages.Status.Eq(1)).
			First()
		if err != nil || pkg == nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, "套餐不存在或已下架"))
			return
		}

		// Calculate total price
		totalPrice := pkg.Price * int64(req.Count)

		// 创建订单
		now := time.Now()
		orderNo := now.Format("20060102150405") + fmt.Sprintf("%04d", now.UnixNano()%10000)
		order := &model.Orders{
			UserID:       userID,
			OrderNo:      "GP" + orderNo,
			SourceType:   4, // 次数卡购买
			TotalAmount:  totalPrice,
			ActualAmount: totalPrice,
			Status:       1, // 待支付
			Remark:       fmt.Sprintf("game_pass_package:%s|count:%d", pkg.Name, req.Count),
			CreatedAt:    now,
			UpdatedAt:    now,
		}

		if err := h.writeDB.Orders.WithContext(ctx.RequestContext()).
			Omit(h.writeDB.Orders.PaidAt, h.writeDB.Orders.CancelledAt).
			Create(order); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, err.Error()))
			return
		}

		// 在备注中记录套餐ID和数量
		remark := fmt.Sprintf("%s|pkg_id:%d|count:%d", order.Remark, pkg.ID, req.Count)
		h.writeDB.Orders.WithContext(ctx.RequestContext()).
			Where(h.writeDB.Orders.ID.Eq(order.ID)).
			Updates(map[string]any{"remark": remark})

		res.OrderNo = order.OrderNo
		res.Message = "订单创建成功，请完成支付"
		ctx.Payload(res)
	}
}
