#!/usr/bin/env python3
"""Génère `catalogue-source.csv` : un export fournisseur réaliste et sale.

Ce fichier n'est PAS le livrable. C'est la matière première de la démonstration : il
reproduit les défauts qu'on trouve réellement dans un export PrestaShop/fournisseur
(unités mélangées, prix en deux formats, doublons de SKU, catégories libres, GTIN
manquants ou invalides, HTML résiduel, espaces insécables, casse aléatoire).
Graine fixe : le fichier est reproductible à l'identique.
"""
import csv, random, os

random.seed(20260802)
HERE = os.path.dirname(os.path.abspath(__file__))

familles = [
    ("Sac à dos", "randonnee", ["20", "30", "40", "55"], "L", (59, 189)),
    ("Réchaud", "cuisine-outdoor", ["48", "95", "130"], "g", (24, 89)),
    ("Lampe frontale", "eclairage", ["200", "400", "600", "1000"], "lm", (19, 79)),
    ("Duvet", "couchage", ["-5", "0", "5", "10"], "°C", (69, 249)),
    ("Matelas gonflable", "couchage", ["3", "5", "7"], "cm", (39, 129)),
    ("Bâtons de marche", "randonnee", ["110", "120", "130"], "cm", (29, 99)),
    ("Gourde isotherme", "hydratation", ["500", "750", "1000"], "ml", (14, 39)),
    ("Tente", "couchage", ["1", "2", "3"], "pl", (99, 399)),
]
marques = ["kerhan", "KERHAN", "Kerhan ", "Nordvik", "NORDVIK", "nordvik", "Aravis", "ARAVIS"]
cat_libres = {
    "randonnee": ["Randonnée", "randonnee", "Rando / Trek", "RANDONNEE", "Randonnée > Sacs", "trek"],
    "cuisine-outdoor": ["Cuisine outdoor", "cuisine", "Réchauds", "COOKING", "Cuisine / Réchauds"],
    "eclairage": ["Éclairage", "eclairage", "Lampes", "LIGHTING", "Eclairage > Frontales"],
    "couchage": ["Couchage", "couchage", "Sommeil", "SLEEPING", "Bivouac / Couchage"],
    "hydratation": ["Hydratation", "hydratation", "Gourdes", "DRINK", "Boissons"],
}
couleurs = ["Noir", "noir", "NOIR", "Bleu marine", "bleu marine", "Vert lichen", "Terracotta", "", "  "]
matieres = ["Nylon ripstop 210D", "nylon 210d", "Polyester 600D", "aluminium 7075",
            "Acier inoxydable", "inox", "Duvet 700 CUIN", "", "n/a", "-"]

def prix(lo, hi):
    v = round(random.uniform(lo, hi), 2)
    style = random.random()
    if style < 0.35:
        return f"{v:.2f} €".replace(".", ",")
    if style < 0.55:
        return f"{v:.2f}EUR"
    if style < 0.65:
        return f"  {v:.2f}  "
    return f"{v:.2f}"

def poids():
    g = random.randint(45, 3200)
    style = random.random()
    if style < 0.30:
        return f"{g}g"
    if style < 0.50:
        return f"{g/1000:.2f} kg".replace(".", ",")
    if style < 0.60:
        return f"{g} grammes"
    if style < 0.68:
        return ""
    return str(g)

def gtin(i):
    r = random.random()
    if r < 0.28:
        return ""
    if r < 0.36:
        return "0000000000000"
    if r < 0.44:
        return str(random.randint(10**11, 10**12 - 1))          # 12 chiffres : trop court
    base = f"301{i:09d}"
    chk = (10 - sum((3 if k % 2 else 1) * int(d) for k, d in enumerate(base)) % 10) % 10
    if r < 0.52:
        chk = (chk + 1) % 10                                     # clé fausse
    return base + str(chk)

rows = []
i = 0
for nom, fam, variantes, unite, (lo, hi) in familles:
    for v in variantes:
        for _ in range(random.randint(3, 5)):
            i += 1
            marque = random.choice(marques)
            sep = random.choice([" ", " ", "  ", " "])
            lib = f"{nom}{sep}{v}{random.choice(['', ' '])}{unite}"
            if random.random() < 0.12:
                lib = f"<p>{lib}</p>"
            if random.random() < 0.10:
                lib = lib.upper()
            if random.random() < 0.08:
                lib += "  "
            rows.append({
                "reference": f"{fam[:3].upper()}-{i:04d}",
                "libelle": lib,
                "marque": marque,
                "categorie": random.choice(cat_libres[fam]),
                "prix_ttc": prix(lo, hi),
                "poids": poids(),
                "couleur": random.choice(couleurs),
                "matiere": random.choice(matieres),
                "gtin": gtin(i),
                "stock": random.choice([str(random.randint(0, 300)), "", "n/c", "-1"]),
                "description_fournisseur": random.choice([
                    "", "", "Produit de qualité supérieure.", "Voir fiche technique",
                    "PRODUIT DE QUALITE SUPERIEURE!!!", "&nbsp;", "<br/>", "à compléter"]),
            })

# doublons de référence (même SKU, deux lignes) : 6 cas
for r in random.sample(rows, 6):
    d = dict(r)
    d["prix_ttc"] = prix(20, 150)
    d["stock"] = str(random.randint(0, 50))
    rows.append(d)

# lignes vides de libellé : 3 cas
for r in random.sample(rows, 3):
    d = dict(r); d["reference"] = d["reference"] + "-BIS"; d["libelle"] = "   "
    rows.append(d)

random.shuffle(rows)
cols = list(rows[0].keys())
with open(os.path.join(HERE, "catalogue-source.csv"), "w", newline="", encoding="utf-8") as f:
    w = csv.DictWriter(f, fieldnames=cols); w.writeheader(); w.writerows(rows)
print(f"catalogue-source.csv : {len(rows)} lignes, {len(cols)} colonnes")
