<?php

declare(strict_types=1);

namespace DoctrineMigrations;

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

/**
 * M1 — Suppression du contact principal inline du `Client` (refonte contact).
 *
 * Modele AVANT : le `Client` portait 5 colonnes de contact principal
 * (first_name, last_name, phone_primary, phone_secondary, email) en doublon
 * conceptuel de la sous-entite `ClientContact` (onglet Contact).
 *
 * Modele APRES (decision produit, README refonte-contact) : les contacts vivent
 * UNIQUEMENT dans `client_contact`. Les 5 colonnes inline disparaissent du
 * `client`. RG-1.01 (firstName OU lastName sur Client) et RG-1.02 (max 2
 * telephones sur Client) sont supprimees : leur equivalent vit deja sur
 * `client_contact` (RG-1.05 / RG-1.14).
 *
 * Le code etant deja en prod, la suppression est precedee d'un BACKFILL : pour
 * tout client n'ayant encore AUCUN contact, on materialise son contact principal
 * inline en une ligne `client_contact` (position 0) avant le DROP, afin de ne
 * perdre aucune donnee.
 *
 * Namespace racine `DoctrineMigrations` (regle ABSOLUE n°11) et NON modulaire
 * Commercial : avec plusieurs migrations_paths, Doctrine Migrations 3.x trie par
 * FQCN alphabetique (AlphabeticalComparator). Une migration
 * `App\Module\Commercial\...` trierait AVANT toutes les `DoctrineMigrations\...`
 * sur base vide -> ce DROP s'executerait avant le CREATE TABLE client
 * (Version20260601000000). Le namespace racine garantit l'ordre par timestamp.
 */
final class Version20260603120000 extends AbstractMigration
{
    /** Colonnes de contact inline supprimees du `client`. */
    private const array INLINE_CONTACT_COLUMNS = [
        'first_name', 'last_name', 'phone_primary', 'phone_secondary', 'email',
    ];

    public function getDescription(): string
    {
        return 'M1 : suppression du contact inline du Client (backfill vers client_contact puis DROP des 5 colonnes).';
    }

    public function up(Schema $schema): void
    {
        // 1. Backfill : tout client SANS contact recoit une ligne client_contact
        //    (position 0) reprenant ses champs inline. phone_primary / email du
        //    client sont NOT NULL -> toujours une donnee a reporter. Le CHECK
        //    chk_client_contact_name (first_name OU last_name) est garanti par le
        //    fallback company_name si jamais les deux noms etaient null (cas qui ne
        //    devrait pas exister, RG-1.01 ayant ete appliquee a l'ecriture).
        //    created_at/updated_at NOT NULL -> NOW() ; created_by/updated_by null
        //    (backfill hors contexte HTTP, libelle « Systeme » cote front).
        $this->addSql(<<<'SQL'
            INSERT INTO client_contact (
                client_id, first_name, last_name, phone_primary, phone_secondary,
                email, position, created_at, updated_at
            )
            SELECT
                c.id,
                c.first_name,
                CASE
                    WHEN c.first_name IS NULL AND c.last_name IS NULL THEN c.company_name
                    ELSE c.last_name
                END,
                c.phone_primary,
                c.phone_secondary,
                c.email,
                0,
                NOW(),
                NOW()
            FROM client c
            WHERE NOT EXISTS (
                SELECT 1 FROM client_contact cc WHERE cc.client_id = c.id
            )
            SQL);

        // 2. DROP des 5 colonnes inline (rien a documenter : suppression).
        $this->addSql(<<<'SQL'
            ALTER TABLE client
                DROP COLUMN first_name,
                DROP COLUMN last_name,
                DROP COLUMN phone_primary,
                DROP COLUMN phone_secondary,
                DROP COLUMN email
            SQL);
    }

    public function down(Schema $schema): void
    {
        // Best-effort : on RECREE les 5 colonnes (en NULLABLE — l'etat NOT NULL
        // d'origine de phone_primary/email ne peut etre restaure sur une table
        // peuplee sans risque) et on retro-alimente depuis le contact principal
        // (position minimale) de chaque client. La donnee n'est pas garantie
        // identique a l'origine : ce down() sert au rollback technique, pas a une
        // restauration fidele.
        $this->addSql('ALTER TABLE client ADD COLUMN first_name VARCHAR(120) DEFAULT NULL');
        $this->addSql('ALTER TABLE client ADD COLUMN last_name VARCHAR(120) DEFAULT NULL');
        $this->addSql('ALTER TABLE client ADD COLUMN phone_primary VARCHAR(20) DEFAULT NULL');
        $this->addSql('ALTER TABLE client ADD COLUMN phone_secondary VARCHAR(20) DEFAULT NULL');
        $this->addSql('ALTER TABLE client ADD COLUMN email VARCHAR(180) DEFAULT NULL');

        // Retro-alimentation depuis le contact de position la plus basse.
        $this->addSql(<<<'SQL'
            UPDATE client c SET
                first_name      = cc.first_name,
                last_name       = cc.last_name,
                phone_primary   = cc.phone_primary,
                phone_secondary = cc.phone_secondary,
                email           = cc.email
            FROM (
                SELECT DISTINCT ON (client_id)
                    client_id, first_name, last_name, phone_primary, phone_secondary, email
                FROM client_contact
                ORDER BY client_id, position ASC, id ASC
            ) cc
            WHERE cc.client_id = c.id
            SQL);

        // Re-pose des commentaires d'origine (regle ABSOLUE n°12) — dollar-quoting
        // Postgres pour eviter tout echappement d apostrophe.
        $this->addSql('COMMENT ON COLUMN client.first_name IS $_$Prenom du contact principal (capitalise serveur, RG-1.19). first_name OU last_name obligatoire (RG-1.01).$_$');
        $this->addSql('COMMENT ON COLUMN client.last_name IS $_$Nom du contact principal (capitalise serveur, RG-1.19). first_name OU last_name obligatoire (RG-1.01).$_$');
        $this->addSql('COMMENT ON COLUMN client.phone_primary IS $_$Telephone principal — stocke en chiffres uniquement (RG-1.20). Obligatoire.$_$');
        $this->addSql('COMMENT ON COLUMN client.phone_secondary IS $_$Telephone secondaire optionnel — chiffres uniquement (RG-1.20).$_$');
        $this->addSql('COMMENT ON COLUMN client.email IS $_$Email principal (lowercase serveur, RG-1.21). NON unique (RG-1.17 supprimee, Q4).$_$');
    }
}
