<?php

namespace Webapp\FileManagement\ApiOperation;

use ApiPlatform\Core\Api\IriConverterInterface;
use DateTime;
use Shared\Authentication\Entity\Site;
use Shared\Authentication\Entity\User;
use Shared\FileManagement\Entity\UserLinkedJob;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Security\Core\Security;
use Webapp\FileManagement\Entity\ParsingJob;

/**
 * Class CreateParsingJobOperation.
 */
final class CreateParsingJobOperation
{

    private IriConverterInterface $iriConverter;

    public function __construct(IriConverterInterface $iriConverter)
    {
        $this->iriConverter = $iriConverter;
    }

    public function __invoke(Request $request, Security $security): ParsingJob
    {
        /** @var $user User */
        $user = $security->getUser();
        /** @var UploadedFile $uploadedFile */
        $uploadedFile = $request->files->get('file');
        if (!$uploadedFile) {
            throw new BadRequestHttpException('"file" is required');
        }
        /** @var Site $site */
        $site = $this->iriConverter->getItemFromIri($request->get('site'));
        if (!$site) {
            throw new BadRequestHttpException('"site" is required');
        }

        $type = $request->get('objectType');
        if (!$type) {
            throw new BadRequestHttpException('"objectType" is required');
        }
        $csvBindings = null;
        $statusDataEntry = null;
        switch ($type) {
            case ParsingJob::TYPE_EXPERIMENT_CSV:
            case ParsingJob::TYPE_PROTOCOL_CSV:
            case ParsingJob::TYPE_DATA_ENTRY_CSV:
            case ParsingJob::TYPE_PATH_BASE_CSV:
                if ($uploadedFile->getClientOriginalExtension() !== 'csv') {
                    throw new BadRequestHttpException(sprintf('"file" must be a csv file %s obtained', $uploadedFile->getClientMimeType()));
                }
                $csvBindings = $request->get('csvBindings');
                if (!$csvBindings) {
                    throw new BadRequestHttpException('"csvBindings" is required');
                }
                break;
            case ParsingJob::TYPE_EXPERIMENT:
            case ParsingJob::TYPE_PLATFORM:
            case ParsingJob::TYPE_VARIABLE_COLLECTION:
                if (
                    $uploadedFile->getClientMimeType() !== 'application/xml' &&
                    $uploadedFile->getClientMimeType() !== 'text/xml' &&
                    $uploadedFile->getClientMimeType() !== 'application/zip' &&
                    $uploadedFile->getClientMimeType() !== 'application/zip-compressed' &&
                    $uploadedFile->getClientMimeType() !== 'application/x-zip-compressed'
                ) {
                    throw new BadRequestHttpException(sprintf('"file" must be a xml or zip file %s obtained', $uploadedFile->getClientMimeType()));
                }
                break;
            case ParsingJob::TYPE_PROJECT_DATA_ZIP:
                if (
                    $uploadedFile->getClientMimeType() !== 'application/zip' &&
                    $uploadedFile->getClientMimeType() !== 'application/zip-compressed' &&
                    $uploadedFile->getClientMimeType() !== 'application/x-zip-compressed'
                ) {
                    throw new BadRequestHttpException(sprintf('"file" must be a zip file %s obtained', $uploadedFile->getClientMimeType()));
                }
                $statusDataEntry = $this->iriConverter->getItemFromIri($request->get('statusDataEntry'));
                break;
            default:
                throw new BadRequestHttpException('"objectType" is not compatible');
        }


        $dataEntryFile = (new ParsingJob())
            ->setSite($site)
            ->setObjectType($type)
            ->setName(pathinfo($uploadedFile->getClientOriginalName(), PATHINFO_FILENAME))
            ->setUniqDirectoryName(uniqid())
            ->setFile($uploadedFile)
            ->setCsvBindings($csvBindings)
            ->setUser($user)
            ->setStatus(UserLinkedJob::STATUS_PENDING)
            ->setStatusDataEntry($statusDataEntry)
            ->setUploadDate(new DateTime());

        return $dataEntryFile;
    }
}
