<?php


# ----------------------------------------------------------------------------------------------------------------

// FORMAT CSV
//
// Coloana 0: id produs
// Coloana 1: titlu produs
// Coloana 2: categoria (asa cum este la dumneavoastra pe site, maparile se vor face ulterior)
// Coloana 3: descriere
// Coloana 4: moneda (RON, EUR sau USD)
// Coloana 5: pret
// Coloana 6: cantitate (numar intreg pozitiv)
// Coloana 7: url catre poza (optional)


# ----------------------------------------------------------------------------------------------------------------


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;

class AS_CSVFEED {

    public static $output;


    public static function fputcsv(array $row) {
        $ok = fputcsv(self::$output, $row, ';');
        if(!$ok) {
            throw new Exception('fputcsv() failed');
        }
    }


    /**
     * timing-safe strcmp
     */
    public static function strcmp($str1, $str2) {
        if(!is_string($str1) || !is_string($str2))
            return 1;
        $len1 = strlen($str1);
        $len2 = strlen($str2);
        if($len1 !== $len2)
            return 2;
        $diff = 0;
        for($i = 0; $i < $len1; $i++) {
            $diff |= ord($str1[$i]) ^ ord($str2[$i]);
        }
        return $diff;
    }


    public static function is_authorized() {
        $key = @$_GET['k'];
        if(!is_string($key) || strlen($key) < 20)
            return FALSE;
        $key = sha1($key);
        $valid_key = 'ad55d884101fb942611a83bfd6948eb9925d7799';
        return !self::strcmp($key, $valid_key);
    }


    public static function is_dev() {
        return (boolean)@$_GET['is_dev'];
    }


    public static function init() {
        ini_set('display_errors', self::is_dev());

        header('Content-Type: text/plain; charset=UTF-8');
        header('X-Robots-Tag: noindex, nofollow');

        /*		if(!self::is_authorized()) {
			header('HTTP/1.1 403 Forbidden');
			die('nothing to see here');
		}*/

        if(!function_exists('fputcsv'))
            throw new Exception('function fputcsv() is missing (PHP v5.1+ is needed)');

        self::loadMage();
        ini_set('display_errors', self::is_dev());

        if(!self::$output)
            self::$output = fopen('php://output', 'wb');

        if(!self::$output)
            throw new Exception('fopen() failed');

        if(isset($_GET['dl']))
            header('Content-Disposition: attachment; filename="feed_' . date('Y-m-d_H-i') . '.csv"');

        register_shutdown_function(array(__CLASS__, 'cleanup'));
        set_time_limit(1200);
    }


    public static function cleanup() {
        if(self::$output) {
            fclose(self::$output);
            self::$output = NULL;
        }
    }


    public static function prepareDescription($s) {
        #$s = preg_replace('@(?<=\>)\s+(?=\<)@', ' ', $s); # strip some whitespace
        $s = trim($s);
        $s = preg_replace('@[\r\n]+@', '<br/>', $s);
        return $s;
    }


    public static function prepareTitle($s) {
        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; # html_entity_decode() may have failed

        $s = preg_replace('/\s+/', ' ', $s);
        $s = trim($s);

        return $s;
    }


    public static function escapeImgURL($url) {
        $url = str_replace(array(' ', '[,]'), array('%20', '[%2C]'), $url);
        return $url;
    }


    public static function loadMage() {
        require_once dirname(__FILE__) . '/app/bootstrap.php';
    }


    /**
     * @param  Throwable
     * @return string
     */
    public static function strerror($e) {
        $errmsg = "[" . date('Y-m-d H:i:s') . "] ";
        $errmsg .= get_class($e) . ": " . $e->getMessage();
        $code = $e->getCode();
        if($code) {
            $errmsg .= " (EXCEPTION CODE: $code)";
        }
        $errmsg .= "\n";
        $stack = "STACK:\n#  "  . $e->getFile() . "(" . $e->getLine() . ")\n" . $e->getTraceAsString() . "\n";
        $stack = str_replace(__DIR__ . '/', '', $stack);
        $stack = str_replace(__DIR__, '', $stack);
        $errmsg .= $stack;
        return $errmsg;
    }


