package handlers

import (
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"

	"mengyastore-backend/internal/models"
)

type ProductPayload struct {
	Name            string   `json:"name"`
	Price           float64  `json:"price"`
	DiscountPrice   float64  `json:"discountPrice"`
	Tags            string   `json:"tags"`
	CoverURL        string   `json:"coverUrl"`
	Codes           []string `json:"codes"`
	ScreenshotURLs  []string `json:"screenshotUrls"`
	PaymentQrURLs   []string `json:"paymentQrUrls"`
	Description     string   `json:"description"`
	Active          *bool    `json:"active"`
	RequireLogin    bool     `json:"requireLogin"`
	MaxPerAccount   int      `json:"maxPerAccount"`
	DeliveryMode    string   `json:"deliveryMode"`
	FulfillmentType string   `json:"fulfillmentType"`
	FixedContent    string   `json:"fixedContent"`
	ShowNote        bool     `json:"showNote"`
	ShowContact     bool     `json:"showContact"`
}

func normalizeFulfillmentPayload(payload *ProductPayload) string {
	ft := strings.TrimSpace(strings.ToLower(payload.FulfillmentType))
	if ft == "fixed" {
		return "fixed"
	}
	return "card"
}

type TogglePayload struct {
	Active bool `json:"active"`
}

// AdminVerifyTokenRequest 管理端校验令牌（Body，非 Header）。
type AdminVerifyTokenRequest struct {
	Token string `json:"token"`
}

// VerifyAdminToken 校验请求中的令牌是否正确。
// @Summary 校验管理员令牌
// @Description 响应为 {"valid": true/false}，不泄露真实口令。
// @Tags 管理端-认证
// @Accept json
// @Produce json
// @Param body body AdminVerifyTokenRequest true "待校验 token"
// @Success 200 {object} SwaggerValidBody
// @Router /api/admin/verify [post]
func (h *AdminHandler) VerifyAdminToken(c *gin.Context) {
	var payload AdminVerifyTokenRequest
	if err := c.ShouldBindJSON(&payload); err != nil || payload.Token == "" {
		c.JSON(http.StatusOK, gin.H{"valid": false})
		return
	}
	c.JSON(http.StatusOK, gin.H{"valid": payload.Token == h.cfg.AdminToken})
}

// ListAllProducts 管理端商品全量列表（含下架与卡密等敏感字段）。
// @Summary 全部商品（管理）
// @Tags 管理端-商品
// @Produce json
// @Security AdminToken
// @Success 200 {object} SwaggerProductListBody
// @Failure 401 {object} SwaggerErrorBody
// @Failure 500 {object} SwaggerErrorBody
// @Router /api/admin/products [get]
func (h *AdminHandler) ListAllProducts(c *gin.Context) {
	if !h.requireAdmin(c) {
		return
	}
	items, err := h.store.ListAll()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": items})
}

// CreateProduct 创建商品。
// @Summary 创建商品
// @Tags 管理端-商品
// @Accept json
// @Produce json
// @Security AdminToken
// @Param body body ProductPayload true "商品字段"
// @Success 200 {object} SwaggerProductOneBody
// @Failure 400 {object} SwaggerErrorBody
// @Failure 401 {object} SwaggerErrorBody
// @Failure 500 {object} SwaggerErrorBody
// @Router /api/admin/products [post]
func (h *AdminHandler) CreateProduct(c *gin.Context) {
	if !h.requireAdmin(c) {
		return
	}
	var payload ProductPayload
	if err := c.ShouldBindJSON(&payload); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数有误"})
		return
	}
	screenshotURLs, valid := normalizeScreenshotURLs(payload.ScreenshotURLs)
	if !valid {
		c.JSON(http.StatusBadRequest, gin.H{"error": "截图链接最多 6 条"})
		return
	}
	paymentQrURLs, valid := normalizePaymentQrURLs(payload.PaymentQrURLs)
	if !valid {
		c.JSON(http.StatusBadRequest, gin.H{"error": "萌芽收款渠道链接最多 6 条"})
		return
	}
	active := true
	if payload.Active != nil {
		active = *payload.Active
	}
	ft := normalizeFulfillmentPayload(&payload)
	if ft == "fixed" && strings.TrimSpace(payload.FixedContent) == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "固定内容发货须填写发货内容（如网盘链接、说明文字）"})
		return
	}
	dm := strings.TrimSpace(payload.DeliveryMode)
	if dm == "" {
		dm = "auto"
	}
	product := models.Product{
		Name:            payload.Name,
		Price:           payload.Price,
		DiscountPrice:   payload.DiscountPrice,
		Tags:            normalizeTags(payload.Tags),
		CoverURL:        strings.TrimSpace(payload.CoverURL),
		Codes:           payload.Codes,
		ScreenshotURLs:  screenshotURLs,
		PaymentQrURLs:   paymentQrURLs,
		Description:     payload.Description,
		Active:          active,
		RequireLogin:    payload.RequireLogin,
		MaxPerAccount:   payload.MaxPerAccount,
		DeliveryMode:    dm,
		FulfillmentType: ft,
		FixedContent:    payload.FixedContent,
		ShowNote:        payload.ShowNote,
		ShowContact:     payload.ShowContact,
	}
	created, err := h.store.Create(product)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": created})
}

