package handlers

import (
	"errors"
	"net/http"
	"os"

	"github.com/gin-gonic/gin"

	"sproutgate-backend/internal/auth"
	"sproutgate-backend/internal/models"
	"sproutgate-backend/internal/storage"
)

func (h *Handler) CheckIn(c *gin.Context) {
	token := bearerToken(c.GetHeader("Authorization"))
	if token == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "missing token"})
		return
	}
	claims, err := auth.ParseToken(h.store.JWTSecret(), h.store.JWTIssuer(), token)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid token"})
		return
	}
	userPre, foundPre, err := h.store.GetUser(claims.Account)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to load user"})
		return
	}
	if !foundPre {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not found"})
		return
	}
	if abortIfUserBanned(c, userPre) {
		return
	}
	if abortIfTokenEpochStale(c, claims, userPre) {
		return
	}
	today := models.CurrentActivityDate()
	nowAt := models.CurrentActivityTime()
	user, reward, alreadyCheckedIn, err := h.store.CheckIn(claims.Account, today, nowAt)
	if err != nil {
		if errors.Is(err, os.ErrNotExist) {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "user not found"})
			return
		}
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save check-in"})
		return
	}
	checkInConfig := h.store.CheckInConfig()
	message := "签到成功"
	if alreadyCheckedIn {
		message = "今日已签到"
	}
	c.JSON(http.StatusOK, gin.H{
		"checkedIn":        !alreadyCheckedIn,
		"alreadyCheckedIn": alreadyCheckedIn,
		"rewardCoins":      h.store.CheckInConfig().RewardCoins,
		"awardedCoins":     reward,
		"message":          message,
		"user":             user.OwnerPublic(),
		"checkIn": gin.H{
			"rewardCoins":     checkInConfig.RewardCoins,
			"checkedInToday":  user.LastCheckInDate == today,
			"lastCheckInDate": user.LastCheckInDate,
			"lastCheckInAt":   user.LastCheckInAt,
			"today":           today,
		},
	})
}

func (h *Handler) GetCheckInConfig(c *gin.Context) {
	cfg := h.store.CheckInConfig()
	c.JSON(http.StatusOK, gin.H{"rewardCoins": cfg.RewardCoins})
}

func (h *Handler) UpdateCheckInConfig(c *gin.Context) {
	var req updateCheckInConfigRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	if req.RewardCoins <= 0 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "rewardCoins must be greater than 0"})
		return
	}
	if err := h.store.UpdateCheckInConfig(storage.CheckInConfig{RewardCoins: req.RewardCoins}); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save check-in config"})
		return
	}
	c.JSON(http.StatusOK, gin.H{"rewardCoins": req.RewardCoins})
}
