const path = require('node:path');

const dotenv = require('dotenv');

const deleteFile = require('../helpers/deleteFile');
const {
  ListingAddOns,
  ListingFiles,
  ListingImages,
  Listings,
  ListingSpots,
  sequelize,
} = require('../models');

dotenv.config({ path: path.join(__dirname, '../.env') });

/**
 * Finds and deletes all listings that have no associated images.
 *
 * This function performs the following operations:
 *
 * 1. Queries the database for listings with no images in the listing_images table
 * 2. For each listing found, deletes all related records in a transaction:
 *
 *    - ListingAddOns associated with the listing
 *    - ListingFiles and their physical files from storage
 *    - ListingSpots associated with the listing
 *    - ListingImages (if any exist) and their physical files
 *    - The listing itself
 *
 * All deletions are wrapped in database transactions to ensure data integrity. Physical file
 * deletions are performed asynchronously via the deleteFile helper.
 *
 * @async
 * @example
 *   // Execute the cleanup script
 *   await run();
 *   // Console output:
 *   // Finding listings with no images...
 *   // Found 3 listings with no images.
 *   // Deleting listing: Camp Site Alpha (123)
 *   // Successfully deleted listing 123
 *   // Deletion complete.
 *
 * @function run
 * @returns {Promise<void>} A promise that resolves when all deletions are complete
 * @throws {Error} If there's an error during the query or deletion process
 */
async function run() {
  try {
    console.log('Finding listings with no images...');

    const listings = await Listings.findAll({
      attributes: ['id', 'name', 'host_id'],
      where: sequelize.literal(`(
        SELECT COUNT(*)
        FROM listing_images
        WHERE listing_images.listing_id = Listings.id
      ) = 0`),
    });

    console.log(`Found ${listings.length} listings with no images.`);

    if (listings.length === 0) {
      console.log('No listings to delete.');
      return;
    }

    await Promise.all(
      listings.map(async (listing) => {
        console.log(`Deleting listing: ${listing.name} (${listing.id})`);

        await sequelize.transaction(async (transaction) => {
          // Delete AddOns
          await ListingAddOns.destroy({
            where: { listing_id: listing.id },
            transaction,
          });

          // Delete Files and their physical files
          const listingFiles = await ListingFiles.findAll({
            where: { listing_id: listing.id },
          });
          await Promise.all(
            listingFiles.map(async (file) => {
              // deleteFile is fire-and-forget in current helper implementation
              deleteFile(file.file, 'host-uploads');
              await file.destroy({ transaction });
            }),
          );

          // Delete Spots
          await ListingSpots.destroy({
            where: { listing_id: listing.id },
            transaction,
          });

          // Delete Images (Should be 0, but just in case)
          const listingImages = await ListingImages.findAll({
            where: { listing_id: listing.id },
          });
          await Promise.all(
            listingImages.map(async (img) => {
              deleteFile(img.image, 'host-uploads');
              await img.destroy({ transaction });
            }),
          );

          // Delete Listing
          await listing.destroy({ transaction });

          console.log(`Successfully deleted listing ${listing.id}`);
        });
      }),
    );

    console.log('Deletion complete.');
  } catch (error) {
    console.error('Error running script:', error);
  } finally {
    // Give some time for async fs operations to complete if any
    setTimeout(async () => {
      await sequelize.close();
    }, 1000);
  }
}

run();
