package feetback

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

// FeedbackService интерфейс сервиса отзывов
type FeedbackService interface {
	Create(feedback *models.Feedback, AuthorID uint) error
	GetByID(id uint) (*models.Feedback, error)
	Update(id uint, AuthorID uint, updates map[string]interface{}) error
	Delete(id uint, AuthorID uint, isAdmin bool) error
	List(offset, limit int) ([]models.Feedback, int64, error)
	ListByOwner(ownerID uint, offset, limit int) ([]models.Feedback, int64, error)
	ListByObject(objectID uint, offset, limit int) ([]models.Feedback, int64, error)
	ListByPlatform(platform models.PlatformType, offset, limit int) ([]models.Feedback, int64, error)
	Search(query string, offset, limit int) ([]models.Feedback, int64, error)
	GetComments(feedbackID uint, offset, limit int) ([]models.Comment, int, error)
	AddComment(feedbackID uint, AuthorID uint, text string) (*models.Comment, error)
	UpdateComment(commentID uint, AuthorID uint, text string, isAdmin bool) error
	DeleteComment(commentID uint, AuthorID uint, isAdmin bool) error
	GetStats() (*FeedbackStatsResponse, error)
}

// FeedbackServiceImpl реализация сервиса отзывов
type FeedbackServiceImpl struct {
	feedbackRepo repository.FeedbackRepository
	db           *gorm.DB
}

// NewFeedbackServiceImpl создает новый экземпляр сервиса
func NewFeedbackServiceImpl(feedbackRepo repository.FeedbackRepository, db *gorm.DB) FeedbackService {
	return &FeedbackServiceImpl{
		feedbackRepo: feedbackRepo,
		db:           db,
	}
}

// Create создает новый отзыв
func (s *FeedbackServiceImpl) Create(feedback *models.Feedback, AuthorID uint) error {
	feedback.OwnerID = AuthorID
	feedback.CommentCount = 0

	return s.feedbackRepo.Create(feedback)
}

// GetByID возвращает отзыв по ID
func (s *FeedbackServiceImpl) GetByID(id uint) (*models.Feedback, error) {
	return s.feedbackRepo.GetByID(id)
}

// Update обновляет отзыв
func (s *FeedbackServiceImpl) Update(id uint, AuthorID uint, updates map[string]interface{}) error {
	// Получаем существующий отзыв
	feedback, err := s.feedbackRepo.GetByID(id)
	if err != nil {
		return err
	}

	// Проверяем права (только владелец может редактировать)
	if feedback.OwnerID != AuthorID {
		return errors.New("you can only update your own feedback")
	}

	// Применяем обновления
	return s.db.Model(&models.Feedback{}).Where("id = ?", id).Updates(updates).Error
}

// Delete удаляет отзыв
func (s *FeedbackServiceImpl) Delete(id uint, AuthorID uint, isAdmin bool) error {
	// Получаем существующий отзыв
	feedback, err := s.feedbackRepo.GetByID(id)
	if err != nil {
		return err
	}

	// Проверяем права (владелец или админ)
	if feedback.OwnerID != AuthorID && !isAdmin {
		return errors.New("you can only delete your own feedback")
	}

	return s.feedbackRepo.Delete(id)
}

// List возвращает список отзывов с пагинацией
func (s *FeedbackServiceImpl) List(offset, limit int) ([]models.Feedback, int64, error) {
	if limit <= 0 || limit > 100 {
		limit = 20
	}
	if offset < 0 {
		offset = 0
	}

	feedbacks, err := s.feedbackRepo.List(offset, limit)
	if err != nil {
		return nil, 0, err
	}

	total, err := s.feedbackRepo.Count()
	if err != nil {
		return nil, 0, err
	}

	return feedbacks, total, nil
}

// ListByOwner возвращает отзывы по владельцу
func (s *FeedbackServiceImpl) ListByOwner(ownerID uint, offset, limit int) ([]models.Feedback, int64, error) {
	if limit <= 0 || limit > 100 {
		limit = 20
	}
	if offset < 0 {
		offset = 0
	}

	feedbacks, err := s.feedbackRepo.ListByOwner(ownerID, offset, limit)
	if err != nil {
		return nil, 0, err
	}

	// Считаем общее количество отзывов пользователя
	var total int64
	err = s.db.Model(&models.Feedback{}).Where("owner_id = ?", ownerID).Count(&total).Error

	return feedbacks, total, err
}

// ListByObject возвращает отзывы по объекту
func (s *FeedbackServiceImpl) ListByObject(objectID uint, offset, limit int) ([]models.Feedback, int64, error) {
	if limit <= 0 || limit > 100 {
		limit = 20
	}
	if offset < 0 {
		offset = 0
	}

	feedbacks, err := s.feedbackRepo.ListByObject(objectID, offset, limit)
	if err != nil {
		return nil, 0, err
	}

	var total int64
	err = s.db.Model(&models.Feedback{}).Where("object_id = ?", objectID).Count(&total).Error

	return feedbacks, total, err
}

