// services/personal_best_service.go
package service

import (
	"api_bb/internal/models"
	"api_bb/internal/repository"
	"fmt"
	"time"

	"gorm.io/gorm"
)

type PersonalBestService struct {
	pbRepo           repository.PersonalBestRepository
	userStatsService UserStatsService
}

func NewPersonalBestService(pbRepo repository.PersonalBestRepository, userStatsService UserStatsService) *PersonalBestService {
	return &PersonalBestService{
		pbRepo:           pbRepo,
		userStatsService: userStatsService,
	}
}

// CreatePersonalBest создает новый личный рекорд
func (s *PersonalBestService) CreatePersonalBest(userID uint, req models.PersonalBestCreateRequest) (*models.PersonalBest, error) {
	// Вычисляем темп, если не предоставлен
	pace := req.Pace
	if pace == "" {
		calculatedPace, err := s.pbRepo.CalculatePace(req.Time, req.DistanceType)
		if err != nil {
			return nil, err
		}
		pace = calculatedPace
	}

	// Проверяем, является ли это личным рекордом
	isBest, err := s.pbRepo.ExistsBetterTime(userID, req.DistanceType, req.Time)
	if err != nil {
		return nil, err
	}

	personalBest := &models.PersonalBest{
		UserID:       userID,
		DistanceType: req.DistanceType,
		Time:         req.Time,
		Pace:         pace,
		Date:         req.Date,
		EventName:    req.EventName,
		Location:     req.Location,
		Verified:     false, // По умолчанию не подтвержден
	}

	if err := s.pbRepo.Create(personalBest); err != nil {
		return nil, err
	}

	if !isBest {
		if err := s.userStatsService.UpdatePersonalBest(userID, string(req.DistanceType), req.Time); err != nil {
			// Логируем ошибку, но не прерываем выполнение
			fmt.Printf("Failed to update user stats: %v\n", err)
		}
	}

	return personalBest, nil
}

// GetPersonalBestByID возвращает личный рекорд по ID
func (s *PersonalBestService) GetPersonalBestByID(id uint) (*models.PersonalBest, error) {
	return s.pbRepo.GetByID(id)
}

// GetUserPersonalBests возвращает все личные рекорды пользователя
func (s *PersonalBestService) GetUserPersonalBests(userID uint) ([]models.PersonalBest, error) {
	return s.pbRepo.GetByUserID(userID)
}

// GetPersonalBestsByDistance возвращает личные рекорды по дистанции
func (s *PersonalBestService) GetPersonalBestsByDistance(userID uint, distanceType models.DistanceType) ([]models.PersonalBest, error) {
	return s.pbRepo.GetByUserAndDistance(userID, distanceType)
}

// GetBestByDistance возвращает лучший результат на дистанции
func (s *PersonalBestService) GetBestByDistance(userID uint, distanceType models.DistanceType) (*models.PersonalBest, error) {
	return s.pbRepo.GetBestByDistance(userID, distanceType)
}

// UpdatePersonalBest обновляет личный рекорд
func (s *PersonalBestService) UpdatePersonalBest(id uint, userID uint, req models.PersonalBestUpdateRequest) (*models.PersonalBest, error) {
	// Получаем существующий рекорд
	pb, err := s.pbRepo.GetByID(id)
	if err != nil {
		return nil, err
	}

	// Проверяем, что рекорд принадлежит пользователю
	if pb.UserID != userID {
		return nil, gorm.ErrRecordNotFound
	}

	// Обновляем поля
	if req.DistanceType != "" {
		pb.DistanceType = req.DistanceType
	}
	if req.Time != "" {
		pb.Time = req.Time
		// Пересчитываем темп при изменении времени
		if req.Pace == "" {
			calculatedPace, err := s.pbRepo.CalculatePace(req.Time, pb.DistanceType)
			if err != nil {
				return nil, err
			}
			pb.Pace = calculatedPace
		}
	}
	if req.Pace != "" {
		pb.Pace = req.Pace
	}
	if !req.Date.IsZero() {
		pb.Date = req.Date
	}
	if req.EventName != "" {
		pb.EventName = req.EventName
	}
	if req.Location != "" {
		pb.Location = req.Location
	}
	pb.Verified = req.Verified

	if err := s.pbRepo.Update(pb); err != nil {
		return nil, err
	}

	return pb, nil
}

// DeletePersonalBest удаляет личный рекорд
func (s *PersonalBestService) DeletePersonalBest(id uint, userID uint) error {
	// Проверяем, что рекорд принадлежит пользователю
	pb, err := s.pbRepo.GetByID(id)
	if err != nil {
		return err
	}

	if pb.UserID != userID {
		return gorm.ErrRecordNotFound
	}

	return s.pbRepo.Delete(id)
}

// GetVerifiedPersonalBests возвращает подтвержденные личные рекорды
func (s *PersonalBestService) GetVerifiedPersonalBests(userID uint) ([]models.PersonalBest, error) {
	return s.pbRepo.GetVerifiedByUserID(userID)
}

// GetPersonalBestsByDateRange возвращает личные рекорды за период
func (s *PersonalBestService) GetPersonalBestsByDateRange(userID uint, startDate, endDate time.Time) ([]models.PersonalBest, error) {
	return s.pbRepo.GetByDateRange(userID, startDate, endDate)
}

// GetRecentPersonalBests возвращает последние личные рекорды
func (s *PersonalBestService) GetRecentPersonalBests(userID uint, limit int) ([]models.PersonalBest, error) {
	return s.pbRepo.GetRecentPersonalBests(userID, limit)
}

// GetPersonalBestsByEvent возвращает личные рекорды по названию события
func (s *PersonalBestService) GetPersonalBestsByEvent(userID uint, eventName string) ([]models.PersonalBest, error) {
	return s.pbRepo.GetByEventName(userID, eventName)
}

// GetPersonalBestsSummary возвращает сводку лучших результатов
func (s *PersonalBestService) GetPersonalBestsSummary(userID uint) (*models.PersonalBestsSummary, error) {
	return s.pbRepo.GetPersonalBestsSummary(userID)
}

// VerifyPersonalBest подтверждает личный рекорд
func (s *PersonalBestService) VerifyPersonalBest(id uint, userID uint) error {
	pb, err := s.pbRepo.GetByID(id)
	if err != nil {
		return err
	}

	// Проверяем, что рекорд принадлежит пользователю
	if pb.UserID != userID {
		return gorm.ErrRecordNotFound
	}

	pb.Verified = true
	return s.pbRepo.Update(pb)
}

// CalculatePace вычисляет темп для времени и дистанции
func (s *PersonalBestService) CalculatePace(timeStr string, distanceType models.DistanceType) (string, error) {
	return s.pbRepo.CalculatePace(timeStr, distanceType)
}
