# Session 2026-01-05 - Améliorations de l'import PCI

## Contexte

Suite à l'implémentation de l'import PCI, l'utilisateur a testé avec ses périphériques réels:
- **NVMe SSD**: Micron/Crucial Technology P2/P3/P3 Plus NVMe PCIe SSD
- **Carte graphique**: NVIDIA GeForce RTX 3060 Lite Hash Rate (Gigabyte)

## Problèmes identifiés

### 1. Parsing incorrect du vendor/device name

**Problème initial:**
```
Description: "Micron/Crucial Technology P2 [Nick P2] / P3 / P3 Plus NVMe PCIe SSD"
├─ Vendor: "Micron/Crucial"  ❌ (incomplet)
└─ Device: "Technology P2 [Nick P2] / P3 / P3 Plus NVMe PCIe SSD"  ❌ (incorrect)

Description: "NVIDIA Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]"
├─ Vendor: "NVIDIA"  ❌ (incomplet)
└─ Device: "Corporation GA106 [GeForce RTX 3060 Lite Hash Rate]"  ❌ (incorrect)
```

Le parser divisait simplement sur le premier espace, ce qui ne fonctionnait pas avec les vendor names multi-mots.

**Solution implémentée:**

Nouvelle fonction `_split_vendor_device()` dans `lspci_parser.py` qui détecte les suffixes de vendor:
- Corporation
- Technology
- Semiconductor
- Co., Ltd.
- Inc.
- GmbH
- AG

```python
def _split_vendor_device(description: str) -> Tuple[str, str]:
    vendor_suffixes = [
        r'\bCo\.,?\s*Ltd\.?',
        r'\bCorporation\b',
        r'\bTechnology\b',
        r'\bSemiconductor\b',
        # ... autres patterns
    ]
    # Trouve le suffixe et divise à sa fin
```

**Résultat:**
```
✅ NVMe:
  Vendor: "Micron/Crucial Technology"
  Device: "P2 [Nick P2] / P3 / P3 Plus NVMe PCIe SSD (DRAM-less)"

✅ GPU:
  Vendor: "NVIDIA Corporation"
  Device: "GA106 [GeForce RTX 3060 Lite Hash Rate]"
```

### 2. Device name contenait prog-if et revision

**Problème:**
```
Device: "P2 [Nick P2] / P3 Plus NVMe PCIe SSD (prog-if 02 [NVM Express])"
```

**Solution:**
Nettoyage du device_name après extraction:
```python
# Clean prog-if from device_name
result["device_name"] = re.sub(r'\s*\(prog-if\s+[0-9a-fA-F]+\s*\[[^\]]+\]\)', '', result["device_name"])
```

**Résultat:**
```
✅ Device: "P2 [Nick P2] / P3 / P3 Plus NVMe PCIe SSD (DRAM-less)"
```

### 3. Extraction incorrecte de la marque et du modèle

**Problème:**
- Marque: vendor name complet au lieu du premier mot
- Modèle: device name complet au lieu du nom commercial

**Solution:**

Nouvelle fonction `extract_brand_model()` dans `lspci_parser.py`:

```python
def extract_brand_model(vendor_name: str, device_name: str, device_class: str) -> Tuple[str, str]:
    # Extract brand (first word of vendor, before /)
    brand = vendor_name.split()[0] if vendor_name else ""
    if '/' in brand:
        brand = brand.split('/')[0]  # "Micron/Crucial" -> "Micron"

    # For GPUs: use bracket content
    if 'vga' in device_class.lower():
        # "GA106 [GeForce RTX 3060]" -> "GeForce RTX 3060"
        bracket_content = extract_from_brackets(device_name)
        model = bracket_content

    # For NVMe: clean brackets and combine
    elif 'nvme' in device_class.lower():
        # "P2 [Nick P2] / P3 / P3 Plus NVMe SSD"
        # -> "P2/P3/P3 Plus NVMe PCIe SSD"
        cleaned = remove_brackets(device_name)
        model = cleaned
```

**Résultats:**

```
✅ NVMe:
  Marque: "Micron"
  Modèle: "P2/P3/P3 Plus NVMe PCIe SSD (DRAM-less)"
  Nom: "Micron P2/P3/P3 Plus NVMe PCIe SSD (DRAM-less)"

✅ GPU:
  Marque: "NVIDIA"
  Modèle: "GeForce RTX 3060 Lite Hash Rate"
  Nom: "NVIDIA GeForce RTX 3060 Lite Hash Rate"
```

### 4. Fabricant de la carte graphique non extrait

**Problème:**
Pour les GPU, le subsystem contient le fabricant de la carte (Gigabyte, ASUS, MSI, etc.) mais n'était pas extrait.

**Solution:**

