package app

import (
	"net/http"
	"strconv"

	"bindbox-game/internal/code"
	"bindbox-game/internal/pkg/core"
	"bindbox-game/internal/pkg/logger"
	"bindbox-game/internal/pkg/validation"
	"bindbox-game/internal/repository/mysql"
	"bindbox-game/internal/repository/mysql/dao"
	prodsvc "bindbox-game/internal/service/product"
	usersvc "bindbox-game/internal/service/user"
)

type productHandler struct {
	logger  logger.CustomLogger
	readDB  *dao.Query
	product prodsvc.Service
	user    usersvc.Service
}

func NewProduct(logger logger.CustomLogger, db mysql.Repo, user usersvc.Service) *productHandler {
	return &productHandler{logger: logger, readDB: dao.Use(db.GetDbR()), product: prodsvc.New(logger, db), user: user}
}

type listAppProductsRequest struct {
	Page       int    `form:"page"`
	PageSize   int    `form:"page_size"`
	CategoryID *int64 `form:"category_id"`
	PriceMin   *int64 `form:"price_min"`
	PriceMax   *int64 `form:"price_max"`
	SalesMin   *int64 `form:"sales_min"`
	InStock    *bool  `form:"in_stock"`
	SortBy     string `form:"sort_by"`
	Order      string `form:"order"`
}

type listAppProductsItem struct {
	ID             int64  `json:"id"`
	Name           string `json:"name"`
	MainImage      string `json:"main_image"`
	Price          int64  `json:"price"`
	PointsRequired int64  `json:"points_required"`
	Sales          int64  `json:"sales"`
	InStock        bool   `json:"in_stock"`
}

type listAppProductsResponse struct {
	Total       int64                 `json:"total"`
	CurrentPage int                   `json:"currentPage"`
	PageSize    int                   `json:"pageSize"`
	List        []listAppProductsItem `json:"list"`
}

// ListProductsForApp 商品列表
// @Summary 商品列表
// @Description 分页查询商品列表，支持分类筛选，返回分页信息与商品数组
// @Tags APP端.商品
// @Accept json
// @Produce json
// @Security LoginVerifyToken
// @Param page query int false "页码，默认1"
// @Param page_size query int false "每页数量，默认20"
// @Param category_id query int false "分类ID"
// @Success 200 {object} listAppProductsResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/products [get]
func (h *productHandler) ListProductsForApp() core.HandlerFunc {
	return func(ctx core.Context) {
		req := new(listAppProductsRequest)
		if err := ctx.ShouldBindForm(req); err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ParamBindError, validation.Error(err)))
			return
		}
		if req.Page <= 0 {
			req.Page = 1
		}
		if req.PageSize <= 0 {
			req.PageSize = 20
		}
		items, total, err := h.product.ListForApp(ctx.RequestContext(), prodsvc.AppListInput{CategoryID: req.CategoryID, PriceMin: req.PriceMin, PriceMax: req.PriceMax, SalesMin: req.SalesMin, InStock: req.InStock, SortBy: req.SortBy, Order: req.Order, Page: req.Page, PageSize: req.PageSize})
		if err != nil {
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, validation.Error(err)))
			return
		}
		rsp := &listAppProductsResponse{Total: total, CurrentPage: req.Page, PageSize: req.PageSize, List: make([]listAppProductsItem, len(items))}
		for i, it := range items {
			pts, _ := h.user.CentsToPoints(ctx.RequestContext(), it.Price)
			rsp.List[i] = listAppProductsItem{ID: it.ID, Name: it.Name, MainImage: it.MainImage, Price: it.Price, PointsRequired: pts, Sales: it.Sales, InStock: it.InStock}
		}
		ctx.Payload(rsp)
	}
}

type getAppProductDetailResponse struct {
	ID              int64                 `json:"id"`
	Name            string                `json:"name"`
	Album           []string              `json:"album"`
	Price           int64                 `json:"price"`
	PointsRequired  int64                 `json:"points_required"`
	Sales           int64                 `json:"sales"`
	Stock           int64                 `json:"stock"`
	Description     string                `json:"description"`
	Service         []string              `json:"service"`
	Recommendations []listAppProductsItem `json:"recommendations"`
}

// GetProductDetailForApp 商品详情
// @Summary 商品详情
// @Description 根据商品ID返回完整商品信息，含相册与同类推荐；校验下架/缺货状态
// @Tags APP端.商品
// @Accept json
// @Produce json
// @Security LoginVerifyToken
// @Param id path int true "商品ID"
// @Success 200 {object} getAppProductDetailResponse
// @Failure 400 {object} code.Failure
// @Router /api/app/products/{id} [get]
func (h *productHandler) GetProductDetailForApp() core.HandlerFunc {
	return func(ctx core.Context) {
		idStr := ctx.Param("id")
		id, _ := strconv.ParseInt(idStr, 10, 64)
		d, err := h.product.GetDetailForApp(ctx.RequestContext(), id)
		if err != nil {
			if err.Error() == "PRODUCT_OFFSHELF" {
				ctx.AbortWithError(core.Error(http.StatusOK, 20001, "商品已下架"))
				return
			}
			if err.Error() == "PRODUCT_OUT_OF_STOCK" {
				ctx.AbortWithError(core.Error(http.StatusOK, 20002, "商品缺货"))
				return
			}
			ctx.AbortWithError(core.Error(http.StatusBadRequest, code.ServerError, validation.Error(err)))
			return
		}
		ptsDetail, _ := h.user.CentsToPoints(ctx.RequestContext(), d.Price)
		rsp := &getAppProductDetailResponse{ID: d.ID, Name: d.Name, Album: d.Album, Price: d.Price, PointsRequired: ptsDetail, Sales: d.Sales, Stock: d.Stock, Description: d.Description, Service: d.Service, Recommendations: make([]listAppProductsItem, len(d.Recommendations))}
		for i, it := range d.Recommendations {
			ptsRec, _ := h.user.CentsToPoints(ctx.RequestContext(), it.Price)
			rsp.Recommendations[i] = listAppProductsItem{ID: it.ID, Name: it.Name, MainImage: it.MainImage, Price: it.Price, PointsRequired: ptsRec, Sales: it.Sales, InStock: it.InStock}
		}
		ctx.Payload(rsp)
	}
}

func parseImages(s string) []string {
	var arr []string
	// lightweight JSON array parser without comments
	if s == "" {
		return arr
	}
	// naive parse: trim brackets and split by comma, remove quotes
	b := []byte(s)
	if len(b) < 2 {
		return arr
	}
	start, end := 0, len(b)
	for start < end && (b[start] == '[' || b[start] == ' ' || b[start] == '\n' || b[start] == '\t') {
		start++
	}
	for end > start && (b[end-1] == ']' || b[end-1] == ' ' || b[end-1] == '\n' || b[end-1] == '\t') {
		end--
	}
	if start >= end {
		return arr
	}
	content := string(b[start:end])
	parts := []rune(content)
	cur := ""
	inStr := false
	for _, r := range parts {
		if r == '"' {
			if inStr {
				arr = append(arr, cur)
				cur = ""
				inStr = false
			} else {
				inStr = true
			}
			continue
		}
		if inStr {
			cur += string(r)
		}
	}
	return arr
}

func parseFirstImage(s string) string {
	imgs := parseImages(s)
	if len(imgs) > 0 {
		return imgs[0]
	}
	return ""
}
