<?php

namespace App\Dto\Input;

use ApiPlatform\Metadata\ApiProperty;
use App\Dto\Output\OrganizationalUnitOutput;
use App\Dto\Output\RemoteCalendarOutput;
use App\Entity\OrganizationalUnit;
use App\Validator\Constraints\OrganizationalUnitParent;
use App\Validator\Constraints\OrganizationalUnitType;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;

#[OrganizationalUnitParent]
class OrganizationalUnitInput
{
    private ?OrganizationalUnit $originalEntity = null;

    #[Assert\NotBlank(message: 'validators.organizational_unit.name.not_blank')]
    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El nombre de la unidad organizativa',
        example: 'Aula 1'
    )]
    public ?string $name = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'La unidad organizativa padre',
        example: null
    )]
    public ?OrganizationalUnitOutput $parent = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'La descripción de la unidad organizativa',
        example: 'Aula de informática principal'
    )]
    public ?string $description = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'La ubicación de la unidad organizativa',
        example: 'Planta baja, edificio A'
    )]
    public ?string $location = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'Si tiene proyector',
        example: true
    )]
    public ?bool $projector = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'Si tiene pizarra digital',
        example: false
    )]
    public ?bool $board = null;

    #[Assert\GreaterThan(0)]
    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'La capacidad de la unidad organizativa',
        example: 30
    )]
    public ?int $capacity = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'Comentarios adicionales',
        example: 'Aula equipada con ordenadores de última generación'
    )]
    public ?string $comments = null;

    #[Groups(['organizational-unit:write'])]
    #[OrganizationalUnitType]
    #[ApiProperty(
        description: 'El tipo de unidad organizativa',
        example: 'aula'
    )]
    public ?string $type = null;

    #[Groups(['organizational-unit:write'])]
    #[Assert\Valid()]
    #[ApiProperty(
        description: 'La configuración de red de la unidad organizativa'
    )]
    public ?NetworkSettingsInput $networkSettings = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'El calendario remoto de la unidad organizativa'
    )]
    public ?RemoteCalendarOutput $remoteCalendar = null;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'Si es un PC remoto',
        example: false
    )]
    public ?bool $remotePc = false;

    #[Groups(['organizational-unit:write'])]
    #[ApiProperty(
        description: 'Si excluir cambios del padre',
        example: false
    )]
    public ?bool $excludeParentChanges = null;

    public function __construct(?OrganizationalUnit $organizationalUnit = null)
    {
        if (!$organizationalUnit) {
            return;
        }

        $this->originalEntity = $organizationalUnit;
        $this->name = $organizationalUnit->getName();
        if ($organizationalUnit->getParent()) {
            $this->parent = new OrganizationalUnitOutput($organizationalUnit->getParent());
        }
        $this->description = $organizationalUnit->getDescription();
        $this->location = $organizationalUnit->getLocation();
        $this->projector = $organizationalUnit->isProjector();
        $this->board = $organizationalUnit->isBoard();
        $this->capacity = $organizationalUnit->getCapacity();
        $this->comments = $organizationalUnit->getComments();
        $this->type = $organizationalUnit->getType();
        $this->remotePc = $organizationalUnit->isRemotePc();
        if ($organizationalUnit->getNetworkSettings()){
            $this->networkSettings = new NetworkSettingsInput($organizationalUnit->getNetworkSettings());
        }

        if ($organizationalUnit->getRemoteCalendar()) {
            $this->remoteCalendar = new RemoteCalendarOutput($organizationalUnit->getRemoteCalendar());
        }
    }

    public function createOrUpdateEntity(?OrganizationalUnit $organizationalUnit = null): OrganizationalUnit
    {
        if (!$organizationalUnit) {
            $organizationalUnit = new OrganizationalUnit();
        }

        $organizationalUnit->setName($this->name);
        if ($this->parent) {
            $organizationalUnit->setParent($this->parent->getEntity());
        }
        $organizationalUnit->setDescription($this->description);
        $organizationalUnit->setLocation($this->location);
        $organizationalUnit->setProjector($this->projector);
        $organizationalUnit->setBoard($this->board);
        $organizationalUnit->setCapacity($this->capacity);
        $organizationalUnit->setComments($this->comments);
        $organizationalUnit->setType($this->type);
        $organizationalUnit->setRemotePc($this->remotePc);
        $organizationalUnit->setExcludeParentChanges($this->excludeParentChanges);

        if ($this->networkSettings){
            $organizationalUnit->setNetworkSettings($this->networkSettings->createOrUpdateEntity($organizationalUnit->getNetworkSettings()));
        }

        if ($this->remoteCalendar) {
            $organizationalUnit->setRemoteCalendar($this->remoteCalendar->getEntity());
        }

        return $organizationalUnit;
    }

    public function getOriginalEntity(): ?OrganizationalUnit
    {
        return $this->originalEntity;
    }
}