<?php

declare(strict_types=1);

namespace DoctrineMigrations;

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

/**
 * Auto-generated Migration: Please modify to your needs!
 */
final class Version20240228100746 extends AbstractMigration
{
    private const PATH_LEVEL_COLUMNS = [
        'adonis.required_annotation' => 'path_level',
        'adonis.variable' => 'path_level',
        'adonis.state_code' => 'propagation',
        'webapp.required_annotation' => 'level',
        'webapp.variable_simple' => 'path_level',
        'webapp.variable_semi_automatic' => 'path_level',
        'webapp.variable_generator' => 'path_level',
    ];

    private const PATH_LEVEL_VALUES = [
        'individual' => ['Individu', 'individu', 'Individual'],
        'block' => ['Bloc', 'bloc', 'Block'],
        'experiment' => ['Dispositif', 'dispositif', 'Device'],
        'unitPlot' => ['Parcelle Unitaire', 'parcelle', 'unit_plot', 'UnitParcel'],
        'subBlock' => ['Sous Bloc', 'sousBloc', 'SubBlock'],
        'platform' => ['plateforme'],
    ];

    private const VARIABLE_TYPE_COLUMNS = [
        'adonis.variable' => 'type',
        'webapp.variable_simple' => 'type',
        'webapp.variable_semi_automatic' => 'type',
    ];

    private const VARIABLE_TYPE_VALUES = [
        'real' => ['reel'],
        'alphanumeric' => ['alphanumerique'],
        'boolean' => ['booleen'],
        'integer' => ['entiere'],
        'date' => [],
        'time' => ['heure'],
    ];

    private const VARIABLE_FORMAT_COLUMNS = [
        'adonis.variable' => 'format',
        'webapp.variable_simple' => 'format',
        'webapp.variable_generator' => 'format',
        'webapp.variable_semi_automatic' => 'format',
    ];

    private const VARIABLE_FORMAT_VALUES = [
        'free' => [],
        'characterNumber' => [],
        'decimalNumber' => [],
        'jjmmyyyy' => [],
        'quantieme' => [],
    ];

    public function getDescription() : string
    {
        return 'Mise à jour des unités de parcours';
    }

    public function up(Schema $schema) : void
    {
        $this->upEnum(self::PATH_LEVEL_COLUMNS, self::PATH_LEVEL_VALUES);
        $this->upEnum(self::VARIABLE_TYPE_COLUMNS, self::VARIABLE_TYPE_VALUES);
    }

    private function upEnum(array $columns, array $values): void
    {
        foreach ($columns as $table => $column) {
            foreach ($values as $new => $olds) {
                if (empty($olds)) {
                    continue;
                }
                $this->addSql(sprintf(
                    "UPDATE $table SET $column = '%s' WHERE $column IN (%s)",
                    $new,
                    implode(', ', array_map(fn (string $old) => "'$old'", $olds))
                ));
            }
            $this->addSql(sprintf(
                "ALTER TABLE $table ADD CONSTRAINT %s CHECK ($column IN (%s));",
                $this->checkConstraintName($table, $column),
                implode(', ', array_map(fn (string $value) => "'$value'", array_keys($values)))
            ));
        }
    }

    public function down(Schema $schema) : void
    {
        $this->downEnum(self::PATH_LEVEL_COLUMNS);
        $this->downEnum(self::VARIABLE_TYPE_COLUMNS);
    }

    private function downEnum(array $columns): void
    {
        foreach ($columns as $table => $column) {
            $this->addSql(sprintf(
                "ALTER TABLE $table DROP CONSTRAINT %s",
                $this->checkConstraintName($table, $column)
            ));
        }
    }

    private function checkConstraintName(string $table, string $column): string {
        return str_replace('.', '_', $table.'.'.$column.'.check');
    }
}
