<?php

/*
 * @author TRYDEA - 2024
 */

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

use Mobile\Project\Entity\DataEntryProject;
use Mobile\Project\Entity\Platform;
use Webapp\FileManagement\Dto\Mobile\CommonDataDto;
use Webapp\FileManagement\Dto\Mobile\ReturnFileDto;
use Webapp\FileManagement\Entity\RequestFile;
use Webapp\FileManagement\Exception\ParsingException;
use Webapp\FileManagement\Service\XmlUtils\CustomXmlEncoder;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\AbstractXmlNormalizer;
use Webapp\FileManagement\Service\XmlUtils\Normalizer\XmlExportConfig;

/**
 * @template-extends CommonDtoNormalizer<ReturnFileDto>
 */
final class ReturnFileDtoNormalizer extends CommonDtoNormalizer
{
    public const PLATFORM_NAME = 'return_file_platform_name';
    public const REQUEST_NAME = 'return_file_request_name';

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

    protected function extractData($object, array $context): array
    {
        $project = $object->dataEntryProject;
        if (null === $project) {
            throw new \LogicException('$object->dataEntryProject object must not be null');
        }

        return array_merge(parent::extractData($object, $context), [
            'adonis.modeleMetier.utilisateur:Utilisateur' => new XmlExportConfig($project->getDesktopUsers(), false),
            'adonis.modeleMetier.plateforme:NatureZhe' => new XmlExportConfig($project->getNaturesZHE(), false),
            'adonis.modeleMetier.plateforme:Plateforme' => new XmlExportConfig($project->getPlatform(), false),
            'adonis.modeleMetier.projetDeSaisie:ProjetDeSaisie' => new XmlExportConfig($project, false),
            'adonis.modeleMetier.saisieTerrain:Saisie' => new XmlExportConfig($project->getDataEntry(), false),
        ]);
    }

    protected function validateImportData($data, array $context): void
    {
        parent::validateImportData($data, $context);

        if (!isset($context[self::PLATFORM_NAME]) || !isset($context[self::REQUEST_NAME])) {
            throw new \LogicException('Platform name and request name must be set in context.');
        }
    }

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

    protected function mapMobileDto(CommonDataDto $mobileDto, $data, ?string $format, array $context): ReturnFileDto
    {
        $object = new ReturnFileDto();
        $object->dataEntryProject = $mobileDto->dataEntryProject;

        return $object;
    }

    protected function readPlatform(array $data, ?string $format, array $context): Platform
    {
        $object = parent::readPlatform($data, $format, $context);
        if ($object->getName() !== $context[self::PLATFORM_NAME]) {
            throw new ParsingException('', RequestFile::ERROR_WRONG_PLATFORM_NAME);
        }

        return $object;
    }

    /**
     * @throws ParsingException
     */
    protected function readProject($data, ?string $format, array $context): DataEntryProject
    {
        $objectDatas = $data[self::TAG_PROJET_SAISIE] ?? [];
        if (0 === \count($objectDatas)) {
            throw new ParsingException('No project is defined');
        } elseif (\count($objectDatas) > 1) {
            throw new ParsingException('More than one project are defined');
        }

        $dataEntryProject = (new DataEntryProject())
            ->setImprovised(false)
            ->setCreationDate(new \DateTime())
            ->setName($context[self::REQUEST_NAME]);

        $reference = AbstractXmlNormalizer::getReaderHelper($context)->createReference('', null, current($objectDatas)[CustomXmlEncoder::NODE_INDEX]);
        AbstractXmlNormalizer::getReaderHelper($context)->add($reference, $dataEntryProject);

        return $dataEntryProject;
    }
}
