package handler

import (
	"errors"
	"net/http"

	"backend/internal/model"
	"backend/internal/service"
	"github.com/gin-gonic/gin"
)

type CDKHandler struct {
	cdks *service.CDKService
}

func NewCDKHandler(cdks *service.CDKService) *CDKHandler {
	return &CDKHandler{cdks: cdks}
}

func (h *CDKHandler) List(c *gin.Context) {
	items, stats, names, err := h.cdks.List(c.Request.Context())
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"detail": "failed to load cdks"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"data": cdkPublic(items, names), "stats": stats})
}

func (h *CDKHandler) Create(c *gin.Context) {
	var body struct {
		Amount int    `json:"amount"`
		Count  int    `json:"count"`
		Note   string `json:"note"`
		Type   string `json:"type"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"detail": "invalid request body"})
		return
	}
	items, err := h.cdks.Generate(c.Request.Context(), body.Amount, body.Count, body.Note, body.Type)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"detail": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"ok": true, "created": cdkPublic(items, nil)})
}

func (h *CDKHandler) Delete(c *gin.Context) {
	if err := h.cdks.Delete(c.Request.Context(), c.Param("code")); err != nil {
		if errors.Is(err, service.ErrNotFound) {
			c.JSON(http.StatusNotFound, gin.H{"detail": "cdk not found"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"detail": "failed to delete cdk"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"ok": true})
}

// DeleteBulk removes multiple CDK codes in one call (multi-select).
func (h *CDKHandler) DeleteBulk(c *gin.Context) {
	var body struct {
		Codes []string `json:"codes"`
	}
	if err := c.ShouldBindJSON(&body); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"detail": "invalid request body"})
		return
	}
	if len(body.Codes) == 0 {
		c.JSON(http.StatusBadRequest, gin.H{"detail": "未选择任何兑换码"})
		return
	}
	n, err := h.cdks.DeleteBulk(c.Request.Context(), body.Codes)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"detail": "failed to delete cdks"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"ok": true, "deleted": n})
}

func cdkPublic(items []model.CDKCode, nameByID map[string]string) []gin.H {
	out := make([]gin.H, 0, len(items))
	for _, item := range items {
		var redeemedByName any
		if item.RedeemedBy != nil && *item.RedeemedBy != "" {
			if name, ok := nameByID[*item.RedeemedBy]; ok {
				redeemedByName = name
			}
		}
		out = append(out, gin.H{
			"code":             item.Code,
			"amount":           item.Amount,
			"status":           item.Status,
			"type":             item.Type,
			"batch_id":         item.BatchID,
			"note":             item.Note,
			"redeemed_by":      item.RedeemedBy,
			"redeemed_by_name": redeemedByName,
			"redeemed_at":      unixSecPtr(item.RedeemedAt),
			"created_at":       unixSec(item.CreatedAt),
		})
	}
	return out
}
