<?php
declare(strict_types=1);
namespace App\Controllers;
use App\Core\Controller;use App\Core\Request;use PDO;
final class CatalogController extends Controller{
 private array$map=['categories'=>['product_categories','name'],'brands'=>['brands','name'],'units'=>['units','name'],'tax-rates'=>['tax_rates','name'],'price-levels'=>['price_levels','name']];
 public function index(Request$r):void{$section=(string)$r->param('section');if(!isset($this->map[$section])){http_response_code(404);app()->view('errors/404');return;}$table=$this->map[$section][0];$s=app()->db()->connection()->prepare("SELECT * FROM $table WHERE company_id=:company ORDER BY name");$s->execute(['company'=>app()->auth()->user()['company_id']]);$items=$s->fetchAll();$categories=[];if($section==='categories')$categories=$items;$this->view('catalog/index',compact('section','items','categories'));}
 public function save(Request$r):never{$section=(string)$r->param('section');if(!isset($this->map[$section]))$this->backWithErrors(['Référentiel invalide.']);$name=trim((string)$r->input('name'));if($name==='')$this->backWithErrors(['Nom obligatoire.']);$company=(int)app()->auth()->user()['company_id'];$id=(int)$r->input('id');$pdo=app()->db()->connection();if($section==='categories'){$parent=(int)$r->input('parent_id')?:null;if($id&&$parent&&$this->wouldLoop($id,$parent))$this->backWithErrors(['Cette catégorie créerait une boucle.']);$data=['name'=>$name,'description'=>$r->input('description')?:null,'parent'=>$parent,'company'=>$company];if($id){$data['id']=$id;$pdo->prepare('UPDATE product_categories SET name=:name,description=:description,parent_id=:parent WHERE id=:id AND company_id=:company')->execute($data);}else$pdo->prepare('INSERT INTO product_categories(company_id,parent_id,name,description)VALUES(:company,:parent,:name,:description)')->execute($data);}elseif($section==='brands'){$this->upsert($pdo,'brands',$id,$company,['name'=>$name,'description'=>$r->input('description')?:null]);}elseif($section==='units'){$dec=(int)$r->input('decimal_places');if($dec<0||$dec>6)$this->backWithErrors(['Décimales invalides.']);$this->upsert($pdo,'units',$id,$company,['name'=>$name,'symbol'=>$r->input('symbol'),'unit_type'=>$r->input('unit_type'),'decimal_places'=>$dec]);}elseif($section==='tax-rates'){$rate=$r->input('rate');if(!is_numeric($rate)||(float)$rate<0||(float)$rate>100)$this->backWithErrors(['Taux invalide.']);if($r->input('is_default'))$pdo->prepare('UPDATE tax_rates SET is_default=0 WHERE company_id=:company')->execute(['company'=>$company]);$this->upsert($pdo,'tax_rates',$id,$company,['name'=>$name,'rate'=>$rate,'is_default'=>$r->input('is_default')?1:0]);}else{$discount=$r->input('discount_rate');if(!is_numeric($discount)||(float)$discount<0||(float)$discount>100)$this->backWithErrors(['Remise invalide.']);$this->upsert($pdo,'price_levels',$id,$company,['name'=>$name,'discount_rate'=>$discount]);}app()->audit()->log($id?'updated':'created',$section,'Référentiel catalogue modifié.',(int)app()->auth()->user()['id'],$company);$this->redirect('catalog/'.$section,$id?'Élément modifié.':'Élément ajouté.');}
 public function toggle(Request$r):never{$section=(string)$r->param('section');if(!isset($this->map[$section]))$this->backWithErrors(['Référentiel invalide.']);$table=$this->map[$section][0];app()->db()->connection()->prepare("UPDATE $table SET is_active=1-is_active WHERE id=:id AND company_id=:company")->execute(['id'=>$r->param('id'),'company'=>app()->auth()->user()['company_id']]);$this->redirect('catalog/'.$section,'Statut modifié.');}
 private function upsert(PDO$pdo,string$table,int$id,int$company,array$values):void{if($id){$values['company']=$company;$values['id']=$id;$set=implode(',',array_map(fn($k)=>"$k=:$k",array_keys(array_diff_key($values,['company'=>1,'id'=>1]))));$pdo->prepare("UPDATE $table SET $set WHERE id=:id AND company_id=:company")->execute($values);}else{$values['company_id']=$company;$cols=array_keys($values);$pdo->prepare("INSERT INTO $table(".implode(',',$cols).')VALUES('.implode(',',array_map(fn($x)=>':'.$x,$cols)).')')->execute($values);}}
 private function wouldLoop(int$id,int$parent):bool{$seen=[];while($parent){if($parent===$id||isset($seen[$parent]))return true;$seen[$parent]=1;$s=app()->db()->connection()->prepare('SELECT parent_id FROM product_categories WHERE id=:id AND company_id=:company');$s->execute(['id'=>$parent,'company'=>app()->auth()->user()['company_id']]);$parent=(int)$s->fetchColumn();}return false;}
}
