package app

import (
	"fmt"
	"net/http"

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

type listCouponsRequest struct {
	Page     int    `form:"page"`
	PageSize int    `form:"page_size"`
	Status   *int32 `form:"status"` // 1未使用 2已使用 3已过期，不传默认1
}
type listCouponsResponse struct {
	Page     int          `json:"page"`
	PageSize int          `json:"page_size"`
	Total    int64        `json:"total"`
	List     []couponItem `json:"list"`
}

type couponItem struct {
	ID         int64  `json:"id"`
	Name       string `json:"name"`
	Amount     int64  `json:"amount"`
	Remaining  int64  `json:"remaining"`
	ValidStart string `json:"valid_start"`
	ValidEnd   string `json:"valid_end"`
	Status     int32  `json:"status"`
	StatusDesc string `json:"status_desc"` // 状态描述：未使用、已用完、已过期
	Rules      string `json:"rules"`
	UsedAt     string `json:"used_at,omitempty"` // 使用时间（已使用时返回）
	UsedAmount int64  `json:"used_amount"`       // 已使用金额
}

// ListUserCoupons 查看用户优惠券
// @Summary 查看用户优惠券
// @Description 查看用户持有的优惠券列表，支持按状态过滤
// @Tags APP端.用户
// @Accept json
// @Produce json
// @Param user_id path integer true "用户ID"
// @Security LoginVerifyToken
// @Param page query int true "页码" default(1)
// @Param page_size query int true "每页数量，最多100" default(20)
// @Param status query int false "状态：1未使用 2已使用 3已过期，不传默认1"
// @Success 200 {object} listCouponsResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/users/{user_id}/coupons [get]
func (h *handler) ListUserCoupons() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(listCouponsRequest)
		rsp := new(listCouponsResponse)
		if err := ctx.ShouldBindForm(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}
		userID := int64(ctx.SessionUserInfo().Id)

		// 状态：0未使用 1已使用 2已过期 (直接对接前端标准)
		status := int32(0)
		if req.Status != nil {
			status = *req.Status
		}

		items, total, err := h.user.ListAppCoupons(ctx.RequestContext(), userID, status, req.Page, req.PageSize)
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, 10003, err.Error()))
			return
		}
		rsp.Page = req.Page
		rsp.PageSize = req.PageSize
		rsp.Total = total
		if len(items) == 0 {
			rsp.List = []couponItem{}
			ctx.Payload(rsp)
			return
		}
		ids := make([]int64, 0, len(items))
		for _, it := range items {
			ids = append(ids, it.CouponID)
		}
		rows, err := h.readDB.SystemCoupons.WithContext(ctx.RequestContext()).Where(h.readDB.SystemCoupons.ID.In(ids...)).Find()
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, 10003, err.Error()))
			return
		}
		mp := make(map[int64]*model.SystemCoupons, len(rows))
		for i := range rows {
			c := rows[i]
			mp[c.ID] = c
		}
		rsp.List = make([]couponItem, 0, len(items))
		for _, it := range items {
			sc := mp[it.CouponID]
			name := ""
			amount := int64(0)
			remaining := int64(0)
			rules := ""
			if sc != nil {
				name = sc.Name
				amount = sc.DiscountValue
				remaining = it.BalanceAmount
				rules = buildCouponRules(sc)
			}
			vs := it.ValidStart.Format("2006-01-02 15:04:05")
			ve := ""
			if !it.ValidEnd.IsZero() {
				ve = it.ValidEnd.Format("2006-01-02 15:04:05")
			}
			usedAt := ""
			if !it.UsedAt.IsZero() {
				usedAt = it.UsedAt.Format("2006-01-02 15:04:05")
			}
			statusDesc := "未使用"
			if it.Status == 2 {
				if it.BalanceAmount == 0 {
					statusDesc = "已使用"
				} else {
					statusDesc = "使用中"
				}
			} else if it.Status == 3 {
				// 若面值等于余额，说明完全没用过，否则为“已到期”
				sc, ok := mp[it.CouponID]
				if ok && it.BalanceAmount < sc.DiscountValue {
					statusDesc = "已到期"
				} else {
					statusDesc = "已过期"
				}
			}
			usedAmount := amount - remaining
			vi := couponItem{ID: it.ID, Name: name, Amount: amount, Remaining: remaining, UsedAmount: usedAmount, ValidStart: vs, ValidEnd: ve, Status: it.Status, StatusDesc: statusDesc, Rules: rules, UsedAt: usedAt}
			rsp.List = append(rsp.List, vi)
		}
		ctx.Payload(rsp)
	}
}

func buildCouponRules(c *model.SystemCoupons) string {
	switch c.DiscountType {
	case 1:
		return fmt.Sprintf("直减%v分，满%v分可用", c.DiscountValue, c.MinSpend)
	case 2:
		return fmt.Sprintf("满%v分减%v分", c.MinSpend, c.DiscountValue)
	case 3:
		p := float64(c.DiscountValue) / 10.0
		return fmt.Sprintf("折扣%0.1f%%，满%v分可用", p, c.MinSpend)
	default:
		return ""
	}
}
