<?php

require_once 'productMain.php';

class ProductList {

  protected ProductFilter $filter;
  protected PDO $pdo;
  protected string $language;
  protected ProductMain $main;
  
  
  protected ?int $pricingCountry = null;
  protected int $pricingQuantity = 1;
  protected ?int $fallbackCountry = null;
  
  protected string $currencyCode   = 'EUR';
  protected string $currencyLocale = 'de';
  protected int    $currencyDecimals = 2;
  

  public function __construct(ProductFilter $filter) {
  	global $language;
    $this->filter = $filter;
    $this->language = $language;
  }
  
  public function setConnection(PDO $conn): void {
    $this->pdo = $conn;
    $this->main = new ProductMain($conn, $this->language);
    
    $this->main->setPricingContext($this->pricingCountry, $this->pricingQuantity);
    $this->main->setPricingFallbackCountry($this->fallbackCountry);
    $this->main->setCurrency($this->currencyCode, $this->currencyLocale, $this->currencyDecimals);
  }
  
  public function setCurrency(string $code='EUR', string $locale='de', int $dec=2): void {
    $this->currencyCode = $code; $this->currencyLocale = $locale; $this->currencyDecimals = $dec;
    if (isset($this->main)) $this->main->setCurrency($code, $locale, $dec);
  }
  
  public function setPricingContext(?int $id_country, int $quantity = 1): void {
    $this->pricingCountry  = $id_country;
    $this->pricingQuantity = max(1, (int)$quantity);
    if (isset($this->main)) $this->main->setPricingContext($id_country, $quantity);
  }

  public function setPricingFallbackCountry(?int $id_country): void {
    $this->fallbackCountry = $id_country;
    if (isset($this->main)) $this->main->setPricingFallbackCountry($id_country);
  }

  public function getDisplayData(int $id, array $opts = []): array {
  	$id_country = array_key_exists('id_country', $opts) ? $opts['id_country'] : $this->pricingCountry;
    $quantity   = array_key_exists('quantity', $opts)   ? (int)$opts['quantity'] : $this->pricingQuantity;
    
    $stock = $this->main->getStockStatus($id);
  	$canAdd = $this->main->canAddToCart($id, $quantity);

    return [
      'content'     		=> $this->main->getContent($id, $this->language, true),
      'images'      		=> $this->main->getImages($id, true),
      'attributes'  		=> $this->getDisplayAttributes($id),
      'price'       		=> $this->main->getPriceSummary($id, $id_country, $quantity, $this->fallbackCountry),
      'stock'       		=> $stock,
	    'can_add_to_cart' => $canAdd,
	    'delivery_hint'   => $this->main->deliveryHintFromStock($stock),
    ];
  }

  protected function getDisplayAttributes(int $id): array {
  	$output = ['tags' => [], 'properties' => []];

    $groups = $this->filter->getDisplayGroups();
    $items = $this->filter->getItems();
    $active = $this->filter->getActiveFilters();
    $product_links = $this->getProductLinks($id);

    uasort($groups, fn($a, $b) => ($a['sortorder'] ?? 0) <=> ($b['sortorder'] ?? 0));
    
	  $variantMatrix = $this->getVariantPropertyMatrix($id);
	  $variantIdsToFetch = [];

    foreach ($groups AS $group_key => $group_value) {
    	if (($group_value['c_list'] ?? '0') !== '1') continue;
      if (empty($items[$group_key])) continue;
      
      $type = $group_value['type'];

      $values = [];
      foreach ($items[$group_key] as $item) {
        if (!in_array($item['guidv4'], $product_links, true)) continue;
        
				$row = [
	        'title' 		=> $item['title'],
	        'checked' 	=> in_array($item['guidv4'], $active[$group_key] ?? [], true),
				  'guidv4' 		=> $item['guidv4'],
				  'class'			=> $item['class'],
				  'url' 			=> $item['url'] ?? null,
				  'id_media'	=> $item['id_media'] ?? [],
	      ];
	      
	      if ($type === 'properties' && !empty($variantMatrix)) {
	        $candidates = [];
	        foreach ($variantMatrix AS $vid => $props) {
	          if (($props[$group_key] ?? null) === $item['guidv4']) $candidates[] = (int)$vid;
	        }
	        if ($candidates) {
	          sort($candidates, SORT_NUMERIC);
	          $chosenVid = $candidates[0];
	          $row['variant_id'] = $chosenVid;
	          $variantIdsToFetch[] = $chosenVid;
	        } else {
	          $row['variant_id'] = null;
	        }
	      }
	
	      $values[] = $row;
      }

      if (!empty($values)) {
        $output[$type][$group_key] = [
          'title' 		=> $group_value['title'],
					'field_type'=> $group_value['field_type'] ?? null,
					'class'			=> $group_value['class'] ?? null,
					'id_media'	=> $group_value['id_media'] ?? null,
          'values' 		=> $values
        ];
      }
    }
    
    if (!empty($variantIdsToFetch)) {
	    $imgsByVid = $this->getImagesForModules($variantIdsToFetch);
	
	    foreach ($output['properties'] as $g => &$grp) {
	      foreach ($grp['values'] as &$val) {
	        $vid = $val['variant_id'] ?? null;
	        $val['variant_images'] = ($vid && isset($imgsByVid[$vid])) ? $imgsByVid[$vid] : [];
	      }
	      unset($val);
	    }
	    unset($grp);
	  }
	
	  return $output;
  }

