import type { EntityManager } from '@mikro-orm/core';
import { Seeder } from '@mikro-orm/seeder';
import { Restaurant } from '../modules/restaurants/entities/restaurant.entity';
import { PermissionsSeeder } from './permissions.seeder';
import { RolesSeeder } from './roles.seeder';
import { RestaurantsSeeder } from './restaurants.seeder';
import { PaymentMethodsSeeder } from './payment-methods.seeder';
import { DeliveryMethodsSeeder } from './delivery-methods.seeder';
import { SchedulesSeeder } from './schedules.seeder';
import { CategoriesSeeder } from './categories.seeder';
import { FoodsSeeder } from './foods.seeder';
import { AdminsSeeder } from './admins.seeder';
import { UsersSeeder } from './users.seeder';
import { CouponsSeeder } from './coupons.seeder';
import { NotificationPreferencesSeeder } from './notification-preferences.seeder';
import { UserWalletsSeeder } from './user-wallets.seeder';
import { InventorySeeder } from './inventory.seeder';
// import { NotificationsSeeder } from './notifications.seeder';

export class DatabaseSeeder extends Seeder {
  async run(em: EntityManager) {
    const TOTAL_STEPS = 15;
    console.info('[Seeder] Starting database seed');
    // 1. Create Permissions
    console.info(`[Seeder] Step 1/${TOTAL_STEPS}: Creating permissions`);
    const permissionsSeeder = new PermissionsSeeder();
    const permissions = await permissionsSeeder.run(em);
    console.info(`[Seeder] Step 1/${TOTAL_STEPS}: Done`);

    // 2. Create Roles
    console.info(`[Seeder] Step 2/${TOTAL_STEPS}: Creating roles`);
    const rolesSeeder = new RolesSeeder();
    const rolesMap = await rolesSeeder.run(em, permissions);
    console.info(`[Seeder] Step 2/${TOTAL_STEPS}: Done`);

    // 3. Create Restaurants
    console.info(`[Seeder] Step 3/${TOTAL_STEPS}: Creating restaurants`);
    const restaurantsSeeder = new RestaurantsSeeder();
    const restaurantsMap = await restaurantsSeeder.run(em);
    console.info(`[Seeder] Step 3/${TOTAL_STEPS}: Done`);

    // 4. Create Payment Methods for all Restaurants
    console.info(`[Seeder] Step 4/${TOTAL_STEPS}: Creating payment methods`);
    const allRestaurants = await em.find(Restaurant, {});
    const paymentMethodsSeeder = new PaymentMethodsSeeder();
    await paymentMethodsSeeder.run(em, allRestaurants);
    console.info(`[Seeder] Step 4/${TOTAL_STEPS}: Done`);

    // 5. Create Delivery Methods for all Restaurants
    console.info(`[Seeder] Step 5/${TOTAL_STEPS}: Creating delivery methods`);
    const deliveryMethodsSeeder = new DeliveryMethodsSeeder();
    await deliveryMethodsSeeder.run(em, allRestaurants);
    console.info(`[Seeder] Step 5/${TOTAL_STEPS}: Done`);

    // 6. Create Schedules for all Restaurants
    console.info(`[Seeder] Step 6/${TOTAL_STEPS}: Creating schedules`);
    const schedulesSeeder = new SchedulesSeeder();
    await schedulesSeeder.run(em, allRestaurants);
    console.info(`[Seeder] Step 6/${TOTAL_STEPS}: Done`);

    // 7. Create Notification Preferences for all Restaurants
    console.info(`[Seeder] Step 7/${TOTAL_STEPS}: Creating notification preferences`);
    const notificationPreferencesSeeder = new NotificationPreferencesSeeder();
    await notificationPreferencesSeeder.run(em, allRestaurants);
    console.info(`[Seeder] Step 7/${TOTAL_STEPS}: Done`);

    // 8. Create Categories
    console.info(`[Seeder] Step 8/${TOTAL_STEPS}: Creating categories`);
    const categoriesSeeder = new CategoriesSeeder();
    const categoriesMap = await categoriesSeeder.run(em, restaurantsMap);
    console.info(`[Seeder] Step 8/${TOTAL_STEPS}: Done`);

    // 9. Create Foods
    console.info(`[Seeder] Step 9/${TOTAL_STEPS}: Creating foods`);
    const foodsSeeder = new FoodsSeeder();
    await foodsSeeder.run(em, restaurantsMap, categoriesMap);
    console.info(`[Seeder] Step 9/${TOTAL_STEPS}: Done`);

    // 10. Create Inventory for all Foods
    console.info(`[Seeder] Step 10/${TOTAL_STEPS}: Creating inventory`);
    const inventorySeeder = new InventorySeeder();
    await inventorySeeder.run(em);
    console.info(`[Seeder] Step 10/${TOTAL_STEPS}: Done`);

    // 11. Create Coupons
    console.info(`[Seeder] Step 11/${TOTAL_STEPS}: Creating coupons`);
    const couponsSeeder = new CouponsSeeder();
    await couponsSeeder.run(em, restaurantsMap);
    console.info(`[Seeder] Step 11/${TOTAL_STEPS}: Done`);

    // 12. Create Admins
    console.info(`[Seeder] Step 12/${TOTAL_STEPS}: Creating admins`);
    const adminsSeeder = new AdminsSeeder();
    await adminsSeeder.run(em, rolesMap, restaurantsMap);
    console.info(`[Seeder] Step 12/${TOTAL_STEPS}: Done`);

    // 13. Create Users
    console.info(`[Seeder] Step 13/${TOTAL_STEPS}: Creating users`);
    const usersSeeder = new UsersSeeder();
    await usersSeeder.run(em);
    console.info(`[Seeder] Step 13/${TOTAL_STEPS}: Done`);

    // 14. Create User Wallets
    console.info(`[Seeder] Step 14/${TOTAL_STEPS}: Creating user wallets`);
    const userWalletsSeeder = new UserWalletsSeeder();
    await userWalletsSeeder.run(em);
    console.info(`[Seeder] Step 14/${TOTAL_STEPS}: Done`);

    // 15. Create Notifications for admins and users for all restaurants
    console.info(`[Seeder] Step 15/${TOTAL_STEPS}: (optional) creating notifications`);
    // const notificationsSeeder = new NotificationsSeeder();
    // await notificationsSeeder.run(em);
    console.info(`[Seeder] Step 15/${TOTAL_STEPS}: Done`);

    console.info('[Seeder] Database seed completed');
  }
}
