package repository

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

	"gorm.io/gorm"
)

// CommentRepo 评论数据访问
type CommentRepo struct {
	db *gorm.DB
}

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

// Create 创建评论
func (r *CommentRepo) Create(comment *model.Comment) error {
	return r.db.Create(comment).Error
}

// FindByID 按 ID 查找评论（含作者信息）
func (r *CommentRepo) FindByID(id uint) (*model.Comment, error) {
	var c model.Comment
	err := r.db.Table("comments").
		Select("comments.*, users.username as author_name, users.avatar as author_avatar").
		Joins("LEFT JOIN users ON users.uid = comments.user_id").
		Where("comments.id = ?", id).
		First(&c).Error
	if err != nil {
		return nil, err
	}
	return &c, nil
}

// FindRootComments 分页查询文章的顶级评论（parent_id IS NULL，未删除）
func (r *CommentRepo) FindRootComments(postID uint, offset, limit int) ([]model.Comment, int64, error) {
	var total int64
	base := r.db.Table("comments").
		Where("post_id = ? AND parent_id IS NULL AND is_deleted = false", postID)

	if err := base.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	var list []model.Comment
	err := base.
		Select("comments.*, users.username as author_name, users.avatar as author_avatar").
		Joins("LEFT JOIN users ON users.uid = comments.user_id").
		Order("comments.created_at DESC").
		Offset(offset).Limit(limit).
		Find(&list).Error
	if err != nil {
		return nil, 0, err
	}

	// 为每条顶级评论填充回复数
	if len(list) > 0 {
		ids := make([]uint, len(list))
		for i, c := range list {
			ids[i] = c.ID
		}
		countMap := r.batchCountReplies(ids)
		for i := range list {
			list[i].RepliesCount = countMap[list[i].ID]
		}
	}

	return list, total, nil
}

// FindReplies 查询某条顶级评论的所有回复（不分页，全量返回，未删除）
func (r *CommentRepo) FindReplies(rootID uint) ([]model.Comment, error) {
	var list []model.Comment
	err := r.db.Table("comments").
		Select("comments.*, users.username as author_name, users.avatar as author_avatar").
		Joins("LEFT JOIN users ON users.uid = comments.user_id").
		Where("comments.root_id = ? AND comments.parent_id IS NOT NULL AND comments.is_deleted = false", rootID).
		Order("comments.created_at ASC").
		Find(&list).Error
	if err != nil {
		return nil, err
	}

	// 填充 reply_to_name
	r.fillReplyToNames(list)

	return list, nil
}

// fillReplyToNames 通过 JOIN users 获取被回复者当前显示名
func (r *CommentRepo) fillReplyToNames(list []model.Comment) {
	if len(list) == 0 {
		return
	}
	type nameRow struct {
		UID      string
		Username string
	}
	var rows []nameRow
	r.db.Table("users").
		Select("uid, username").
		Where("uid IN (SELECT reply_to_uid FROM comments WHERE root_id IN (?) AND parent_id IS NOT NULL)", r.rootIDsFromList(list)).
		Find(&rows)

	m := make(map[string]string)
	for _, row := range rows {
		m[row.UID] = row.Username
	}
	for i := range list {
		if list[i].ReplyToUID != "" {
			list[i].ReplyToName = m[list[i].ReplyToUID]
		}
	}
}

func (r *CommentRepo) rootIDsFromList(list []model.Comment) []uint {
	ids := make([]uint, len(list))
	for i, c := range list {
		ids[i] = c.RootID
	}
	return ids
}

// batchCountReplies 批量统计回复数
func (r *CommentRepo) batchCountReplies(rootIDs []uint) map[uint]int {
	type countRow struct {
		RootID uint
		Count  int
	}
	var rows []countRow
	r.db.Table("comments").
		Select("root_id, COUNT(*) as count").
		Where("root_id IN ? AND parent_id IS NOT NULL AND is_deleted = false", rootIDs).
		Group("root_id").
		Find(&rows)

	m := make(map[uint]int)
	for _, row := range rows {
		m[row.RootID] = row.Count
	}
	return m
}

// SoftDelete 软删除评论（设置 is_deleted=true）
func (r *CommentRepo) SoftDelete(id uint) error {
	return r.db.Model(&model.Comment{}).Where("id = ?", id).Update("is_deleted", true).Error
}

// IncrCommentsCount 文章评论数+1
func (r *CommentRepo) IncrCommentsCount(postID uint) error {
	return r.db.Model(&model.Post{}).Where("id = ?", postID).
		UpdateColumn("comments_count", gorm.Expr("comments_count + 1")).Error
}

