<?php
declare(strict_types=1);

namespace Neos\Flow\Persistence\Doctrine\Migrations;

use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
use Neos\ContentRepository\Utility;

final class Version20230727164600 extends AbstractMigration
{
    public function getDescription() : string
    {
        return 'add dimensions hash to node event model';
    }

    /**
     * @param Schema $schema
     * @throws Exception
     */
    public function up(Schema $schema) : void
    {
        $this->abortIf(!($this->connection->getDatabasePlatform() instanceof PostgreSQLPlatform), 'Migration can only be executed safely on "postgresql".');

        $this->addSql('ALTER TABLE neos_neos_eventlog_domain_model_event ADD dimensionshash VARCHAR(32) DEFAULT NULL');
        $this->addSql('CREATE INDEX dimensionshash ON neos_neos_eventlog_domain_model_event (dimensionshash)');
    }

    /**
     * @param Schema $schema
     * @throws Exception
     */
    public function down(Schema $schema) : void
    {
        $this->abortIf(!($this->connection->getDatabasePlatform() instanceof PostgreSQLPlatform), 'Migration can only be executed safely on "postgresql".');

        $this->addSql('DROP INDEX dimensionshash');
        $this->addSql('ALTER TABLE neos_neos_eventlog_domain_model_event DROP dimensionshash');
    }

    /**
     * @param Schema $schema
     * @throws \Doctrine\DBAL\Driver\Exception
     * @throws Exception
     */
    public function postUp(Schema $schema): void
    {
        $eventLogResult = $this->connection->executeQuery('SELECT dimension FROM neos_neos_eventlog_domain_model_event where dimensionshash IS NULL AND dimension IS NOT NULL LIMIT 1');

        while ($eventLogInfo = $eventLogResult->fetchAssociative()) {
            $dimensionsArray = unserialize($eventLogInfo['dimension'], ['allowed_classes' => false]);
            $dimensionsHash = Utility::sortDimensionValueArrayAndReturnDimensionsHash($dimensionsArray);
            $this->connection->executeStatement('UPDATE neos_neos_eventlog_domain_model_event SET dimensionshash = ? WHERE dimension = ?', [$dimensionsHash, $eventLogInfo['dimension']]);
            $eventLogResult = $this->connection->executeQuery('SELECT dimension FROM neos_neos_eventlog_domain_model_event where dimensionshash IS NULL AND dimension IS NOT NULL LIMIT 1');
        }
    }
}
