<?php

namespace Leadlion\Autogedal\Model\Export;

use Amasty\Feed\Api\Data\FeedInterface;
use Amasty\Feed\Model\Config as FeedConfigProvider;
use Amasty\Feed\Model\Export\Product\Attributes\AttributesCache;
use Amasty\Feed\Model\Export\Product\Attributes\FeedAttributesProcessor;
use Leadlion\Autogedal\Model\Export\Product\Attributes\FeedAttributesStorage;
use Amasty\Feed\Model\Export\Product\Attributes\FeedAttributesStorageFactory;
use Amasty\Feed\Model\Export\Product\Attributes\ProductFeedAttributesPool;
use Amasty\Feed\Model\Export\Product\GetMediaGalleryData;
use Amasty\Feed\Model\Export\RowCustomizer\Composite;
use Amasty\Feed\Model\Export\RowCustomizer\CompositeFactory;
use Amasty\Feed\Model\Export\RowCustomizer\Relation;
use Amasty\Feed\Model\InventoryResolver;
use Amasty\Feed\Model\ResourceModel\Product\CollectionFactory;
use Magento\Catalog\Model\Category\StoreCategories;
use Magento\Catalog\Model\Product as ProductEntity;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Catalog\Model\Product\LinkTypeProvider;
use Magento\Catalog\Model\ResourceModel\Category\CollectionFactory as CategoryCollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory as ProductAttrCollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory as ProductCollectionFactory;
use Magento\Catalog\Model\ResourceModel\Product\Option\CollectionFactory as ProductOptionCollectionFactory;
use Magento\Catalog\Model\ResourceModel\ProductFactory;
use Magento\CatalogImportExport\Model\Export\Product as ProductBase;
use Magento\CatalogImportExport\Model\Export\Product\Type\Factory as TypeFactory;
use Magento\CatalogImportExport\Model\Import\Product as ImportProduct;
use Magento\CatalogInventory\Model\ResourceModel\Stock\ItemFactory;
use Magento\CatalogInventory\Model\StockRegistry;
use Magento\Eav\Model\Config;
use Magento\Eav\Model\Entity\Attribute\AbstractAttribute;
use Magento\Eav\Model\Entity\Collection\AbstractCollection;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Collection;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory as AttrSetCollectionFactory;
use Magento\Framework\App\Area;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
use Magento\ImportExport\Model\Export;
use Magento\ImportExport\Model\Export\ConfigInterface;
use Magento\ImportExport\Model\Import;
use Magento\Store\Model\App\Emulation;
use Magento\Store\Model\Store;
use Magento\Store\Model\StoreManagerInterface;
use Psr\Log\LoggerInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;

class Product extends \Amasty\Feed\Model\Export\Product
{
    const XML_SHIP_COST_CATEG = 'leadlion/shipping_cost_category/shipping_cost_category';

    private const IS_IN_STOCK_ATTRIBUTE_CODE = 'is_in_stock';
    public const GALLERY_IMAGE_QTY = 5;
    public const ROW_CATEGORIES_KEY = 'rowCategories';
    protected $_scopeConfig;

    /**
     * @var array
     */
    protected $_fieldsMap = [
        ProductBase::COL_TYPE => 'product_type',
        ProductBase::COL_PRODUCT_WEBSITES => 'product_websites'
    ];

    /**
     * Attribute code to its values. Only attributes with options and only default store values used.
     *
     * @var array
     */
    protected $amAttrCodes = null;

    /**
     * @var array
     */
    protected $_bannedAttributes = [
        'media_gallery',
        'gallery',
        'custom_design',
        'custom_design_from',
        'custom_design_to',
        'custom_layout_update',
        'page_layout',
        'pattern'
    ];

    /**
     * @var Composite
     */
    protected $rowCustomizer;

    /**
     * @var int|string
     */
    private $storeId;

    /**
     * @var Composite
     */
    private $rowCustomizerComposite;

    /**
     * @var array
     */
    private $categoriesPath = [];

