<?php
// Copyright (c) Pickware GmbH. All rights reserved.
// This file is part of software that is released under a proprietary license.
// You must not copy, modify, distribute, make publicly available, or execute
// its contents or parts thereof without express permission by the copyright
// holder, unless otherwise permitted by law.

namespace Shopware\Plugins\ViisonSetArticles\Subscribers\Backend;

use Shopware\Plugins\ViisonCommon\Classes\Subscribers\Base;

/**
 * Subscriber manipulate the SQL statement that is used when exporting article information (e.g. search engines).
 */
class ExportSubscriber extends Base
{
    /**
     * @inheritdoc
     */
    public static function getSubscribedEvents()
    {
        return [
            'sExport::sCreateSql::after' => 'onAfterCreateSql',
        ];
    }

    /**
     * Manipulates the SQL SELECT statement to fetch set article information as intended. For now it manipulates:
     * SELECT statements:
     *  instock
     *  weight
     *
     * WHERE clauses:
     *  minStock
     *  instock
     *  hideNoInstock (SW config)
     *
     * @param \Enlight_Hook_HookArgs $args
     */
    public function onAfterCreateSql(\Enlight_Hook_HookArgs $args)
    {
        $sql = $args->getReturn();
        $sExport = $args->getSubject();
        $instockFilter = $sExport->sSettings['instock_filter'];
        $limitFilter = $sExport->sSettings['count_filter'];
        $minStockFilter = $sExport->sSettings['stockmin_filter'];

        // Manipulate SELECT instock
        $sql = str_replace(
            'IF(v.instock IS NOT NULL,v.instock,d.instock) as instock,',
            'IF(at.viison_setarticle_active,

            (SELECT MIN(sad.instock DIV savs.quantity) as instock
            FROM s_articles_details as sad
            LEFT JOIN s_articles_viison_setarticles as savs ON sad.id = savs.articledetailid
            WHERE savs.setid = d.id),

            IF(v.instock IS NOT NULL,v.instock,d.instock)

        ) as instock,',
            $sql
        );

        // Manipulate SELECT shippingtime
        $sql = str_replace(
            'd.shippingtime,',
            'IF(at.viison_setarticle_active,
                (
                    SELECT max(sad.shippingtime)
                    FROM s_articles_details sad
                    LEFT JOIN s_articles_viison_setarticles sets ON sad.id = sets.articledetailid
                    WHERE sets.setid = d.id
                ),
                d.shippingtime
            ) as shippingtime,',
            $sql
        );

        // Manipulate SELECT weight
        $sql = str_replace(
            'd.weight,',
            'IF(at.viison_setarticle_active,
                (
                    SELECT sum(vd.weight)
                    FROM s_articles_details vd LEFT JOIN s_articles_viison_setarticles vset ON vd.id = vset.articledetailid
                    WHERE vset.setid = d.id
                ),
                d.weight
            ) as weight,',
            $sql
        );

        // Find "old" WHERE instock restriction and replace with new HAVING restriction
        // This manipulation works with or without the new set article instock clause
        $instockClause = 'AND (v.instock>=' . $instockFilter . ' OR (v.instock IS NULL AND d.instock>=' . $instockFilter . '))';
        $havingClause = ' HAVING (instock >= ' . $instockFilter . ')';
        $limitClause = 'LIMIT ' . $limitFilter;
        if (mb_strpos($sql, $instockClause) !== false) {
            $sql = str_replace($instockClause, '', $sql);

            // Remark: HAVING clause must be placed behind LIMIT clause
            if (!empty($limitFilter)) {
                $sql = str_replace($limitClause, '', $sql);
                $sql .= $havingClause . ' ' . $limitClause;
            } else {
                $sql .= $havingClause;
            }
        }

        // Manipulate minStock clause - do not apply to set-article-active articles
        if (!empty($minStockFilter)) {
            $sql = str_replace(
                'AND (v.instock>=d.stockmin OR (v.instock IS NULL AND d.instock>=d.stockmin))',
                'AND (at.viison_setarticle_active OR (v.instock>=d.stockmin OR (v.instock IS NULL AND d.instock>=d.stockmin)))',
                $sql
            );
        }

        // Manipulate laststock clause - do not apply to set-article-active articles
        // Remark: this clause is actually longer but this substring suffices
        $laststockClause = '(a.laststock * v.instock >= a.laststock * v.minpurchase)';
        if (mb_strpos($sql, $laststockClause) !== false) {
            $sql = str_replace(
                $laststockClause,
                'at.viison_setarticle_active OR ' . $laststockClause,
                $sql
            );
        }

        $args->setReturn($sql);
    }
}
