const fs = require('fs');
const path = require('path');
const csvParser = require('csv-parser');
const koillectionBaseUrl = 'https://koillection.nelson-household.com/api'; // Verify this URL
const authenticationUrl = `${koillectionBaseUrl}/authentication_token`; // URL to obtain JWT
const imagesDir = path.join(__dirname, 'master-set-images/perfect-order'); // Use __dirname for correct path

// Define mapping of collection names to their corresponding CSV files
const collectionsMapping = {
  'Perfect Order': './csv/ME03PerfectOrderProductsAndPrices.csv',
};

const createJWTToken = async (username, password) => {
  try {
    const response = await fetch(authenticationUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ username, password }),
    });
    if (!response.ok) {
      throw new Error(`Failed to obtain JWT token: ${response.status} - ${response.statusText}`);
    }
    const data = await response.json();
    console.log(`JWT Token obtained: ${data.token}`);
    return data.token;
  } catch (error) {
    console.error(`Error obtaining JWT token:`, error);
    throw error; // Re-throw to be caught in other functions
  }
};
const createCollectionIfNotExists = async (name, parentCollectionId, token) => {
  try {
    const url = `${koillectionBaseUrl}/collections`;
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ title: name, visibility: 'public', parent: `/api/collections/${parentCollectionId}` }),
    });
    if (!response.ok) {
      throw new Error(`Failed to create collection "${name}": ${response.status} - ${response.statusText} - ${JSON.stringify(await response.json())}`);
    }
    const data = await response.json();
    console.log(`Successfully created collection "${name}" with ID: ${data.id}`);
    return data.id;
  } catch (error) {
    console.error(`Error creating collection ${name} from CSV:`, error);
    throw error;
  }
};
const createItem = async (payload, token) => {
  try {
    const response = await fetch(`${koillectionBaseUrl}/items`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(payload),
    });

    if (!response.ok) {
      throw new Error(`Failed to create item: ${response.status} - ${await response.text()}`);
    }

    const createdItem = await response.json();
    return createdItem;
  } catch (error) {
    console.error('Error creating item:', error);
    throw error;
  }
};
async function downloadTcgImage(productId, imageUrl) {
  try {
    // 1. Ensure directory exists
    if (!fs.existsSync(imagesDir)) {
      fs.mkdirSync(imagesDir, { recursive: true });
    }
    // 2. Construct file destination
    const filename = `${productId}_${path.basename(new URL(imageUrl).pathname)}`;
    const dest = path.join(imagesDir, filename);
    // 3. Fetch the image
    const response = await fetch(imageUrl);
    if (!response.ok) {
      console.error(`Failed to fetch ${imageUrl}: ${response.statusText}`);
      return {};
    }
    const arrayBuffer = await response.arrayBuffer();
    const buffer = Buffer.from(arrayBuffer);
    fs.writeFileSync(dest, buffer); // Use the correct destination path
    console.log(`Successfully saved: ${dest}`);
    return { success: true, destination: dest };
  } catch (error) {
    console.error('Error downloading image:', error);
    return {};
  }
}
const applyImageToItem = async (itemId, localImagePath, fileName, token) => {
  try {
    console.log(`Local Image Path: ${localImagePath}`);

    if (!fs.existsSync(localImagePath)) {
      console.log('Looks like the image does not exists?');
      return {};
    }

    const formData = new FormData();
    formData.append('image', fs.readFileSync(path.join(localImagePath, fileName)), filename);
    const response = await fetch(`${koillectionBaseUrl}/items/${itemId}/image`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${token}`,
      },
      body: formData
    });

    if (!response.ok) {
      const errorData = await response.json();
      throw new Error(`HTTP error! Status: ${response.status}, Error: ${JSON.stringify(errorData)}`);
    }

    const data = await response.json();
    console.log(`Returned item with image: ${JSON.stringify(data, null, 2)}`);
    return data; // Returns the item with the new image
  } catch (error) {
    console.error('Error applying image:', error);
    throw error; // Re-throw for handling in the caller
  }
};
const parseCsv = async (collectionId, csvFilePath, token) => {
  try {
    const rows = [];
    const results = {};
    const stream = fs.createReadStream(csvFilePath)
      .pipe(csvParser()); // Now using the stream directly

    return await new Promise((resolve, reject) => {
      stream.on('data', (row) => rows.push(row));
      stream.on('end', async () => {
        try {
          const processingPromises = rows.map(async (row) => {
            const payload = {
              name: row.name,
              collection: `/api/collections/${collectionId}`,
              visibility: 'public',
            };
            const createdItem = await createItem(payload, token);
            console.log(`Created item: ${createdItem.name}`);
            //const imageUrl = await downloadTcgImage(itemId, row.imageUrl); // Await the image download
            results[row.productId] = { imageUrl: row.imageUrl, itemId: createdItem.id };
          });

          await Promise.all(processingPromises);

          resolve(results);
        } catch (err) {
          reject(err);
        }
      });

      stream.on('error', (err) => reject(err));
    });
  } catch (error) {
    console.error(`Error creating collection ${name} from CSV:`, error);
    return {};
  }
}
function mergeObjects(o1, o2) {
  const merged = { ...o1 };

  for (const key in o2) {
    if (merged[key]) {
      // Key exists, convert itemId to itemIds array
      const existing = merged[key];
      const incoming = o2[key];
      
      // Keep existing itemId if it's already an array, otherwise make it one
      const items = Array.isArray(existing.itemIds) ? existing.itemIds : [existing.itemId];
      items.push(incoming.itemId);

      merged[key] = {
        ...existing,
        ...incoming,
        itemIds: items,
        itemId: undefined // Remove old field
      };
      // Optionally cleanup undefined
      delete merged[key].itemId;
    } else {
      // Key is new, add as is
      merged[key] = o2[key];
    }
  }
  return merged;
}
const createCollectionFromCSV = async (name, csvFilePath) => {
  const token = await createJWTToken('bigassdragon', 'd7Bis4Y4EUhfMf');
  const joeCollectionId = await createCollectionIfNotExists(name, '019dc310-a130-799e-8c0d-db90774b7b77', token);
  const tylerCollectionId = await createCollectionIfNotExists(name, '019dc310-d175-7e59-b465-c8e684ee7186', token);
  const joeCollectionData = await parseCsv(joeCollectionId, csvFilePath, token).then((results) => results);
  const tylerCollectionData = await parseCsv(tylerCollectionId, csvFilePath, token).then((results) => results);
  const mergedCollectionData = mergeObjects(joeCollectionData, tylerCollectionData);
  const itemIdImageLocations = [];
  
  for (const productId of Object.keys(mergedCollectionData)) {
    const item = mergedCollectionData[productId];
    // Await each download before starting the next
    // const { destination } = await downloadTcgImage(productId, item.imageUrl);

    item.itemIds.forEach((id) => itemIdImageLocations.push({ itemId: id, imageDest: imagesDir, fileName: `${productId}.jpg` }));
  }

  // After processing all collections, check the imagesDir
  console.log("Finished processing collections.");
  const files = fs.readdirSync(imagesDir);
  console.log(`Files in ${imagesDir}: ${files}`);
  console.log(`Item ID Image Locations: ${JSON.stringify(itemIdImageLocations, null, 2)}`);
  // Process multiple images concurrently using Promise.all()
  const promises = itemIdImageLocations.map(async (item) => {
    await applyImageToItem(item.itemId, item.imageDest, item.fileName, token);
  });
  await Promise.all(promises);
};
// Main execution
async function main() {
  for (const collectionName in collectionsMapping) {
    try {
      console.log(`Processing collection: ${collectionName}`);
      await createCollectionFromCSV(collectionName, collectionsMapping[collectionName]);
      console.log(`Collection ${collectionName} processed successfully.`);
    } catch (error) {
      console.error(`Error processing collection - ${collectionName}:`, error);
      // Break the loop if an error occurs
      break;
    }
  }
}
main();
