import { Injectable, Logger } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
import { CreateRequestContext } from '@mikro-orm/core';
import { EntityManager } from '@mikro-orm/postgresql';
import { OrderStatus } from '../../orders/interface/order.interface';

const COUNTED_ORDER_STATUSES = [
  OrderStatus.PAID,
  OrderStatus.PREPARING,
  OrderStatus.DELIVERED_TO_WAITER,
  OrderStatus.DELIVERED_TO_RECEPTIONIST,
  OrderStatus.SHIPPED,
  OrderStatus.COMPLETED,
];

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

  constructor(private readonly em: EntityManager) {}

  // run every day at 03:00 (3:00 AM)
  @Cron('0 3 * * *', {
    name: 'syncUserRestaurantOrderStats',
    timeZone: 'UTC',
  })
  @CreateRequestContext()
  async handleCron() {
    try {
      this.logger.debug('Starting nightly user-restaurant order stats sync');

      const statusPlaceholders = COUNTED_ORDER_STATUSES.map(() => '?').join(', ');

      await this.em.execute(
        `UPDATE user_restuarant
         SET order_count = 0, total_order_amount = 0, updated_at = now()
         WHERE deleted_at IS NULL`,
      );

      await this.em.execute(
        `
        UPDATE user_restuarant ur
        SET
          order_count = stats.order_count,
          total_order_amount = stats.total_order_amount,
          updated_at = now()
        FROM (
          SELECT
            o.user_id,
            o.restaurant_id,
            COUNT(*)::int AS order_count,
            COALESCE(SUM(o.total), 0)::int AS total_order_amount
          FROM orders o
          WHERE o.status IN (${statusPlaceholders})
            AND o.deleted_at IS NULL
          GROUP BY o.user_id, o.restaurant_id
        ) stats
        WHERE ur.user_id = stats.user_id
          AND ur.restaurant_id = stats.restaurant_id
          AND ur.deleted_at IS NULL
        `,
        COUNTED_ORDER_STATUSES,
      );

      this.logger.log('Successfully synced user-restaurant order stats');
    } catch (err) {
      this.logger.error(`UserRestaurantCrone failed: ${err?.message}`, err);
    }
  }
}
