package repository

import (
	"api_yal/internal/models"
	"gorm.io/gorm"
)

// commentRepositoryImpl реализация интерфейса CommentRepository
type commentRepositoryImpl struct {
	db *gorm.DB
}

// NewCommentRepository создает новый экземпляр репозитория комментариев
func NewCommentRepository(db *gorm.DB) CommentRepository {
	return &commentRepositoryImpl{db: db}
}

// Create создает новый комментарий
func (r *commentRepositoryImpl) Create(comment *models.Comment) error {
	return r.db.Create(comment).Error
}

// GetByID возвращает комментарий по ID
func (r *commentRepositoryImpl) GetByID(id uint) (*models.Comment, error) {
	var comment models.Comment
	err := r.db.Preload("Author").Preload("Feedback").Preload("Parent").Preload("Replies").First(&comment, id).Error
	if err != nil {
		return nil, err
	}
	return &comment, nil
}

// Update обновляет существующий комментарий
func (r *commentRepositoryImpl) Update(comment *models.Comment) error {
	return r.db.Save(comment).Error
}

// Delete помечает комментарий как удаленный
func (r *commentRepositoryImpl) Delete(id uint) error {
	return r.db.Delete(&models.Comment{}, id).Error
}

// List возвращает список комментариев с пагинацией
func (r *commentRepositoryImpl) List(offset, limit int) ([]models.Comment, error) {
	var comments []models.Comment
	err := r.db.Preload("Author").Preload("Feedback").Offset(offset).Limit(limit).Find(&comments).Error
	if err != nil {
		return nil, err
	}
	return comments, nil
}

// Count возвращает общее количество комментариев
func (r *commentRepositoryImpl) Count() (int64, error) {
	var count int64
	err := r.db.Model(&models.Comment{}).Count(&count).Error
	return count, err
}

// ListByFeedback возвращает комментарии по отзыву
func (r *commentRepositoryImpl) ListByFeedback(feedbackID uint, offset, limit int) ([]models.Comment, error) {
	var comments []models.Comment
	err := r.db.Preload("Author").Where("feedback_id = ?", feedbackID).Order("created_at asc").Offset(offset).Limit(limit).Find(&comments).Error
	if err != nil {
		return nil, err
	}
	return comments, nil
}

// ListByAuthor возвращает комментарии по автору
func (r *commentRepositoryImpl) ListByAuthor(authorID uint, offset, limit int) ([]models.Comment, error) {
	var comments []models.Comment
	err := r.db.Preload("Feedback").Where("author_id = ?", authorID).Order("created_at desc").Offset(offset).Limit(limit).Find(&comments).Error
	if err != nil {
		return nil, err
	}
	return comments, nil
}

// ListReplies возвращает ответы на комментарий
func (r *commentRepositoryImpl) ListReplies(parentID uint, offset, limit int) ([]models.Comment, error) {
	var replies []models.Comment
	err := r.db.Preload("Author").Where("parent_id = ?", parentID).Order("created_at asc").Offset(offset).Limit(limit).Find(&replies).Error
	if err != nil {
		return nil, err
	}
	return replies, nil
}

// GetAuthor возвращает автора комментария
func (r *commentRepositoryImpl) GetAuthor(commentID uint) (*models.Account, error) {
	var comment models.Comment
	err := r.db.Select("author_id").First(&comment, commentID).Error
	if err != nil {
		return nil, err
	}
	return r.getAccountByID(comment.AuthorID)
}

// GetFeedback возвращает отзыв, к которому относится комментарий
func (r *commentRepositoryImpl) GetFeedback(commentID uint) (*models.Feedback, error) {
	var comment models.Comment
	err := r.db.Select("feedback_id").First(&comment, commentID).Error
	if err != nil {
		return nil, err
	}
	return r.getFeedbackByID(comment.FeedbackID)
}

// GetParent возвращает родительский комментарий
func (r *commentRepositoryImpl) GetParent(commentID uint) (*models.Comment, error) {
	var comment models.Comment
	err := r.db.Select("parent_id").First(&comment, commentID).Error
	if err != nil {
		return nil, err
	}
	if comment.ParentID == nil {
		return nil, nil // No parent
	}
	return r.GetByID(*comment.ParentID)
}

// GetRepliesCount возвращает количество ответов на комментарий
func (r *commentRepositoryImpl) GetRepliesCount(commentID uint) (int64, error) {
	var count int64
	err := r.db.Model(&models.Comment{}).Where("parent_id = ?", commentID).Count(&count).Error
	return count, err
}

// MarkAsEdited помечает комментарий как отредактированный
func (r *commentRepositoryImpl) MarkAsEdited(id uint) error {
	return r.db.Model(&models.Comment{}).Where("id = ?", id).Update("is_edited", true).Error
}

// ToggleVerification переключает статус верификации комментария
func (r *commentRepositoryImpl) ToggleVerification(id uint, verified bool) error {
	return r.db.Model(&models.Comment{}).Where("id = ?", id).Update("is_verified", verified).Error
}

// Вспомогательные методы для получения связанных сущностей
func (r *commentRepositoryImpl) getAccountByID(id uint) (*models.Account, error) {
	var account models.Account
	err := r.db.First(&account, id).Error
	if err != nil {
		return nil, err
	}
	return &account, nil
}

func (r *commentRepositoryImpl) getFeedbackByID(id uint) (*models.Feedback, error) {
	var feedback models.Feedback
	err := r.db.First(&feedback, id).Error
	if err != nil {
		return nil, err
	}
	return &feedback, nil
}