// ListByPlatform возвращает отзывы по платформе
func (s *FeedbackServiceImpl) ListByPlatform(platform models.PlatformType, offset, limit int) ([]models.Feedback, int64, error) {
	if limit <= 0 || limit > 100 {
		limit = 20
	}
	if offset < 0 {
		offset = 0
	}

	feedbacks, err := s.feedbackRepo.ListByPlatform(platform, offset, limit)
	if err != nil {
		return nil, 0, err
	}

	var total int64
	err = s.db.Model(&models.Feedback{}).Where("platform = ?", platform).Count(&total).Error

	return feedbacks, total, err
}

// Search ищет отзывы по тексту
func (s *FeedbackServiceImpl) Search(query string, offset, limit int) ([]models.Feedback, int64, error) {
	if limit <= 0 || limit > 100 {
		limit = 20
	}
	if offset < 0 {
		offset = 0
	}

	feedbacks, err := s.feedbackRepo.Search(query, offset, limit)
	if err != nil {
		return nil, 0, err
	}

	var total int64
	err = s.db.Model(&models.Feedback{}).Where("text LIKE ?", "%"+query+"%").Count(&total).Error

	return feedbacks, total, err
}

// GetComments возвращает комментарии к отзыву
func (s *FeedbackServiceImpl) GetComments(feedbackID uint, offset, limit int) ([]models.Comment, int, error) {
	if limit <= 0 || limit > 50 {
		limit = 20
	}
	if offset < 0 {
		offset = 0
	}

	comments, err := s.feedbackRepo.GetComments(feedbackID, offset, limit)
	if err != nil {
		return nil, 0, err
	}

	total, err := s.feedbackRepo.GetCommentCount(feedbackID)
	if err != nil {
		return nil, 0, err
	}

	return comments, total, err
}

// AddComment добавляет комментарий к отзыву
func (s *FeedbackServiceImpl) AddComment(feedbackID uint, AuthorID uint, text string) (*models.Comment, error) {
	// Проверяем существование отзыва
	_, err := s.feedbackRepo.GetByID(feedbackID)
	if err != nil {
		return nil, errors.New("feedback not found")
	}

	// Создаем комментарий
	comment := &models.Comment{
		FeedbackID: feedbackID,
		AuthorID:  AuthorID, // Используем AuthorID, а не OwnerID
		Text:       text,
	}

	err = s.db.Create(comment).Error
	if err != nil {
		return nil, err
	}

	// Загружаем аккаунт для комментария
	s.db.Preload("Account").First(comment, comment.ID)

	// Обновляем счетчик комментариев
	newCount, _ := s.feedbackRepo.GetCommentCount(feedbackID)
	s.feedbackRepo.UpdateCommentCount(feedbackID, newCount)

	return comment, nil
}

// UpdateComment обновляет комментарий
func (s *FeedbackServiceImpl) UpdateComment(commentID uint, AuthorID uint, text string, isAdmin bool) error {
	var comment models.Comment
	err := s.db.First(&comment, commentID).Error
	if err != nil {
		return err
	}

	// Проверяем права (владелец или админ)
	if comment.AuthorID != AuthorID && !isAdmin {
		return errors.New("you can only update your own comments")
	}

	return s.db.Model(&comment).Update("text", text).Error
}

// DeleteComment удаляет комментарий
func (s *FeedbackServiceImpl) DeleteComment(commentID uint, AuthorID uint, isAdmin bool) error {
	var comment models.Comment
	err := s.db.First(&comment, commentID).Error
	if err != nil {
		return err
	}

	// Проверяем права (владелец или админ)
	if comment.AuthorID != AuthorID && !isAdmin {
		return errors.New("you can only delete your own comments")
	}

	feedbackID := comment.FeedbackID

	err = s.db.Delete(&comment).Error
	if err != nil {
		return err
	}

	// Обновляем счетчик комментариев у отзыва
	newCount, _ := s.feedbackRepo.GetCommentCount(feedbackID)
	s.feedbackRepo.UpdateCommentCount(feedbackID, newCount)

	return nil
}

// GetStats возвращает статистику по отзывам
func (s *FeedbackServiceImpl) GetStats() (*FeedbackStatsResponse, error) {
	stats := &FeedbackStatsResponse{
		RatingDistribution: make(map[int]int64),
		PlatformStats:      make(map[models.PlatformType]int64),
	}

	// Общее количество
	s.db.Model(&models.Feedback{}).Count(&stats.TotalFeedbacks)

	// Средний рейтинг
	var avgRating float64
	s.db.Model(&models.Feedback{}).Select("COALESCE(AVG(rating), 0)").Row().Scan(&avgRating)
	stats.AverageRating = avgRating

	// Распределение рейтингов
	for i := 1; i <= 5; i++ {
		var count int64
		s.db.Model(&models.Feedback{}).Where("rating = ?", i).Count(&count)
		stats.RatingDistribution[i] = count
	}

	// Статистика по платформам
	platforms := []models.PlatformType{"google", "yandex", "2gis", "whatsapp", "telegram", "vk"}
	for _, platform := range platforms {
		var count int64
		s.db.Model(&models.Feedback{}).Where("platform = ?", platform).Count(&count)
		stats.PlatformStats[platform] = count
	}

	return stats, nil
}