<?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;

use Chill\MainBundle\Entity\Center;
use Chill\MainBundle\Entity\ExportGeneration;
use Chill\MainBundle\Entity\SavedExport;
use Chill\MainBundle\Form\Type\Export\ExportType;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface;
use Chill\MainBundle\Service\Regroupement\CenterRegroupementResolver;
use Doctrine\Common\Collections\Collection;

final readonly class ExportFormHelper
{
    public function __construct(
        private AuthorizationHelperForCurrentUserInterface $authorizationHelper,
        private ExportManager $exportManager,
        private ExportConfigNormalizer $configNormalizer,
        private CenterRegroupementResolver $centerRegroupementResolver,
    ) {}

    public function getDefaultData(string $step, DirectExportInterface|ExportInterface $export, array $options = []): array
    {
        return match ($step) {
            'centers', 'generate_centers' => ['centers' => $this->authorizationHelper->getReachableCenters($export->requiredRole()), 'regroupments' => []],
            'export', 'generate_export' => ['export' => $this->getDefaultDataStepExport($export, $options)],
            'formatter', 'generate_formatter' => ['formatter' => $this->getDefaultDataStepFormatter($options)],
            default => throw new \LogicException('step not allowed : '.$step),
        };
    }

    private function getDefaultDataStepFormatter(array $options): array
    {
        $formatter = $this->exportManager->getFormatter($options['formatter_alias']);

        return $formatter->getFormDefaultData($options['aggregator_aliases']);
    }

    private function getDefaultDataStepExport(DirectExportInterface|ExportInterface $export, array $options): array
    {
        $data = [
            ExportType::EXPORT_KEY => $export->getFormDefaultData(),
            ExportType::FILTER_KEY => [],
            ExportType::AGGREGATOR_KEY => [],
            ExportType::PICK_FORMATTER_KEY => [],
        ];

        $filters = $this->exportManager->getFiltersApplyingOn($export, $options['picked_centers']);
        foreach ($filters as $alias => $filter) {
            $data[ExportType::FILTER_KEY][$alias] = [
                FilterType::ENABLED_FIELD => false,
                'form' => $filter->getFormDefaultData(),
            ];
        }

        $aggregators = $this->exportManager
            ->getAggregatorsApplyingOn($export, $options['picked_centers']);
        foreach ($aggregators as $alias => $aggregator) {
            $data[ExportType::AGGREGATOR_KEY][$alias] = [
                'enabled' => false,
                'form' => $aggregator->getFormDefaultData(),
            ];
        }

        if ($export instanceof ExportInterface) {
            $allowedFormatters = $this->exportManager
                ->getFormattersByTypes($export->getAllowedFormattersTypes());
            $choices = [];
            foreach (array_keys(iterator_to_array($allowedFormatters)) as $alias) {
                $choices[] = $alias;
            }

            $data[ExportType::PICK_FORMATTER_KEY]['alias'] = match (count($choices)) {
                1 => $choices[0],
                default => null,
            };
        } else {
            unset($data[ExportType::PICK_FORMATTER_KEY]);
        }

        return $data;
    }

    public function savedExportDataToFormData(
        ExportGeneration|SavedExport $savedExport,
        string $step,
    ): array {
        return match ($step) {
            'centers', 'generate_centers' => $this->savedExportDataToFormDataStepCenter($savedExport),
            'export', 'generate_export' => $this->savedExportDataToFormDataStepExport($savedExport),
            'formatter', 'generate_formatter' => $this->savedExportDataToFormDataStepFormatter($savedExport),
            default => throw new \LogicException('this step is not allowed: '.$step),
        };
    }

    private function savedExportDataToFormDataStepCenter(
        ExportGeneration|SavedExport $savedExport,
    ): array {

        return [
            'centers' => $this->configNormalizer->denormalizeConfig($savedExport->getExportAlias(), $savedExport->getOptions(), true)['centers'],
        ];
    }

    private function savedExportDataToFormDataStepExport(
        ExportGeneration|SavedExport $savedExport,
    ): array {
        $data = $this->configNormalizer->denormalizeConfig($savedExport->getExportAlias(), $savedExport->getOptions(), true);

        return [
            'export' => [
                'export' => $data['export'],
                'filters' => $data['filters'],
                'pick_formatter' => ['alias' => $data['pick_formatter']],
                'aggregators' => $data['aggregators'],
            ],
        ];
    }

    private function savedExportDataToFormDataStepFormatter(
        ExportGeneration|SavedExport $savedExport,
    ): array {
        $data = $this->configNormalizer->denormalizeConfig($savedExport->getExportAlias(), $savedExport->getOptions(), true);

        return [
            'formatter' => $data['formatter'],
        ];
    }

    /**
     * Get the Center picked by the user for this export. The data are
     * extracted from the PickCenterType data.
     *
     * @param array $data the data as given by the @see{Chill\MainBundle\Form\Type\Export\PickCenterType}
     *
     * @return list<Center>
     */
    public function getPickedCenters(array $data): array
    {
        if (!array_key_exists('centers', $data)) {
            throw new \RuntimeException('array has not the expected shape');
        }

        $centers = $data['centers'] instanceof Collection ? $data['centers']->toArray() : $data['centers'];
        $regroupments = ($data['regroupments'] ?? []) instanceof Collection ? $data['regroupments']->toArray() : ($data['regroupments'] ?? []);

        return $this->centerRegroupementResolver->resolveCenters($regroupments, $centers);
    }
}