// UpdateProduct 更新商品。
// @Summary 更新商品
// @Tags 管理端-商品
// @Accept json
// @Produce json
// @Security AdminToken
// @Param id path string true "商品 ID"
// @Param body body ProductPayload true "商品字段"
// @Success 200 {object} SwaggerProductOneBody
// @Failure 400 {object} SwaggerErrorBody
// @Failure 401 {object} SwaggerErrorBody
// @Failure 404 {object} SwaggerErrorBody
// @Failure 500 {object} SwaggerErrorBody
// @Router /api/admin/products/{id} [put]
func (h *AdminHandler) UpdateProduct(c *gin.Context) {
	if !h.requireAdmin(c) {
		return
	}
	id := c.Param("id")
	var payload ProductPayload
	if err := c.ShouldBindJSON(&payload); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数有误"})
		return
	}
	screenshotURLs, valid := normalizeScreenshotURLs(payload.ScreenshotURLs)
	if !valid {
		c.JSON(http.StatusBadRequest, gin.H{"error": "截图链接最多 6 条"})
		return
	}
	paymentQrURLs, valid := normalizePaymentQrURLs(payload.PaymentQrURLs)
	if !valid {
		c.JSON(http.StatusBadRequest, gin.H{"error": "萌芽收款渠道链接最多 6 条"})
		return
	}
	active := false
	if payload.Active != nil {
		active = *payload.Active
	}
	ft := normalizeFulfillmentPayload(&payload)
	if ft == "fixed" && strings.TrimSpace(payload.FixedContent) == "" {
		c.JSON(http.StatusBadRequest, gin.H{"error": "固定内容发货须填写发货内容（如网盘链接、说明文字）"})
		return
	}
	dm := strings.TrimSpace(payload.DeliveryMode)
	if dm == "" {
		dm = "auto"
	}
	patch := models.Product{
		Name:            payload.Name,
		Price:           payload.Price,
		DiscountPrice:   payload.DiscountPrice,
		Tags:            normalizeTags(payload.Tags),
		CoverURL:        strings.TrimSpace(payload.CoverURL),
		Codes:           payload.Codes,
		ScreenshotURLs:  screenshotURLs,
		PaymentQrURLs:   paymentQrURLs,
		Description:     payload.Description,
		Active:          active,
		RequireLogin:    payload.RequireLogin,
		MaxPerAccount:   payload.MaxPerAccount,
		DeliveryMode:    dm,
		FulfillmentType: ft,
		FixedContent:    payload.FixedContent,
		ShowNote:        payload.ShowNote,
		ShowContact:     payload.ShowContact,
	}
	updated, err := h.store.Update(id, patch)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": updated})
}

// ToggleProduct 上架/下架切换。
// @Summary 切换上架状态
// @Tags 管理端-商品
// @Accept json
// @Produce json
// @Security AdminToken
// @Param id path string true "商品 ID"
// @Param body body TogglePayload true "{active}"
// @Success 200 {object} SwaggerProductOneBody
// @Failure 400 {object} SwaggerErrorBody
// @Failure 401 {object} SwaggerErrorBody
// @Failure 404 {object} SwaggerErrorBody
// @Router /api/admin/products/{id}/status [patch]
func (h *AdminHandler) ToggleProduct(c *gin.Context) {
	if !h.requireAdmin(c) {
		return
	}
	id := c.Param("id")
	var payload TogglePayload
	if err := c.ShouldBindJSON(&payload); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数有误"})
		return
	}
	updated, err := h.store.Toggle(id, payload.Active)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": updated})
}

// DeleteProduct 删除商品。
// @Summary 删除商品
// @Tags 管理端-商品
// @Produce json
// @Security AdminToken
// @Param id path string true "商品 ID"
// @Success 200 {object} SwaggerBoolOKWrap
// @Failure 401 {object} SwaggerErrorBody
// @Failure 500 {object} SwaggerErrorBody
// @Router /api/admin/products/{id} [delete]
func (h *AdminHandler) DeleteProduct(c *gin.Context) {
	if !h.requireAdmin(c) {
		return
	}
	id := c.Param("id")
	if err := h.store.Delete(id); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": gin.H{"ok": true}})
}

const maxScreenshotURLsAdmin = 6
const maxPaymentQrURLsAdmin = 6

func normalizePaymentQrURLs(urls []string) ([]string, bool) {
	cleaned := make([]string, 0, len(urls))
	seen := map[string]bool{}
	for _, u := range urls {
		trimmed := strings.TrimSpace(u)
		if trimmed == "" || seen[trimmed] {
			continue
		}
		seen[trimmed] = true
		cleaned = append(cleaned, trimmed)
		if len(cleaned) > maxPaymentQrURLsAdmin {
			return nil, false
		}
	}
	return cleaned, true
}

func normalizeScreenshotURLs(urls []string) ([]string, bool) {
	cleaned := make([]string, 0, len(urls))
	for _, url := range urls {
		trimmed := strings.TrimSpace(url)
		if trimmed == "" {
			continue
		}
		cleaned = append(cleaned, trimmed)
		if len(cleaned) > maxScreenshotURLsAdmin {
			return nil, false
		}
	}
	return cleaned, true
}

func normalizeTags(tagsCSV string) []string {
	if tagsCSV == "" {
		return []string{}
	}
	parts := strings.Split(tagsCSV, ",")
	clean := make([]string, 0, len(parts))
	seen := map[string]bool{}
	for _, p := range parts {
		t := strings.TrimSpace(p)
		if t == "" {
			continue
		}
		key := strings.ToLower(t)
		if seen[key] {
			continue
		}
		seen[key] = true
		clean = append(clean, t)
		if len(clean) >= 20 {
			break
		}
	}
	return clean
}
