<?php

declare(strict_types=1);

/*
 * Chill is a software for social workers
 *
 * For the full copyright and license information, please view
 * the LICENSE file that was distributed with this source code.
 */

namespace Chill\MainBundle\Export\Migrator;

use Chill\MainBundle\Service\RollingDate\RollingDate;

class SavedExportOptionsMigrator
{
    public static function migrate(array $fromOptions): array
    {
        $to = [];
        $to['aggregators'] = array_map(
            self::mapEnabledStatus(...),
            $fromOptions['export']['export']['aggregators'] ?? [],
        );

        $to['filters'] = array_map(
            self::mapEnabledStatus(...),
            $fromOptions['export']['export']['filters'] ?? [],
        );

        $to['export'] = [
            'form' => array_map(
                self::mapFormData(...),
                array_filter(
                    $fromOptions['export']['export']['export'] ?? [],
                    static fn (string $key) => !in_array($key, ['filters', 'aggregators', 'pick_formatter'], true),
                    ARRAY_FILTER_USE_KEY,
                ),
            ),
            'version' => 1,
        ];

        $to['pick_formatter'] = $fromOptions['export']['export']['pick_formatter']['alias'] ?? null;
        $to['centers'] = [
            'centers' => array_values(array_map(static fn ($id) => (int) $id, $fromOptions['centers']['centers']['c'] ?? $fromOptions['centers']['centers']['center'] ?? [])),
            'regroupments' => array_values(array_map(static fn ($id) => (int) $id, $fromOptions['centers']['centers']['regroupment'] ?? [])),
        ];
        $to['formatter'] = [
            'form' => $fromOptions['formatter']['formatter'] ?? [],
            'version' => 1,
        ];

        return $to;
    }

    private static function mapEnabledStatus(array $modifiersData): array
    {
        if ('1' === ($modifiersData['enabled'] ?? '0')) {
            return [
                'form' => array_map(self::mapFormData(...), $modifiersData['form'] ?? []),
                'version' => 1,
                'enabled' => true,
            ];
        }

        return ['enabled' => false];
    }

    private static function mapFormData(array|string $formData): array|string|null
    {
        if (is_array($formData) && array_key_exists('roll', $formData)) {
            return self::refactorRollingDate($formData);
        }

        if (is_string($formData)) {
            // we try different date formats
            if (false !== \DateTimeImmutable::createFromFormat('d-m-Y', $formData)) {
                return $formData;
            }
            if (false !== \DateTimeImmutable::createFromFormat('Y-m-d', $formData)) {
                return $formData;
            }

            // we try json content
            try {
                $data = json_decode($formData, true, 512, JSON_THROW_ON_ERROR);

                if (is_array($data)) {
                    if (array_key_exists('type', $data) && array_key_exists('id', $data) && in_array($data['type'], ['person', 'thirdParty', 'user'], true)) {
                        return $data['id'];
                    }
                    $response = [];
                    foreach ($data as $item) {
                        if (array_key_exists('type', $item) && array_key_exists('id', $item) && in_array($item['type'], ['person', 'thirdParty', 'user'], true)) {
                            $response[] = $item['id'];
                        }
                    }
                    if ([] !== $response) {
                        return $response;
                    }
                }
            } catch (\JsonException) {
                return $formData;
            }
        }

        return $formData;
    }

    private static function refactorRollingDate(array $formData): ?array
    {
        if ('' === $formData['roll']) {
            return null;
        }

        $fixedDate = null !== ($formData['fixedDate'] ?? null) && '' !== $formData['fixedDate'] ?
            \DateTimeImmutable::createFromFormat('Y-m-d H:i:s', sprintf('%s 00:00:00', $formData['fixedDate']), new \DateTimeZone(date_default_timezone_get())) : null;

        return (new RollingDate(
            $formData['roll'],
            $fixedDate,
        ))->normalize();
    }
}
