package repository

import (
	"metazone.cc/metalab/internal/model"

	"gorm.io/gorm"
)

// NotificationRepo 消息/通知数据访问
type NotificationRepo struct {
	db *gorm.DB
}

// NewNotificationRepo 构造函数
func NewNotificationRepo(db *gorm.DB) *NotificationRepo {
	return &NotificationRepo{db: db}
}

// Create 创建消息
func (r *NotificationRepo) Create(n *model.Notification) error {
	return r.db.Create(n).Error
}

// ListByUser 分页查询用户消息
func (r *NotificationRepo) ListByUser(userID uint, offset, limit int) ([]model.Notification, error) {
	var list []model.Notification
	err := r.db.Where("user_id = ?", userID).
		Order("created_at DESC").
		Offset(offset).Limit(limit).
		Find(&list).Error
	return list, err
}

// CountByUser 统计用户消息总数
func (r *NotificationRepo) CountByUser(userID uint) (int64, error) {
	var count int64
	err := r.db.Model(&model.Notification{}).Where("user_id = ?", userID).Count(&count).Error
	return count, err
}

// CountUnread 统计用户未读消息数
func (r *NotificationRepo) CountUnread(userID uint) (int64, error) {
	var count int64
	err := r.db.Model(&model.Notification{}).
		Where("user_id = ? AND is_read = false", userID).
		Count(&count).Error
	return count, err
}

// MarkRead 标记单条消息为已读
func (r *NotificationRepo) MarkRead(id, userID uint) error {
	return r.db.Model(&model.Notification{}).
		Where("uid = ? AND user_id = ?", id, userID).
		Update("is_read", true).Error
}

// MarkAllRead 将用户所有未读消息标记为已读
func (r *NotificationRepo) MarkAllRead(userID uint) error {
	return r.db.Model(&model.Notification{}).
		Where("user_id = ? AND is_read = false", userID).
		Update("is_read", true).Error
}

// ListByUserAndType 按类型分页查询用户消息
func (r *NotificationRepo) ListByUserAndType(userID uint, notifyType string, offset, limit int) ([]model.Notification, error) {
	var list []model.Notification
	err := r.db.Where("user_id = ? AND notify_type = ?", userID, notifyType).
		Order("created_at DESC").
		Offset(offset).Limit(limit).
		Find(&list).Error
	return list, err
}

// CountByUserAndType 按类型统计用户消息数
func (r *NotificationRepo) CountByUserAndType(userID uint, notifyType string) (int64, error) {
	var count int64
	err := r.db.Model(&model.Notification{}).Where("user_id = ? AND notify_type = ?", userID, notifyType).Count(&count).Error
	return count, err
}

// CountUnreadByType 按类型统计用户未读消息数
func (r *NotificationRepo) CountUnreadByType(userID uint, notifyType string) (int64, error) {
	var count int64
	err := r.db.Model(&model.Notification{}).
		Where("user_id = ? AND is_read = false AND notify_type = ?", userID, notifyType).
		Count(&count).Error
	return count, err
}

// GetUnnotifiedDailyLikeSummaries 获取未通知的每日点赞汇总
func (r *NotificationRepo) GetUnnotifiedDailyLikeSummaries(userID uint) ([]model.DailyLikeSummary, error) {
	var summaries []model.DailyLikeSummary
	err := r.db.Where("author_uid = ? AND notified = ?", userID, false).Find(&summaries).Error
	return summaries, err
}

// MarkDailyLikeSummaryNotified 标记汇总已通知
func (r *NotificationRepo) MarkDailyLikeSummaryNotified(id uint) error {
	return r.db.Model(&model.DailyLikeSummary{}).Where("id = ?", id).Update("notified", true).Error
}

// GetUsernameByID 根据用户ID获取用户名
func (r *NotificationRepo) GetUsernameByID(userID uint) (string, error) {
	var user model.User
	err := r.db.Select("username").First(&user, userID).Error
	return user.Username, err
}

// GetNotifyPrefs 获取用户通知偏好（NotifyPrefs 字段原始 JSON）
func (r *NotificationRepo) GetNotifyPrefs(userID uint) (string, error) {
	var prefs string
	err := r.db.Table("users").Select("notify_prefs").Where("uid = ?", userID).Scan(&prefs).Error
	return prefs, err
}

// ListByUserExcludeTypes 分页查询用户消息（排除指定通知类型）
func (r *NotificationRepo) ListByUserExcludeTypes(userID uint, excludeTypes []string, offset, limit int) ([]model.Notification, error) {
	var list []model.Notification
	q := r.db.Where("user_id = ?", userID)
	if len(excludeTypes) > 0 {
		q = q.Where("notify_type NOT IN ?", excludeTypes)
	}
	err := q.Order("created_at DESC").Offset(offset).Limit(limit).Find(&list).Error
	return list, err
}

// CountByUserExcludeTypes 统计用户消息总数（排除指定通知类型）
func (r *NotificationRepo) CountByUserExcludeTypes(userID uint, excludeTypes []string) (int64, error) {
	var count int64
	q := r.db.Model(&model.Notification{}).Where("user_id = ?", userID)
	if len(excludeTypes) > 0 {
		q = q.Where("notify_type NOT IN ?", excludeTypes)
	}
	err := q.Count(&count).Error
	return count, err
}

// CountUnreadExcludeTypes 统计用户未读消息数（排除指定通知类型）
func (r *NotificationRepo) CountUnreadExcludeTypes(userID uint, excludeTypes []string) (int64, error) {
	var count int64
	q := r.db.Model(&model.Notification{}).Where("user_id = ? AND is_read = false", userID)
	if len(excludeTypes) > 0 {
		q = q.Where("notify_type NOT IN ?", excludeTypes)
	}
	err := q.Count(&count).Error
	return count, err
}
