// services/parcoursService.js
const { db } = require("../db/db-connect");
const logger = require("../utils/logger");
const globalService = require("../services/globalService");

/**
 * Récupère un parcours par son numéro (avec expand utiles)
 */
async function getParcoursByNumParcours(numParcours) {
  const criteria = {
    filter: `numParcours='${numParcours}'`,
    expand: [
      "dernierUtilisateur.region",
      "contrat",
      "contrat.client",
      "contrat.intermediaire"
    ].join(",")
  };
  return globalService.fetchInfoByCriteria("parcours", criteria);
}

/**
 * Full list (batch côté PocketBase). | Fetch l'ensemble de la BD via chunk "batch"
 * SDK 0.7.x : getFullList(collection, batchSize, options)
 */
async function getParcoursFullList({ filter, sort, expand, fields, batch = 500 }) {
  const options = {
    sort: sort || "-created",
  };
  
  // Ajouter expand si défini
  if (expand) {
    options.expand = expand;
  }
  
  // Ajouter fields si défini
  if (fields) {
    options.fields = fields;
  }
  
  // Ajouter filter SEULEMENT s'il n'est pas vide (SDK 0.7.x rejette les filtres vides)
  if (filter && filter.trim() !== "") {
    options.filter = filter;
  }
  
  // SDK 0.7.x : getFullList(collection, batchSize, options)
  return db.records.getFullList("parcours", batch, options);
}
/**
 * Pagination multi-régions + filtres/tri optionnels (server-side DataTables)
 * – Parcours une seule fois db par requête
 * @param {string[]} regions
 * @param {number} page
 * @param {number} perPage
 * @param {{filter?: string, sort?: string}} opts
 */
async function getParcoursByRegionsPage(regions = [], page = 1, perPage = 10, opts = {}) {
  try {
    let regFilter = "";
    if (Array.isArray(regions) && regions.length > 0) {
      const ors = regions.map(r => `dernierUtilisateur.region.nom = "${r}"`);
      regFilter = `(${ors.join(" || ")})`;
    }

    const filter = [regFilter, opts.filter].filter(Boolean).join(" && ");

    /**
     * Récupération des parcours avec expands nécessaires
     * Note: L'expand de contrat.client ne fonctionne pas toujours,
     * d'où la nécessité d'un fallback dans le contrôleur
     */
    const list = await db.records.getList("parcours", page, perPage, {
      sort: opts.sort || "-created",
      filter: filter || "",
      expand: [
        "contrat",
        "contrat.client",
        "contrat.intermediaire",
        "dernierUtilisateur.region"
      ].join(","),
    });

    return {
      page: list.page,
      perPage: list.perPage,
      totalItems: list.totalItems,
      totalPages: list.totalPages,
      items: list.items,
    };
  } catch (error) {
    logger.log('error', error);
    throw error;
  }
}

/**
 * Création d'un parcours vide
 */
async function createNewEmptyParcours(numParcours) {
  try {
    const data = { ["numParcours"]: numParcours };
    const record = await db.records.create("parcours", data);
    if (record) {
      return record.id;
    } else {
      return null;
    }
  } catch (error) {
    logger.log("error", error);
    return null;
  }
}

/**
 * MAJ d'un champ d'un parcours
 */
async function updateFieldValueParcours(id, field, value) {
  try {
    const data = { [field]: value };
    const record = await db.records.update("parcours", id, data);
    if (record) {
      return record.id;
    } else {
      return null;
    }
  } catch (error) {
    logger.log("error", error);
    return null;
  }
}

/**
 * Génère le prochain numéro de parcours
 */
async function getNewParcoursNumber() {
  try {
    const list = await db.records.getList("parcours", 1, 1, { sort: "-numParcours" });
    const last = list?.items?.[0];
    if (!last?.numParcours) return null;

    const numericValue = parseInt(String(last.numParcours).substring(1), 10);
    if (Number.isNaN(numericValue)) return null;

    const next = numericValue + 1;
    return "P" + next.toString().padStart(9, "0");
  } catch (error) {
    logger.log("error", error);
    return null;
  }
}

// --- Section détails profonds (contrat + fiche produit) --- //

/**
 * Récupère un parcours (via numParcours) avec les expands utiles pour détails.
 */
async function getParcoursForDetails(numParcours) {
  try {
    const list = await db.records.getList("parcours", 1, 1, {
      filter: `numParcours='${numParcours}'`,
      expand: [
        "contrat",
        "contrat.client",
        "contrat.intermediaire",
        "dernierUtilisateur.region"
      ].join(","),
    });
    return list?.items?.[0] || null;
  } catch (e) {
    logger.log("error", e);
    return null;
  }
}

/**
 * Mappe un libellé produit vers la collection PocketBase (à ajuster si changement de parcours).
 */
function mapProduitToCollection(produitRaw = "") {
  const p = String(produitRaw || "").trim().toUpperCase();
  const map = {
    "TPPC": "tppc",
    "RC": "rc",
    "FAC": "fac",
  };
  return map[p] || null;
}

/**
 * Récupère la fiche produit pour un contrat donné.
 * On tente d'abord par relation "contrat = contratId" si elle existe,
 * sinon fallback par "numContrat = x" si jamais la fiche stocke le numéro.
 */
async function getProduitRecordForContrat(contrat, opts = {}) {
  try {
    if (!contrat) return null;
    const collection = mapProduitToCollection(contrat.produit);
    if (!collection) return null;

    // Tente via une relation directe "contrat" (champ le plus propre)
    try {
      const record = await db.records.getFirstListItem(collection, `contrat='${contrat.id}'`, {
      });
      if (record) return record;
    } catch (_) { /* ignore, on tente le fallback */ }

    // Fallback
    if (contrat.numContrat) {
      try {
        const record = await db.records.getFirstListItem(collection, `numContrat='${contrat.numContrat}'`, {});
        if (record) return record;
      } catch (_) { /* ignore */ }
    }

    return null;
  } catch (e) {
    logger.log("error", e);
    return null;
  }
}

/**
 * reformatage texte - a virer
 */
function escPB(s = "") {
  return String(s).replace(/"/g, '\\"');
}


/**
 * Détails complets: parcours + contrat + fiche produit
 */
async function getDeepDetailsByNumParcours(numParcours) {
  try {
    const filter = `numParcours = "${escPB(numParcours)}"`;

    const list = await db.records.getList("parcours", 1, 1, {
      filter,
      expand: [
        "contrat",
        "contrat.client",
        "contrat.intermediaire",
        "dernierUtilisateur.region",
        // produit lié
        "contrat.tppc",
        "contrat.rc",
        "contrat.fac",
        // sous-relations TPPC
        "contrat.tppc.tarif",
        "contrat.tppc.projet",
      ].join(","),
    });

    return list?.items?.[0] || null;
  } catch (e) {
    logger.log("error", e);
    return null;
  }
}

module.exports = {
  getNewParcoursNumber,
  getParcoursByNumParcours,
  createNewEmptyParcours,
  updateFieldValueParcours,
  getParcoursByRegionsPage,
  getParcoursFullList,
  getParcoursForDetails,
  getProduitRecordForContrat,
  getDeepDetailsByNumParcours,
  mapProduitToCollection,      
};