package api

import (
	"licserver/internal/service"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

type TokenHandler struct {
	tokenService *service.TokenService
}

func NewTokenHandler(tokenService *service.TokenService) *TokenHandler {
	return &TokenHandler{tokenService: tokenService}
}

func (h *TokenHandler) CreateToken(c *gin.Context) {
	var input struct {
		DeviceUID  string   `json:"device_uid" binding:"required"`
		TokenType  string   `json:"token_type" binding:"required,oneof=api device"`
		ExpireDays int      `json:"expire_days" binding:"required,min=1"`
		IPList     []string `json:"ip_list"`
	}

	if err := c.ShouldBindJSON(&input); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	expireTime := time.Now().AddDate(0, 0, input.ExpireDays)
	userID := c.GetUint("userID")

	token, err := h.tokenService.CreateToken(
		input.DeviceUID,
		input.TokenType,
		expireTime,
		input.IPList,
		userID,
	)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, token)
}

func (h *TokenHandler) ValidateToken(c *gin.Context) {
	token := c.GetHeader("X-Access-Token")
	if token == "" {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未提供访问令牌"})
		return
	}

	clientIP := c.ClientIP()
	accessToken, err := h.tokenService.ValidateToken(token, clientIP)
	if err != nil {
		c.JSON(http.StatusUnauthorized, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, accessToken)
}

func (h *TokenHandler) RevokeToken(c *gin.Context) {
	token := c.Param("token")
	userID := c.GetUint("userID")

	if err := h.tokenService.RevokeToken(token, userID); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "令牌已撤销"})
}

func (h *TokenHandler) GetTokens(c *gin.Context) {
	deviceUID := c.Query("device_uid")
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))

	tokens, total, err := h.tokenService.GetTokens(deviceUID, page, pageSize)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "获取令牌列表成功",
		"count":   total,
		"data":    tokens,
	})
}

func (h *TokenHandler) GetTokenLogs(c *gin.Context) {
	tokenID, err := strconv.ParseUint(c.Param("id"), 10, 32)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的令牌ID"})
		return
	}

	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))

	logs, total, err := h.tokenService.GetTokenLogs(uint(tokenID), page, pageSize)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    0,
		"message": "获取令牌使用日志成功",
		"count":   total,
		"data":    logs,
	})
}
