<?php

/*
 * @author TRYDEA - 2024
 */

namespace Webapp\FileManagement\Service\XmlUtils\Normalizer\Webapp;

use Doctrine\Common\Collections\Collection;
use Webapp\Core\Entity\AbstractVariable;
use Webapp\Core\Entity\GeneratorVariable;
use Webapp\Core\Entity\Test;
use Webapp\FileManagement\Entity\RequestFile;
use Webapp\FileManagement\Exception\ParsingException;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\XmlImportConfig;

/**
 * @template-extends AbstractVariableNormalizer<GeneratorVariable, GeneratorVariableXmlDto>
 *
 * @psalm-type GeneratorVariableXmlDto = array{
 *       "@nom": string,
 *       "@nomCourt": string,
 *       "@dateCreation": \DateTime,
 *       "@dateDerniereModification": \DateTime,
 *       "@saisieObligatoire": ?bool,
 *       "@nbRepetitionSaisies": int,
 *       "@ordre": ?int,
 *       "@commentaire": ?string,
 *       "@unite": ?string,
 *       "@valeurDefaut": ?bool,
 *       "@typeVariable": ?string,
 *       "@uniteParcoursType": ?string,
 *       "tests": Collection<int, Test>,
 *      "@nomGenere": ?string,
 *      "@extension": ?string,
 *      "variablesGenerees": AbstractVariable[],
 * }
 */
class GeneratorVariableNormalizer extends AbstractVariableNormalizer
{
    public const ATTR_NOM_GENERE = '@nomGenere';
    private const ATTR_EXTENSION = '@extension';
    private const TAG_VARIABLES_GENEREES = 'variablesGenerees';
    private const XSI_TYPE_VARIABLE_GENERATRICE = 'adonis.modeleMetier.projetDeSaisie.variables:VariableGeneratrice';

    protected function getClass(): string
    {
        return GeneratorVariable::class;
    }

    public function supportsDenormalization($data, string $type, ?string $format = null, array $context = []): bool
    {
        if (parent::supportsDenormalization($data, $type, $format, $context)) {
            return true;
        } elseif (AbstractVariable::class !== $type) {
            return false;
        }

        // Manage target $type AbstractVariable
        return isset($data[self::ATTR_NOM_GENERE]);
    }

    /**
     * @throws ParsingException
     */
    protected function validateImportData($data, array $context): void
    {
        parent::validateImportData($data, $context);

        if (!isset($data[self::TAG_VARIABLES_GENEREES])) {
            throw new ParsingException('', RequestFile::ERROR_NO_GENERATED_VARIABLE);
        }
    }

    protected function getImportDataConfig(array $context): array
    {
        return array_merge(parent::getCommonImportDataConfig($context), [
            self::ATTR_NOM_GENERE => 'string',
            self::ATTR_EXTENSION => 'string',
            self::TAG_VARIABLES_GENEREES => XmlImportConfig::values(AbstractVariable::class),
        ]);
    }

    protected function generateImportedObject($data, array $context): GeneratorVariable
    {
        return new GeneratorVariable();
    }

    protected function completeImportedObject($object, $data, ?string $format, array $context): GeneratorVariable
    {
        $object = parent::completeImportedObject($object, $data, $format, $context);
        $object
            ->setGeneratedPrefix($data[self::ATTR_NOM_GENERE] ?? '')
            ->setNumeralIncrement(null === $data[self::ATTR_EXTENSION])
            ->setGeneratedVariable($data[self::TAG_VARIABLES_GENEREES]);

        return $object;
    }

    protected function extractData($object, array $context): array
    {
        return array_merge(
            [
                self::ATTR_XSI_TYPE => self::XSI_TYPE_VARIABLE_GENERATRICE,
            ],
            parent::extractCommonData($object, $context),
            [
                self::ATTR_NOM_GENERE => $object->getGeneratedPrefix(),
                self::ATTR_EXTENSION => $object->isNumeralIncrement() ? 'numerique' : 'alphabetique',
                self::TAG_VARIABLES_GENEREES => array_merge($object->getGeneratedSimpleVariables()->getValues(), $object->getGeneratedGeneratorVariables()->getValues()),
            ]
        );
    }
}