    /**
     * @var array
     */
    private $categoriesLast = [];

    /**
     * @var array
     */
    private $multirawData;

    /**
     * @var int[]
     */
    private $matchingProductIds;

    /**
     * @var int
     */
    private $page = 1;

    /**
     * @var CollectionFactory
     */
    private $collectionAmastyFactory;

    /**
     * @var StockRegistry
     */
    private $stockRegistry;

    /**
     * @var InventoryResolver
     */
    private $inventoryResolver;

    /**
     * @var StoreCategories
     */
    private $storeCategories;

    /**
     * @var ProductFeedAttributesPool|null
     */
    private $feedAttributesPool;

    /**
     * @var FeedInterface|null
     */
    private $feedProfile;

    /**
     * @var GetMediaGalleryData
     */
    private $getMediaGalleryData;

    /**
     * @var FeedAttributesProcessor
     */
    private $feedAttributesProcessor;

    /**
     * @var FeedAttributesStorageFactory
     */
    private $attributesStorageFactory;

    /**
     * @var FeedAttributesStorage
     */
    private $attributesStorage;

    /**
     * @var FeedConfigProvider
     */
    private $configProvider;

    /**
     * @var array
     */
    private $userDefinedAttributes = [];

    /**
     * @var AttributesCache
     */
    private $attributesCache;

    /**
     * @var Emulation
     */
    private $emulation;

    /**
     * @var array
     */
    private array $storeGroupCategories = [];

    public function __construct(
        StockRegistry $stockRegistry,
        TimezoneInterface $localeDate,
        Config $config,
        ResourceConnection $resource,
        StoreManagerInterface $storeManager,
        StoreCategories $storeCategories,
        LoggerInterface $logger,
        ProductCollectionFactory $collectionFactory,
        ConfigInterface $exportConfig,
        ProductFactory $productFactory,
        AttrSetCollectionFactory $attrSetColFactory,
        CategoryCollectionFactory $categoryColFactory,
        ItemFactory $itemFactory,
        ProductOptionCollectionFactory $optionColFactory,
        ProductAttrCollectionFactory $attributeColFactory,
        TypeFactory $typeFactory,
        LinkTypeProvider $linkTypeProvider,
        CompositeFactory $rowCustomizerFactory,
        FeedConfigProvider $configProvider,
        CollectionFactory $collectionAmastyFactory,
        InventoryResolver $inventoryResolver,
        ProductFeedAttributesPool $feedAttributesPool,
        GetMediaGalleryData $getMediaGalleryData,
        FeedAttributesProcessor $feedAttributesProcessor,
        FeedAttributesStorageFactory $attributesStorageFactory,
        AttributesCache $attributesCache,
        Emulation $emulation,
        ScopeConfigInterface $scopeConfig,
        ?FeedInterface $feedProfile = null,
        ?int $storeId = null
    ) {
        $this->rowCustomizerComposite = $rowCustomizerFactory->create();
        $this->collectionAmastyFactory = $collectionAmastyFactory;
        $this->stockRegistry = $stockRegistry;
        $this->inventoryResolver = $inventoryResolver;
        $this->storeCategories = $storeCategories;
        $this->feedAttributesPool = $feedAttributesPool;
        $this->getMediaGalleryData = $getMediaGalleryData;
        $this->feedAttributesProcessor = $feedAttributesProcessor;
        $this->attributesStorageFactory = $attributesStorageFactory;
        $this->configProvider = $configProvider;
        $this->attributesCache = $attributesCache;
        $this->storeId = $storeId;
        $this->feedProfile = $feedProfile;
        $this->emulation = $emulation;
        $this->_scopeConfig = $scopeConfig;

        parent::__construct(
            $stockRegistry,
            $localeDate,
            $config,
            $resource,
            $storeManager,
            $storeCategories,
            $logger,
            $collectionFactory,
            $exportConfig,
            $productFactory,
            $attrSetColFactory,
            $categoryColFactory,
            $itemFactory,
            $optionColFactory,
            $attributeColFactory,
            $typeFactory,
            $linkTypeProvider,
            $rowCustomizerFactory,
            $configProvider,
            $collectionAmastyFactory,
            $inventoryResolver,
            $feedAttributesPool,
            $getMediaGalleryData,
            $feedAttributesProcessor,
            $attributesStorageFactory,
            $attributesCache,
            $emulation,
            $feedProfile,
            $storeId
        );
    }

