package service

import (
	"errors"
	"fmt"
	"regexp"
	"strings"

	"metazone.cc/metalab/internal/common"
	"metazone.cc/metalab/internal/model"

	"gorm.io/gorm"
)

var mentionPattern = regexp.MustCompile(`@(\S{1,16})`)

// CommentService 评论业务逻辑
type CommentService struct {
	repo     commentStore
	notifier commentNotifier
}

// NewCommentService 构造函数
func NewCommentService(repo commentStore, notifier commentNotifier) *CommentService {
	return &CommentService{repo: repo, notifier: notifier}
}

// CreateRoot 创建顶级评论
func (s *CommentService) CreateRoot(userID uint, postID uint, body string) (*model.Comment, error) {
	if strings.TrimSpace(body) == "" {
		return nil, common.ErrCommentEmpty
	}

	postAuthorID, err := s.repo.FindPostAuthorID(postID)
	if err != nil {
		return nil, fmt.Errorf("查询文章失败: %w", err)
	}

	comment := &model.Comment{
		PostID: postID,
		RootID: 0,
		Body:   body,
		UserID: userID,
	}
	if err := s.repo.Create(comment); err != nil {
		return nil, fmt.Errorf("创建评论失败: %w", err)
	}

	// RootID 指向自身（UPDATE 而非 INSERT）
	comment.RootID = comment.ID
	if err := s.repo.UpdateRootID(comment.ID, comment.ID); err != nil {
		return nil, fmt.Errorf("更新根评论ID失败: %w", err)
	}

	// 文章评论数+1
	_ = s.repo.IncrCommentsCount(postID)

	// 解析 @ 提及
	s.parseMentions(comment.ID, body)

	// 通知文章作者（评论者 ≠ 作者），RelatedID 存 postID 以便消息页生成跳转链接
	if s.notifier != nil && userID != postAuthorID {
		commenterName, _ := s.repo.GetUsernameByID(userID)
		if commenterName == "" {
			commenterName = "用户"
		}
		s.notifier.Create(postAuthorID, model.NotifyComment,
			"新评论",
			fmt.Sprintf("%s 评论了你的文章", commenterName),
			&comment.PostID, &comment.ID)
	}

	return comment, nil
}

// CreateReply 创建回复
func (s *CommentService) CreateReply(userID uint, parentID uint, body string) (*model.Comment, error) {
	if strings.TrimSpace(body) == "" {
		return nil, common.ErrCommentEmpty
	}

	parent, err := s.repo.FindByID(parentID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, common.ErrCommentNotFound
		}
		return nil, fmt.Errorf("查询父评论失败: %w", err)
	}

	comment := &model.Comment{
		PostID:     parent.PostID,
		RootID:     parent.RootID,
		ParentID:   &parentID,
		Body:       body,
		UserID:     userID,
		ReplyToUID: parent.UserID,
	}

	if err := s.repo.Create(comment); err != nil {
		return nil, fmt.Errorf("创建回复失败: %w", err)
	}

	// 文章评论数+1
	_ = s.repo.IncrCommentsCount(parent.PostID)

	// 解析 @ 提及
	s.parseMentions(comment.ID, body)

	// 通知被回复者（不自己回复自己），RelatedID 存 postID 以便消息页生成跳转链接
	if s.notifier != nil && parent.UserID != userID {
		commenterName, _ := s.repo.GetUsernameByID(userID)
		if commenterName == "" {
			commenterName = "用户"
		}
		s.notifier.Create(parent.UserID, model.NotifyCommentReply,
			"新回复",
			fmt.Sprintf("%s 回复了你的评论", commenterName),
			&parent.PostID, &comment.ID)
	}

	return comment, nil
}

// Delete 软删除评论（requesterID 为请求者，isAdmin 表示是否为管理员）
func (s *CommentService) Delete(commentID uint, requesterID uint, isAdmin bool) error {
	comment, err := s.repo.FindByID(commentID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return common.ErrCommentNotFound
		}
		return fmt.Errorf("查询评论失败: %w", err)
	}

	if comment.IsDeleted {
		return nil
	}

	// 权限检查：仅本人或管理员可删除
	if !isAdmin && comment.UserID != requesterID {
		return common.ErrPermissionDenied
	}

	if err := s.repo.SoftDelete(commentID); err != nil {
		return fmt.Errorf("删除评论失败: %w", err)
	}

	_ = s.repo.DecrCommentsCount(comment.PostID)
	return nil
}

// ListRootComments 分页获取文章顶级评论
func (s *CommentService) ListRootComments(postID uint, page, pageSize int) ([]model.Comment, int64, error) {
	p := common.Pagination{Page: page, PageSize: pageSize}
	p.DefaultPagination()
	return s.repo.FindRootComments(postID, p.Offset(), p.PageSize)
}

// ListReplies 获取某条顶级评论的全部回复
func (s *CommentService) ListReplies(rootID uint) ([]model.Comment, error) {
	list, err := s.repo.FindReplies(rootID)
	if err != nil {
		return nil, fmt.Errorf("查询回复失败: %w", err)
	}
	if list == nil {
		list = []model.Comment{}
	}
	return list, nil
}

// ListAllComments 后台评论列表（分页+搜索）
func (s *CommentService) ListAllComments(keyword string, showDeleted bool, page, pageSize int) ([]model.AdminCommentRow, int64, error) {
	p := common.Pagination{Page: page, PageSize: pageSize}
	p.DefaultPagination()
	rows, total, err := s.repo.ListAllComments(keyword, showDeleted, p.Offset(), p.PageSize)
	if rows == nil {
		rows = []model.AdminCommentRow{}
	}
	return rows, total, err
}

// SearchUsers 搜索LV3+用户（用于@艾特）
func (s *CommentService) SearchUsers(keyword string) ([]model.UserSearchResult, error) {
	rows, err := s.repo.SearchUsersByLevel(keyword, 3, 10)
	if err != nil {
		return nil, fmt.Errorf("搜索用户失败: %w", err)
	}

	users := make([]model.UserSearchResult, len(rows))
	for i, row := range rows {
		users[i] = model.UserSearchResult{
			UID:      row.UID,
			Username: row.Username,
			Level:    model.GetLevelByExp(row.Exp),
		}
	}
	return users, nil
}

// parseMentions 解析@用户并存储到 comment_mentions 表
func (s *CommentService) parseMentions(commentID uint, body string) {
	matches := mentionPattern.FindAllStringSubmatch(body, -1)
	seen := make(map[string]bool)
	for _, m := range matches {
		username := m[1]
		if seen[username] {
			continue
		}
		seen[username] = true
		rows, _ := s.repo.SearchUsersByLevel(username, 0, 1)
		if len(rows) > 0 {
			_ = s.repo.CreateMention(&model.CommentMention{
				CommentID: commentID,
				UID:       rows[0].UID,
			})
		}
	}
}