    public static function export() {
        self::init();
        # https://docs.magento.com/mbi/data-analyst/data-warehouse-mgr/mage-store-data.html#catalog_product_entity

        $bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
        $objectManager = $bootstrap->getObjectManager();
        $state = $objectManager->get(Magento\Framework\App\State::class);
        $state->setAreaCode(\Magento\Framework\App\Area::AREA_FRONTEND);

        $store = $objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->getStore();
        $currency = $store->getCurrentCurrency()->getCode();

        #$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        $productCollection = $objectManager->create(CollectionFactory::class);
        $collection = $productCollection->create()
            ->addAttributeToSelect('*')
            ->addAttributeToFilter('visibility', Visibility::VISIBILITY_BOTH)
            ->addAttributeToFilter('status', Status::STATUS_ENABLED)
            ->addPriceData()
            //->addFieldToFilter('sku', ['like' => 'GVB%'])
            # https://magento.stackexchange.com/a/303902
            #->setFlag('has_stock_status_filter', false)
            #->joinField('stock_item', 'cataloginventory_stock_item', 'is_in_stock', 'product_id=entity_id', 'is_in_stock=1')

            #->addAttributeToFilter("visibility", array("in" =>[2,4] ))
            #->load()
        ;

        $productsPrice = [];
        $categoryRules = [

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

                $category = array();
                foreach($catCollection as $cat) {
                    $categoryPath = explode('/', $cat->getPath());
                    foreach ($categoryPath as $categoryId) {
                        if (in_array($categoryId, array_keys($categoryRules))) {
                            $productsPrice[$product->getId()] = $categoryRules[$categoryId];
                        }
                    }

                    $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();
            #print_r($data);
            $description = $data['description'];
            $values = array();
            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] = array('label' => $attribute->getFrontendLabel(), 'value' => $value);
                    }
                }
            }
            if(@$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'];
            }

            $img_relpath = $product->getImage();
            $images = array();
            $main_img_url = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $product->getImage();
            if($main_img_url) {
                $images[$main_img_url] = $main_img_url;
            }
            $objectManager->get(ReadHandler::class)->execute($product);
            foreach($product->getMediaGalleryImages() as $img) {
                $images[$img['url']] = $img['url'];
            }

            $stock = 99999;
            //try {
            //$stock = (int)$objectManager->get('Magento\CatalogInventory\Api\StockRegistryInterface')->getStockItem($product->getId())->getQty();
            //} catch(Throwable $e) {}
            //if($stock < 1) $stock = 20;

            $price = round(($data['final_price'] - 0), 2);
            /*try {
                $productDiscount = 0;
                if (isset($productsPrice[$product->getId()])) {
                    $productDiscount = $productsPrice[$product->getId()];
                }
                $price = $product->getPriceInfo()->getPrice('final_price')->getValue() - $productDiscount;
            } catch(Throwable $e) {}*/

            $row = array(
                $product->getId(), // Coloana 0: id produs
                self::prepareTitle($product->getName()), // Coloana 1: titlu produs
                $category, // Coloana 2: categoria (asa cum este la dumneavoastra pe site, maparile se vor face ulterior)
                self::prepareDescription($description), // Coloana 3: descriere
                $currency, // Coloana 4: moneda (RON, EUR sau USD)
                $price, // Coloana 5: pret
                $stock, // Coloana 6: cantitate (numar intreg pozitiv)
                implode('[,]', str_replace('[,]', '[%2C]', $images)), // Coloana 7: url catre poza (optional)
            );

            if(!$row[3]) {
                $row[3] = $row[1];
            }

            self::fputcsv($row);
        }

        self::cleanup();
    }

}


# ----------------------------------------------------------------------------------------------------------------


try {
    AS_CSVFEED::export();
} catch(Throwable $e) {
    @header('HTTP/1.1 500 Internal Server Error');
    if(AS_CSVFEED::is_dev() && AS_CSVFEED::is_authorized()) {
        echo AS_CSVFEED::strerror($e);
    } else {
        echo 'eroare...';
    }
}
die;



# ----------------------------------------------------------------------------------------------------------------

