<?php

namespace App\Dto\Input;

use ApiPlatform\Metadata\ApiProperty;
use App\Dto\Output\HardwareProfileOutput;
use App\Dto\Output\ImageRepositoryOutput;
use App\Dto\Output\MenuOutput;
use App\Dto\Output\OgLiveOutput;
use App\Dto\Output\OrganizationalUnitOutput;
use App\Dto\Output\PxeTemplateOutput;
use App\Entity\Client;
use App\Entity\ImageRepository;
use App\Model\ClientStatus;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;

final class ClientInput
{
    #[Assert\NotBlank(message: 'validators.client.name.not_blank')]
    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'El nombre del cliente',
        example: 'Cliente 1',
    )]
    public ?string $name = null;

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'La descripción del cliente',
        example: 'Cliente descripcion 1',
    )]
    public ?string $serialNumber = null;

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'La interfaz de red del cliente',
        example: 'eth0'
    )]
    public ?string $netiface = null;

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'El driver de red del cliente',
        example: 'e1000e'
    )]
    public ?string $netDriver = null;

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'La dirección MAC del cliente',
        example: '00:00:00:00:00:00'
    )]
    public ?string $mac = null;

    #[Groups(['client:write'])]
    #[Assert\Ip(message: 'validators.ip_address.invalid')]
    #[ApiProperty(
        description: 'La dirección IP del cliente',
        example: '192.168.1.1'
    )]
    public ?string $ip = null;

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'El estado del cliente',
        example: 'active'
    )]
    public ?string $status = ClientStatus::OFF;

    #[Assert\NotNull(message: 'validators.organizational_unit.not_null')]
    #[Groups(['client:write', 'client:patch'])]
    #[ApiProperty(
        description: 'La unidad organizativa del cliente'
    )]
    public ?OrganizationalUnitOutput $organizationalUnit = null;

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'El menú del cliente'
    )]
    public ?MenuOutput $menu = null;

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'La plantilla PXE del cliente'
    )]
    public ?PxeTemplateOutput $pxeTemplate = null;

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'El perfil de hardware del cliente'
    )]
    public ?HardwareProfileOutput $hardwareProfile = null;

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'OgLive del cliente'
    )]
    public ?OgLiveOutput $ogLive = null;

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'La posición del cliente dentro del aula'
    )]
    public ?array $position = ['x' => 0, 'y' => 0];

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'descriptions.client.validation'
    )]
    public ?ImageRepositoryOutput $repository = null;

    #[Groups(['client:write'])]
    #[ApiProperty(
        description: 'descriptions.client.validation'
    )]
    public ?bool $maintenance = false;


    public function __construct(?Client $client = null)
    {
        if (!$client) {
            return;
        }

        $this->name = $client->getName();
        $this->serialNumber = $client->getSerialNumber();
        $this->netiface = $client->getNetiface();
        $this->organizationalUnit = new OrganizationalUnitOutput($client->getOrganizationalUnit());
        $this->netDriver = $client->getNetDriver();
        $this->mac = $client->getMac();
        $this->ip = $client->getIp();
        $this->position = $client->getPosition();
        $this->status = $client->getStatus();

        if ($client->getMenu()) {
            $this->menu = new MenuOutput($client->getMenu());
        }

        if ($client->getOgLive()) {
            $this->ogLive = new OgLiveOutput($client->getOgLive());
        }

        if ($client->getTemplate()) {
            $this->pxeTemplate = new PxeTemplateOutput($client->getTemplate());
        }

        if ($client->getHardwareProfile()) {
            $this->hardwareProfile = new HardwareProfileOutput($client->getHardwareProfile());
        }

        if ($client->getRepository()) {
            $this->repository = new ImageRepositoryOutput($client->getRepository());
        }
    }

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

        $menu = $this->menu?->getEntity() ?? $client->getOrganizationalUnit()?->getNetworkSettings()?->getMenu();
        $ogLive = $this->ogLive?->getEntity() ?? $client->getOrganizationalUnit()?->getNetworkSettings()?->getOgLive();
        $hardwareProfile = $this->hardwareProfile?->getEntity() ?? $client->getOrganizationalUnit()?->getNetworkSettings()?->getHardwareProfile();
        $repository = $this->repository?->getEntity() ?? $client->getOrganizationalUnit()?->getNetworkSettings()?->getRepository();
        $template = $this->pxeTemplate?->getEntity() ?? $client->getOrganizationalUnit()?->getNetworkSettings()?->getPxeTemplate();

        $client->setName($this->name);
        $client->setSerialNumber($this->serialNumber);
        $client->setNetiface($this->netiface);
        $client->setOrganizationalUnit($this->organizationalUnit->getEntity());
        $client->setNetDriver($this->netDriver);
        $client->setMac($this->mac);
        $client->setIp($this->ip);
        $client->setMenu($menu);
        $client->setOgLive($ogLive);
        $client->setHardwareProfile($hardwareProfile);
        $client->setRepository($repository);
        $client->setTemplate($template);
        $client->setPosition($this->position);
        $client->setStatus($this->status);
        $client->setMaintenance($this->maintenance);

        return $client;
    }
}
