<?php

declare(strict_types=1);

namespace App\Controller\OgAgent;

use App\Dto\Input\BootClientsInput;
use App\Dto\Input\MultipleClientsInput;
use App\Entity\Client;
use App\Entity\Command;
use App\Entity\Image;
use App\Entity\Partition;
use App\Entity\Trace;
use App\Model\ClientStatus;
use App\Model\CommandTypes;
use App\Model\ImageStatus;
use App\Model\TraceStatus;
use App\Service\Trace\CreateService;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Validator\Exception\ValidatorException;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;

class LoginAction extends AbstractOgAgentController
{
    /**
     * @throws TransportExceptionInterface
     * @throws ServerExceptionInterface
     * @throws RedirectionExceptionInterface
     * @throws ClientExceptionInterface
     */
    public function __invoke(BootClientsInput $input): JsonResponse
    {
        /** @var Partition $partition */
        $partition = $input->partition->getEntity();

        foreach ($input->clients as $clientEntity) {
            /** @var Client $client */
            $client = $clientEntity->getEntity();


            if (!$client->getIp()) {
                throw new BadRequestHttpException('IP is required');
            }

            if ($client->getStatus() !== ClientStatus::OG_LIVE) {
                $this->createService->__invoke($client, CommandTypes::LOGIN, TraceStatus::PENDING, null, []);
                continue;
            }

            $data = [
                'nfn' => 'IniciarSesion',
                'dsk' => (string) $partition->getDiskNumber(),
                'par' => (string) $partition->getPartitionNumber(),
                'ids' => '0'
            ];

            $response = $this->createRequest(
                method: 'POST',
                url: 'https://'.$client->getIp().':8000/opengnsys/IniciarSesion',
                params: [
                    'json' => $data,
                ],
                token: $client->getToken(),
            );

            if (isset($response['error']) && $response['code'] === Response::HTTP_INTERNAL_SERVER_ERROR) {
                $this->createService->__invoke($client, CommandTypes::LOGIN, TraceStatus::PENDING, null, []);
                continue;
            }

            $this->logger->info('Login client', ['client' => $client->getId()]);

            $jobId = $response['job_id'];

            $client->setStatus(ClientStatus::INITIALIZING);
            $this->entityManager->persist($client);
            $this->entityManager->flush();

            $this->createService->__invoke($client, CommandTypes::LOGIN, TraceStatus::SUCCESS, $jobId, []);
        }

        return new JsonResponse(data: [], status: Response::HTTP_OK);
    }
}
