const fs = require("fs");
const path = require("path");
const sharp = require("sharp");

const fetchCategoryTree = (socket, categoryId) => {
  return new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      reject(
        new Error(`Timeout fetching category tree for category ${categoryId}`)
      );
    }, 5000);

    socket.emit(
      "categoryList",
      { categoryId: parseInt(categoryId) },
      (response) => {
        clearTimeout(timeout);
        if (response && response.categoryTree) {
          resolve(response);
        } else {
          reject(
            new Error(
              `Invalid category tree response for category ${categoryId}: ${JSON.stringify(
                response
              )}`
            )
          );
        }
      }
    );
  });
};

const fetchCategoryProducts = (socket, categoryId) => {
  return new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      reject(new Error(`Timeout fetching products for category ${categoryId}`));
    }, 5000);

    // Prerender system fetches German version by default
    socket.emit(
      "getCategoryProducts",
      {
        full: true,
        nocount: true,
        categoryId:
          categoryId === "neu" || categoryId === "bald"
            ? categoryId
            : parseInt(categoryId),
        language: 'de',
        requestTranslation: false
      },
      (response) => {
        clearTimeout(timeout);
        if (response && response.products !== undefined) {
          resolve(response);
        } else {
          reject(
            new Error(
              `Invalid response for category ${categoryId}: ${JSON.stringify(
                response
              )}`
            )
          );
        }
      }
    );
  });
};

const fetchProductDetails = (socket, productSeoName) => {
  return new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      reject(
        new Error(
          `Timeout fetching product details for product ${productSeoName}`
        )
      );
    }, 5000);

    // Prerender system fetches German version by default
    socket.emit("getProductView", {
      seoName: productSeoName,
      nocount: true,
      language: 'de',
      requestTranslation: false
    }, (response) => {
      clearTimeout(timeout);
      if (response && response.product) {
        response.product.seoName = productSeoName;
        resolve(response);
      } else {
        reject(
          new Error(
            `Invalid product response for product ${productSeoName}: ${JSON.stringify(
              response
            )}`
          )
        );
      }
    });
  });
};

const fetchProductImage = (socket, bildId) => {
  return new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      reject(new Error(`Timeout fetching image ${bildId}`));
    }, 10000);

    socket.emit("getPic", { bildId, size: "medium" }, (res) => {
      clearTimeout(timeout);
      if (res.success && res.imageBuffer) {
        resolve(res.imageBuffer);
      } else {
        reject(
          new Error(`Failed to fetch image ${bildId}: ${JSON.stringify(res)}`)
        );
      }
    });
  });
};

const fetchCategoryImage = (socket, categoryId) => {
  return new Promise((resolve, reject) => {
    const timeout = setTimeout(() => {
      reject(new Error(`Timeout fetching category image for category ${categoryId}`));
    }, 10000);

    socket.emit("getCategoryPic", { categoryId }, (response) => {
      clearTimeout(timeout);
      if (response.success && response.image) {
        resolve(response.image);
      } else {
        reject(
          new Error(`Failed to fetch category image for ${categoryId}: ${JSON.stringify(response)}`)
        );
      }
    });
  });
};