Ajout dans l'endpoint `/import/pci/extract`:
```python
# For GPUs, extract card manufacturer from subsystem
if sous_type == "Carte graphique" and device_info.get("subsystem"):
    subsystem_parts = device_info["subsystem"].split()
    if subsystem_parts:
        card_manufacturer = subsystem_parts[0]
        if card_manufacturer.lower() not in ["device", "subsystem"]:
            suggested["fabricant"] = card_manufacturer
```

**Résultat:**
```
✅ GPU:
  Marque: "NVIDIA" (chipset manufacturer)
  Fabricant: "Gigabyte" (card manufacturer)
  Modèle: "GeForce RTX 3060 Lite Hash Rate"
```

## Fichiers modifiés

### 1. `/backend/app/utils/lspci_parser.py`

**Nouvelles fonctions:**
- `extract_brand_model()` - Extraction intelligente marque/modèle
- `_split_vendor_device()` - Division vendor/device basée sur suffixes

**Améliorations:**
- Nettoyage du `prog-if` dans device_name
- Meilleure extraction du vendor name

### 2. `/backend/app/api/endpoints/peripherals.py`

**Import ajouté:**
```python
from app.utils.lspci_parser import extract_brand_model
```

**Amélioration de la construction du peripheral suggéré:**
```python
# Extract brand and model
brand, model = extract_brand_model(
    device_info.get("vendor_name", ""),
    device_info.get("device_name", ""),
    device_info.get("device_class", "")
)

# Build name
nom = f"{brand} {model}".strip()

suggested = {
    "nom": nom,
    "marque": brand,
    "modele": model,
    # ... autres champs
}

# For GPUs, add card manufacturer
if sous_type == "Carte graphique":
    suggested["fabricant"] = extract_from_subsystem()
```

## Résultats des tests

### Test NVMe - Micron/Crucial P2/P3

```json
{
  "nom": "Micron P2/P3/P3 Plus NVMe PCIe SSD (DRAM-less)",
  "type_principal": "PCI",
  "sous_type": "SSD NVMe",
  "marque": "Micron",
  "modele": "P2/P3/P3 Plus NVMe PCIe SSD (DRAM-less)",
  "pci_device_id": "c0a9:5407",
  "caracteristiques_specifiques": {
    "slot": "01:00.0",
    "device_class": "Non-Volatile memory controller",
    "vendor_name": "Micron/Crucial Technology",
    "subsystem": "Micron/Crucial Technology P2 [Nick P2] / P3 / P3 Plus NVMe PCIe SSD (DRAM-less)",
    "driver": "nvme",
    "iommu_group": "14",
    "revision": "01",
    "modules": "nvme"
  }
}
```

### Test GPU - NVIDIA RTX 3060

```json
{
  "nom": "NVIDIA GeForce RTX 3060 Lite Hash Rate",
  "type_principal": "PCI",
  "sous_type": "Carte graphique",
  "marque": "NVIDIA",
  "modele": "GeForce RTX 3060 Lite Hash Rate",
  "pci_device_id": "10de:2504",
  "fabricant": "Gigabyte",
  "caracteristiques_specifiques": {
    "slot": "08:00.0",
    "device_class": "VGA compatible controller",
    "vendor_name": "NVIDIA Corporation",
    "subsystem": "Gigabyte Technology Co., Ltd Device 4074",
    "driver": "nvidia",
    "iommu_group": "16",
    "revision": "a1",
    "modules": "nvidia"
  }
}
```

## Workflow complet de l'import PCI

1. **Détection**: Utilisateur colle `lspci -v` et `lspci -n` dans la modale
2. **Parsing**: Backend détecte tous les périphériques avec slots
3. **Sélection**: Frontend affiche les périphériques avec checkboxes
4. **Queue**: Périphériques sélectionnés ajoutés à `window.pciImportQueue`
5. **Import séquentiel**: Pour chaque périphérique:
   - Backend extrait et classifie
   - Détecte les doublons
   - Construit le peripheral suggéré avec marque/modèle
   - Frontend ouvre la modale d'ajout pré-remplie
   - Utilisateur valide/modifie
   - Sauvegarde et passe au suivant automatiquement

## Améliorations futures possibles

1. **Base de données PCI IDs**: Intégrer une base pour résoudre les vendor:device IDs en noms
2. **Photos automatiques**: Rechercher des photos de produits via API (Google Images, etc.)
3. **Détection de specs**: Extraire RAM pour GPU, capacité pour NVMe depuis autres sources
4. **Import groupé**: Option pour importer tous les périphériques sélectionnés sans validation individuelle

## Conclusion

✅ Le parsing PCI est maintenant intelligent et extrait correctement:
- Vendor names multi-mots (Corporation, Technology, Co., Ltd.)
- Device names nettoyés (sans prog-if, rev)
- Marques commerciales (premier mot du vendor)
- Modèles commerciaux (contenu des brackets pour GPU, nettoyé pour storage)
- Fabricant de carte (pour GPU, depuis subsystem)

Les périphériques importés auront des noms propres et exploitables pour l'inventaire.
