<?php

declare(strict_types=1);

namespace App\EventSubscriber;

use App\Entity\ModelType;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\PreRemoveEventArgs;
use Doctrine\ORM\Events;

use function sprintf;

/**
 * Belt-and-suspenders cleanup of weak references to a ModelType before deletion:
 * runs the equivalent of every "ON DELETE SET NULL" cascade applicatively, in case
 * the database FK fails to fire (observed on prod in 2026-04 — the deletion of
 * ModelType "Paliers" left an orphan in skeleton_subcomponent_requirements).
 */
#[AsDoctrineListener(event: Events::preRemove)]
final class ModelTypeReferenceCleanupSubscriber
{
    /** @var list<array{0: string, 1: string}> */
    private const NULLABLE_REFERENCES = [
        ['skeleton_subcomponent_requirements', 'typecomposantid'],
        ['skeleton_piece_requirements', 'typepieceid'],
        ['skeleton_product_requirements', 'typeproductid'],
        ['composant_piece_slots', 'typepieceid'],
        ['composant_product_slots', 'typeproductid'],
        ['composant_subcomponent_slots', 'typecomposantid'],
        ['piece_product_slots', 'typeproductid'],
        ['machine_component_links', 'modeltypeid'],
        ['machine_piece_links', 'modeltypeid'],
        ['machine_product_links', 'modeltypeid'],
    ];

    public function preRemove(PreRemoveEventArgs $args): void
    {
        $entity = $args->getObject();
        if (!$entity instanceof ModelType) {
            return;
        }

        $id = $entity->getId();
        if (!$id) {
            return;
        }

        $conn = $args->getObjectManager()->getConnection();
        foreach (self::NULLABLE_REFERENCES as [$table, $column]) {
            $conn->executeStatement(
                sprintf('UPDATE %s SET %s = NULL WHERE %s = ?', $table, $column, $column),
                [$id],
            );
        }
    }
}
