<?php

declare(strict_types=1);

namespace Leadlion\Autogedal\Cron;

use Magento\Framework\Exception\CouldNotDeleteException;
use Magento\InventoryApi\Api\Data\SourceItemInterfaceFactory;
use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockItem;
use Magento\InventoryCatalog\Model\ResourceModel\SetDataToLegacyStockStatus;
use Magento\Catalog\Model\Product\Action;
use Magento\Framework\Filesystem\DirectoryList;
use Magento\Framework\App\Filesystem\DirectoryList as AppDirectoryList;
use Monolog\Logger as MonoLogger;
use Monolog\Handler\StreamHandler;
use Monolog\Level;

class FeedOosProducts
{
    protected $resource;
    protected $productCollectionFactory;
    protected $storeManager;
    protected $emulation;
    protected $customHelper;
    protected $historyFactory;
    protected $stockRegistry;
    protected $jobRepo;
    protected $directoryList;

    /**
     * @var Action
     */
    private $productAction;

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

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

    public function __construct(
        \Magento\Framework\App\ResourceConnection $resource,
        \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Store\Model\App\Emulation $emulation,
        \Leadlion\Autogedal\Helper\Data $customHelper,
        \Firebear\ImportExport\Model\Import\HistoryFactory $historyFactory,
        \Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry,
        \Firebear\ImportExport\Api\JobRepositoryInterface $jobRepo,
        SourceItemInterfaceFactory $sourceItemFactory,
        SetDataToLegacyStockItem $setDataToLegacyStockItem,
        SetDataToLegacyStockStatus $setDataToLegacyStockStatus,
        Action $productAction,
        DirectoryList $directoryList
    ) {
        $this->customHelper = $customHelper;
        $this->storeManager = $storeManager;
        $this->emulation = $emulation;
        $this->resource = $resource;
        $this->productCollectionFactory = $productCollectionFactory;
        $this->historyFactory = $historyFactory;
        $this->stockRegistry = $stockRegistry;
        $this->jobRepo = $jobRepo;
        $this->sourceItemFactory = $sourceItemFactory;
        $this->setDataToLegacyStockItem = $setDataToLegacyStockItem;
        $this->setDataToLegacyStockStatus = $setDataToLegacyStockStatus;
        $this->productAction = $productAction;
        $this->directoryList = $directoryList;
    }

