/* =====================================================================
 * Modèle de données habillement JSP + détection des commandes.
 * ===================================================================== */

const JSP_NIVEAUX = [
  { value: 'JSP1', label: 'JSP 1', row: 'bg-sky-50', dot: 'bg-sky-500', chip: 'bg-sky-100 text-sky-800 border-sky-300' },
  { value: 'JSP2', label: 'JSP 2', row: 'bg-emerald-50', dot: 'bg-emerald-500', chip: 'bg-emerald-100 text-emerald-800 border-emerald-300' },
  { value: 'JSP3', label: 'JSP 3', row: 'bg-amber-50', dot: 'bg-amber-500', chip: 'bg-amber-100 text-amber-800 border-amber-300' },
  { value: 'JSP4', label: 'JSP 4', row: 'bg-rose-50', dot: 'bg-rose-500', chip: 'bg-rose-100 text-rose-800 border-rose-300' },
];
const niveauOf = (v) => JSP_NIVEAUX.find((n) => n.value === v) || JSP_NIVEAUX[0];

const JSP_CHECK_FIELDS = [
  { key: 'ceinture', label: 'Ceinture' },
  { key: 'ecusson', label: 'Écusson' },
  { key: 'grade', label: 'Grade' },
];

const JSP_OPS_FIELDS = [
  { key: 'casque', label: 'Casque', placeholder: 'N°' },
  { key: 'pantalon', label: 'Pantalon', placeholder: '14/4' },
  { key: 'polo', label: 'Polo', placeholder: '12/3' },
  { key: 'veste', label: 'Veste', placeholder: '14/3' },
  { key: 'softshell', label: 'Softshell', placeholder: '14/3' },
  { key: 'rangers', label: 'Rangers', placeholder: '40' },
  { key: 'gants', label: 'Gants', placeholder: '8/4' },
];

const JSP_SPORT_FIELDS = [
  { key: 'sportPantalon', label: 'Pantalon sport', placeholder: '164/2' },
  { key: 'sportPolo', label: 'Polo sport', placeholder: 'S' },
  { key: 'sportVeste', label: 'Veste sport', placeholder: 'M/6' },
];

const JSP_TEXT_FIELDS = [...JSP_OPS_FIELDS, ...JSP_SPORT_FIELDS];

function newJsp(annee) {
  const jsp = { id: uid(), annee, nom: '', prenom: '', niveau: 'JSP1', notes: '' };
  JSP_CHECK_FIELDS.forEach((f) => (jsp[f.key] = false));
  JSP_TEXT_FIELDS.forEach((f) => (jsp[f.key] = ''));
  return jsp;
}

/* ---------- Détection « à commander » ----------
 * Exemples reconnus :
 *   "Commande 164"      → demandé : 164
 *   "40 COMMANDE 41"    → actuel : 40, demandé : 41
 *   "Commande 6 gants"  → demandé : 6 gants
 *   "M à commander"     → demandé : M
 *   "cde 38"            → demandé : 38
 */
const COMMANDE_REGEX = /^(.*?)(?<![\p{L}\p{N}])(?:commander|commandées?|commandés?|commande|cmde|cde|cmd)(?![\p{L}\p{N}])[\s:.\-]*(.*)$/iu;

function parseCommande(value) {
  if (value === null || value === undefined) return null;
  const raw = String(value).trim();
  if (!raw) return null;
  const m = raw.match(COMMANDE_REGEX);
  if (!m) return null;
  const avant = m[1]
    .trim()
    .replace(/(^|\s)[àa]$/iu, '')
    .replace(/[-:/]+$/, '')
    .trim();
  const apres = m[2].trim();
  return {
    brut: raw,
    actuel: apres && avant ? avant : '',
    demande: apres || avant || 'À préciser',
  };
}

const isCommande = (value) => parseCommande(value) !== null;

/** Liste à plat des équipements à commander pour un ensemble de JSP. */
function jspCommandes(jsps) {
  const out = [];
  jsps.forEach((jsp) => {
    JSP_TEXT_FIELDS.forEach((field) => {
      const parsed = parseCommande(jsp[field.key]);
      if (parsed) out.push({ jsp, field, ...parsed });
    });
  });
  return out;
}

/** Équipements « à cocher » non encore attribués. */
function jspManquants(jsps) {
  const out = [];
  jsps.forEach((jsp) => {
    JSP_CHECK_FIELDS.forEach((field) => {
      if (!jsp[field.key]) out.push({ jsp, field });
    });
  });
  return out;
}

/** Regroupe les commandes par article puis par taille demandée. */
function groupCommandes(commandes) {
  const groups = new Map();
  commandes.forEach((c) => {
    if (!groups.has(c.field.key)) groups.set(c.field.key, { field: c.field, tailles: new Map(), total: 0 });
    const g = groups.get(c.field.key);
    const key = c.demande.toUpperCase();
    if (!g.tailles.has(key)) g.tailles.set(key, { taille: c.demande, jsps: [] });
    g.tailles.get(key).jsps.push(c.jsp);
    g.total += 1;
  });
  const order = JSP_TEXT_FIELDS.map((f) => f.key);
  return [...groups.values()].sort((a, b) => order.indexOf(a.field.key) - order.indexOf(b.field.key));
}

function currentSchoolYear(date = new Date()) {
  const y = date.getFullYear();
  return date.getMonth() >= 7 ? `${y}-${y + 1}` : `${y - 1}-${y}`;
}

