package auctiora;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;

import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.SQLException;
import java.util.List;

/**
 * Service responsible for processing images from the IMAGES table.
 * Downloads images, performs object detection, and updates the database.
 *
 * This separates image processing concerns from scraping, allowing this project
 * to focus on enriching data scraped by the external process.
 */
@Slf4j
class ImageProcessingService {

   private final RateLimitedHttpClient httpClient;
   private final DatabaseService       db;
   private final ObjectDetectionService detector;

   ImageProcessingService(DatabaseService db, ObjectDetectionService detector, RateLimitedHttpClient httpClient) {
      this.httpClient = httpClient;
      this.db         = db;
      this.detector   = detector;
   }
   
   /**
    * Downloads an image from the given URL to local storage.
    * Images are organized by saleId/lotId for easy management.
    *
    * @param imageUrl remote image URL
    * @param saleId   sale identifier
    * @param lotId    lot identifier
    * @return absolute path to saved file or null on failure
    */
   String downloadImage(String imageUrl, int saleId, int lotId) {
      try {
         var response = httpClient.sendGetBytes(imageUrl);
         
         if (response.statusCode() == 200) {
            // Use Windows path: C:\mnt\okcomputer\output\images
            var baseDir = Paths.get("C:", "mnt", "okcomputer", "output", "images");
            var dir     = baseDir.resolve(String.valueOf(saleId)).resolve(String.valueOf(lotId));
            Files.createDirectories(dir);
            
            // Extract filename from URL
            var fileName = imageUrl.substring(imageUrl.lastIndexOf('/') + 1);
            // Remove query parameters if present
            int queryIndex = fileName.indexOf('?');
            if (queryIndex > 0) {
               fileName = fileName.substring(0, queryIndex);
            }
            var dest = dir.resolve(fileName);
            
            Files.write(dest, response.body());
            return dest.toAbsolutePath().toString();
         }
      } catch (IOException | InterruptedException e) {
         System.err.println("Failed to download image " + imageUrl + ": " + e.getMessage());
         if (e instanceof InterruptedException) {
            Thread.currentThread().interrupt();
         }
      } catch (Exception e) {
         throw new RuntimeException(e);
      }
      return null;
   }
   
   /**
    * Processes images for a specific lot: downloads and runs object detection.
    *
    * @param lotId lot identifier
    * @param saleId sale identifier
    * @param imageUrls list of image URLs to process
    */
   void processImagesForLot(int lotId, int saleId, List<String> imageUrls) {
      log.info("  Processing {} images for lot {}", imageUrls.size(), lotId);
      
      for (var imgUrl : imageUrls) {
         var fileName = downloadImage(imgUrl, saleId, lotId);
         
         if (fileName != null) {
            // Run object detection
            var labels = detector.detectObjects(fileName);
            
            // Save to database
            try {
               db.insertImage(lotId, imgUrl, fileName, labels);
               
               if (!labels.isEmpty()) {
                  log.info("    Detected: {}", String.join(", ", labels));
               }
            } catch (SQLException e) {
               System.err.println("    Failed to save image to database: " + e.getMessage());
            }
         }
      }
   }
   
   /**
    * Batch processes all pending images in the database.
    * Useful for processing images after the external scraper has populated lot data.
    */
   void processPendingImages() {
      log.info("Processing pending images...");
      
      try {
         var lots = db.getAllLots();
         log.info("Found {} lots to check for images", lots.size());
         
         for (var lot : lots) {
            // Check if images already processed for this lot
            var existingImages = db.getImagesForLot(lot.lotId());
            
            if (existingImages.isEmpty()) {
               log.info("  Lot {} has no images yet - needs external scraper data", lot.lotId());
            }
         }
         
      } catch (SQLException e) {
         System.err.println("Error processing pending images: " + e.getMessage());
      }
   }
}