    private function getFeedContent($logger, $filePath, $fieldSeparator)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $filePath);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 300);

        $response = curl_exec($ch);

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

        curl_close($ch);

        return $this->parseCsvContent($response, $fieldSeparator);
    }

    /**
     * Parse CSV content into rows keyed by the first column (SKU).
     *
     * Uses fgetcsv on a stream instead of splitting on newlines, because
     * some columns (eg. GalleryImagesList) contain quoted multi-line values
     * with embedded newlines that would otherwise be split into bogus rows.
     */
    private function parseCsvContent(string $content, string $fieldSeparator): array
    {
        $contentFile = [];
        $stream = fopen('php://temp', 'r+');
        fwrite($stream, $content);
        rewind($stream);

        while (($row = fgetcsv($stream, 0, $fieldSeparator)) !== false) {
            if (isset($row[0]) && !empty($row[0])) {
                $contentFile[$row[0]] = $row;
            }
        }

        fclose($stream);

        return $contentFile;
    }

    private function getSavedFeedContent($logger, $feedName, $fieldSeparator)
    {
        $mediaPath = $this->directoryList->getPath(AppDirectoryList::MEDIA);
        $feedsPath = $mediaPath . DIRECTORY_SEPARATOR . 'cronimportfeeds';
        
        $possibleExtensions = ['xml', 'csv', 'txt'];
        $filePath = null;
        
        foreach ($possibleExtensions as $ext) {
            $testPath = $feedsPath . DIRECTORY_SEPARATOR . $feedName . '.' . $ext;
            if (file_exists($testPath)) {
                $filePath = $testPath;
                break;
            }
        }
        
        if (!$filePath) {
            $logger->info('Saved feed file not found for: ' . $feedName);
            return [];
        }

        $logger->info('Reading saved feed from: ' . $filePath);
        
        $content = file_get_contents($filePath);
        if ($content === false) {
            $logger->info('Could not read saved feed file: ' . $filePath);
            return [];
        }

        return $this->parseCsvContent($content, $fieldSeparator);
    }

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

        $feeds = [
            'bare_transversale' => [
                'separator' => ',',
                'url' => 'https://www.suportbicicleta.ro/feed/products/0d67d127c039f6bf7ad22ecca2c83e98'
            ],
            'cutii_portbagaj' =>  [
                'separator' => ',',
                'url' => 'https://www.suportbicicleta.ro/feed/products/5ee0c3d912a3eb453ba9597272d27cc0'
            ],
            'suporturi_biciclete' => [
                'separator' => ',',
                'url' => 'https://www.suportbicicleta.ro/feed/products/2376da2334cc06d8a3e5ba053b2ae8ae'
            ],
            'schiuri' =>  [
                'separator' => ',',
                'url' => 'https://www.suportbicicleta.ro/feed/products/061ca76d790a9030413a92706c3273a0'
            ],
            'rrp_portbagaje' =>  [
                'separator' => ',',
                'url' => 'https://b2b.aleo.ro/userfiles/CCEAD380-5E19-4246-96CD-5E0BBEB6C560/feeds/CEADE686-459A-4B2F-9921-99CED181A2DF.csv?key=E277C639-7F52-4862-ABE7-D5493AA705A2'
            ]
        ];

        $this->emulation->startEnvironmentEmulation(1, \Magento\Framework\App\Area::AREA_FRONTEND, true);
        $outOfStockProdIds = [];
        $sourceItems = [];

        $logger->info('Starting feed OOS products check...');

        foreach ($feeds as $feedName => $feedConfig) {
            $logger->info('Processing feed: ' . $feedName);
            
            try {
                $currentFeedContent = $this->getFeedContent($logger, $feedConfig['url'], $feedConfig['separator']);
                $logger->info('Current feed SKUs count for ' . $feedName . ': ' . count($currentFeedContent));
                if (count($currentFeedContent) < 2) {
                    $logger->info('Current feed not generated yet ... skip ' . $feedName);
                    continue;
                } 
                $savedFeedContent = $this->getSavedFeedContent($logger, $feedName, $feedConfig['separator']);
                $logger->info('Saved feed SKUs count for ' . $feedName . ': ' . count($savedFeedContent));
                
                $missingSkus = array_diff_key($savedFeedContent, $currentFeedContent);
                $logger->info('Missing SKUs count for ' . $feedName . ': ' . count($missingSkus));
                
                if (count($missingSkus) > 1500) {
                    $logger->info('Skip out of stock functionality ... something might be wrong with feed ' . $feedName);
                    continue;
                }
                foreach ($missingSkus as $sku => $info) {
                    $logger->info('Processing missing SKU: ' . $sku . ' from feed: ' . $feedName);
                    
                    $productCollection = $this->productCollectionFactory->create()
                        ->addAttributeToSelect('sku_fz')
                        ->addAttributeToSelect('sku')
                        ->addAttributeToFilter('sku_fz', $sku);
                    
                    foreach ($productCollection as $product) {
                        $logger->info('Missing from feed, setting out of stock for sku: ' . $product->getData('sku') . ' sku_fz: ' . $product->getData('sku_fz'));
                        
                        $outOfStockProdIds[] = $product->getId();
                        $isInStock = 0;
                        $qty = 0;

                        $sourceItem = $this->sourceItemFactory->create();
                        $sourceItem->setData('source_code', 'default');
                        $sourceItem->setData('sku', $product->getData('sku'));
                        $sourceItem->setData('quantity', $qty);
                        $sourceItem->setData('status', $isInStock);
                        $sourceItems[] = $sourceItem;
                        
                        try {
                            $this->setDataToLegacyStockItem->execute(
                                (string)$product->getData('sku'),
                                (float)$qty,
                                $isInStock
                            );
                            $this->setDataToLegacyStockStatus->execute(
                                (string)$product->getData('sku'),
                                (float)$qty,
                                $isInStock
                            );
                            $logger->info('Successfully updated stock for SKU: ' . $product->getData('sku'));
                        } catch (\Exception $e) {
                            $logger->info('(stockRegistry) cant save stock for product sku: ' . $product->getData('sku') . ' Error: ' . $e->getMessage());
                        }
                    }
                }
                
            } catch (\Exception $e) {
                $logger->info('Error processing feed ' . $feedName . ': ' . $e->getMessage());
                continue;
            }
        }
        
        if (!empty($outOfStockProdIds)) {
            try {
                $this->productAction->updateAttributes(
                    $outOfStockProdIds,
                    ['keep_out_of_stock' => 1],
                    0
                );
                $logger->info('Successfully updated keep_out_of_stock attribute for ' . count($outOfStockProdIds) . ' products');
            } catch (\Exception $e) {
                $logger->info('Cannot save the value for keep_out_of_stock. Error: ' . $e->getMessage());
            }
        }
        
        $logger->info('Feed OOS products check completed. Total products marked as OOS: ' . count($outOfStockProdIds));
        $this->emulation->stopEnvironmentEmulation();
    }
}
