<?php

/*
 * @author TRYDEA - 2024
 */

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

use Doctrine\Common\Collections\Collection;
use Mobile\Measure\Entity\DataEntry;
use Mobile\Measure\Entity\Session;
use Mobile\Measure\Entity\Variable\Base\Variable;
use Mobile\Measure\Entity\Variable\Material;
use Webapp\FileManagement\Dto\Mobile\DataEntryWithMaterialsAndVariablesDto;
use Webapp\FileManagement\Entity\RequestFile;
use Webapp\FileManagement\Exception\ParsingException;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\AbstractXmlNormalizer;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\XmlImportConfig;

/**
 * @template-extends AbstractXmlNormalizer<DataEntryWithMaterialsAndVariablesDto, DataEntryWithMaterialsAndVariablesDtoXmlDto>
 *
 * @psalm-type DataEntryWithMaterialsAndVariablesDtoXmlDto = array{
 *      "@projetDeSaisie": ?string,
 *      materiel: Material[],
 *      sessions: Collection<int, Session>,
 *      variables: Variable[]
 * }
 */
class DataEntryWithMaterialsAndVariablesDtoNormalizer extends AbstractXmlNormalizer
{
    protected const TAG_MATERIEL = 'materiel';
    protected const TAG_VARIABLES = 'variables';
    protected const TAG_SESSIONS = 'sessions';
    protected const ATTR_PROJET_DE_SAISIE = '@projetDeSaisie';

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

    protected function extractData($object, array $context): array
    {
        throw new \LogicException('Method not implemented');
    }

    protected function getImportDataConfig(array $context): array
    {
        return [
            self::ATTR_PROJET_DE_SAISIE => 'string',
            self::TAG_MATERIEL => XmlImportConfig::values(Material::class),
            self::TAG_VARIABLES => XmlImportConfig::values(Variable::class),
            self::TAG_SESSIONS => XmlImportConfig::collection(Session::class),
        ];
    }

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

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

    protected function completeImportedObject($object, $data, ?string $format, array $context): DataEntryWithMaterialsAndVariablesDto
    {
        $object->dataEntry = new DataEntry();
        $object->dataEntry->setSessions($data[self::TAG_SESSIONS]);

        $endedAt = $object->dataEntry->getEndedAt();
        foreach ($object->dataEntry->getSessions() as $session) {
            if (null === $endedAt || $session->getEndedAt() > $object->dataEntry->getEndedAt()) {
                $object->dataEntry->setEndedAt($endedAt);
            }
        }

        $object->materials = $data[self::TAG_MATERIEL];
        $object->variables = $data[self::TAG_VARIABLES];

        return $object;
    }
}
