<?php

namespace App\Validator\Constraints;

use App\Dto\Input\DeployImageInput;
use App\Dto\Input\DeployGitImageInput;
use App\Dto\Output\ClientOutput;
use App\Entity\Client;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Constraint;

class ClientsHaveSamePartitionSizeValidator extends ConstraintValidator
{
    public function validate($value, Constraint $constraint): void
    {
        if (!$value instanceof DeployImageInput && !$value instanceof DeployGitImageInput) {
            return;
        }

        if (!isset($value->clients) || !is_array($value->clients) || empty($value->clients)) {
            return;
        }

        if ($value->diskNumber === null || $value->partitionNumber === null) {
            return;
        }

        $partitionSizes = [];
        
        foreach ($value->clients as $client) {
            $clientEntity = $client->getEntity();
            
            if (!$clientEntity instanceof Client) {
                continue;
            }
            
            $clientIp = (string) $clientEntity->getIp();
            
            $targetPartition = null;
            foreach ($clientEntity->getPartitions() as $partition) {
                if ($partition->getDiskNumber() === $value->diskNumber && 
                    $partition->getPartitionNumber() === $value->partitionNumber) {
                    $targetPartition = $partition;
                    break;
                }
            }

            if ($targetPartition === null) {
                $partitionSizes[$clientIp] = null;
            } else {
                $partitionSizes[$clientIp] = $targetPartition->getSize();
            }
        }

        $validSizes = array_filter($partitionSizes, fn($size) => $size !== null);

        if (count($validSizes) !== count($partitionSizes)) {
            $clientsWithoutPartition = array_keys(array_filter($partitionSizes, fn($size) => $size === null));
            $this->context->buildViolation('Algunos clientes no tienen la partición seleccionada (Disco: ' . $value->diskNumber . ', Partición: ' . $value->partitionNumber . '). Clientes sin partición: ' . implode(', ', $clientsWithoutPartition))
                ->addViolation();
            return;
        }

        if (count(array_unique($validSizes)) > 1) {
            $errorDetails = [];
            foreach ($partitionSizes as $clientIp => $partitionSize) {
                $errorDetails[] = "Cliente $clientIp tiene tamaño $partitionSize KB.";
            }

            $detailedMessage = implode(" ", $errorDetails);

            $this->context->buildViolation($constraint->message . ' Detalles: ' . $detailedMessage)
                ->addViolation();
        }
    }
}