<?php
global $Session;
global $Conf;
global $Route;

//! on va chercher la data de la Session au format tableau
$session_data = $Session->get_data();
//! où on récupère le fk_tiers sur lequel l'utilisateur travaille
if (isset($session_data["tiers"])) {
  $fk_tiers = $session_data["tiers"];
} else {
  $fk_tiers = 0;
}

$fk_user = $Session->_user["rowid"];

eLog("jxpost action : " . $Route->_action);

function cleanData(&$str)
{
  // Fonction de nettoyage des données pour l'export Excel
  if ($str == 't') $str = 'TRUE';
  if ($str == 'f') $str = 'FALSE';
  if (preg_match("/^0/", $str) || preg_match("/^\+?\d{8,}$/", $str) || preg_match("/^\d{4}.\d{1,2}.\d{1,2}/", $str)) {
    $str = "'$str";
  }
  if (strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
  $str = mb_convert_encoding($str, 'UTF-16LE', 'UTF-8');
}

function filterData(&$str)
{
  $str = preg_replace("/\t/", "\\t", $str);
  $str = preg_replace("/\r?\n/", "\\n", $str);
  if (strstr($str, '"')) $str = '"' . str_replace('"', '""', $str) . '"';
}

switch ($Route->_action) {
  case "filter":
    $idfilter = $_POST["idfilter"];
    switch ($idfilter) {
      case "filtertiers":
        $Session->set_data($idfilter . "_search", $_POST["filter_search"]);
        $Session->set_data($idfilter . "_contact", $_POST["filter_contact"]);
        $Session->set_data($idfilter . "_ape", $_POST["filter_ape"]);
        if (isset($_POST["filter_recent"])) {
          $recent = 1;
        } else {
          $recent = 0;
        }
        $Session->set_data($idfilter . "_recent", $recent);
        if (isset($_POST["filter_agenda"])) {
          $agenda = 1;
        } else {
          $agenda = 0;
        }
        $Session->set_data($idfilter . "_agenda", $agenda);
        if (isset($_POST["filter_archive"])) {
          $archive = 1;
        } else {
          $archive = 0;
        }
        $Session->set_data($idfilter . "_archive", $archive);
        $Session->set_data($idfilter . "_type_tiers", $_POST["filter_type_tiers"]);
        $Session->set_data($idfilter . "_ville", $_POST["filter_villeA"]);      //! filter_villeA parce que c'est un autocomplete : retourne le rowid qui est en fait la ville !
        break;
    }
    break;

  case "upfind":
    $tab = $_POST["win"];
    $lid = $Route->_param1;

    if ($Conf::erp) {
      $sql = 'SELECT * FROM medias WHERE dir2="' . $tab . '" AND support_rowid=' . $lid . ';';
    } else {
      $sql = 'SELECT * FROM medias WHERE support="' . $tab . '" AND support_rowid=' . $lid . ';';
    }
    $upls = array();
    $upls = getinfos($sql, "groupe");
    echo json_encode($upls);
    break;

  case "updelete":
    updelete($_POST);
    break;

  case "upload":
    if ($Conf::erp) {
      upload($_POST);
    } else {
      upload_old($_POST);
    }
    break;

  case "medias":
    $user = $Session->_user["rowid"];
    $type = $Route->_param1; //! facture par exemple
    if (isset($_POST["rowid"])) {
      $rowid = $_POST["rowid"];  //! c'est le rowid de la facture par exemple
      if ($type == "facture" || $type == "devis") {
        //! on doit aller chercher le num_facture pour avoir le nom du fichier
        if ($type == "facture") {
          $num_facture = getdata("devis", $rowid, "num_facture");
        } else {
          $num_facture = getdata("devis", $rowid, "num_devis");
        }
        $fk_tiers = getdata("devis", $rowid, "fk_soc");
        $nom_tiers = str_normalize(getdata("clients", $fk_tiers, "libelle", "groupe"));
        if ($Conf->_entite["raz_num_devis"]) {
          $num_facture = substr('000' . $num_facture, -3);
        } else {
          $num_facture = substr('0000' . $num_facture, -4);
        }
        $support = $fk_tiers;
        $filename = $fk_tiers . "_" . $type . "_" . $num_facture . ".pdf";
        if (isset($_POST["relance"])) {
          $filename = $fk_tiers . "_" . $type . "_" . $num_facture . "_relance_" . date("Ymd") . ".pdf";
        }
        $typ = "pdf";
        $dir0 = "tiers";
        $dir1 = $nom_tiers;
      } else {
        $support = $type;
        $filename = $rowid . ".pdf";
        $typ = "pdf";
        $rep = $type . DS . $rowid . DS . "pdf";
        $dir0 = "tiers";
        $dir1 = "dir1";
      }
      $dir2 = $type;
      $des = "";
      $pos = "L";
      $hau = 0;
      $lar = 0;
      //! On vérifie d'abord qu'il n'y ait pas un média existant pour le même support, le même support_rowid et le même nom de fichier : doublon !
      $sql = 'SELECT * FROM medias WHERE dir0="' . $dir0 . '" AND dir1="' . $dir1 . '" AND dir2="' . $dir2 . '" AND fichier="' . $filename . '";';
      $doublon = getinfos($sql, "groupe");
      if (count($doublon) == 0) {
        //! il n'y a pas de doublon, on peut créer l'enregistrement
        $sql = 'INSERT INTO medias SET dir0="' . $dir0 . '", dir1="' . $dir1 . '", dir2="' . $dir2 . '",  support_rowid=' . $rowid . ', fichier="' . $filename . '", fk_user_creat=' . $user . ', ';
        $sql .= 'type_fichier="' . $typ . '", date_creat="' . date("Y-m-d H:i:s") . '", description="' . $des . '", position="' . $pos . '", hauteur=' . $hau . ', largeur=' . $lar . ';';
      } else {
        //! l'enregistrement existe déjà : on met à jour date_modif et fk_user_modif
        $sql = 'UPDATE medias SET date_modif="' . date("Y-m-d H:i:s") . '", fk_user_modif=' . $user . ' WHERE dir0="' . $dir0 . '" AND dir1="' . $dir1 . '" AND dir2="' . $dir2 . '" AND fichier="' . $filename . '";';
      }
      eLog("jxpost medias : " . $sql);
      qSQL($sql, "groupe");
    }
    break;

  case "refresh":
    $win = $Route->_param1;
    if ($win != "") {
      if (isset($_POST["input"])) {
        $input = $_POST["input"];
        switch ($win) {
          case "winaction":
            //! un refresh dans la fenêtre modale winaction
            if ($input == "fk_contact") {
              $sql = "SELECT rowid, CONCAT(firstname, ' ', name) AS libelle FROM contacts WHERE fk_soc=" . $fk_tiers . " ORDER BY libelle;";
              $res = qSQL($sql, "groupe");
              $arr = array();
              if ($res instanceof PDOStatement) {
                while ($rec = $res->fetch(PDO::FETCH_ASSOC)) {
                  $arr[] = $rec;
                }
              }
              $jsonresult = json_encode($arr);
              $lignes = $jsonresult;
              echo $lignes;
            }
            break;
        }
      }
    }
    break;

  case "mediafind":
    $tab = $_POST["win"];
    $lid = $Route->_param1;

    if ($Conf::erp) {
      $sql = 'SELECT * FROM medias WHERE dir2="' . $tab . '" AND support_rowid=' . $lid . ';';
    } else {
      $sql = 'SELECT * FROM medias WHERE support="' . $tab . '" AND support_rowid=' . $lid . ';';
    }
    $upls = array();
    $upls = getinfos($sql, "groupe");
    $upls = $upls[0];
    echo json_encode($upls);
    break;

  case "getdata":
    $chp = $_POST["chp"];
    $typ = $Route->_param1;
    $upls = array();
    
    switch ($typ) {
      case "tiers":
        // SÉCURITÉ : Liste blanche des colonnes autorisées
        $allowedColumns = ['code', 'libelle', 'adresse1', 'adresse2', 'adresse3', 'cp', 'ville', 
                          'contact_nom', 'contact_prenom', 'contact_fonction', 'telephone', 'mobile', 'email'];
        
        if (!in_array($chp, $allowedColumns)) {
          echo json_encode(array('error' => 'Colonne non autorisée'));
          break;
        }
        
        try {
          $db = Database::getInstance();
          // SÉCURITÉ : Utilisation de requête préparée pour l'ID
          $sql = "SELECT `$chp` AS data FROM clients WHERE rowid = :id";
          $result = $db->fetchOne($sql, [':id' => intval($fk_tiers)]);
          if ($result) {
            $upls = $result;
          }
        } catch (Exception $e) {
          error_log("Erreur getdata : " . $e->getMessage());
        }
        break;
    }
    
    echo json_encode($upls);
    break;

  case "setsession":
    if (isset($_POST["key"]) && isset($_POST["val"])) {
      $Session->set_data($_POST["key"], $_POST["val"]);
    }
    break;

  // case "autocomplete" supprimé car non utilisé dans l'application
  // L'autocomplétion est gérée côté client JavaScript

  case "get_context":
    //! Renvoie le contexte de l'utilisateur
    $ajson = array();
    $ajson["user"] = $Session->_user;
    $ajson["session"] = $Session->get_data();
    $ajson["devip"] = $Conf->_devIp ? "1" : "0";
    echo json_encode($ajson);
    break;

  case "load_client":
    //! Charge les infos d'un client
    //! Réception et lecture de la demande en json
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->cid)) {
      // SÉCURITÉ : Validation de l'ID et requête préparée
      $cid = intval($data->cid);
      if ($cid <= 0) {
        echo json_encode(array('error' => 'ID client invalide'));
        break;
      }
      
      try {
        $db = Database::getInstance();
        $result = $db->getById('clients', $cid);
        echo json_encode($result ?: array());
      } catch (Exception $e) {
        error_log("Erreur load_client : " . $e->getMessage());
        echo json_encode(array('error' => 'Erreur lors du chargement du client'));
      }
    } else {
      echo json_encode(array('error' => 'Pas de client spécifié'));
    }
    break;

  case "search_clients":
    //! Cherche les clients correspondant à un libellé, une adresse, un code postal, une ville, un nom, un prénom, une fonction ou un email
    //! Réception et lecture de la demande en json
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->search)) {
      // SÉCURITÉ : Utilisation de requêtes préparées pour la recherche
      $search = trim($data->search);
      
      try {
        $db = Database::getInstance();
        $sql = 'SELECT c.rowid, c.libelle, c.type_client, c.adresse1, c.cp, c.ville FROM clients c 
                WHERE c.libelle LIKE :search 
                   OR c.adresse1 LIKE :search 
                   OR c.cp LIKE :search 
                   OR c.ville LIKE :search 
                   OR c.contact_nom LIKE :search 
                   OR c.contact_prenom LIKE :search 
                   OR c.contact_fonction LIKE :search 
                   OR c.email LIKE :search 
                ORDER BY c.libelle';
        
        $searchParam = '%' . $search . '%';
        $results = $db->fetchAll($sql, [':search' => $searchParam]);
        echo json_encode($results);
      } catch (Exception $e) {
        error_log("Erreur search_clients : " . $e->getMessage());
        echo json_encode(array('error' => 'Erreur lors de la recherche'));
      }
    } else {
      echo json_encode(array('ret' => "ko"));
    }
    break;

  case "load_marches":
    //! charge des infos de tous les marchés
    $sql = 'SELECT m.rowid, m.libelle FROM marches m ORDER BY m.libelle DESC;';
    echo getinfos($sql, "gen", "json");
    break;

  case "load_marche":
    //! Charge les infos d'un marché
    //! Réception et lecture de la demande en json
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->cid)) {
      $cid = nettoie_input($data->cid);
      $sql = 'SELECT m.* FROM marches m WHERE m.rowid=' . $cid . ';';
      echo getinfos($sql, "gen", "json");
    } else {
      $ret = array('ret' => "ko");
      echo json_encode($ret);
    }
    break;

  case "search_produits":
    //! Cherche les produits correspondant à un code ou à un libellé
    //! Réception et lecture de la demande en json
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->search)) {
      $search = nettoie_input($data->search);
      $sql = 'SELECT p.*, pf.famille FROM produits p LEFT JOIN produits_familles pf ON p.fk_famille_produit=pf.rowid ';
      $sql .= 'WHERE (p.code LIKE "%' . $search . '%" OR p.libelle LIKE "%' . $search . '%" OR p.groupe LIKE "%' . $search . '%" OR pf.famille LIKE "%' . $search . '%") AND p.prix_vente>0 AND p.active=1 ';
      $sql .= 'ORDER BY p.libelle;';
      echo getinfos($sql, "gen", "json");
    } else {
      $ret = array('ret' => "ko");
      echo json_encode($ret);
    }
    break;

  case "load_familles":
    //! Charge les familles de produits existantes
    $sql = 'SELECT xf.* FROM x_familles xf ORDER BY xf.ordre;';
    echo getinfos($sql, "gen", "json");
    break;

  case "load_familles_groupes":
    //! Charge les familles par groupes de produits existantes
    $sql = 'SELECT pf.* FROM produits_familles pf ORDER BY pf.ordre, pf.groupe;';
    echo getinfos($sql, "gen", "json");
    break;

  case "save_familles":
    //! Réception et lecture de la demande en json
    $data = json_decode(file_get_contents("php://input"));

    //! on récupère les familles existantes
    $sql = 'SELECT pf.rowid FROM produits_familles pf ORDER BY pf.rowid;';
    $pf = getinfos($sql, "gen");
    //! on les désactive toutes
    $sql = 'UPDATE produits_familles SET active=0;';
    qSQL($sql);

    //! on boucle sur les familles reçues
    foreach ($data as $row) {
      $rowid = nettoie_input($row->id);
      $set = 'groupe="' . nettoie_input(trim($row->groupe)) . '", ';
      $set .= 'ordre="' . nettoie_input(trim($row->ordre)) . '", ';
      $set .= 'fk_famille="' . nettoie_input(trim($row->famille)) . '", ';
      $set .= 'code_maintenance="' . nettoie_input(trim($row->maintenance)) . '", ';
      $set .= 'marge_rr="' . nettoie_input(trim($row->margerr)) . '", ';
      $set .= 'marge_dv="' . nettoie_input(trim($row->margedv)) . '", ';
      $set .= 'active=1 ';
      //! on recherche si la famille existe déjà
      $found = false;
      foreach ($pf as $p) {
        if ($p["rowid"] == $rowid) {
          $found = true;
          break;
        }
      }

      if (!$found) {
        //! Si la famille n'existe pas, on la crée
        $sql = 'INSERT INTO produits_familles SET ' . $set . ';';
      } else {
        //! Sinon on la met à jour
        $sql = 'UPDATE produits_familles SET ' . $set . ' ';
        $sql .= 'WHERE rowid=' . $rowid . ';';
      }
      eLog($sql);
      qSQL($sql, "gen");
    }
    //! enfin, on supprime toutes les familles qui n'ont pas été reçues, active=0
    $sql = 'DELETE FROM produits_familles WHERE active=0;';
    eLog($sql);
    qSQL($sql, "gen");

    $ret = array('ret' => "ok", 'msg' => "Enregistrement des familles effectué");
    echo json_encode($ret);
    break;

  case "save_marche":
    //! Réception et lecture de la demande en json
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->rowid)) {
      $cid = nettoie_input($data->rowid);
      $act = nettoie_input($data->act);

      $set = 'SET libelle="' . nettoie_input(trim($data->libelle)) . '"';
      $set .= ', numero="' . nettoie_input($data->numero) . '"';
      $set .= ', nom="' . nettoie_input($data->nom) . '"';
      $set .= isset($data->chk_remise_sur_tg) ? ', chk_remise_sur_tg=1' : ', chk_remise_sur_tg=0';
      $set .= isset($data->chk_prix_nets) ? ', chk_prix_nets=1' : ', chk_prix_nets=0';
      $set .= isset($data->chk_marche_public) ? ', chk_marche_public=1' : ', chk_marche_public=0';

      if ($data->taux_remise_trimestrielle == "") {
        $set .= ', taux_remise_trimestrielle=0';
      } else {
        $set .= ', taux_remise_trimestrielle=' . $data->taux_remise_trimestrielle;
      }
      if ($data->taux_remise_semestrielle == "") {
        $set .= ', taux_remise_semestrielle=0';
      } else {
        $set .= ', taux_remise_semestrielle=' . $data->taux_remise_semestrielle;
      }
      if ($data->taux_remise_annuelle == "") {
        $set .= ', taux_remise_annuelle=0';
      } else {
        $set .= ', taux_remise_annuelle=' . $data->taux_remise_annuelle;
      }
      $set .= ', date_debut="' . d6GetDate($data->date_debut, "FM") . '"';
      $set .= ', date_fin="' . d6GetDate($data->date_fin, "FM") . '"';
      $set .= ', date_validite_prix="' . d6GetDate($data->date_validite_prix, "FM") . '"';
      $set .= ', franco_de_port="' . nettoie_input(trim($data->franco_de_port)) . '"';
      $set .= ', garantie="' . nettoie_input(trim($data->garantie)) . '"';
      $set .= ', delai_de_livraison="' . nettoie_input(trim($data->delai_de_livraison)) . '"';
      $set .= ', remises_commerciales="' . nettoie_input(trim($data->remises_commerciales)) . '"';
      if ($data->remise_palier_1 == "") {
        $set .= ', remise_palier_1=0';
      } else {
        $set .= ', remise_palier_1=' . $data->remise_palier_1;
      }
      if ($data->remise_taux_1 == "") {
        $set .= ', remise_taux_1=0';
      } else {
        $set .= ', remise_taux_1=' . $data->remise_taux_1;
      }
      if ($data->remise_palier_2 == "") {
        $set .= ', remise_palier_2=0';
      } else {
        $set .= ', remise_palier_2=' . $data->remise_palier_2;
      }
      if ($data->remise_taux_2 == "") {
        $set .= ', remise_taux_2=0';
      } else {
        $set .= ', remise_taux_2=' . $data->remise_taux_2;
      }
      if ($data->remise_palier_3 == "") {
        $set .= ', remise_palier_3=0';
      } else {
        $set .= ', remise_palier_3=' . $data->remise_palier_3;
      }
      if ($data->remise_taux_3 == "") {
        $set .= ', remise_taux_3=0';
      } else {
        $set .= ', remise_taux_3=' . $data->remise_taux_3;
      }
      if ($data->remise_palier_4 == "") {
        $set .= ', remise_palier_4=0';
      } else {
        $set .= ', remise_palier_4=' . $data->remise_palier_4;
      }
      if ($data->remise_taux_4 == "") {
        $set .= ', remise_taux_4=0';
      } else {
        $set .= ', remise_taux_4=' . $data->remise_taux_4;
      }

      $set .= ', commentaire="' . nettoie_input(trim($data->commentaire)) . '"';
      $set .= isset($data->chk_cache_commerciaux) ? ', chk_cache_commerciaux=1' : ', chk_cache_commerciaux=0';
      $set .= isset($data->chk_marche_hybride) ? ', chk_marche_hybride=1' : ', chk_marche_hybride=0';
      $set .= isset($data->chk_regle_seuils_marge) ? ', chk_regle_seuils_marge=1' : ', chk_regle_seuils_marge=0';
      $set .= isset($data->active) ? ', active=1' : ', active=0';

      if ($cid == 0) {
        $set .= ', date_creat = "' . date("Y-m-d H:i:s") . '", fk_user_creat=' . $fk_user;
        $sql = 'INSERT INTO marches ' . $set . ';';
      } else {
        $set .= ', date_modif = "' . date("Y-m-d H:i:s") . '", fk_user_modif=' . $fk_user;
        $sql = 'UPDATE marches ' . $set . ' WHERE rowid=' . $cid . ';';
      }
      eLog($sql);
      qSQL($sql, "gen");

      $ret = array('ret' => "ok");
      echo json_encode($ret);
    } else {
      $ret = array('ret' => "ko");
      echo json_encode($ret);
    }
    break;

  case "delete_marche":
    //! Supprime un marché
    //! Réception de l'id du marché à supprimer
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->cid)) {
      // SÉCURITÉ : Validation de l'ID comme entier
      $cid = intval($data->cid);
      if ($cid <= 0) {
        echo json_encode(array('ret' => "ko", 'msg' => 'ID invalide'));
        break;
      }
      
      try {
        $db = Database::getInstance();
        
        // Utilisation de requêtes préparées pour la suppression
        $sql1 = 'DELETE FROM marches WHERE rowid = :id';
        $db->query($sql1, ['id' => $cid]);
        
        $sql2 = 'DELETE FROM marches_listes WHERE fk_marche = :id';
        $db->query($sql2, ['id' => $cid]);
        
        $sql3 = 'DELETE FROM produits WHERE fk_marche = :id';
        $db->query($sql3, ['id' => $cid]);
        
        eLog("Marché supprimé : ID=$cid");
        $ret = array('ret' => "ok", 'msg' => 'Marché supprimé');
        echo json_encode($ret);
      } catch (Exception $e) {
        eLog("Erreur suppression marché : " . $e->getMessage());
        echo json_encode(array('ret' => "ko", 'msg' => 'Erreur lors de la suppression'));
      }
    } else {
      $ret = array('ret' => "ko", 'msg' => 'Marché non supprimé');
      echo json_encode($ret);
    }
    break;

  case "save_marches_listes":
    //! Enregistre les mises à jour du tableau des listes tarifaires par marché
    //! Réception du tableau des mots clés par marché en json
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->idListe)) {
      if ($data->idListe == "1") {
        foreach ($data as $key => $val) {
          if (substr($key, 0, 7) == "motcle_") {
            $fk_marche = trim(substr($key, 7));
            $motCle = trim($val);
            $motCleAchat = "";
            $motCleVente = "";
            foreach ($data as $keyAV => $valAV) {
              if ($keyAV == "motcleachat_" . $fk_marche) {
                $motCleAchat = trim($valAV);
              } else {
                if ($keyAV == "motclevente_" . $fk_marche) {
                  $motCleVente = trim($valAV);
                }
              }
            }

            $sql = 'SELECT l.rowid FROM marches_listes l WHERE l.fk_marche=' . $fk_marche . ';';
            $retour = getinfos($sql, "gen");
            if (count($retour) > 0) {
              $sql = 'UPDATE marches_listes SET mot_cle="' . $motCle . '", terme_achat="' . $motCleAchat . '", terme_vente="' . $motCleVente . '" WHERE fk_marche=' . $fk_marche . ';';
              qSQL($sql, "gen");
            } else {
              $sql = 'INSERT INTO marches_listes SET fk_marche=' . $fk_marche . ', mot_cle="' . $motCle . '", terme_achat="' . $motCleAchat . '", terme_vente="' . $motCleVente . '";';
              qSQL($sql, "gen");
            }
          }
        }
        $ret = array('ret' => "ok", "msg" => "Enregistrement des données effectué");
        echo json_encode($ret);
      } else {
        $ret = array('ret' => "ko", "msg" => "Erreur lors de la réception des données à enregistrer");
        echo json_encode($ret);
      }
    } else {
      $ret = array('ret' => "ko", "msg" => "Erreur lors de la réception des données à enregistrer");
      echo json_encode($ret);
    }
    break;

  case "load_produits_marche":
    //! Charge les produits d'un marché
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->cid)) {
      $cid = nettoie_input($data->cid);

      // On récupère certaines infos du marché pour savoir si on doit appliquer des filtres
      $sql = 'SELECT m.chk_remise_sur_tg FROM marches m WHERE m.rowid=' . $cid . ';';
      $retour = getinfos($sql, "gen");
      $chk_remise_sur_tg = $retour[0]["chk_remise_sur_tg"];

      if ($cid == 999 || $chk_remise_sur_tg == 1) {
        // c'est directement le TG, on ne fait rien de spécial
        $sql = 'SELECT p.rowid, p.code, p.libelle, concat(p.code, " # ", p.libelle) as rech, p.groupe, p.prix_achat_net, p.prix_vente, p.prc_discount_1 ';
        $sql .= 'FROM produits p WHERE p.fk_marche=' . $cid . ' AND p.active=1 ORDER BY p.code DESC;';
        echo getinfos($sql, "gen", "json");
      } else {
        // On regarde le terme_achat du marché
        $sql = 'SELECT l.terme_achat FROM marches_listes l WHERE l.fk_marche=' . $cid . ';';
        $retour = getinfos($sql, "gen");
        $terme_achat = $retour[0]["terme_achat"];

        if ($terme_achat == "Purchasing") {
          // On doit alors récupérer leur prix d'achat dans le marché TG
          $sql = 'SELECT p.rowid, p.code, p.libelle, concat(p.code, " # ", p.libelle) as rech, p.groupe, p.prix_achat_net, p.prix_vente, p.prc_discount_1 ';
          $sql .= 'FROM produits p WHERE p.fk_marche=' . $cid . ' AND p.active=1 ORDER BY p.code DESC;';
          $retour = getinfos($sql, "gen");
          if (count($retour) > 0) {
            foreach ($retour as &$prod) {
              $sql = 'SELECT p.prix_achat_net, p.prc_discount_1 FROM produits p WHERE p.fk_marche=999 AND p.code="' . $prod["code"] . '";';
              $retour2 = getinfos($sql, "gen");
              if (count($retour2) == 1) {
                $prod["prix_achat_net"] = $retour2[0]["prix_achat_net"];
                $prod["prc_discount_1"] = $retour2[0]["prc_discount_1"];
              }
            }
          }
          echo json_encode($retour);
        } else {
          $sql = 'SELECT p.rowid, p.code, p.libelle, concat(p.code, " # ", p.libelle) as rech, p.groupe, p.prix_achat_net, p.prix_vente, p.prc_discount_1 ';
          $sql .= 'FROM produits p WHERE p.fk_marche=' . $cid . ' AND p.active=1 ORDER BY p.code DESC;';
          echo getinfos($sql, "gen", "json");
        }

      }
    } else {
      $ret = array("ret" => "ko", "msg" => "Erreur lors de l'envoi du marché à charger");
      echo json_encode($ret);
    }
    break;

  case "load_marches_listes":
    //! Charge la liste des mots clés des marchés à retrouver dans les fichiers d'importation
    $sql = 'SELECT l.* FROM marches_listes l;';
    echo getinfos($sql, "gen", "json");
    break;

  case "load_user":
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->cid)) {
      $cid = nettoie_input($data->cid);
      $sql = 'SELECT u.* FROM users u WHERE u.rowid=' . $cid . ';';
      echo getinfos($sql, "gen", "json");
    } else {
      $ret = array("ret" => "ko", "msg" => "Erreur lors de la récupération des infos de l'utilisateur");
      echo json_encode($ret);
    }
    break;

  case "save_user":
    //! Réception et lecture de la demande en json
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->rowid)) {
      $cid = nettoie_input($data->rowid);
      $act = nettoie_input($data->act);

      $set = 'SET libelle="' . nettoie_input(trim($data->libelle)) . '"';
      $set .= ', prenom="' . nettoie_input(trim($data->prenom)) . '"';
      $set .= ', mobile="' . nettoie_input(trim($data->mobile)) . '"';
      $set .= ', email="' . nettoie_input(trim($data->email)) . '"';
      $set .= ', username="' . nettoie_input(trim($data->username)) . '"';
      $set .= ', fk_role=' . nettoie_input(trim($data->fk_role));
      $set .= ', fk_region=' . nettoie_input(trim($data->fk_region));
      if (isset($data->fk_parent)) {
        $set .= ', fk_parent=' . nettoie_input(trim($data->fk_parent));
      } else {
        $set .= ', fk_parent=0';
      }
      $set .= ', lst_depts="' . nettoie_input(trim($data->lst_depts)) . '"';
      $set .= isset($data->chk_grands_comptes) ? ', chk_grands_comptes=1' : ', chk_grands_comptes=0';
      $set .= isset($data->active) ? ', active=1' : ', active=0';

      if ($cid == 0) {
        // on lui crée un mot de passe par défaut : initiale prénom en majuscule + initiale nom Maj + 3 caractères suivants du nom en minuscules + . + mois + année
        // On supprime les espaces dans le nom de l'utilisateur et on ne garde que les 3 premiers caractères
        $libUser = str_replace(" ", "", nettoie_input(trim($data->libelle)));
        $pwd = strtoupper(substr(nettoie_input(trim($data->prenom)), 0, 1)) . strtoupper(substr($libUser, 0, 1)) . strtolower(substr($libUser, 1, 3)) . "." . date("mY");
        eLog($pwd);
        $set .= ', userpswd="' . hashPsswd($pwd) . '"';

        $set .= ', date_creat = "' . date("Y-m-d H:i:s") . '", fk_user_creat=' . $fk_user;
        $sql = 'INSERT INTO users ' . $set . ';';
      } else {
        $set .= ', date_modif = "' . date("Y-m-d H:i:s") . '", fk_user_modif=' . $fk_user;
        $sql = 'UPDATE users ' . $set . ' WHERE rowid=' . $cid . ';';
      }
      eLog($sql);
      qSQL($sql, "gen");

      $ret = array('ret' => "ok");
      echo json_encode($ret);
    } else {
      $ret = array('ret' => "ko");
      echo json_encode($ret);
    }
    break;

  case "delete_user":
    //! Réception et lecture de la demande en json
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->cid)) {
      // SÉCURITÉ : Validation de l'ID comme entier
      $cid = intval($data->cid);
      if ($cid <= 0) {
        echo json_encode(array('ret' => "ko", 'msg' => 'ID invalide'));
        break;
      }
      
      try {
        $db = Database::getInstance();
        // TODO : Supprimer les devis créés par cet utilisateur
        
        // Utilisation de la fonction sécurisée deleteById
        $result = $db->deleteById('users', $cid);
        
        if ($result) {
          eLog("Utilisateur supprimé : ID=$cid");
          echo json_encode(array('ret' => "ok"));
        } else {
          echo json_encode(array('ret' => "ko", 'msg' => 'Utilisateur non trouvé'));
        }
      } catch (Exception $e) {
        eLog("Erreur suppression utilisateur : " . $e->getMessage());
        echo json_encode(array('ret' => "ko", 'msg' => 'Erreur lors de la suppression'));
      }
    } else {
      echo json_encode(array('ret' => "ko", 'msg' => 'ID manquant'));
    }
    break;

  case "maintenance":
    if ($Conf->_devIp) {
      // Mise à jour des mots de passe Utilisateurs
      $sql = 'SELECT u.rowid, u.prenom, u.libelle FROM users u WHERE u.active=1 AND u.rowid=39;';
      $users = getinfos($sql, "gen");
      foreach ($users as $user) {
        $uId = $user["rowid"];
        $libUser = str_replace(" ", "", nettoie_input(trim($user["libelle"])));
        $pwd = strtoupper(substr(nettoie_input(trim($user["prenom"])), 0, 1)) . strtoupper(substr($libUser, 0, 1)) . strtolower(substr($libUser, 1, 3)) . "." . date("mY");
        eLog($pwd);
        $sql = 'UPDATE users SET userpswd="' . hashPsswd($pwd) . '" WHERE rowid=' . $uId . ';';
        eLog($sql);
        qSQL($sql, "gen");
      }
    }
    break;

  case "load_roles":
    $sql = 'SELECT xro.rowid, xro.libelle FROM x_roles xro WHERE xro.active=1 ORDER BY xro.rowid;';
    echo getinfos($sql, "gen", "json");
    break;

  case "load_regions":
    $sql = 'SELECT xre.rowid, xre.libelle FROM x_regions xre WHERE xre.active=1 ORDER BY xre.rowid;';
    echo getinfos($sql, "gen", "json");
    break;

  case "export_sap_devis":
    $data = json_decode(file_get_contents("php://input"));
    eLog("export_sap_devis: ");
    if (isset($data->cid)) {
      $cid = nettoie_input($data->cid);
      $sql = 'SELECT d.* FROM devis d WHERE d.rowid=' . $cid . ';';
      $dev = getinfos($sql, "gen");
      $devis = $dev[0];
      eLog("export_sap_devis: " . $cid . " & " . $devis["fk_client"]);

      $filename = "devis_" . $cid . "_" . date('Y_m_d_hi') . ".csv";
      $fields = array("Code", "Etablissement", "Adresse 1", "Adresse 2");

      // SÉCURITÉ : Utilisation de requête préparée pour l'ID client
      try {
        $db = Database::getInstance();
        $sql = 'SELECT c.code, c.libelle, c.adresse1, c.adresse2 FROM clients c WHERE c.rowid = :id';
        $client = $db->fetchOne($sql, [':id' => intval($devis["fk_client"])]);
        if (!$client) {
          $client = ['code' => '', 'libelle' => '', 'adresse1' => '', 'adresse2' => ''];
        }
      } catch (Exception $e) {
        error_log("Erreur export_sap_devis : " . $e->getMessage());
        $client = ['code' => '', 'libelle' => '', 'adresse1' => '', 'adresse2' => ''];
      }

      $excelData = implode("\t", array_values($fields)) . "\n";

      eLog($excelData);

      array_walk($client, 'filterData');
      $excelData .= implode("\t", array_values($client)) . "\n";

      $sql = 'SELECT p.code, p.libelle, p.prix_achat_net, p.prix_vente, dp.qte, dp.remise, dp.totalht FROM devis_produits dp LEFT JOIN produits p ON dp.fk_produit=p.rowid WHERE dp.fk_devis=' . $cid . ';';
      eLog($sql);
      $data = getinfos($sql, "gen");

      // une ligne vierge de séparation
      $excelData .= "\n";
      $fields = array("Code", "Désignation", "Prix Achat", "Prix Vente", "Quantité", "Remise", "Total HT");
      $excelData .= implode("\t", array_values($fields)) . "\n";

      foreach ($data as $row) {
        array_walk($row, 'filterData');
        $excelData .= implode("\t", $row) . "\n";
      }
      eLog($excelData);
      header("Content-Type: application/vnd.ms-excel; charset=UTF-16LE");
      header("Content-Disposition: attachment; filename=$filename");
      header("Content-Disposition: attachment; filename=\"$filename\"");
      echo $excelData;
      exit;
    }
    break;

  case "load_info":
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->cid)) {
      $cid = nettoie_input($data->cid);
      $sql = 'SELECT i.* FROM infos i WHERE i.rowid=' . $cid . ';';
      echo getinfos($sql, "gen", "json");
    }
    break;

  case "save_info":
    //! Réception et lecture de la demande en json
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->cid)) {
      $cid = nettoie_input($data->cid);

      $set = 'SET date_infos="' . nettoie_input($data->cdate) . '" ';
      $set .= ', titre_infos="' . nettoie_input(trim($data->ctitre)) . '" ';
      $set .= ', text_infos="' . nettoie_input(trim($data->ctexte)) . '" ';
      if (isset($data->cpublie)) {
        if ($data->cpublie == false || $data->cpublie == 0) {
          $set .= ', chk_publie=0';
        } else {
          $set .= ', chk_publie=1';
        }
      } else {
        $set .= ', chk_publie=0';
      }

      if ($cid == 0) {
        $set .= ', date_creat = "' . date("Y-m-d H:i:s") . '", fk_user_creat=' . $fk_user;
        $sql = 'INSERT INTO infos ' . $set . ';';
      } else {
        $set .= ', date_modif = "' . date("Y-m-d H:i:s") . '", fk_user_modif=' . $fk_user;
        $sql = 'UPDATE infos ' . $set . ' WHERE rowid=' . $cid . ';';
      }
      eLog($sql);
      qSQL($sql, "gen");
      $ret = array('ret' => "ok");
      echo json_encode($ret);
    } else {
      $ret = array('ret' => "ko");
      echo json_encode($ret);
    }
    break;

  case "supp_info":
    //! Réception et lecture de la demande en json
    $data = json_decode(file_get_contents("php://input"));
    if (isset($data->cid)) {
      // SÉCURITÉ : Validation de l'ID comme entier
      $cid = intval($data->cid);
      if ($cid <= 0) {
        echo json_encode(array('ret' => "ko", 'msg' => 'ID invalide'));
        break;
      }
      
      try {
        $db = Database::getInstance();
        $sql = 'DELETE FROM infos WHERE rowid = :id';
        $stmt = $db->query($sql, ['id' => $cid]);
        $result = $stmt->rowCount() > 0;
        
        if ($result) {
          eLog("Info supprimée : ID=$cid");
          echo json_encode(array('ret' => "ok"));
        } else {
          echo json_encode(array('ret' => "ko", 'msg' => 'Info non trouvée'));
        }
      } catch (Exception $e) {
        eLog("Erreur suppression info : " . $e->getMessage());
        echo json_encode(array('ret' => "ko", 'msg' => 'Erreur lors de la suppression'));
      }
    }
    break;

}
exit();
