<?php

namespace AC_SYNC\Includes\Classes\Product {
  if (!defined('ABSPATH'))
    exit; // Exit if accessed directly
  require_once ABSPATH . 'wp-admin/includes/image.php';
  require_once ABSPATH . 'wp-admin/includes/file.php';
  require_once ABSPATH . 'wp-admin/includes/media.php';

  class Action_Wear_Product_Image
  {

    private $images;
    private $sku;
    private $placeholders = [];
    private $productId;

    public function __construct(string $sku, int $productId)
    {
      $this->sku = $sku;
      $this->productId = $productId;
    }

    public function addPlaceholder($id)
    {
      $this->placeholders[] = $id;
    }

    public static function getPixelBase64()
    {
      return "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+P+/HgAFhAJ/wlseKgAAAABJRU5ErkJggg==";
    }

    public static function getPixelmagePath()
    {
      $wp_upload_dir = wp_upload_dir();
      $dir = $wp_upload_dir["base_dir"] ?? "";
      if (empty($dir))
        $dir = WP_CONTENT_DIR . "/uploads";
      return $dir . "/camac-placeholder.png";
    }

    /**
     * Pending meta entries to be flushed in batch.
     * @var array
     */
    private $pendingMeta = [];

    /**
     * Slug counter cache to avoid repeated DB lookups for sequential placeholders.
     * @var array
     */
    private static $slugCounters = [];

    public function createPlaceHolder($sku)
    {
      global $wpdb;
      $metadata = [
        "width" => 1200,
        "height" => 1600,
        "file" => $this->getPixelmagePath(),
        "sizes" => [],
        'image_meta' => [
          'aperture' => '0', 'credit' => '', 'camera' => '', 'caption' => '',
          'created_timestamp' => '0', 'copyright' => '', 'focal_length' => '0',
          'iso' => '0', 'shutter_speed' => '0', 'title' => '', 'orientation' => '0',
          'keywords' => [],
        ]
      ];

      $slugBase = "placeholder-image-$sku-";

      // Use cached counter to avoid repeated slug lookups for same SKU
      if (!isset(self::$slugCounters[$slugBase])) {
        $slug_exist = $wpdb->get_var($wpdb->prepare(
          "SELECT post_name FROM {$wpdb->prefix}posts WHERE post_name LIKE %s ORDER BY ID DESC",
          $wpdb->esc_like($slugBase) . '%'
        ));
        if ($slug_exist !== null) {
          $slug_parts = explode("-", $slug_exist);
          self::$slugCounters[$slugBase] = (int) end($slug_parts) + 1;
        } else {
          self::$slugCounters[$slugBase] = 0;
        }
      }

      $slug = $slugBase . self::$slugCounters[$slugBase];
      self::$slugCounters[$slugBase]++;

      $now = current_time('mysql');
      $nowGmt = current_time('mysql', true);

      $wpdb->insert($wpdb->prefix . "posts", [
        "post_author" => 0,
        "post_content" => $sku,
        "post_title" => $sku,
        "post_excerpt" => "",
        "post_date" => $now,
        "post_date_gmt" => $nowGmt,
        "post_modified" => $now,
        "post_modified_gmt" => $nowGmt,
        "post_status" => "inherit",
        "comment_status" => "open",
        "ping_status" => "closed",
        "post_name" => $slug,
        "post_parent" => $this->getProductId(),
        "guid" => "/",
        "post_type" => "attachment",
        "post_mime_type" => "image/png"
      ]);

      $id = $wpdb->insert_id;

      // Collect meta for batch flush instead of 4 individual update_post_meta calls
      $pixelPath = $this->getPixelmagePath();
      $productId = $this->getProductId();
      $this->pendingMeta[] = [$id, "_wp_attachment_metadata", maybe_serialize($metadata)];
      $this->pendingMeta[] = [$id, "_wp_attached_file", $pixelPath];
      $this->pendingMeta[] = [$id, "camac_product_id", $productId];
      $this->pendingMeta[] = [$id, "camac_product_sku", $sku];

      return $id;
    }

    /**
     * Flush all pending meta entries in a single multi-row INSERT.
     * Call this after all createPlaceHolder calls are done.
     */
    public function flushPendingMeta()
    {
      if (empty($this->pendingMeta)) return;
      global $wpdb;

      $values = [];
      foreach ($this->pendingMeta as $meta) {
        $values[] = $wpdb->prepare("(%d, %s, %s)", $meta[0], $meta[1], $meta[2]);
      }

      // Batch INSERT all meta in one query
      $wpdb->query(
        "INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES " . implode(',', $values)
      );

      $this->pendingMeta = [];
    }

