<?php

declare(strict_types=1);

namespace App\Controller;

use ApiPlatform\Validator\ValidatorInterface;
use App\Dto\Input\DeployGitImageInput;
use App\Model\CommandTypes;
use App\Model\DeployMethodTypes;
use App\Model\TraceStatus;
use App\Service\Trace\CreateService;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;

class DeployGitImageAction extends AbstractController
{
    public function __construct(
        protected readonly CreateService          $createService,
        protected readonly ValidatorInterface     $validator,
        protected readonly LoggerInterface        $logger,
        public readonly \App\Controller\OgAgent\DeployGitImageAction $deployGitImageOgAgentAction,
    ) {
    }

    /**
     * @throws RedirectionExceptionInterface
     * @throws ClientExceptionInterface
     * @throws ServerExceptionInterface
     */
    public function __invoke(DeployGitImageInput $input): JsonResponse
    {
        $this->validator->validate($input);
        
        $clientJobs = $this->handleGitDeployment($input);

        return new JsonResponse(data: $clientJobs, status: Response::HTTP_OK);
    }

    private function handleGitDeployment(DeployGitImageInput $input): array
    {
        $clientJobs = [];

        foreach ($input->clients as $client) {
            try {
                $inputData = $this->createInputData($input, $client->getEntity());
                $jobId = $this->processDeployment($client->getEntity(), $input, $inputData, DeployMethodTypes::GIT);
                
                if ($jobId) {
                    $clientJobs[(string) '/clients/' . $client->getEntity()->getUuid()] = $jobId;
                }
            } catch (\Exception $e) {
                $this->logger->warning('Error deploying git image to client', [
                    'client_uuid' => $client->getEntity()->getUuid(),
                    'error' => $e->getMessage()
                ]);
                
                if ($input->queue) {
                    $inputData = $this->createInputData($input, $client->getEntity());
                    $this->createService->__invoke($client->getEntity(), CommandTypes::DEPLOY_IMAGE, TraceStatus::PENDING, null, $inputData);
                }
                
                continue;
            }
        }

        return $clientJobs;
    }

    private function processDeployment($client, DeployGitImageInput $input, array $inputData, string $deployType): ?string
    {
        $agentJobId = $this->deployGitImageOgAgentAction->__invoke($input, $client);
        
        if (!$agentJobId) {
            if ($input->queue) {
                $this->createService->__invoke($client, CommandTypes::DEPLOY_IMAGE, TraceStatus::PENDING, null, $inputData);
            }
            return null;
        }

        $this->createService->__invoke($client, CommandTypes::DEPLOY_IMAGE, TraceStatus::IN_PROGRESS, $agentJobId, $inputData);
        
        return $agentJobId;
    }

    private function createInputData(DeployGitImageInput $input, $client): array
    {
        return [
            'client' => $client->getUuid(),
            'hexsha' => $input->hexsha,
            'repositoryName' => $input->repositoryName,
            'branch' => $input->branch,
            'numDisk' => (string) $input->diskNumber,
            'numPartition' => (string) $input->partitionNumber,
            'type' => $input->type,
        ];
    }
} 