<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use App\Shared\Infrastructure\Database\ColumnCommentsCatalog;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
 * ERP-67 — Retrofit `COMMENT ON COLUMN` / `COMMENT ON TABLE` sur toutes les
 * tables metier existantes.
 *
 * Postgres stocke la description dans `pg_description`. Les outils d'admin
 * (DBeaver, DataGrip, pgAdmin) l'affichent automatiquement, ce qui evite de
 * remonter au code Doctrine pour comprendre la semantique d'une colonne.
 *
 * Source unique : `ColumnCommentsCatalog::comments()`. Le meme catalogue est
 * rejoue par `app:apply-column-comments` apres `doctrine:schema:update --force`
 * en environnement de test (Doctrine ORM ne conservant pas les commentaires
 * absents du mapping PHP).
 *
 * Convention :
 * - Description en francais, ≤ 200 caracteres.
 * - Semantique du champ + contraintes / lien RG si pertinent.
 *
 * Migration placee au namespace racine `DoctrineMigrations` (regle ABSOLUE
 * Starseed n°11) car elle touche plusieurs modules. Les futures migrations
 * applicatives devront poser leur propre `COMMENT ON COLUMN` au moment de
 * creer leurs colonnes (cf. regle ABSOLUE n°12 + .claude/rules/backend.md).
 */
final class Version20260528120000 extends AbstractMigration
{
    public function getDescription(): string
    {
        return 'ERP-67 : retrofit COMMENT ON COLUMN/TABLE sur toutes les tables metier existantes.';
    }

    public function up(Schema $schema): void
    {
        // Ne commente que les tables ET colonnes deja presentes a ce stade de la
        // chaine de migrations. Les tables des modules crees plus tard (M1
        // Commercial, 06-01) ET les colonnes ajoutees ensuite sur une table
        // existante (ex: category.code, ERP-78 06-02) figurent desormais dans le
        // catalogue partage mais n'existent pas encore ici : elles posent leur
        // propre COMMENT dans leur migration dediee (regle ABSOLUE n°12). Garde-fou
        // indispensable (table + colonne), sinon enrichir le catalogue casse ce
        // retrofit avec un "relation/column X does not exist".
        foreach (ColumnCommentsCatalog::comments() as $table => $entries) {
            if (!$schema->hasTable($table)) {
                continue;
            }

            $dbTable     = $schema->getTable($table);
            $quotedTable = '"'.str_replace('"', '""', $table).'"';

            foreach ($entries as $column => $description) {
                if ('_table' === $column) {
                    $this->addSql(sprintf('COMMENT ON TABLE %s IS $_$%s$_$', $quotedTable, $description));

                    continue;
                }

                if (!$dbTable->hasColumn($column)) {
                    continue;
                }

                $this->addSql(sprintf(
                    'COMMENT ON COLUMN %s.%s IS $_$%s$_$',
                    $quotedTable,
                    '"'.str_replace('"', '""', $column).'"',
                    $description,
                ));
            }
        }
    }

    public function down(Schema $schema): void
    {
        foreach (ColumnCommentsCatalog::comments() as $table => $entries) {
            // Symetrie avec up() : on n'efface que les commentaires des tables
            // presentes (les tables des modules ulterieurs sont gerees par leur
            // propre migration).
            if (!$schema->hasTable($table)) {
                continue;
            }

            $quotedTable = '"'.str_replace('"', '""', $table).'"';
            foreach ($entries as $column => $_) {
                if ('_table' === $column) {
                    $this->addSql(sprintf('COMMENT ON TABLE %s IS NULL', $quotedTable));

                    continue;
                }

                $this->addSql(sprintf(
                    'COMMENT ON COLUMN %s.%s IS NULL',
                    $quotedTable,
                    '"'.str_replace('"', '""', $column).'"',
                ));
            }
        }
    }
}
