import { Injectable, Logger } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
import { EntityManager } from '@mikro-orm/postgresql';
import { FoodRepository } from '../../foods/repositories/food.repository';
import { ReviewRepository } from '../repositories/review.repository';
import { ReviewStatus } from '../enums/review-status.enum';

@Injectable()
export class FoodRatingCronService {
  private readonly logger = new Logger(FoodRatingCronService.name);

  constructor(
    private readonly em: EntityManager,
    private readonly foodRepository: FoodRepository,
    private readonly reviewRepository: ReviewRepository,
  ) { }

  /**
   * Cron job that runs at midnight every day (00:00:00 UTC)
   * Calculates and updates the average rating for each restaurant food
   */
  @Cron('0 0 * * *', {
    name: 'calculateFoodRatings',
    timeZone: 'UTC',
  })
  async handleCron() {
    this.logger.log('Starting daily food rating calculation cron job...');

    try {
      // Get all foods from all restaurants
      const foods = await this.foodRepository.find({});

      this.logger.log(`Found ${foods.length} foods to process`);

      let updatedCount = 0;
      let errorCount = 0;

      // Process each food item
      for (const food of foods) {
        try {
          // Get all approved reviews for this food that are not deleted
          const reviews = await this.reviewRepository.find(
            {
              food: { id: food.id },
              status: ReviewStatus.APPROVED,
              deletedAt: null,
            },
            { fields: ['rating'] },
          );

          // Calculate average rating
          let averageRating = 0;
          if (reviews.length > 0) {
            const sum = reviews.reduce((acc, review) => acc + review.rating, 0);
            averageRating = sum / reviews.length;
          }

          // Update food score
          food.score = parseFloat(averageRating.toFixed(2));
          this.em.persist(food);

          updatedCount++;
        } catch (error) {
          this.logger.error(`Error processing food ${food.id}: ${error.message}`, error.stack);
          errorCount++;
        }
      }

      // Flush all updates at once for better performance
      await this.em.flush();

      this.logger.log(`Food rating calculation completed. Updated: ${updatedCount}, Errors: ${errorCount}`);
    } catch (error) {
      this.logger.error(`Error in food rating cron job: ${error.message}`, error.stack);
    }
  }
}