function nextSchoolYear(annee) {
  const start = parseInt(String(annee).split('-')[0], 10);
  if (!start) return currentSchoolYear();
  return `${start + 1}-${start + 2}`;
}

function promoteNiveau(niveau) {
  const idx = JSP_NIVEAUX.findIndex((n) => n.value === niveau);
  if (idx < 0 || idx >= JSP_NIVEAUX.length - 1) return null;
  return JSP_NIVEAUX[idx + 1].value;
}

const jspFullName = (j) => `${(j.nom || '').toUpperCase()} ${j.prenom || ''}`.trim() || 'Sans nom';

function sortJsps(list) {
  return [...list].sort(
    (a, b) =>
      JSP_NIVEAUX.findIndex((n) => n.value === a.niveau) - JSP_NIVEAUX.findIndex((n) => n.value === b.niveau) ||
      (a.nom || a.prenom || '').localeCompare(b.nom || b.prenom || '', 'fr') ||
      (a.prenom || '').localeCompare(b.prenom || '', 'fr'),
  );
}

/* ---------- Stock d'habillement ----------
 * Notation du tableau : « taille/numéro » (ex : S/10 = 10e polo de taille S).
 * Chaque pièce du stock est identifiée par (article, taille, numéro).
 * Les casques n'ont qu'un numéro. Les rangers (simple pointure) ne sont pas numérotées.
 */
const STOCK_ARTICLES = [
  ...JSP_OPS_FIELDS.filter((f) => f.key !== 'rangers'),
  ...JSP_SPORT_FIELDS,
];
const stockArticleOf = (key) => STOCK_ARTICLES.find((a) => a.key === key) || { key, label: key };

/** Lit « S/10 » → { taille: 'S', numero: 10 } ; casque « 6 » → { taille: '', numero: 6 }. */
function parseTailleNumero(value, articleKey) {
  const s = String(value ?? '').trim();
  if (!s || isCommande(s)) return null;
  if (articleKey === 'casque') {
    const m = s.match(/^(?:n°\s*)?(\d+)$/i);
    return m ? { taille: '', numero: Number(m[1]) } : null;
  }
  const m = s.match(/^([A-Za-z0-9]+)\s*\/\s*(\d+)$/);
  return m ? { taille: m[1].toUpperCase(), numero: Number(m[2]) } : null;
}

const stockKey = (article, taille, numero) => `${article}|${taille}|${numero}`;
const stockCode = (taille, numero) => (taille ? `${taille}/${numero}` : `N° ${numero}`);

/** Ordre des tailles : numériques croissantes (12, 14, 16, 164) puis lettres (XS → XXL). */
const LETTER_SIZES = ['XXS', 'XS', 'S', 'M', 'L', 'XL', 'XXL', 'XXXL'];
function compareTailles(a, b) {
  const na = /^\d+$/.test(a), nb = /^\d+$/.test(b);
  if (na && nb) return Number(a) - Number(b);
  if (na !== nb) return na ? -1 : 1;
  const ia = LETTER_SIZES.indexOf(a), ib = LETTER_SIZES.indexOf(b);
  if (ia >= 0 && ib >= 0) return ia - ib;
  return a.localeCompare(b, 'fr');
}

/**
 * Analyse les affectations du tableau :
 *  - attributions : Map clé de pièce → liste des { jsp, field }
 *  - anomalies    : saisies non reconnues (ex : « 16/pas de numéro »)
 */
function stockAttributions(jsps) {
  const attributions = new Map();
  const anomalies = [];
  jsps.forEach((jsp) => {
    STOCK_ARTICLES.forEach((field) => {
      const raw = jsp[field.key];
      if (!raw || !String(raw).trim() || isCommande(raw)) return;
      const parsed = parseTailleNumero(raw, field.key);
      if (!parsed) {
        // Taille seule (ex : « S » en tenue de sport) : pas de numéro à suivre.
        if (/^[A-Za-z0-9]+$/.test(String(raw).trim()) && field.key !== 'casque') return;
        anomalies.push({ jsp, field, raw });
        return;
      }
      const key = stockKey(field.key, parsed.taille, parsed.numero);
      if (!attributions.has(key)) attributions.set(key, []);
      attributions.get(key).push({ jsp, field });
    });
  });
  return { attributions, anomalies };
}

/** Complète le stock : pour chaque (article, taille), crée les numéros 1 → numéro max rencontré. */
function buildStockFromJsps(jsps, existing = []) {
  const max = new Map();
  jsps.forEach((jsp) => {
    STOCK_ARTICLES.forEach((field) => {
      const parsed = parseTailleNumero(jsp[field.key], field.key);
      if (!parsed) return;
      const k = `${field.key}|${parsed.taille}`;
      max.set(k, Math.max(max.get(k) || 0, parsed.numero));
    });
  });
  const known = new Set(existing.map((i) => stockKey(i.article, i.taille, i.numero)));
  const added = [];
  max.forEach((n, k) => {
    const [article, taille] = k.split('|');
    for (let numero = 1; numero <= n; numero += 1) {
      const key = stockKey(article, taille, numero);
      if (!known.has(key)) {
        known.add(key);
        added.push({ id: uid(), article, taille, numero, hs: false });
      }
    }
  });
  return { stock: [...existing, ...added], added: added.length };
}
