<?php

declare(strict_types=1);

namespace App\Module\Sites\Infrastructure\DataFixtures;

use App\Module\Sites\Domain\Entity\Site;
use App\Module\Sites\Domain\Repository\SiteRepositoryInterface;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;

/**
 * Fixtures du module Sites : 3 etablissements de demonstration utilises par
 * les tickets suivants (rattachement utilisateurs, navbar, etc.).
 *
 * Idempotence supportee : le purger Doctrine (ORMPurger) vide la table
 * `site` avant chaque `doctrine:fixtures:load`. Si le purger est
 * desactive et la fixture rejouee telle quelle sur une base deja seedee,
 * le lookup par nom evite le doublon et re-aligne les autres champs.
 *
 * Idempotence NON supportee :
 *  - chargement cumulatif apres qu'une autre fixture ait persiste (sans
 *    flush) des Site dans la meme session : `findByName()` s'appuie sur
 *    `findOneBy`, qui n'inspecte pas les entites en attente dans l'unit-of-work
 *    et peut renvoyer null alors qu'un homonyme est deja manage ;
 *  - renommage d'un site : le nom etant la cle de lookup, modifier
 *    `name` dans cette fixture cree un nouveau site et laisse l'ancien
 *    en base (purger desactive). Les autres champs (city, color, etc.)
 *    sont en revanche bien re-synchronises pour un site retrouve.
 */
class SitesFixtures extends Fixture
{
    public function __construct(
        private readonly SiteRepositoryInterface $siteRepository,
    ) {}

    public function load(ObjectManager $manager): void
    {
        // Chatellerault : bleu Starseed.
        $this->ensureSite(
            $manager,
            name: 'Chatellerault',
            street: "14 All. d'Argenson",
            complement: null,
            postalCode: '86100',
            city: 'Châtellerault',
            color: '#056CF2',
        );

        // Saint-Jean : jaune vif. Le nom du site (identifier) ne reflete
        // pas la ville reelle (Fontenet) — c'est une nomenclature interne
        // client.
        $this->ensureSite(
            $manager,
            name: 'Saint-Jean',
            street: 'Z i',
            complement: null,
            postalCode: '17400',
            city: 'Fontenet',
            color: '#F3CB00',
        );

        // Pommevic : vert clair.
        $this->ensureSite(
            $manager,
            name: 'Pommevic',
            street: '1 Av. Jean Duquesne',
            complement: null,
            postalCode: '82400',
            city: 'Pommevic',
            color: '#74BF04',
        );

        $manager->flush();
    }

    /**
     * Cree le site s'il n'existe pas encore, sinon re-aligne rue, complement,
     * code postal, ville et couleur sur les valeurs de reference.
     *
     * Note : le nom sert de cle de lookup (il est unique en base) et n'est
     * donc pas resynchronise. Consequence : renommer un site dans la
     * fixture cree un nouveau site sans supprimer l'ancien, sauf si le
     * purger Doctrine est actif (cas nominal de `doctrine:fixtures:load`).
     */
    private function ensureSite(
        ObjectManager $manager,
        string $name,
        string $street,
        ?string $complement,
        string $postalCode,
        string $city,
        string $color,
    ): Site {
        $site = $this->siteRepository->findByName($name);

        if (null === $site) {
            $site = new Site($name, $street, $complement, $postalCode, $city, $color);
            $manager->persist($site);

            return $site;
        }

        $site->setStreet($street);
        $site->setComplement($complement);
        $site->setPostalCode($postalCode);
        $site->setCity($city);
        $site->setColor($color);

        return $site;
    }
}
