<?php

namespace Autogedal\Extend\Cron;

use Magento\Catalog\Model\Product\Gallery\ReadHandler;
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Catalog\Model\Product\Visibility;
use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Filesystem;
use Magento\Store\Model\App\Emulation;
use Magento\Store\Model\StoreManagerInterface;
use Magento\Framework\UrlInterface;

class GeneratePieseAutoFeed
{
    private const OUTPUT_FILE = 'feeds/feed_piese.txt';

    private CollectionFactory $collectionFactory;
    private ReadHandler $readHandler;
    private StoreManagerInterface $storeManager;
    private Filesystem $filesystem;
    private Emulation $emulation;

    public function __construct(
        CollectionFactory $collectionFactory,
        ReadHandler $readHandler,
        StoreManagerInterface $storeManager,
        Filesystem $filesystem,
        Emulation $emulation
    ) {
        $this->collectionFactory = $collectionFactory;
        $this->readHandler = $readHandler;
        $this->storeManager = $storeManager;
        $this->filesystem = $filesystem;
        $this->emulation = $emulation;
    }

    public function execute(): void
    {
        $this->emulation->startEnvironmentEmulation(1, \Magento\Framework\App\Area::AREA_FRONTEND, true);

        $store = $this->storeManager->getStore();
        $currency = $store->getCurrentCurrency()->getCode();
        $mediaBaseUrl = $store->getBaseUrl(UrlInterface::URL_TYPE_MEDIA);

        $pubDir = $this->filesystem->getDirectoryWrite(DirectoryList::PUB);
        $pubDir->create('feeds');
        $stream = $pubDir->openFile(self::OUTPUT_FILE, 'w');

        $collection = $this->collectionFactory->create()
            ->addAttributeToSelect('*')
            ->addAttributeToFilter('visibility', Visibility::VISIBILITY_BOTH)
            ->addAttributeToFilter('status', Status::STATUS_ENABLED)
            ->addPriceData();

        foreach ($collection as $product) {
            try {
                $catCollection = $product->getCategoryCollection()->addAttributeToSelect('name');
                if (!$catCollection) {
                    throw new \Exception();
                }

                $category = [];
                foreach ($catCollection as $cat) {
                    $catname = trim($cat->getName());
                    if ($catname && !preg_match('@^(promotii|black\s*friday|piese\s*auto|diverse)$@i', $catname)) {
                        $category[$catname] = $catname;
                    }
                }
                $category = implode(' >> ', $category);
                if (!$category) {
                    throw new \Exception();
                }
            } catch (\Exception $e) {
                $category = 'NONE';
            }

            $data = $product->getData();
            $description = $data['description'] ?? '';

            $values = [];
            foreach ($product->getAttributes() as $attribute) {
                $value = $attribute->getFrontend()->getValue($product);
                if ($value && $attribute->getIsVisibleOnFront()) {
                    $value = trim($value);
                    $name = trim($attribute->getName());
                    if ($value && $name) {
                        $values[$name] = ['label' => $attribute->getFrontendLabel(), 'value' => $value];
                    }
                }
            }

            if (!empty($values['in_depth'])) {
                $description .= '<br/> ' . $values['in_depth']['value'];
                unset($values['in_depth']);
            }

            foreach ($values as $v) {
                $description .= '<br/> <strong>' . $v['label'] . '</strong>: ' . $v['value'];
            }

            $mainImgUrl = $mediaBaseUrl . 'catalog/product' . $product->getImage();
            $images = [];
            if ($mainImgUrl) {
                $images[$mainImgUrl] = $mainImgUrl;
            }

            $this->readHandler->execute($product);
            foreach ($product->getMediaGalleryImages() as $img) {
                $images[$img['url']] = $img['url'];
            }

            $price = round(($data['final_price'] - 0), 2);

            $title = $this->prepareTitle($product->getName());
            $desc = $this->prepareDescription($description);
            if (!$desc) {
                $desc = $title;
            }

            $imagesStr = implode('[,]', str_replace('[,]', '[%2C]', $images));

            $row = [
                $product->getId(),
                $title,
                $category,
                $desc,
                $currency,
                $price,
                99999,
                $imagesStr,
            ];

            $stream->write($this->rowToCsv($row));
        }

        $stream->close();

        $this->emulation->stopEnvironmentEmulation();
    }

    private function rowToCsv(array $row): string
    {
        $handle = fopen('php://temp', 'r+');
        fputcsv($handle, $row, ';');
        rewind($handle);
        $csv = stream_get_contents($handle);
        fclose($handle);
        return $csv;
    }

    private function prepareDescription(string $s): string
    {
        $s = trim($s);
        $s = preg_replace('@[\r\n]+@', '<br/>', $s);
        return $s;
    }

    private function prepareTitle(string $s): string
    {
        if (function_exists('iconv')) {
            $s = iconv('UTF-8', 'UTF-8//IGNORE', $s);
        }
        $backup = $s;
        $s = html_entity_decode($s, ENT_QUOTES, 'UTF-8');
        if (!$s) {
            $s = $backup;
        }
        $s = preg_replace('/\s+/', ' ', $s);
        return trim($s);
    }
}
