<?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\PersonBundle\Actions\PersonCreate\Service;

use Chill\PersonBundle\Actions\PersonCreate\PersonCreateDTO;
use Chill\PersonBundle\Config\ConfigPersonAltNamesHelper;
use Chill\PersonBundle\Entity\Identifier\PersonIdentifier;
use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\PersonAltName;
use Chill\PersonBundle\PersonIdentifier\PersonIdentifierManagerInterface;

class PersonCreateDTOFactory
{
    public function __construct(
        private readonly ConfigPersonAltNamesHelper $configPersonAltNamesHelper,
        private readonly PersonIdentifierManagerInterface $personIdentifierManager,
    ) {}

    public function createPersonCreateDTO(Person $person): PersonCreateDTO
    {
        $dto = new PersonCreateDTO();
        $dto->firstName = $person->getFirstName();
        $dto->lastName = $person->getLastName();
        $dto->birthdate = $person->getBirthdate();
        $dto->gender = $person->getGender();
        $dto->civility = $person->getCivility();
        $dto->phonenumber = $person->getPhonenumber();
        $dto->mobilenumber = $person->getMobilenumber();
        $dto->email = $person->getEmail();
        $dto->center = $person->getCenter();
        // address/addressForm are not mapped on Person entity; left to defaults

        foreach ($this->configPersonAltNamesHelper->getChoices() as $key => $labels) {
            $altName = $person->getAltNames()->findFirst(fn (int $k, PersonAltName $altName) => $altName->getKey() === $key);
            if (null === $altName) {
                $altName = new PersonAltName();
                $altName->setKey($key);
            }
            $dto->altNames[$key] = $altName;
        }

        foreach ($this->personIdentifierManager->getWorkers() as $worker) {
            $identifier = $person
                ->getIdentifiers()
                ->findFirst(fn (int $key, PersonIdentifier $identifier) => $worker->getDefinition() === $identifier->getDefinition());
            if (null === $identifier) {
                $identifier = new PersonIdentifier($worker->getDefinition());
                $person->addIdentifier($identifier);
            }
            $dto->identifiers['identifier_'.$worker->getDefinition()->getId()] = $identifier;
        }

        return $dto;
    }

    public function mapPersonCreateDTOtoPerson(PersonCreateDTO $personCreateDTO, Person $person): void
    {
        $person
            ->setFirstName($personCreateDTO->firstName)
            ->setLastName($personCreateDTO->lastName)
            ->setBirthdate($personCreateDTO->birthdate)
            ->setGender($personCreateDTO->gender)
            ->setCivility($personCreateDTO->civility)
            ->setPhonenumber($personCreateDTO->phonenumber)
            ->setMobilenumber($personCreateDTO->mobilenumber)
            ->setEmail($personCreateDTO->email)
            ->setCenter($personCreateDTO->center);

        foreach ($personCreateDTO->altNames as $altName) {
            if ('' === $altName->getLabel()) {
                $person->removeAltName($altName);
            } else {
                $person->addAltName($altName);
            }
        }

        foreach ($personCreateDTO->identifiers as $identifier) {
            $worker = $this->personIdentifierManager->buildWorkerByPersonIdentifierDefinition($identifier->getDefinition());
            if ($worker->isEmpty($identifier)) {
                $person->removeIdentifier($identifier);
            } else {
                $person->addIdentifier($identifier);
            }
        }
        // Note: address and addressForm are handled by controller/form during creation, not mapped here
    }
}
