<?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\PersonEdit\Service;

use Chill\PersonBundle\Actions\PersonEdit\PersonEditDTO;
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 PersonEditDTOFactory
{
    public function __construct(
        private readonly ConfigPersonAltNamesHelper $configPersonAltNamesHelper,
        private readonly PersonIdentifierManagerInterface $personIdentifierManager,
    ) {}

    public function createPersonEditDTO(Person $person): PersonEditDTO
    {
        $dto = new PersonEditDTO();
        $dto->firstName = $person->getFirstName();
        $dto->lastName = $person->getLastName();
        $dto->birthdate = $person->getBirthdate();
        $dto->deathdate = (null !== $deathDate = $person->getDeathdate()) ? \DateTimeImmutable::createFromInterface($deathDate) : null;
        $dto->gender = $person->getGender();
        $dto->genderComment = $person->getGenderComment();
        $dto->numberOfChildren = $person->getNumberOfChildren();
        $dto->memo = $person->getMemo() ?? '';
        $dto->employmentStatus = $person->getEmploymentStatus();
        $dto->administrativeStatus = $person->getAdministrativeStatus();
        $dto->placeOfBirth = $person->getPlaceOfBirth() ?? '';
        $dto->contactInfo = $person->getcontactInfo();
        $dto->phonenumber = $person->getPhonenumber();
        $dto->mobilenumber = $person->getMobilenumber();
        $dto->acceptSms = $person->getAcceptSMS();
        $dto->otherPhonenumbers = $person->getOtherPhoneNumbers();
        $dto->email = $person->getEmail();
        $dto->acceptEmail = $person->getAcceptEmail();
        $dto->countryOfBirth = $person->getCountryOfBirth();
        $dto->nationality = $person->getNationality();
        $dto->spokenLanguages = $person->getSpokenLanguages();
        $dto->civility = $person->getCivility();
        $dto->maritalStatus = $person->getMaritalStatus();
        $dto->maritalStatusDate = $person->getMaritalStatusDate();
        $dto->maritalStatusComment = $person->getMaritalStatusComment();
        $dto->cFData = $person->getCFData();


        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 mapPersonEditDTOtoPerson(PersonEditDTO $personEditDTO, Person $person): void
    {
        // Copy all editable fields from the DTO back to the Person entity
        $person
            ->setFirstName($personEditDTO->firstName)
            ->setLastName($personEditDTO->lastName)
            ->setBirthdate($personEditDTO->birthdate)
            ->setDeathdate($personEditDTO->deathdate)
            ->setGender($personEditDTO->gender)
            ->setGenderComment($personEditDTO->genderComment)
            ->setNumberOfChildren($personEditDTO->numberOfChildren)
            ->setMemo($personEditDTO->memo)
            ->setEmploymentStatus($personEditDTO->employmentStatus)
            ->setAdministrativeStatus($personEditDTO->administrativeStatus)
            ->setPlaceOfBirth($personEditDTO->placeOfBirth)
            ->setcontactInfo($personEditDTO->contactInfo)
            ->setPhonenumber($personEditDTO->phonenumber)
            ->setMobilenumber($personEditDTO->mobilenumber)
            ->setAcceptSMS($personEditDTO->acceptSms ?? false)
            ->setOtherPhoneNumbers($personEditDTO->otherPhonenumbers)
            ->setEmail($personEditDTO->email)
            ->setAcceptEmail($personEditDTO->acceptEmail ?? false)
            ->setCountryOfBirth($personEditDTO->countryOfBirth)
            ->setNationality($personEditDTO->nationality)
            ->setSpokenLanguages($personEditDTO->spokenLanguages)
            ->setCivility($personEditDTO->civility)
            ->setMaritalStatus($personEditDTO->maritalStatus)
            ->setMaritalStatusDate($personEditDTO->maritalStatusDate)
            ->setMaritalStatusComment($personEditDTO->maritalStatusComment)
            ->setCFData($personEditDTO->cFData);

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

        foreach ($personEditDTO->identifiers as $identifier) {
            $worker = $this->personIdentifierManager->buildWorkerByPersonIdentifierDefinition($identifier->getDefinition());
            if ($worker->isEmpty($identifier)) {
                $person->removeIdentifier($identifier);
            } else {
                $person->addIdentifier($identifier);
            }
        }
    }
}