    public function setPage(int $page): self
    {
        $this->page = $page;

        return $this;
    }

    public function getRawExport(): array
    {
        $result = parent::getRawExport();
        foreach ($result as &$row) {
            if (!array_key_exists('inventory|qty', $row) || $row['inventory|qty'] === null || $row['inventory|qty'] === '') {
                $row['inventory|qty'] = '0.0000';
            }
        }
        return $result;
    }

   public function export(bool $lastPage = false): string
    {
        $exportData = $this->getRawExport();

        $writer = $this->getWriter();
        if ($this->page === 0) {
            $writer->writeHeader();
        }

        foreach ($exportData as $dataRow) {
            $writer->writeDataRow($dataRow);
        }

        if ($lastPage) {
            $writer->writeFooter();
        }

        return $writer->getContents();
    }

    // protected function _prepareRowBeforeWrite(&$dataRow)
    // {
    //     $exportRow = [];

    //     $dataRow = $this->_customFieldsMapping($dataRow);

    //     $basicTypes = [
    //         self::PREFIX_BASIC_ATTRIBUTE,
    //         self::PREFIX_PRODUCT_ATTRIBUTE,
    //         self::PREFIX_INVENTORY_ATTRIBUTE
    //     ];

    //     $customTypes = [
    //         self::PREFIX_CUSTOM_PRODUCT_TYPE,
    //         self::PREFIX_CATEGORY_SHIP_COST,
    //         self::PREFIX_CATEGORY_ATTRIBUTE,
    //         self::PREFIX_CATEGORY_PATH_ATTRIBUTE,
    //         self::PREFIX_MAPPED_CATEGORY_ATTRIBUTE,
    //         self::PREFIX_MAPPED_CATEGORY_PATHS_ATTRIBUTE,
    //         self::PREFIX_CUSTOM_FIELD_ATTRIBUTE,
    //         self::PREFIX_IMAGE_ATTRIBUTE,
    //         self::PREFIX_GALLERY_ATTRIBUTE,
    //         self::PREFIX_URL_ATTRIBUTE,
    //         self::PREFIX_PRICE_ATTRIBUTE,
    //         self::PREFIX_OTHER_ATTRIBUTES,
    //         self::PREFIX_ADVANCED_ATTRIBUTE
    //     ];

    //     if (is_array($this->_attributes) && !empty($this->_attributes)) {
    //         $this->_createExportRow($this->_attributes, $dataRow, [], $basicTypes, $customTypes, $exportRow);
    //     }

    //     if (is_array($this->_parentAttributes) && !empty($this->_parentAttributes)) {
    //         $parentDataRow = isset($dataRow['amasty_custom_data']['parent_data'])
    //             ? $dataRow['amasty_custom_data']['parent_data']
    //             : [];
    //         $this->_createExportRow(
    //             $this->_parentAttributes,
    //             $parentDataRow,
    //             $dataRow,
    //             $basicTypes,
    //             $customTypes,
    //             $exportRow
    //         );
    //     }

    //     return $exportRow;
    // }

