<?php

declare(strict_types=1);

namespace App\Module\Catalog\Infrastructure\DataFixtures;

use App\Module\Catalog\Domain\Entity\CategoryType;
use App\Module\Catalog\Domain\Repository\CategoryTypeRepositoryInterface;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;

/**
 * Fixtures du module Catalog : seed du type de categorie (M1).
 *
 * Refonte taxonomie ERP-78 : le type CLIENT (code CLIENT, label « Client »)
 * porte les categories clients ; Distributeur / Courtier / Secteur / Autre (et
 * les categories metier fines) sont des `Category` codees rattachees a ce type
 * (cf. CategoryFixtures + migration Version20260602100000).
 *
 * ERP-84 : ajout du type FOURNISSEUR (code FOURNISSEUR, label « Fournisseur »),
 * taxonomie distincte des fournisseurs (Negociant, Cooperative...). Mirroir de
 * la migration Version20260605120000.
 *
 * M3 1.1 : ajout du type PRESTATAIRE (code PRESTATAIRE, label « Prestataire »),
 * taxonomie distincte des prestataires (Maintenance industrielle, Nettoyage,
 * Transport). Mirroir de la migration Version20260612080000.
 *
 * Pourquoi une fixture EN PLUS du seed de la migration : `category_type` est une
 * entite managee par l ORM, donc le purger Doctrine la vide avant chaque
 * `doctrine:fixtures:load`. Sans cette fixture, le type CLIENT seede par la
 * migration disparaitrait apres `make db-reset` / setup de test. Le seed
 * migration couvre la prod (ou les fixtures ne tournent pas) ; cette fixture
 * re-aligne dev et test. Les deux chemins produisent un etat identique.
 *
 * Idempotence : lookup par `code` parmi les types existants avant insertion,
 * sur le modele d AppFixtures::ensureSystemRole. Rejouable sans doublon meme
 * si le purger est desactive.
 */
class CategoryTypeFixtures extends Fixture
{
    /**
     * Source unique des types : code technique => libelle FR. Doit rester aligne
     * sur le seed des migrations Version20260602100000 (CLIENT),
     * Version20260605120000 (FOURNISSEUR) et Version20260612080000 (PRESTATAIRE).
     */
    private const TYPES = [
        'CLIENT'      => 'Client',
        'FOURNISSEUR' => 'Fournisseur',
        'PRESTATAIRE' => 'Prestataire',
    ];

    public function __construct(
        private readonly CategoryTypeRepositoryInterface $categoryTypeRepository,
    ) {}

    public function load(ObjectManager $manager): void
    {
        // Index des types deja presents par code, pour ne pas creer de doublon.
        $existingByCode = [];
        foreach ($this->categoryTypeRepository->findAllOrderedByLabel() as $type) {
            $existingByCode[$type->getCode()] = $type;
        }

        foreach (self::TYPES as $code => $label) {
            $type = $existingByCode[$code] ?? new CategoryType();
            $type->setCode($code);
            $type->setLabel($label);
            $manager->persist($type);
        }

        $manager->flush();
    }
}
