package recommend

import (
	"go.uber.org/zap"

	"rmser/internal/domain/recommendations"
	"rmser/pkg/logger"
)

const (
	AnalyzeDaysNoIncoming = 90 // Ищем ингредиенты без закупок за 30 дней
	AnalyzeDaysStale      = 90 // Ищем неликвид за 60 дней
)

type Service struct {
	repo recommendations.Repository
}

func NewService(repo recommendations.Repository) *Service {
	return &Service{repo: repo}
}

// RefreshRecommendations выполняет анализ и сохраняет результаты в БД
func (s *Service) RefreshRecommendations() error {
	logger.Log.Info("Запуск пересчета рекомендаций...")

	var all []recommendations.Recommendation

	// 1. Unused
	if unused, err := s.repo.FindUnusedGoods(); err == nil {
		all = append(all, unused...)
	} else {
		logger.Log.Error("Ошибка unused", zap.Error(err))
	}

	// 2. Purchased but Unused
	if purchUnused, err := s.repo.FindPurchasedButUnused(AnalyzeDaysNoIncoming); err == nil {
		all = append(all, purchUnused...)
	} else {
		logger.Log.Error("Ошибка purchased_unused", zap.Error(err))
	}

	// 3. No Incoming (Ингредиенты без закупок)
	if noInc, err := s.repo.FindNoIncomingIngredients(AnalyzeDaysNoIncoming); err == nil {
		all = append(all, noInc...)
	} else {
		logger.Log.Error("Ошибка no_incoming", zap.Error(err))
	}

	// 4. Usage without Purchase (Расход без прихода) <-- НОВОЕ
	if usageNoPurch, err := s.repo.FindUsageWithoutPurchase(AnalyzeDaysNoIncoming); err == nil {
		all = append(all, usageNoPurch...)
	} else {
		logger.Log.Error("Ошибка usage_no_purchase", zap.Error(err))
	}

	// 5. Stale (Неликвид)
	if stale, err := s.repo.FindStaleGoods(AnalyzeDaysStale); err == nil {
		all = append(all, stale...)
	} else {
		logger.Log.Error("Ошибка stale", zap.Error(err))
	}

	// 6. Dish in Recipe
	if dishInRec, err := s.repo.FindDishesInRecipes(); err == nil {
		all = append(all, dishInRec...)
	} else {
		logger.Log.Error("Ошибка dish_in_recipe", zap.Error(err))
	}

	// Сохраняем
	if err := s.repo.SaveAll(all); err != nil {
		return err
	}

	logger.Log.Info("Рекомендации обновлены", zap.Int("total_count", len(all)))
	return nil
}

func (s *Service) GetRecommendations() ([]recommendations.Recommendation, error) {
	return s.repo.GetAll()
}