    protected function initCategories(): self
    {
        if (!empty($this->categoriesPath)) {
            return $this;
        }
        $collection = $this->_categoryColFactory->create()->addNameToResult();
        foreach ($collection as $category) {
            $structure = preg_split('#/+#', $category->getPath());
            $pathSize = count($structure);

            if ($pathSize > 1) {
                $path = [];
                for ($i = 1; $i < $pathSize; $i++) {
                    if ($collection->getItemById($structure[$i])) {
                        $path[$structure[$i]] = $collection->getItemById($structure[$i])->getName();
                    } else {
                        $path[$structure[$i]] = null;
                    }
                }
                $this->categoriesPath[$category->getId()] = $path;
                $this->_rootCategories[$category->getId()] = array_shift($path);
                if ($pathSize > 2) {
                    $this->_categories[$category->getId()] = implode('/', $path);
                }
                $this->categoriesLast[$category->getId()] = end($this->categoriesPath[$category->getId()]);
            }
        }

        return $this;
    }

    protected function getExportData(): array
    {
        $exportData = [];

        $rawData = $this->collectRawData();
        $multiRowData = $this->collectMultirawData();
        $productIds = array_keys($rawData);
        $stockItemRows = $this->inventoryResolver->getInventoryData($productIds);

        $this->rowCustomizer->initFromProfile($this);
        $this->rowCustomizer->prepareData($this->_getEntityCollection(), $productIds);
        foreach ($rawData as $productId => $productData) {
            foreach ($productData as $dataRow) {
                if (isset($stockItemRows[$productId])) {
                    $dataRow += $stockItemRows[$productId];
                }
                $exportData[] = $this->addMultirawCustomizerData($dataRow, $multiRowData);
            }
        }

        return $exportData;
    }
    
    /**
     * Applying row customizers to the data row
     */
    private function addMultirawCustomizerData(array $dataRow, array &$multiRowData): array
    {
        if (array_key_exists('product_id', $dataRow)) {
            $productId = $dataRow['product_id'];
            $this->updateDataWithCategoryColumns($dataRow, $multiRowData[self::ROW_CATEGORIES_KEY], $productId);
            $dataRow = $this->rowCustomizer->addData($dataRow, $productId);
        }

        return $dataRow;
    }

    private function getCatShipCost()
    {
        $confSettings = $this->_scopeConfig->getValue(
            self::XML_SHIP_COST_CATEG,
            \Magento\Store\Model\ScopeInterface::SCOPE_STORE
        );
        $info = [];
        if ($confSettings) {
            $serializer = \Magento\Framework\App\ObjectManager::getInstance()->get(\Magento\Framework\Serialize\SerializerInterface::class);

            $feedConfig = $serializer->unserialize($confSettings);

            $info = [];
            foreach ($feedConfig as $config) {
                $info[$config['category_id']] = $config['shipping_cost'];
            }
        }
        
        return $info;
    }

    protected function updateDataWithCategoryColumns(&$dataRow, &$rowCategories, $productId): bool
    {
        if (isset($dataRow['amasty_custom_data'])) {
            $dataRow['amasty_custom_data'] = [];
        }

        $customData = &$dataRow['amasty_custom_data'];
        if (isset($rowCategories[$productId]) && !empty($rowCategories[$productId])) {
            $shipCostConfig = $this->getCatShipCost();
            $categories = $rowCategories[$productId];
            $lastCategoryId = end($categories);
            if ($lastCategoryId == $this->getRootCategoryId()) {
                $lastCategoryId = prev($categories);
            }
            
            if (isset($this->categoriesPath[$lastCategoryId])) {
                $counter = 0;
                foreach ($this->categoriesPath[$lastCategoryId] as $catId => $catName) {
                    $counter++;
                    if ($counter == 2) {
                        $lastCategoryId = $catId;
                    }
                }
                $customData[FeedAttributesStorage::PREFIX_CATEGORY_ATTRIBUTE]['category'] = isset($this->categoriesLast[$lastCategoryId])
                ? $this->categoriesLast[$lastCategoryId]
                : '';
                $customData[FeedAttributesStorage::PREFIX_CATEGORY_ID_ATTRIBUTE] = $lastCategoryId;

                $customData[FeedAttributesStorage::PREFIX_CATEGORY_SHIP_COST] =
                    isset($shipCostConfig[$customData[FeedAttributesStorage::PREFIX_CATEGORY_ID_ATTRIBUTE]]) ?
                    $shipCostConfig[$customData[FeedAttributesStorage::PREFIX_CATEGORY_ID_ATTRIBUTE]] :
                    '19.00 RON';
            } else {
                var_dump($this->categoriesLast);
                $customData[FeedAttributesStorage::PREFIX_CATEGORY_ATTRIBUTE]['category'] = isset($this->categoriesLast[$lastCategoryId])
                ? $this->categoriesLast[$lastCategoryId]
                : '';
                $customData[FeedAttributesStorage::PREFIX_CATEGORY_ID_ATTRIBUTE] = $lastCategoryId;

                $customData[FeedAttributesStorage::PREFIX_CATEGORY_SHIP_COST] =
                    isset($shipCostConfig[$customData[FeedAttributesStorage::PREFIX_CATEGORY_ID_ATTRIBUTE]]) ?
                    $shipCostConfig[$customData[FeedAttributesStorage::PREFIX_CATEGORY_ID_ATTRIBUTE]] :
                    '19.00 RON';
            }
            
        }

        $ret = \Magento\CatalogImportExport\Model\Export\Product::updateDataWithCategoryColumns(
            $dataRow,
            $rowCategories,
            $productId
        );

        if (isset($dataRow[self::COL_CATEGORY])) {
            $customData[FeedAttributesStorage::PREFIX_CATEGORY_PATH_ATTRIBUTE]['category'] = $dataRow[self::COL_CATEGORY];
        }

        return $ret;
    }