    /**
     * Create images placeholder starting from given urls and associate to given sku
     *
     * NOTE: Temporary disabled multi simple images because WC doesn't manage multiples
     *
     * @param string $sku Sku string of simple product
     * @param array $urls Array of urls
     * @return array An array containing generated ids
     **/
    public function setSimpleImagesBySku(string $sku, array $urls): array
    {
      $ids = [];
      $urls = [$urls[array_keys($urls)[0]]]; // constraint to manage only first url
      foreach ($urls as $url) {
        $id = $this->createPlaceHolder($sku);
        $this->addPlaceholder($id);
        $ids[] = $id;
      }
      $this->images[$sku] = $urls;
      return $ids;
    }

    /**
     * Create images placeholder starting from given urls and associate to current object sku
     *
     * @param array $urls Array of urls
     * @return array An array containing generated ids
     **/
    public function setConfigurableImages($urls): array
    {
      $ids = [];
      foreach ($urls as $url) {
        $id = $this->createPlaceHolder($this->sku);
        $this->addPlaceholder($id);
        $ids[] = $id;
      }
      $this->images[$this->sku] = $urls;
      return $ids;
    }

    public static function getOrphanImages()
    {
      global $wpdb;
      $ids = $wpdb->get_results("SELECT ID FROM {$wpdb->prefix}posts WHERE post_type = 'attachment' AND post_parent = 0");
      return $ids;
    }

    public static function getImagesBySku($sku)
    {
      global $wpdb;
      $temp_sku = explode("-", $sku);
      if (count($temp_sku) > 2) {
        $baseSku = $temp_sku[0] . "-" . $temp_sku[1];
        $images = $wpdb->get_var($wpdb->prepare(
          "SELECT images FROM {$wpdb->prefix}actionwear_images WHERE sku LIKE %s",
          $wpdb->esc_like($baseSku) . '%'
        ));
      } else {
        $images = $wpdb->get_var($wpdb->prepare(
          "SELECT images FROM {$wpdb->prefix}actionwear_images WHERE sku = %s",
          $sku
        ));
      }
      if (!empty($images)) {
        return json_decode($images);
      }
      return [];
    }

    /**
     * Batch fetch images for multiple SKUs in a single query.
     * Returns a map of sku => decoded images array.
     *
     * @param array $skus Array of SKU strings
     * @return array Map of sku => images array
     */
    public static function getImagesBySkuBatch(array $skus)
    {
      if (empty($skus)) return [];
      global $wpdb;

      // Split into exact match SKUs and prefix-match SKUs
      $exactSkus = [];
      $prefixSkus = [];
      foreach ($skus as $sku) {
        $parts = explode("-", $sku);
        if (count($parts) > 2) {
          $prefixSkus[$sku] = $parts[0] . "-" . $parts[1];
        } else {
          $exactSkus[] = $sku;
        }
      }

      $imageMap = [];

      // Batch exact matches
      if (!empty($exactSkus)) {
        $placeholders = implode(',', array_fill(0, count($exactSkus), '%s'));
        $results = $wpdb->get_results($wpdb->prepare(
          "SELECT sku, images FROM {$wpdb->prefix}actionwear_images WHERE sku IN ($placeholders)",
          ...$exactSkus
        ));
        foreach ($results as $row) {
          $decoded = json_decode($row->images);
          if (!empty($decoded)) {
            $imageMap[$row->sku] = $decoded;
          }
        }
      }

      // Batch prefix matches (group by base SKU to avoid duplicate queries)
      $uniquePrefixes = array_unique(array_values($prefixSkus));
      if (!empty($uniquePrefixes)) {
        $conditions = [];
        $params = [];
        foreach ($uniquePrefixes as $prefix) {
          $conditions[] = "sku LIKE %s";
          $params[] = $wpdb->esc_like($prefix) . '%';
        }
        $results = $wpdb->get_results($wpdb->prepare(
          "SELECT sku, images FROM {$wpdb->prefix}actionwear_images WHERE " . implode(' OR ', $conditions),
          ...$params
        ));
        // Build a prefix → images lookup
        $prefixResults = [];
        foreach ($results as $row) {
          $decoded = json_decode($row->images);
          if (!empty($decoded)) {
            $prefixResults[$row->sku] = $decoded;
          }
        }
        // Map original SKUs to their prefix-matched results
        foreach ($prefixSkus as $originalSku => $prefix) {
          foreach ($prefixResults as $dbSku => $images) {
            if (strpos($dbSku, $prefix) === 0) {
              $imageMap[$originalSku] = $images;
              break;
            }
          }
        }
      }

      return $imageMap;
    }

    public function getCover()
    {
      return $this->images[$this->sku][0];
    }

    public function getImageMetas()
    {
      return json_encode($this->images);
    }

    public function saveToMeta()
    {
      update_post_meta($this->getProductId(), "camac_cdn_urls", $this->getImageMetas());
      update_post_meta($this->getProductId(), "camac_attachment_ids", implode(",", $this->placeholders));
    }

    /**
     * Get the value of productId
     */
    public function getProductId()
    {
      return $this->productId;
    }

    /**
     * Set the value of productId
     *
     * @return  self
     */
    public function setProductId($productId)
    {
      $this->productId = $productId;

      return $this;
    }
  }
}