  protected function getProductLinks(int $id): array {
    $links = [];

    foreach (['tags', 'properties'] AS $type) {
      $sql = "SELECT guidv4 FROM products_product_".$type."_links WHERE id_module = :id_module";
      $result = $this->pdo->prepare($sql);
      $result->bindValue(':id_module', $id, PDO::PARAM_INT);
      $result->execute();
      if ($result->rowCount()){
      	while ($arr = $result->fetch()){
      		$links[] = $arr['guidv4'];
      	}
      }
    }

    return $links;
  }
  
  protected function getVariantPropertyMatrix(int $id): array {
	  $matrix = [];
	  
	  $sql = "SELECT products.id AS variant_id, products_product_properties_links.guidv4_group, products_product_properties_links.guidv4
	  				FROM products AS products
	  				LEFT JOIN products_product_properties_links AS products_product_properties_links ON products_product_properties_links.id_module = products.id
	  				WHERE products.id_module = :id_module";
	  $result = $this->pdo->prepare($sql);
	  $result->bindValue(':id_module', $id, PDO::PARAM_INT);
	  $result->execute();

	  while ($arr = $result->fetch()) {
	    if (!isset($matrix[$arr['variant_id']])) $matrix[$arr['variant_id']] = [];
	    if ($arr['guidv4_group'] && $arr['guidv4']) {
	      $matrix[$arr['variant_id']][$arr['guidv4_group']] = $arr['guidv4'];
	    }
	  }
	  return $matrix;
	}

	protected function getImagesForModules(array $moduleIds): array {
	  if (empty($moduleIds)) return [];
	  $moduleIds = array_values(array_unique(array_map('intval', $moduleIds)));
	  $ids = implode(',', array_fill(0, count($moduleIds), '?'));
	          
  	$sql = "SELECT module_images.id_module, 
  					images.file, 
						module_images.r_position_outside, 
						module_images.r_position_inside, 
						module_images.c_enlarge, 
						IF(module_images.title != '', module_images.title, images.title) AS title, 
						IF(module_images.alt != '', module_images.alt, images.alt) AS alt, 
						IF(module_images.text != '', module_images.text, images.text) AS text, 
						IF(module_images.source != '', module_images.source, images.source) AS source,
						IF(module_images.copyright != '', module_images.copyright, images.copyright) AS copyright,
						IF(module_images.photographer != '', module_images.photographer, images.photographer) AS photographer 
						FROM images AS images 
						LEFT JOIN products_images AS module_images ON module_images.id_media = images.id 
						WHERE module_images.id_module IN ($ids)
						GROUP BY module_images.id_media ORDER BY module_images.sortorder ASC";
	  $result = $this->pdo->prepare($sql);
	  foreach ($moduleIds as $i => $id) $result->bindValue($i+1, $id, PDO::PARAM_INT);
	  $result->execute();
	
	  $images = [];
	  while ($arr = $result->fetch()) {
	    $images[(int)$arr['id_module']][] = $arr;
	  }
	  return $images;
	}
}
