<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
 * ERP-154 — Infra d'upload de fichiers generique et reutilisable (src/Shared).
 *
 * Cree la table `uploaded_document` : reference technique d'un fichier televerse
 * (PDF / image), gere par le service Shared\Infrastructure\Upload\FileUploader.
 * La « Decharge » du M4 transporteurs en sera le premier consommateur, mais ce
 * ticket ne touche AUCUN module : la table vit cote Shared.
 *
 * Caracteristiques :
 *  - Document IMMUABLE : pas d'onglet edition, pas de updated_at / updated_by.
 *    Seules les colonnes created_at (UTC, remplie par le FileUploader via
 *    l'horloge injectee) et created_by (auteur HTTP, null hors HTTP) tracent
 *    l'origine. C'est pourquoi l'entite Shared n'implemente PAS
 *    Timestampable/Blamable (qui imposeraient les 4 colonnes).
 *  - checksum sha256 (64 caracteres hex) : controle d'integrite + future
 *    deduplication eventuelle (hors scope ici).
 *
 * Namespace racine `DoctrineMigrations` (regle ABSOLUE Starseed n°11) et non
 * modulaire : la table porte une FK cross-module vers "user" (created_by). Le
 * tri par version au sein du namespace racine garantit qu'elle joue APRES la
 * creation de "user" sur base vide.
 *
 * Style DDL aligne sur le M1/M2/M3 : `INT GENERATED BY DEFAULT AS IDENTITY` et
 * `TIMESTAMP(0) WITHOUT TIME ZONE` (mapping ORM `datetime_immutable`), pour que
 * `schema:update --force` reste un no-op une fois l'entite mappee.
 *
 * COMMENT ON COLUMN inline (regle ABSOLUE n°12) : chaque colonne porte sa
 * description ici. La table est aussi ajoutee a `ColumnCommentsCatalog` car
 * l'entite UploadedDocument existe des ce ticket — `app:apply-column-comments`
 * du `test-db-setup` rejoue donc ces COMMENT apres le `schema:update --force`.
 */
final class Version20260615130000 extends AbstractMigration
{
    public function getDescription(): string
    {
        return 'ERP-154 : table uploaded_document (infra upload generique Shared) — fichier televerse immuable, checksum sha256.';
    }

    public function up(Schema $schema): void
    {
        $this->addSql(<<<'SQL'
            CREATE TABLE uploaded_document (
                id INT GENERATED BY DEFAULT AS IDENTITY NOT NULL,
                original_filename VARCHAR(255) NOT NULL,
                stored_path VARCHAR(512) NOT NULL,
                mime_type VARCHAR(100) NOT NULL,
                size_bytes INT NOT NULL,
                checksum VARCHAR(64) NOT NULL,
                created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL,
                created_by INT DEFAULT NULL,
                PRIMARY KEY (id),
                CONSTRAINT fk_uploaded_document_created_by
                    FOREIGN KEY (created_by) REFERENCES "user" (id) ON DELETE SET NULL
            )
            SQL);

        // Postgres n'indexe pas automatiquement les colonnes de FK.
        $this->addSql('CREATE INDEX idx_uploaded_document_created_by ON uploaded_document (created_by)');
        // Recherche d'integrite / future deduplication par empreinte sha256.
        $this->addSql('CREATE INDEX idx_uploaded_document_checksum ON uploaded_document (checksum)');

        $this->addSql('COMMENT ON TABLE uploaded_document IS $_$Fichiers televerses (infra generique Shared, ERP-154) — documents immuables (PDF / images), 1er consommateur la Decharge M4.$_$');
        $this->addSql('COMMENT ON COLUMN uploaded_document.id IS $_$Identifiant interne auto-incremente.$_$');
        $this->addSql('COMMENT ON COLUMN uploaded_document.original_filename IS $_$Nom de fichier d origine fourni par le client (≤ 255) — metadonnee d affichage uniquement, jamais utilise pour le stockage disque.$_$');
        $this->addSql('COMMENT ON COLUMN uploaded_document.stored_path IS $_$Chemin relatif du fichier sous var/uploads (ex: 2026/06/<hash>.pdf) — nom genere aleatoirement, jamais le nom client.$_$');
        $this->addSql('COMMENT ON COLUMN uploaded_document.mime_type IS $_$Type MIME detecte SERVER-SIDE via getMimeType (jamais getClientMimeType, spoofable) — borne a la whitelist FileUploader (PDF + images).$_$');
        $this->addSql('COMMENT ON COLUMN uploaded_document.size_bytes IS $_$Taille du fichier en octets — bornee par FileUploader::MAX_SIZE_BYTES.$_$');
        $this->addSql('COMMENT ON COLUMN uploaded_document.checksum IS $_$Empreinte SHA-256 du contenu (64 caracteres hex) — controle d integrite + deduplication eventuelle (hors scope).$_$');
        $this->addSql('COMMENT ON COLUMN uploaded_document.created_at IS $_$Horodatage UTC du televersement — rempli par FileUploader via l horloge injectee (pas via TimestampableBlamableSubscriber).$_$');
        $this->addSql('COMMENT ON COLUMN uploaded_document.created_by IS $_$ID de l utilisateur ayant televerse le fichier — null hors HTTP (CLI, fixture). FK -> "user".id, ON DELETE SET NULL.$_$');
    }

    public function down(Schema $schema): void
    {
        $this->addSql('DROP TABLE IF EXISTS uploaded_document');
    }
}