// DecrCommentsCount 文章评论数-1
func (r *CommentRepo) DecrCommentsCount(postID uint) error {
	return r.db.Model(&model.Post{}).Where("id = ?", postID).
		UpdateColumn("comments_count", gorm.Expr("GREATEST(comments_count - 1, 0)")).Error
}

// CountRepliesByRootByStatus 统计某条顶级评论的回复数（可选是否统计已删除）
func (r *CommentRepo) CountRepliesByRoot(rootID uint, includeDeleted bool) (int, error) {
	var count int64
	q := r.db.Model(&model.Comment{}).Where("root_id = ? AND parent_id IS NOT NULL", rootID)
	if !includeDeleted {
		q = q.Where("is_deleted = false")
	}
	err := q.Count(&count).Error
	return int(count), err
}

// CreateMention 创建@提及记录
func (r *CommentRepo) CreateMention(mention *model.CommentMention) error {
	return r.db.Create(mention).Error
}

// FindMentionsByComment 查询某条评论的@提及列表
func (r *CommentRepo) FindMentionsByComment(commentID uint) ([]model.CommentMention, error) {
	var list []model.CommentMention
	err := r.db.Where("comment_id = ?", commentID).Find(&list).Error
	return list, err
}

// SearchUsersByLevel 搜索指定等级及以上用户（用于@艾特），返回 uid/username/exp
func (r *CommentRepo) SearchUsersByLevel(keyword string, minLevel int, limit int) ([]struct {
	UID      string
	Username string
	Exp      int
}, error) {
	type result struct {
		UID      uint
		Username string
		Exp      int
	}
	var list []result

	threshold := model.LevelThresholds[minLevel]

	err := r.db.Table("users").
		Select("uid, username, exp").
		Where("username LIKE ? AND exp >= ? AND deleted_at IS NULL", "%"+keyword+"%", threshold).
		Order("exp DESC").
		Limit(limit).
		Find(&list).Error

	var res []struct {
		UID      string
		Username string
		Exp      int
	}
	for _, u := range list {
		res = append(res, struct {
			UID      string
			Username string
			Exp      int
		}{UID: strconv.FormatUint(uint64(u.UID), 10), Username: u.Username, Exp: u.Exp})
	}
	return res, err
}

// GetUserUIDByID 通过 uint ID 获取 user 的 UID 字符串
func (r *CommentRepo) GetUserUIDByID(userID uint) (string, error) {
	var uid uint
	err := r.db.Table("users").Select("uid").Where("uid = ?", userID).Scan(&uid).Error
	if err != nil {
		return "", err
	}
	return strconv.FormatUint(uint64(uid), 10), nil
}

// GetUsernameByID 通过 userID 获取用户名（用于通知内容）
func (r *CommentRepo) GetUsernameByID(userID uint) (string, error) {
	var username string
	err := r.db.Table("users").Select("username").Where("uid = ?", userID).Scan(&username).Error
	return username, err
}

// FindPostIDByComment 查询评论所属的文章ID
func (r *CommentRepo) FindPostIDByComment(commentID uint) (uint, error) {
	var postID uint
	err := r.db.Table("comments").Select("post_id").Where("id = ?", commentID).Scan(&postID).Error
	return postID, err
}

// UpdateRootID 更新评论的 root_id 字段（顶级评论创建后回填）
func (r *CommentRepo) UpdateRootID(id, rootID uint) error {
	return r.db.Model(&model.Comment{}).Where("id = ?", id).Update("root_id", rootID).Error
}

// FindPostAuthorID 查询文章的作者 user_id
func (r *CommentRepo) FindPostAuthorID(postID uint) (uint, error) {
	var authorID uint
	err := r.db.Table("posts").Select("user_id").Where("id = ?", postID).Scan(&authorID).Error
	return authorID, err
}

// ListAllComments 后台评论列表（支持关键词搜索、分页）
func (r *CommentRepo) ListAllComments(keyword string, showDeleted bool, offset, limit int) ([]model.AdminCommentRow, int64, error) {
	var total int64
	q := r.db.Table("comments").
		Joins("LEFT JOIN users ON users.uid = comments.user_id").
		Joins("LEFT JOIN posts ON posts.id = comments.post_id")

	if !showDeleted {
		q = q.Where("comments.is_deleted = false")
	}
	if keyword != "" {
		like := "%" + keyword + "%"
		q = q.Where("comments.body LIKE ? OR users.username LIKE ? OR posts.title LIKE ?", like, like, like)
	}

	if err := q.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	var rows []model.AdminCommentRow
	err := q.
		Select("comments.id, comments.post_id, posts.title as post_title, comments.body, users.username as author_name, comments.is_deleted, comments.created_at, comments.updated_at").
		Order("comments.created_at DESC").
		Offset(offset).Limit(limit).
		Scan(&rows).Error
	return rows, total, err
}
