package handler

import (
	"net/http"

	"github.com/gin-gonic/gin"

	"sproutworkcollect-backend/internal/service"
)

// PublicHandler handles all publicly accessible API endpoints.
type PublicHandler struct {
	workSvc     *service.WorkService
	settingsSvc *service.SettingsService
	rateLimiter *service.RateLimiter
}

// NewPublicHandler wires up a PublicHandler with its dependencies.
func NewPublicHandler(
	workSvc *service.WorkService,
	settingsSvc *service.SettingsService,
	rateLimiter *service.RateLimiter,
) *PublicHandler {
	return &PublicHandler{
		workSvc:     workSvc,
		settingsSvc: settingsSvc,
		rateLimiter: rateLimiter,
	}
}

// GetSettings handles GET /api/settings
func (h *PublicHandler) GetSettings(c *gin.Context) {
	settings, err := h.settingsSvc.Load()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	c.JSON(http.StatusOK, settings)
}

// GetWorks handles GET /api/works
func (h *PublicHandler) GetWorks(c *gin.Context) {
	works, err := h.workSvc.LoadAllWorks()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"success": false, "message": err.Error()})
		return
	}

	responses := make([]any, len(works))
	for i, w := range works {
		responses[i] = h.workSvc.BuildResponse(w)
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"data":    responses,
		"total":   len(responses),
	})
}

// GetWorkDetail handles GET /api/works/:work_id
func (h *PublicHandler) GetWorkDetail(c *gin.Context) {
	workID := c.Param("work_id")

	work, err := h.workSvc.LoadWork(workID)
	if err != nil {
		c.JSON(http.StatusNotFound, gin.H{"success": false, "message": "作品不存在"})
		return
	}

	fp := service.Fingerprint(c.ClientIP(), c.GetHeader("User-Agent"))
	if h.rateLimiter.CanPerform(fp, "view", workID) {
		_ = h.workSvc.UpdateStats(workID, "view")
		// Reload to return the updated view count.
		if fresh, err2 := h.workSvc.LoadWork(workID); err2 == nil {
			work = fresh
		}
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"data":    h.workSvc.BuildResponse(work),
	})
}

// SearchWorks handles GET /api/search?q=...&category=...
func (h *PublicHandler) SearchWorks(c *gin.Context) {
	works, err := h.workSvc.SearchWorks(c.Query("q"), c.Query("category"))
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"success": false, "message": err.Error()})
		return
	}

	responses := make([]any, len(works))
	for i, w := range works {
		responses[i] = h.workSvc.BuildResponse(w)
	}

	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"data":    responses,
		"total":   len(responses),
	})
}

// GetCategories handles GET /api/categories
func (h *PublicHandler) GetCategories(c *gin.Context) {
	cats, err := h.workSvc.AllCategories()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"success": false, "message": err.Error()})
		return
	}
	c.JSON(http.StatusOK, gin.H{"success": true, "data": cats})
}

// LikeWork handles POST /api/like/:work_id
func (h *PublicHandler) LikeWork(c *gin.Context) {
	workID := c.Param("work_id")

	if _, err := h.workSvc.LoadWork(workID); err != nil {
		c.JSON(http.StatusNotFound, gin.H{"success": false, "message": "作品不存在"})
		return
	}

	fp := service.Fingerprint(c.ClientIP(), c.GetHeader("User-Agent"))
	if !h.rateLimiter.CanPerform(fp, "like", workID) {
		c.JSON(http.StatusTooManyRequests, gin.H{
			"success": false,
			"message": "操作太频繁，请稍后再试",
		})
		return
	}

	if err := h.workSvc.UpdateStats(workID, "like"); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"success": false, "message": "点赞失败"})
		return
	}

	work, _ := h.workSvc.LoadWork(workID)
	c.JSON(http.StatusOK, gin.H{
		"success": true,
		"message": "点赞成功",
		"likes":   work.Likes,
	})
}
