<?php

declare(strict_types=1);

/*
 * This source file is available under two different licenses:
 *   - GNU General Public License version 3 (GPLv3)
 *   - DACHCOM Commercial License (DCL)
 * Full copyright and license information is available in
 * LICENSE.md which is distributed with this source code.
 *
 * @copyright  Copyright (c) DACHCOM.DIGITAL AG (https://www.dachcom-digital.com)
 * @license    GPLv3 and DCL
 */

namespace FormBuilderBundle\Migrations;

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

final class Version20230908101855 extends AbstractMigration
{
    public function getDescription(): string
    {
        return 'Replace all workflowId fields with workflowName in switchWorkflow action';
    }

    public function up(Schema $schema): void
    {
        $workflowIdMapData = $this->connection->fetchAllAssociative('SELECT id, name FROM formbuilder_output_workflow');

        $workflowIdMap = array_reduce($workflowIdMapData, static function ($carry, $data) {
            $carry[$data['id']] = $data['name'];

            return $carry;
        }, []);

        $forms = $this->connection->fetchAllAssociative("SELECT id, conditionalLogic FROM formbuilder_forms WHERE (conditionalLogic LIKE '%\"switchOutputWorkflow\"%' OR conditionalLogic LIKE '%\"outputWorkflow\"%')");

        foreach ($forms as $form) {
            $conditionalLogic = array_map(static function ($logic) use ($workflowIdMap) {
                return [
                    'condition' => array_filter(
                        array_map(static function ($condition) use ($workflowIdMap) {
                            if ($condition['type'] !== 'outputWorkflow') {
                                return $condition;
                            }

                            foreach ($condition['outputWorkflows'] as $index => $outputWorkflowId) {
                                if (!isset($workflowIdMap[$outputWorkflowId])) {
                                    unset($condition['outputWorkflows'][$index]);

                                    continue;
                                }

                                $condition['outputWorkflows'][$index] = $workflowIdMap[$outputWorkflowId];
                            }

                            if (count($condition['outputWorkflows']) === 0) {
                                return null;
                            }

                            $condition['outputWorkflows'] = array_values($condition['outputWorkflows']);

                            return $condition;
                        }, $logic['condition'] ?? [])
                    ),
                    'action'    => array_filter(
                        array_map(static function ($action) use ($workflowIdMap) {
                            if ($action['type'] !== 'switchOutputWorkflow') {
                                return $action;
                            }

                            if (!isset($workflowIdMap[$action['workflowId']])) {
                                return null;
                            }

                            $action['workflowName'] = $workflowIdMap[$action['workflowId']];
                            unset($action['workflowId']);

                            return $action;
                        }, $logic['action'] ?? [])
                    )
                ];
            }, unserialize($form['conditionalLogic']));

            $this->addSql('UPDATE formbuilder_forms SET conditionalLogic = ? WHERE id = ?', [serialize($conditionalLogic), $form['id']]);
        }
    }

    public function down(Schema $schema): void
    {
        $workflowIdMapData = $this->connection->fetchAllAssociative('SELECT id, name FROM formbuilder_output_workflow');

        $workflowIdMap = array_reduce($workflowIdMapData, static function ($carry, $data) {
            $carry[$data['name']] = $data['id'];

            return $carry;
        }, []);

        $forms = $this->connection->fetchAllAssociative("SELECT id, conditionalLogic FROM formbuilder_forms WHERE (conditionalLogic LIKE '%\"switchOutputWorkflow\"%' OR conditionalLogic LIKE '%\"outputWorkflow\"%')");

        foreach ($forms as $form) {
            $conditionalLogic = array_map(static function ($logic) use ($workflowIdMap) {
                return [
                    'condition' => array_map(static function ($condition) use ($workflowIdMap) {
                        if ($condition['type'] !== 'outputWorkflow') {
                            return $condition;
                        }

                        foreach ($condition['outputWorkflows'] as $index => $outputWorkflowId) {
                            $condition['outputWorkflows'][$index] = $workflowIdMap[$outputWorkflowId];
                        }

                        return $condition;
                    }, $logic['condition'] ?? []),
                    'action'    => array_map(static function ($action) use ($workflowIdMap) {
                        if ($action['type'] !== 'switchOutputWorkflow') {
                            return $action;
                        }

                        $action['workflowId'] = $workflowIdMap[$action['workflowName']];
                        unset($action['workflowName']);

                        return $action;
                    }, $logic['action'] ?? [])
                ];
            }, unserialize($form['conditionalLogic']));

            $this->addSql('UPDATE formbuilder_forms SET conditionalLogic = ? WHERE id = ?', [serialize($conditionalLogic), $form['id']]);
        }
    }
}
