<?php

declare(strict_types=1);

namespace Leadlion\StockUpdates\Cron;

use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\CollectionFactory as AttributeSetCollectionFactory;
use Magento\Inventory\Model\SourceItem\Command\Handler\SourceItemsSaveHandler;
use Magento\InventoryApi\Api\Data\SourceItemInterfaceFactory;
use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockItem;
use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockStatus;
use Monolog\Logger as MonoLogger;
use Monolog\Handler\StreamHandler;
use Monolog\Level;

class AlfaromtransStock
{
    const FEED_URL = "https://www.alfaromtrans.ro/index.php?route=extension/lisal/feed/product_feed&module_id=5";
    const ATTRIBUTE_SET_NAME = 'Paravanturi';

    /**
     * @var CollectionFactory
     */
    protected $collectionFactory;

    /**
     * @var AttributeSetCollectionFactory
     */
    private $attributeSetCollectionFactory;

    /**
     * @var SourceItemInterfaceFactory
     */
    private $sourceItemFactory;

    /**
     * @var SourceItemsSaveHandler
     */
    private $sourceItemsSaveHandler;

    /**
     * @var SetDataToLegacyStockItem
     */
    private $setDataToLegacyStockItem;

    /**
     * @var SetDataToLegacyStockStatus
     */
    private $setDataToLegacyStockStatus;

    public function __construct(
        CollectionFactory $collectionFactory,
        AttributeSetCollectionFactory $attributeSetCollectionFactory,
        SourceItemInterfaceFactory $sourceItemFactory,
        SourceItemsSaveHandler $sourceItemsSaveHandler,
        SetDataToLegacyStockItem $setDataToLegacyStockItem,
        SetDataToLegacyStockStatus $setDataToLegacyStockStatus
    ) {
        $this->collectionFactory = $collectionFactory;
        $this->attributeSetCollectionFactory = $attributeSetCollectionFactory;
        $this->sourceItemFactory = $sourceItemFactory;
        $this->sourceItemsSaveHandler = $sourceItemsSaveHandler;
        $this->setDataToLegacyStockItem = $setDataToLegacyStockItem;
        $this->setDataToLegacyStockStatus = $setDataToLegacyStockStatus;
    }

    public function execute()
    {
        $monolog = new MonoLogger('alfaromtrans_stock');
        $monolog->pushHandler(new StreamHandler(BP . '/var/log/alfaromtrans_stock.log', Level::Debug));
        $logger = $monolog;

        $attributeSetId = $this->getAttributeSetIdByName(self::ATTRIBUTE_SET_NAME);
        if (!$attributeSetId) {
            $logger->info('Attribute set "' . self::ATTRIBUTE_SET_NAME . '" not found. Aborting.');
            return;
        }

        $feedContent = $this->getFeedContent($logger);
        if (empty($feedContent)) {
            $logger->info('Feed is empty or could not be fetched. Aborting.');
            return;
        }

        $skuFzs[] = array_keys($feedContent);

        $collection = $this->collectionFactory->create()
            ->addAttributeToSelect('sku_fz')
            ->addAttributeToSelect('sku')
            ->addAttributeToFilter('sku_fz', $skuFzs)
            ->addAttributeToFilter('attribute_set_id', $attributeSetId)
            ->addAttributeToFilter('status', Status::STATUS_ENABLED);

        $sourceItems = [];

        foreach ($collection as $product) {
            if (isset($feedContent[$product->getSkuFz()])) {
                $sku = $product->getSku();
                $availability = $feedContent[$product->getSkuFz()]['availability'];

                $isInStock = ($availability === 'instock') ? 1 : 0;
                $qty = $isInStock ? 9999 : 0;

                $sourceItem = $this->sourceItemFactory->create();
                $sourceItem->setData('source_code', 'default');
                $sourceItem->setData('sku', $sku);
                $sourceItem->setData('quantity', $qty);
                $sourceItem->setData('status', $isInStock);
                $sourceItems[] = $sourceItem;

                try {
                    $this->setDataToLegacyStockItem->execute(
                        (string)$sku,
                        (float)$qty,
                        $isInStock
                    );
                    $this->setDataToLegacyStockStatus->execute(
                        (string)$sku,
                        (float)$qty,
                        $isInStock
                    );
                } catch (\Exception $e) {
                    $logger->info('Error saving stock for sku: ' . $sku . ' - ' . $e->getMessage());
                }

                $logger->info('Alfaromtrans sku: ' . $sku . ' sku_fz: ' . $product->getSkuFz() . ' qty: ' . $qty . ' in_stock: ' . $isInStock);
            }
        }

        if (!empty($sourceItems)) {
            $this->sourceItemsSaveHandler->execute($sourceItems);
        }

        $logger->info('Done. Updated ' . count($sourceItems) . ' products.');
    }

    private function getAttributeSetIdByName(string $name): ?int
    {
        $collection = $this->attributeSetCollectionFactory->create()
            ->addFieldToFilter('attribute_set_name', $name)
            ->addFieldToFilter('entity_type_id', 4)
            ->setPageSize(1);

        $attributeSet = $collection->getFirstItem();

        return $attributeSet->getId() ? (int)$attributeSet->getId() : null;
    }

    private function getFeedContent($logger): array
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, self::FEED_URL);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');

        $response = curl_exec($ch);

        if (curl_errno($ch)) {
            $logger->info('Error when reading the feed: ' . curl_error($ch));
            curl_close($ch);
            return [];
        }

        curl_close($ch);

        if (empty($response)) {
            $logger->info('Empty response from feed.');
            return [];
        }

        $logger->info('Feed response (first 500 chars): ' . substr($response, 0, 500));

        $xml = simplexml_load_string($response);
        if ($xml === false) {
            $logger->info('Could not parse XML feed.');
            return [];
        }

        $contentFile = [];
        foreach ($xml->item as $item) {
            $sku = trim((string)$item->sku);
            $availability = strtolower(trim((string)$item->Stoc));

            if (!empty($sku)) {
                $contentFile[$sku] = [
                    'availability' => $availability,
                ];
            }
        }

        $logger->info('Feed parsed: ' . count($contentFile) . ' products found.');

        return $contentFile;
    }
}