const saveProductImages = async (socket, products, categoryName, outputDir) => {
  if (!products || products.length === 0) return;

  const assetsPath = path.resolve(
    __dirname,
    "..",
    outputDir,
    "assets",
    "images"
  );
  const overlayPath = path.resolve(
    __dirname,
    "..",
    "public",
    "assets",
    "images",
    "sh.avif"
  );

  // Ensure assets/images directory exists
  if (!fs.existsSync(assetsPath)) {
    fs.mkdirSync(assetsPath, { recursive: true });
  }

  // Check if overlay file exists
  if (!fs.existsSync(overlayPath)) {
    console.log(
      `   ⚠️ Overlay file not found at ${overlayPath} - images will be saved without overlay`
    );
  }

  let imagesSaved = 0;
  let imagesSkipped = 0;

  console.log(
    `   📷 Fetching images for ${products.length} products in "${categoryName}"...`
  );

  for (const product of products) {
    if (product.pictureList && product.pictureList.trim()) {
      // Parse pictureList string to get image IDs
      const imageIds = product.pictureList
        .split(",")
        .map((id) => id.trim())
        .filter((id) => id);

      if (imageIds.length > 0) {
        // Process first image for each product — store AVIF + JPEG (e.g. for Twitter / social)
        const bildId = parseInt(imageIds[0]);
        const avifFilename = `prod${bildId}.avif`;
        const jpegFilename = `prod${bildId}.jpg`;
        const avifPath = path.join(assetsPath, avifFilename);
        const jpegPath = path.join(assetsPath, jpegFilename);

        if (fs.existsSync(avifPath) && fs.existsSync(jpegPath)) {
          imagesSkipped++;
          continue;
        }

        const writeAvifAndJpegFromBuffer = async (buf) => {
          if (!fs.existsSync(avifPath)) {
            await sharp(buf).avif().toFile(avifPath);
          }
          if (!fs.existsSync(jpegPath)) {
            await sharp(buf)
              .jpeg({ quality: 85, mozjpeg: true })
              .toFile(jpegPath);
          }
        };

        try {
          if (fs.existsSync(avifPath) && !fs.existsSync(jpegPath)) {
            await sharp(avifPath)
              .jpeg({ quality: 85, mozjpeg: true })
              .toFile(jpegPath);
          } else if (!fs.existsSync(avifPath) && fs.existsSync(jpegPath)) {
            await sharp(jpegPath).avif().toFile(avifPath);
          } else {
            const imageBuffer = await fetchProductImage(socket, bildId);
            const buf = Buffer.from(imageBuffer);

            // If overlay exists, apply it to the image
            if (false && fs.existsSync(overlayPath)) {
              try {
                const baseImage = sharp(buf);
                const baseMetadata = await baseImage.metadata();

                const overlaySize =
                  Math.min(baseMetadata.width, baseMetadata.height) * 0.4;

                const resizedOverlayBuffer = await sharp(overlayPath)
                  .resize({
                    width: Math.round(overlaySize),
                    height: Math.round(overlaySize),
                    fit: "contain",
                    background: { r: 0, g: 0, b: 0, alpha: 0 },
                  })
                  .toBuffer();

                const centerX = Math.floor(
                  (baseMetadata.width - overlaySize) / 2
                );
                const centerY = Math.floor(
                  (baseMetadata.height - overlaySize) / 2
                );

                const processedImageBuffer = await baseImage
                  .composite([
                    {
                      input: resizedOverlayBuffer,
                      top: centerY,
                      left: centerX,
                      blend: "multiply",
                      opacity: 0.3,
                    },
                  ])
                  .toBuffer();

                await writeAvifAndJpegFromBuffer(processedImageBuffer);
                console.log(
                  `     ✅ Applied overlay → ${avifFilename} + ${jpegFilename}`
                );
              } catch (overlayError) {
                console.log(
                  `     ⚠️ Failed to apply overlay to prod${bildId}: ${overlayError.message}`
                );
                await writeAvifAndJpegFromBuffer(buf);
              }
            } else {
              await writeAvifAndJpegFromBuffer(buf);
            }
          }

          imagesSaved++;

          await new Promise((resolve) => setTimeout(resolve, 50));
        } catch (error) {
          console.log(
            `     ⚠️ Failed to fetch/save prod${bildId} (${avifFilename} / ${jpegFilename}): ${error.message}`
          );
        }
      }
    }
  }

  if (imagesSaved > 0 || imagesSkipped > 0) {
    console.log(
      `   📷 Images: ${imagesSaved} saved, ${imagesSkipped} already exist`
    );
  }
};

const saveCategoryImages = async (socket, categories, outputDir) => {
  if (!categories || categories.length === 0) {
    console.log("   ⚠️ No categories provided for image collection");
    return;
  }

  console.log(`   📂 Attempting to fetch images for ${categories.length} categories via socket calls...`);
  
  // Debug: Log categories that will be processed
  console.log("   🔍 Categories to process:");
  categories.forEach((cat, index) => {
    console.log(`     ${index + 1}. "${cat.name}" (ID: ${cat.id}) -> cat${cat.id}.avif`);
  });

  const assetsPath = path.resolve(
    __dirname,
    "..",
    outputDir,
    "assets",
    "images"
  );

  // Ensure assets/images directory exists
  if (!fs.existsSync(assetsPath)) {
    fs.mkdirSync(assetsPath, { recursive: true });
  }

  let imagesSaved = 0;
  let imagesSkipped = 0;
  let categoriesProcessed = 0;

  console.log(
    `   📂 Processing categories for image collection...`
  );

  for (const category of categories) {
    categoriesProcessed++;
    
    const estimatedFilename = `cat${category.id}.avif`; // Use 'cat' prefix with category ID
    const imagePath = path.join(assetsPath, estimatedFilename);

    // Skip if image already exists
    if (fs.existsSync(imagePath)) {
      imagesSkipped++;
      console.log(`     ⏭️ Category image already exists: ${estimatedFilename} (${category.name})`);
      continue;
    }

    try {
      console.log(`     🔍 Fetching image for category "${category.name}" (ID: ${category.id})...`);
      const imageBuffer = await fetchCategoryImage(socket, category.id);

      // Convert to Uint8Array if needed (similar to CategoryBox.js)
      const uint8Array = new Uint8Array(imageBuffer);

      // Save category images without overlay processing
      fs.writeFileSync(imagePath, Buffer.from(uint8Array));
      console.log(
        `     💾 Saved category image: ${estimatedFilename} (${category.name})`
      );

      imagesSaved++;

      // Small delay to avoid overwhelming server
      await new Promise((resolve) => setTimeout(resolve, 100));
    } catch (error) {
      console.log(
        `     ⚠️ Failed to fetch category image for "${category.name}" (ID: ${category.id}): ${error.message}`
      );
      // Continue processing other categories even if one fails
    }
  }

  console.log(
    `   📂 Category image collection complete: ${imagesSaved} saved, ${imagesSkipped} already exist`
  );
  console.log(
    `   📊 Summary: ${categoriesProcessed}/${categories.length} categories processed`
  );
  
  if (imagesSaved === 0 && imagesSkipped === 0) {
    console.log("   ⚠️ No category images were found via socket calls - categories may not have images available");
  }
};

module.exports = {
  fetchCategoryTree,
  fetchCategoryProducts,
  fetchProductDetails,
  fetchProductImage,
  fetchCategoryImage,
  saveProductImages,
  saveCategoryImages,
};
