<?php

/*
 * @author TRYDEA - 2024
 */

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

use Webapp\Core\Entity\StateCode;
use Webapp\Core\Enumeration\SpreadingEnum;
use Webapp\FileManagement\Dto\Common\ColorDto;
use Webapp\FileManagement\Entity\RequestFile;
use Webapp\FileManagement\Exception\ParsingException;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\AbstractXmlNormalizer;

/**
 * @template-extends AbstractXmlNormalizer<StateCode, StateCodeXmlDto>
 *
 * @psalm-type StateCodeXmlDto =array{
 *      "@code": int,
 *      "@couleur": ?int,
 *      "@intitule": string,
 *      "@propagation": ?string,
 *      "@signification": ?string
 * }
 */
class StateCodeNormalizer extends AbstractXmlNormalizer
{
    protected const ATTR_CODE = '@code';
    protected const ATTR_INTITULE = '@intitule';
    protected const ATTR_SIGNIFICATION = '@signification';
    protected const ATTR_PROPAGATION = '@propagation';
    protected const ATTR_COULEUR = '@couleur';
    protected const PROPAGATION_INDIVIDU = 'individu';
    protected const PROPAGATION_PARCELLE = 'parcelle';

    private const PROPAGATION_MAP = [
        SpreadingEnum::INDIVIDUAL => self::PROPAGATION_INDIVIDU,
        SpreadingEnum::UNIT_PLOT => self::PROPAGATION_PARCELLE,
    ];

    private const REVERSE_PROPAGATION_MAP = [
        self::PROPAGATION_INDIVIDU => SpreadingEnum::INDIVIDUAL,
        self::PROPAGATION_PARCELLE => SpreadingEnum::UNIT_PLOT,
    ];

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

    protected function getImportDataConfig(array $context): array
    {
        return [
            self::ATTR_CODE => 'int',
            self::ATTR_INTITULE => 'string',
            self::ATTR_SIGNIFICATION => 'string',
            self::ATTR_PROPAGATION => 'string',
            self::ATTR_COULEUR => ColorDto::class,
        ];
    }

    protected function validateImportData($data, array $context): void
    {
        if (
            !isset($data[self::ATTR_CODE])
            || !isset($data[self::ATTR_INTITULE])
        ) {
            throw new ParsingException('', RequestFile::ERROR_STATE_CODE_INFO_MISSING);
        }
    }

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

    protected function completeImportedObject($object, $data, ?string $format, array $context): StateCode
    {
        $object
            ->setCode($data[self::ATTR_CODE])
            ->setTitle($data[self::ATTR_INTITULE])
            ->setPermanent(\in_array($object->getTitle(), ['Mort', 'Donnée Manquante'], true))
            ->setMeaning($data[self::ATTR_SIGNIFICATION])
            ->setSpreading(self::REVERSE_PROPAGATION_MAP[$data[self::ATTR_PROPAGATION] ?? ''] ?? null)
            ->setColor($data[self::ATTR_COULEUR]);

        return $object;
    }

    protected function extractData($object, array $context): array
    {
        return [
            self::ATTR_CODE => $object->getCode(),
            self::ATTR_INTITULE => $object->getTitle(),
            self::ATTR_SIGNIFICATION => $object->getMeaning(),
            self::ATTR_PROPAGATION => self::PROPAGATION_MAP[$object->getSpreading() ?? ''] ?? null,
            self::ATTR_COULEUR => null !== $object->getColor() ? new ColorDto($object->getColor()) : null,
        ];
    }
}
