package handler

import (
	"context"
	"net/http"
	"time"

	"git.zkcoi.com/zkcoi/meshray/internal/model"
	"git.zkcoi.com/zkcoi/meshray/internal/service"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

// NotificationHandler 通知处理器
type NotificationHandler struct {
	notificationSvc *service.NotificationService
	logger          *zap.Logger
	db              *gorm.DB
}

// NewNotificationHandler 创建通知处理器
func NewNotificationHandler(notificationSvc *service.NotificationService, logger *zap.Logger, db *gorm.DB) *NotificationHandler {
	return &NotificationHandler{
		notificationSvc: notificationSvc,
		logger:          logger,
		db:              db,
	}
}

// GetNotifications 获取用户通知列表（未读/已读）
// @Summary 获取用户通知列表
// @Tags Notifications
// @Accept json
// @Produce json
// @Param type query string false "通知类型 (all/alert/system/update)"
// @Param unread query bool false "是否仅未读"
// @Success 200 {object} map[string]interface{}
// @Router /api/v1/notifications [get]
func (h *NotificationHandler) GetNotifications(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
		return
	}

	notifType := c.Query("type")
	unreadOnly := c.Query("unread") == "true"

	query := h.notificationSvc.GetDB().Where("user_id = ?", userID)

	// 按类型筛选
	if notifType != "" && notifType != "all" {
		query = query.Where("type = ?", notifType)
	}

	// 只看未读
	if unreadOnly {
		query = query.Where("is_read = ?", false)
	}

	// 查询最近 100 条通知
	var notifications []model.Notification
	query.Order("created_at DESC").Limit(100).Find(&notifications)

	c.JSON(http.StatusOK, gin.H{
		"data": notifications,
	})
}

// MarkAsRead 标记通知为已读
// @Summary 标记通知为已读
// @Tags Notifications
// @Accept json
// @Produce json
// @Param id path uint true "通知 ID"
// @Success 200 {object} map[string]interface{}
// @Router /api/v1/notifications/:id/read [post]
func (h *NotificationHandler) MarkAsRead(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
		return
	}

	notifID := c.Param("id")
	now := time.Now()

	result := h.notificationSvc.GetDB().Model(&model.Notification{}).
		Where("id = ? AND user_id = ?", notifID, userID).
		Updates(map[string]interface{}{
			"is_read": true,
			"read_at": now,
		})

	if result.Error != nil || result.RowsAffected == 0 {
		c.JSON(http.StatusNotFound, gin.H{"error": "通知不存在"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "已标记为已读",
	})
}

// MarkAllAsRead 标记所有通知为已读
// @Summary 标记所有通知为已读
// @Tags Notifications
// @Accept json
// @Produce json
// @Success 200 {object} map[string]interface{}
// @Router /api/v1/notifications/read-all [post]
func (h *NotificationHandler) MarkAllAsRead(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
		return
	}

	now := time.Now()

	result := h.notificationSvc.GetDB().Model(&model.Notification{}).
		Where("user_id = ? AND is_read = ?", userID, false).
		Updates(map[string]interface{}{
			"is_read": true,
			"read_at": now,
		})

	c.JSON(http.StatusOK, gin.H{
		"message":  "已全部标记为已读",
		"affected": result.RowsAffected,
	})
}

// DeleteNotification 删除通知
// @Summary 删除通知
// @Tags Notifications
// @Accept json
// @Produce json
// @Param id path uint true "通知 ID"
// @Success 200 {object} map[string]interface{}
// @Router /api/v1/notifications/:id [delete]
func (h *NotificationHandler) DeleteNotification(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
		return
	}

	notifID := c.Param("id")

	result := h.notificationSvc.GetDB().Where("id = ? AND user_id = ?", notifID, userID).
		Delete(&model.Notification{})

	if result.Error != nil || result.RowsAffected == 0 {
		c.JSON(http.StatusNotFound, gin.H{"error": "通知不存在"})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"message": "通知已删除",
	})
}

// GetUnreadCount 获取未读通知数
// @Summary 获取未读通知数
// @Tags Notifications
// @Accept json
// @Produce json
// @Success 200 {object} map[string]interface{}
// @Router /api/v1/notifications/unread-count [get]
func (h *NotificationHandler) GetUnreadCount(c *gin.Context) {
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
		return
	}

	var count int64
	h.notificationSvc.GetDB().Model(&model.Notification{}).
		Where("user_id = ? AND is_read = ?", userID, false).
		Count(&count)

	c.JSON(http.StatusOK, gin.H{
		"data": gin.H{
			"count": count,
		},
	})
}

// TestSendNotification 测试发送通知（开发用）
// @Summary 测试发送通知
// @Tags Notifications
// @Accept json
// @Produce json
// @Param message body object true "通知内容"
// @Success 200 {object} map[string]interface{}
// @Router /api/v1/notifications/test [post]
func (h *NotificationHandler) TestSendNotification(c *gin.Context) {
	var req struct {
		Type    string `json:"type"`
		Title   string `json:"title"`
		Message string `json:"message"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "请求参数错误"})
		return
	}

	// 从上下文获取用户 ID
	userID, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "未认证"})
		return
	}

	// 发送测试通知
	h.notificationSvc.SendSystemNotification(userID.(uint), req.Title, req.Message)

	c.JSON(http.StatusOK, gin.H{
		"message": "测试通知已发送",
	})
}

// ClearExpiredNotifications 清理过期通知（定时任务）
func (h *NotificationHandler) ClearExpiredNotifications() {
	// 启动定期清理任务（每 24 小时清理一次超过 30 天的通知）
	go func() {
		ticker := time.NewTicker(24 * time.Hour)
		defer ticker.Stop()

		for range ticker.C {
			h.cleanupOldNotifications()
		}
	}()
	h.logger.Info("清理过期通知完成")
}

// cleanupOldNotifications 清理超过 30 天的通知记录
func (h *NotificationHandler) cleanupOldNotifications() {
	ctx := context.Background()
	cutoffTime := time.Now().AddDate(0, 0, -30)

	result := h.db.WithContext(ctx).
		Where("created_at < ?", cutoffTime).
		Delete(&model.Notification{})

	if result.Error != nil {
		h.logger.Error("清理过期通知失败", zap.Error(result.Error))
	} else {
		h.logger.Info("清理过期通知完成", zap.Int64("deleted", result.RowsAffected))
	}
}

// StartNotificationCleaner 启动通知清理定时器
func (h *NotificationHandler) StartNotificationCleaner(stopCh <-chan struct{}) {
	ticker := time.NewTicker(24 * time.Hour) // 每天执行一次
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			h.ClearExpiredNotifications()
		case <-stopCh:
			return
		}
	}
}
