<?php
require_once '../app/Models/Product.php';
require_once '../app/Models/Category.php';
require_once '../app/Models/ReportFlag.php';
require_once '../app/Models/ProductionSite.php';
class ProductImportController {
  private $product; private $category; private $flag; private $site;
  public function __construct(){ if(!isset($_SESSION['user_id'])){ redirect('login'); exit; } $this->product=new Product(); $this->category=new Category(); $this->flag=new ReportFlag(); $this->site=new ProductionSite(); }
  public function form(){ $this->view('products/import',[ 'categories'=>$this->category->all(), 'flags'=>$this->flag->all(), 'sites'=>$this->site->all() ]); }
  public function preview(){ if($_SERVER['REQUEST_METHOD']!=='POST'){ redirect('products/import'); exit; }
  if(!isset($_FILES['csv'])||$_FILES['csv']['error']!==UPLOAD_ERR_OK){ $_SESSION['error']='CSV upload failed'; redirect('products/import'); exit; }
  $tmp = $_FILES['csv']['tmp_name']; $raw = file_get_contents($tmp); if($raw===false){ $_SESSION['error']='Cannot read file'; redirect('products/import'); exit; }
  // Detect delimiters
  $fieldDelim = $_POST['field_delim'] ?? 'auto'; $textDelim = $_POST['text_delim'] ?? 'auto'; $assumeAllQuoted = !empty($_POST['assume_all_quoted']);
  [$detField,$detText] = $this->detectDelimiters($raw,$fieldDelim,$textDelim);
  $fieldDelim = $detField; $textDelim = $detText;
  $fh = fopen($tmp,'r'); if(!$fh){ $_SESSION['error']='Cannot reopen file'; redirect('products/import'); exit; }
  $header = fgetcsv($fh,0,$fieldDelim,$textDelim==='none' ? "\0" : $textDelim); if(!$header){ $_SESSION['error']='Empty file'; redirect('products/import'); exit; }
  $rows=[]; $max=5; while(($r=fgetcsv($fh,0,$fieldDelim,$textDelim==='none' ? "\0" : $textDelim))!==false && count($rows)<$max){ $rows[]=$r; }
  fclose($fh);
  $_SESSION['import_file'] = $raw; // store raw in session (small files)
  $_SESSION['import_meta'] = [ 'field_delim'=>$fieldDelim,'text_delim'=>$textDelim,'assume_all_quoted'=>$assumeAllQuoted ];
    $dbFields = [ 'code'=>'Code','name'=>'Name','description'=>'Description','category_id'=>'Category (auto-create by name)','price'=>'Price','price_unit'=>'Price Unit','notes'=>'Notes','production_site'=>'Production Site','factor'=>'Factor','production_unit'=>'Production Unit','sort_order'=>'Sort Order','status'=>'Status','flag:ogolny'=>'Flag Ogólny','flag:kategoria'=>'Flag Kategoria','flag:piekarnia'=>'Flag Piekarnia','flag:cukiernia'=>'Flag Cukiernia','flag:lodziarnia'=>'Flag Lodziarnia','flag:magazyn'=>'Flag Magazyn','flag:wydawka1'=>'Flag Wydawka 1','flag:wydawka2'=>'Flag Wydawka 2' ];
  $this->view('products/import_map',[ 'header'=>$header, 'sample'=>$rows, 'fields'=>$dbFields, 'meta'=>['field_delim'=>$fieldDelim,'text_delim'=>$textDelim] ]);
  }
  public function process(){ if($_SERVER['REQUEST_METHOD']!=='POST'){ redirect('products/import'); exit; }
  if(empty($_SESSION['import_file'])){ $_SESSION['error']='No staged file'; redirect('products/import'); exit; }
  $raw = $_SESSION['import_file']; $meta = $_SESSION['import_meta'] ?? ['field_delim'=>',','text_delim'=>'"','assume_all_quoted'=>false];
  $tmp=tempnam(sys_get_temp_dir(),'imp'); file_put_contents($tmp,$raw); $fh=fopen($tmp,'r');
  $fieldDelim=$meta['field_delim']; $textDelim=$meta['text_delim'];
  $header=fgetcsv($fh,0,$fieldDelim,$textDelim==='none'?"\0":$textDelim);
    $map = $_POST['map'] ?? []; // csv index => field key
    $flagPrefix='flag:'; $created=0;$updated=0;$count=0;$errors=[];$line=1;$categoryCache=[];
  while(($row=fgetcsv($fh,0,$fieldDelim,$textDelim==='none'?"\0":$textDelim))!==false){ $line++; if(count(array_filter($row,fn($v)=>$v!==''))===0) continue; $assoc=[]; foreach($row as $i=>$val){ if(!isset($map[$i])||$map[$i]==='') continue; $assoc[$map[$i]]=$val; }
      $code=trim($assoc['code']??''); $name=trim($assoc['name']??''); if($code===''||$name===''){ $errors[]="Line $line missing code or name"; continue; }
      // Flags
      $flags=[]; foreach($assoc as $k=>$v){ if(strpos($k,$flagPrefix)===0 && trim($v)!==''){ $flags[]=substr($k,strlen($flagPrefix)); } }
      // Category name from mapped field if provided
      $catId=null; if(isset($assoc['category_id']) && trim($assoc['category_id'])!==''){ $catId=$this->ensureCategory(trim($assoc['category_id']),$categoryCache); }
      $price=$this->toDecimal($assoc['price']??null); $factor=$this->toDecimal($assoc['factor']??null); $sort_order=isset($assoc['sort_order']) && $assoc['sort_order']!=='' ? (int)$assoc['sort_order'] : 0;
      $payload=[ 'code'=>$code,'name'=>$name,'description'=>$assoc['description']??'','category_id'=>$catId,'price'=>$price,'price_unit'=>$assoc['price_unit']??null,'notes'=>$assoc['notes']??'','production_site'=>$assoc['production_site']??null,'factor'=>$factor,'production_unit'=>$assoc['production_unit']??null,'report_flags'=>$flags,'sort_order'=>$sort_order,'status'=>$assoc['status']??'active' ];
      $existing=$this->product->findByCode($code); if($existing){ $this->product->update($existing['id'],$payload); $updated++; } else { $this->product->create($payload); $created++; }
      $count++;
    }
    fclose($fh); unlink($tmp); unset($_SESSION['import_file']);
    $_SESSION['success']="Imported $count products (created: $created, updated: $updated)" . (count($errors)? ' - Errors: '.implode('; ',$errors):'');
    redirect('products');
  }
  public function upload(){ if($_SERVER['REQUEST_METHOD']!=='POST'){ redirect('products/import'); exit; }
  if(!isset($_FILES['csv'])||$_FILES['csv']['error']!==UPLOAD_ERR_OK){ $_SESSION['error']='CSV upload failed'; redirect('products/import'); exit; }
  $path=$_FILES['csv']['tmp_name']; $raw=file_get_contents($path); if($raw===false){ $_SESSION['error']='Cannot read file'; redirect('products/import'); exit; }
  $fieldDelim = $_POST['field_delim'] ?? 'auto'; $textDelim = $_POST['text_delim'] ?? 'auto';
  [$detField,$detText] = $this->detectDelimiters($raw,$fieldDelim,$textDelim);
  $fieldDelim=$detField; $textDelim=$detText;
  $fh=fopen($path,'r'); if(!$fh){ $_SESSION['error']='Cannot read file'; redirect('products/import'); exit; }
  $header = fgetcsv($fh,0,$fieldDelim,$textDelim==='none'?"\0":$textDelim); if(!$header){ $_SESSION['error']='Empty file'; redirect('products/import'); exit; }
    // Normalize header keys (strip BOM, trim)
    $norm=[]; foreach($header as $h){ $h=trim($h); $h=preg_replace('/^[\xEF\xBB\xBF]/','',$h); $norm[]=mb_strtolower($h,'UTF-8'); }
    $count=0; $created=0; $updated=0; $errors=[]; $line=1;
    $categoryCache=[]; $siteMap=$this->indexByCode($this->site->all(),'code');
  while(($row=fgetcsv($fh,0,$fieldDelim,$textDelim==='none'?"\0":$textDelim))!==false){ $line++; if(count(array_filter($row,fn($v)=>$v!==''))===0) continue; $dataAssoc=[]; foreach($row as $i=>$v){ $key=$norm[$i]??('col'.$i); $dataAssoc[$key]=$v; }
      $code=trim($dataAssoc['kod']??''); $name=trim($dataAssoc['nazwa']??''); if($code===''||$name===''){ $errors[]="Line $line missing code or name"; continue; }
      $catName=trim($dataAssoc['kategoria']??''); $catId=null; if($catName!==''){ $catId=$this->ensureCategory($catName,$categoryCache); }
      $priceRaw=trim($dataAssoc['cena']??''); $price=$priceRaw!==''? (float)str_replace(',','.', $priceRaw): null; $priceUnit=trim($dataAssoc['za ceną']??'') ?: null;
      $prodSite=trim($dataAssoc['produkcja']??'') ?: null;
      $factorRaw=trim($dataAssoc['faktor']??''); $factor=$factorRaw!==''? (float)str_replace(',','.', $factorRaw): null;
      $prodUnit=trim($dataAssoc['jed. prod.']??'') ?: null;
      $status=trim($dataAssoc['status']??'active');
      // Report flags columns names in Polish per sample
      $flags=[]; $flagCols=['ogólny'=>'ogolny','kategoria'=>'kategoria','piekarnia'=>'piekarnia','cukiernia'=>'cukiernia','lodziarnia'=>'lodziarnia','magazyn'=>'magazyn','wydawka 1'=>'wydawka1','wydawka 2'=>'wydawka2'];
      foreach($flagCols as $csvCol=>$code){ if(array_key_exists($csvCol,$dataAssoc) && trim($dataAssoc[$csvCol])!==''){ $flags[]=$code; } }
      $orderRaw=trim($dataAssoc['order']??''); $sort_order=$orderRaw!==''?(int)$orderRaw:0;
      $notes=trim($dataAssoc['uwagi']??'');
      $payload=[ 'code'=>$code,'name'=>$name,'description'=>trim($dataAssoc['opis']??''),'category_id'=>$catId,'price'=>$price,'price_unit'=>$priceUnit,'notes'=>$notes,'production_site'=>$prodSite,'factor'=>$factor,'production_unit'=>$prodUnit,'report_flags'=>$flags,'sort_order'=>$sort_order,'status'=>$status ];
      $existing=$this->product->findByCode($code); if($existing){ $this->product->update($existing['id'],$payload); $updated++; } else { $this->product->create($payload); $created++; }
      $count++;
    }
    fclose($fh);
    $_SESSION['success']="Imported $count products (created: $created, updated: $updated)" . (count($errors)? ' - Errors: '.implode('; ',$errors):'');
    redirect('products');
  }
  private function ensureCategory($name,&$cache){ $key=mb_strtolower($name,'UTF-8'); if(isset($cache[$key])) return $cache[$key]; $existingId=null; $pdo=$GLOBALS['pdo']; $st=$pdo->prepare('SELECT id FROM categories WHERE name=?'); $st->execute([$name]); $existingId=$st->fetchColumn(); if(!$existingId){ $catModel=new Category(); $catModel->create(['name'=>$name,'description'=>null,'sort_order'=>0]); $existingId=$pdo->lastInsertId(); } $cache[$key]=$existingId; return $existingId; }
  private function indexByCode($rows,$key){ $m=[]; foreach($rows as $r){ $m[$r[$key]]=$r; } return $m; }
  private function view($v,$d=[]){ extract($d); require_once "../app/Views/$v.php"; }
  private function toDecimal($val){ if($val===null) return null; $val=trim($val); if($val==='') return null; return (float)str_replace(',','.', $val); }
  private function detectDelimiters($raw,$fieldChoice,$textChoice){
    $sample = substr($raw,0,20000); // first 20KB
    $candidates = [',',';','\t','|'];
    $field=','; $text='"';
    if($fieldChoice!=='auto'){ $field=$fieldChoice==="\t"?"\t":$fieldChoice; }
    else {
      $best=0; foreach($candidates as $cand){ $cnt=substr_count($sample,$cand); if($cnt>$best){ $best=$cnt; $field=$cand; } }
    }
    if($textChoice==='auto'){ $dq=substr_count($sample,'"'); $sq=substr_count($sample,"'"); if($dq>=2 || $sq>=2){ $text = $dq >= $sq ? '"' : "'"; } else { $text='"'; } }
    elseif($textChoice==='none'){ $text='none'; }
    else { $text=$textChoice; }
    return [$field,$text];
  }
}