    public function getCategoriesPath(): array
    {
        return $this->categoriesPath;
    }

    public function getCategoriesLast(): array
    {
        return $this->categoriesLast;
    }

    protected function getRootCategoryId()
    {
        return $this->_storeManager->getStore()->getRootCategoryId();
    }

    public function getMediaGallery(array $productIds): array
    {
        if (empty($productIds)) {
            return [];
        }
        $productEntityJoinField = $this->getProductEntityLinkField();

        $select = $this->_connection->select()->from(
            ['mgvte' => $this->_resourceModel->getTableName('catalog_product_entity_media_gallery_value_to_entity')],
            [
                "mgvte.$productEntityJoinField",
                'mgvte.value_id'
            ]
        )->joinLeft(
            ['mg' => $this->_resourceModel->getTableName('catalog_product_entity_media_gallery')],
            '(mg.value_id = mgvte.value_id)',
            [
                'mg.attribute_id',
                'filename' => 'mg.value',
            ]
        )->joinLeft(
            ['mgv' => $this->_resourceModel->getTableName('catalog_product_entity_media_gallery_value')],
            "(mg.value_id = mgv.value_id) and (mgvte.$productEntityJoinField = mgv.$productEntityJoinField)",
            [
                'mgv.label',
                'mgv.position',
                'mgv.disabled',
                'mgv.store_id',
            ]
        )->joinLeft(
            ['ent' => $this->_resourceModel->getTableName('catalog_product_entity')],
            "(mgvte.$productEntityJoinField = ent.$productEntityJoinField)",
            [
                'ent.entity_id'
            ]
        )->where(
            "ent.entity_id IN (?)",
            $productIds
        )->where(
            "mgv.store_id IN (?)",
            [\Magento\Store\Model\Store::DEFAULT_STORE_ID, $this->storeId]
        );
        $rowMediaGallery = [];
        $stmt = $this->_connection->query($select);

        while ($mediaRow = $stmt->fetch()) {
            if (0 == $mediaRow['store_id']) {
                $rowMediaGallery[$mediaRow[$productEntityJoinField]][] = [
                    '_media_attribute_id' => $mediaRow['attribute_id'],
                    '_media_image' => $mediaRow['filename'],
                    '_media_label' => $mediaRow['label'],
                    '_media_position' => $mediaRow['position'],
                    '_media_is_disabled' => $mediaRow['disabled'],
                    '_media_store_id' => $mediaRow['store_id'],
                ];
            }
        }

        return $rowMediaGallery;
    }
}
