<?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\SavedExport;
use Chill\MainBundle\Form\Type\Export\ExportType;
use Chill\MainBundle\Form\Type\Export\FilterType;
use Chill\MainBundle\Form\Type\Export\FormatterType;
use Chill\MainBundle\Form\Type\Export\PickCenterType;
use Chill\MainBundle\Security\Authorization\AuthorizationHelperForCurrentUserInterface;
use Symfony\Component\Form\Extension\Core\Type\FormType;
use Symfony\Component\Form\FormFactoryInterface;

final readonly class ExportFormHelper
{
    public function __construct(
        private AuthorizationHelperForCurrentUserInterface $authorizationHelper,
        private ExportManager $exportManager,
        private FormFactoryInterface $formFactory,
    ) {}

    public function getDefaultData(string $step, DirectExportInterface|ExportInterface $export, array $options = []): array
    {
        return match ($step) {
            'centers', 'generate_centers' => ['centers' => $this->authorizationHelper->getReachableCenters($export->requiredRole())],
            '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(
        SavedExport $savedExport,
        string $step,
        array $formOptions = [],
    ): array {
        return match ($step) {
            'centers', 'generate_centers' => $this->savedExportDataToFormDataStepCenter($savedExport),
            'export', 'generate_export' => $this->savedExportDataToFormDataStepExport($savedExport, $formOptions),
            'formatter', 'generate_formatter' => $this->savedExportDataToFormDataStepFormatter($savedExport, $formOptions),
            default => throw new \LogicException('this step is not allowed: '.$step),
        };
    }

    private function savedExportDataToFormDataStepCenter(
        SavedExport $savedExport,
    ): array {
        $builder = $this->formFactory
            ->createBuilder(
                FormType::class,
                [],
                [
                    'csrf_protection' => false,
                ]
            );

        $builder->add('centers', PickCenterType::class, [
            'export_alias' => $savedExport->getExportAlias(),
        ]);
        $form = $builder->getForm();
        $form->submit($savedExport->getOptions()['centers']);

        return $form->getData();
    }

    private function savedExportDataToFormDataStepExport(
        SavedExport $savedExport,
        array $formOptions,
    ): array {
        $builder = $this->formFactory
            ->createBuilder(
                FormType::class,
                [],
                [
                    'csrf_protection' => false,
                ]
            );

        $builder->add('export', ExportType::class, [
            'export_alias' => $savedExport->getExportAlias(), ...$formOptions,
        ]);
        $form = $builder->getForm();
        $form->submit($savedExport->getOptions()['export']);

        return $form->getData();
    }

    private function savedExportDataToFormDataStepFormatter(
        SavedExport $savedExport,
        array $formOptions,
    ): array {
        $builder = $this->formFactory
            ->createBuilder(
                FormType::class,
                [],
                [
                    'csrf_protection' => false,
                ]
            );

        $builder->add('formatter', FormatterType::class, [
            'export_alias' => $savedExport->getExportAlias(), ...$formOptions,
        ]);
        $form = $builder->getForm();
        $form->submit($savedExport->getOptions()['formatter']);

        return $form->getData();
    }
}
