<?php

declare(strict_types=1);

namespace Webkul\WebkulCsvImportBundle\JobParameters;

use Akeneo\Pim\Enrichment\Component\Product\Query\Filter\Operators;
use Akeneo\Pim\Enrichment\Component\Product\Validator\Constraints\FilterStructureLocale;
use Akeneo\Platform\Bundle\ImportExportBundle\Infrastructure\Validation\FilePath;
use Akeneo\Tool\Component\Batch\Job\JobInterface;
use Akeneo\Tool\Component\Batch\Job\JobParameters\ConstraintCollectionProviderInterface;
use Akeneo\Tool\Component\Batch\Job\JobParameters\DefaultValuesProviderInterface;
use Akeneo\Tool\Component\Localization\Localizer\LocalizerInterface;
use Symfony\Component\Validator\Constraints\Choice;
use Symfony\Component\Validator\Constraints\Collection;
use Symfony\Component\Validator\Constraints\NotBlank;
use Symfony\Component\Validator\Constraints\NotEqualTo;
use Symfony\Component\Validator\Constraints\Optional;
use Symfony\Component\Validator\Constraints\Type;

/**
 * Constraints for product CSV import
 */
class ProductCsvImport implements
    ConstraintCollectionProviderInterface,
    DefaultValuesProviderInterface
{
    public function __construct(
        protected ConstraintCollectionProviderInterface $simpleProvider,
        protected DefaultValuesProviderInterface $simpleDefaultProvider,
        protected $supportedJobNames,
        protected $channelRepository
    ) {
    }

    /**
     * {@inheritdoc}
     */
    public function getDefaultValues()
    {
        $parameters = $this->simpleDefaultProvider->getDefaultValues();
        $channelData = $this->channelRepository->getFullChannels();
        $defaultChannelCode = isset($channelData[0]) ? $channelData[0]->getCode() : null;
        $defaultLocaleCode = isset($channelData[0]) ? [$channelData[0]->getLocales()->first()->getCode()] : [];
        $currency = isset($channelData[0]) ? $channelData[0]->getCurrencies()->first()->getCode() : null;

        $parameters['filters'] = [
            'data'      => [
                [
                    'field'    => 'enabled',
                    'operator' => Operators::EQUALS,
                    'value'    => true,
                ],
                [
                    'field'    => 'categories',
                    'operator' => Operators::IN_CHILDREN_LIST,
                    'value'    => []
                ]
            ],
            'structure'    => [
                'scope'    => $defaultChannelCode,
                'locale'   => $defaultLocaleCode,
                'locales'  => $defaultLocaleCode,
                'currency' => $currency,
            ],
        ];

        $parameters['dateFormat'] = LocalizerInterface::DEFAULT_DATE_FORMAT;
        $parameters['with_media'] = true;
        $parameters['withHeader'] = true;
        $parameters['exportProductModelFirst'] = false;
        $parameters['exportVariantAfterModel'] = false;
        $parameters['convertVariantToSimple'] = false;
        $parameters['enabledComparison'] = false;
        $parameters['delimiter'] = ';';
        $parameters['enclosure'] = '"';
        $parameters['WebkulCsvCategoryDelimeter'] = '/';
        $parameters['WebkulCsvCategorySeperator'] = '///';
        $parameters['exportProfile'] = 0;
        $parameters['realTimeVersioning'] = false;
        $parameters['storage'] = [ 'type' => 'none',
        'filePath' => sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'export_%job_label%_%datetime%.csv' ];

        return $parameters;
    }

    /**
     * {@inheritdoc}
     */
    public function getConstraintCollection()
    {
        $baseConstraint = $this->simpleProvider->getConstraintCollection();
        $constraintFields = $baseConstraint->fields;
        $constraintFields['user_to_notify'] = new Optional();
        $constraintFields['filters'] = [
            new Collection(
                [
                    'fields'           => [
                        'structure' => [
                            new FilterStructureLocale(['groups' => ['Default', 'DataFilters']]),
                            new Collection(
                                [
                                    'fields'             => [
                                        'locales'    => new NotBlank(['groups' => ['Default', 'DataFilters']]),
                                        'locale'     => new NotBlank(['groups' => ['Default', 'DataFilters']]),
                                        'scope'      => new NotBlank(['groups' => ['Default', 'DataFilters']]),
                                        'currency'   => new NotBlank(),
                                        'attributes' => new Type(
                                            [
                                                'type'   => 'array',
                                                'groups' => ['Default', 'DataFilters'],
                                            ]
                                        ),
                                    ],
                                    'allowMissingFields' => true,
                                ]
                            ),
                        ],
                    ],
                    'allowExtraFields' => true,
                ]
            ),
        ];

        if ($this->filterData()) {
            $constraintFields['filters'][] = $this->filterData();
        }

        $constraintFields['withHeader']         = new Optional();
        $constraintFields['product_only']       = new Optional();
        $constraintFields['exportProfile'] = new Optional([
            new NotBlank(),
            new NotEqualTo(
                [
                    'value' => 0,
                    'message' => 'Please select any template'
                ])
        ]);
        $constraintFields['delimiter']          = new Choice([
                                                            'strict' => true,
                                                            'choices' => [",", ";", "|"],
                                                            'message' => 'The value must be one of , or ; or |'
                                                        ]);
        $constraintFields['enclosure']          = new NotBlank();
        $constraintFields['filePath']           = new NotBlank();
        $constraintFields['enabledComparison']  = new Optional();
        $constraintFields['convertVariantToSimple'] = new Type('bool');
        $constraintFields['WebkulCsvCategoryDelimeter'] = new NotBlank();
        $constraintFields['WebkulCsvCategorySeperator'] = new NotBlank();        

        return new Collection([
            'fields' => $constraintFields,
            'allowMissingFields' => true,
            'allowExtraFields' => true,
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function supports(JobInterface $job)
    {
        return in_array($job->getName(), $this->supportedJobNames);
    }

    public function filterData()
    {
        if (class_exists('\Pim\Component\Connector\Validator\Constraints\FilterData')) {
            return new \Pim\Component\Connector\Validator\Constraints\FilterData(['groups' => ['Default', 'DataFilters']]);
        } elseif (class_exists('\Pim\Component\Connector\Validator\Constraints\ProductFilterData')) {
            return new \Pim\Component\Connector\Validator\Constraints\ProductFilterData(['groups' => ['Default', 'DataFilters']]);
        }
    }
}
