<?php

namespace App\Dto\Output;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\Get;
use App\Entity\Client;
use App\Entity\OrganizationalUnit;
use Symfony\Component\Serializer\Annotation\Groups;

#[Get(shortName: 'OrganizationalUnit')]
final class OrganizationalUnitOutput extends AbstractOutput
{
    #[Groups(['organizational-unit:read', "client:read", "user:read", 'organizational-unit:read:collection:short', 'software-profile:read', 'command-task:read'])]
    #[ApiProperty(
        description: 'El nombre de la unidad organizativa',
        example: 'Aula 1'
    )]
    public string $name;

    #[Groups(['organizational-unit:read'])]
    #[ApiProperty(
        description: 'Comentarios adicionales',
        example: 'Aula de informática equipada con 30 equipos'
    )]
    public ?string $comments = null;

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

    #[Groups(['organizational-unit:read'])]
    #[ApiProperty(
        description: 'La ubicación física',
        example: 'Planta baja, edificio A'
    )]
    public ?string $location = null;

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

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

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

    #[Groups(['organizational-unit:read', "client:read"])]
    #[ApiProperty(
        description: 'El tipo de unidad organizativa',
        example: 'aula'
    )]
    public string $type;

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

    #[Groups(['organizational-unit:read', 'client:read', 'organizational-unit:read:collection:short'])]
    #[ApiProperty(
        description: 'La ruta completa de la unidad organizativa',
        example: '/Edificio A/Planta Baja/Aula 1'
    )]
    public string $path;

    #[Groups(['organizational-unit:read', "client:read"])]
    #[ApiProperty(
        description: 'La configuración de red de la unidad organizativa',
        readableLink: true
    )]
    public ?NetworkSettingsOutput $networkSettings = null;

    #[Groups(['organizational-unit:read'])]
    #[ApiProperty(
        description: 'Las unidades organizativas hijas',
        example: []
    )]
    public array $children = [];

    #[Groups(['organizational-unit:read', "client:read"])]
    #[ApiProperty(
        description: 'El calendario remoto asociado',
        readableLink: true
    )]
    public ?RemoteCalendarOutput $remoteCalendar = null;

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

    #[Groups(['organizational-unit:read'])]
    #[ApiProperty(
        description: 'Indica si está disponible según el calendario',
        example: true
    )]
    public ?bool $available = null;

    #[Groups(['organizational-unit:read'])]
    #[ApiProperty(
        description: 'Indica si excluye cambios del padre',
        example: false
    )]
    public ?bool $excludeParentChanges = null;

    #[Groups(['organizational-unit:read'])]
    #[ApiProperty(
        description: 'Fecha de creación de la unidad organizativa',
        example: '2024-01-15T10:30:00+00:00'
    )]
    public \DateTime $createdAt;

    #[Groups(['organizational-unit:read'])]
    #[ApiProperty(
        description: 'Usuario que creó este registro',
        example: 'admin'
    )]
    public ?string $createdBy = null;

    public function __construct(OrganizationalUnit $organizationalUnit, array $context = [])
    {
        parent::__construct($organizationalUnit);

        $this->name = $organizationalUnit->getName();
        $this->comments = $organizationalUnit->getComments();
        $this->description = $organizationalUnit->getDescription();
        $this->location = $organizationalUnit->getLocation();
        $this->projector = $organizationalUnit->isProjector();
        $this->board = $organizationalUnit->isBoard();
        $this->capacity = $organizationalUnit->getCapacity();
        $this->type = $organizationalUnit->getType();
        $this->remotePc = $organizationalUnit->isRemotePc();
        $this->available = $organizationalUnit->getRemoteCalendar() && $organizationalUnit->getRemoteCalendar()->isAvailable();
        $this->networkSettings = $organizationalUnit->getNetworkSettings() ? new NetworkSettingsOutput($organizationalUnit->getNetworkSettings()) : null;
        $this->remoteCalendar = $organizationalUnit->getRemoteCalendar() ? new RemoteCalendarOutput($organizationalUnit->getRemoteCalendar()) : null;
        if ($organizationalUnit->getParent()) {
            $this->parent = new self($organizationalUnit->getParent());
        }

        if (isset($context['groups']) && in_array('organizational-unit:read', $context['groups'])) {
            $this->children = $organizationalUnit->getOrganizationalUnits()->map(
                fn(OrganizationalUnit $organizationalUnit) => new self($organizationalUnit, $context)
            )->toArray();
        }

        $this->excludeParentChanges = $organizationalUnit->isExcludeParentChanges();
        $this->path = $organizationalUnit->getPath();
        $this->createdAt = $organizationalUnit->getCreatedAt();
        $this->createdBy = $organizationalUnit->getCreatedBy();
    }
}