<?php
/**
 * Class represents records from table coupon_batch
 * {autogenerated}
 * @property int $batch_id PK
 * @property string|null $comment
 * @property string|null $discount_type 'percent'|'number'
 * @property float|null $discount
 * @property date|null $begin_date
 * @property date|null $expire_date
 * @property int $is_disabled
 * @property int $is_recurring
 * @property string|null $product_ids
 * @property string|null $not_product_ids
 * @property int|null $use_count
 * @property int|null $user_use_count
 * @property int|null $user_id FK user
 * @property string|null $require_product
 * @property string|null $prevent_if_product
 * {/autogenerated}
 */
class CouponBatch extends Am_Record
{
    function delete()
    {
        $this->getDi()->couponTable->deleteByBatchId($this->pk(), false);
        parent::delete();
    }

    function generateCoupons($count, $minLen, $maxLen, $prefix = null)
    {
        $table = $this->getDi()->couponTable;
        for ($i=0; $i<$count; $i++) {
            $coupon = $this->getDi()->couponRecord;
            $coupon->code = $table->generateCouponCode($minLen, $maxLen, $prefix);
            $coupon->batch_id = $this->pk();
            $coupon->insert();
        }
    }

    /**
     * Retrieve array of product ids coupon can be applied for
     *
     * @return array|null null in case of there is not any restriction
     */
    function getApplicableProductIds()
    {
        return $this->_getProductIds('product_ids');
    }

    /**
     * Retrieve array of product ids coupon can not be applied for
     *
     * @return array|null null in case of there is not any restriction
     */
    function getNotApplicableProductIds()
    {
        return $this->_getProductIds('not_product_ids');
    }

    protected function _getProductIds($token)
    {
        //return null in case this field is empty
        if (!$this->$token) return null;

        $catProducts = $this->getDi()->productCategoryTable->getCategoryProducts();
        $res = array_filter(explode(',', $this->$token));
        foreach ($res as $k => $g) {
            if (preg_match('/^BP-(\d*)/', $g, $match)) {
                unset($res[$k]);
            }
            if (preg_match('/^BPCATEGORY-(\d*)/', $g, $match)) {
                unset($res[$k]);
            }
            if (preg_match('/^CATEGORY-(\d*)/', $g, $match)) {
                unset($res[$k]);
                $catId = $match[1];
                foreach ($catProducts[$catId] as $prId) {
                    $res[] = $prId;
                }
            }
        }
        return $res;
    }

    function getOnlyApplicableProductIds()
    {
        return $this->_getOnlyProductIds('product_ids');
    }

    function getOnlyNotApplicableProductIds()
    {
        return $this->_getOnlyProductIds('not_product_ids');
    }

    protected function _getOnlyProductIds($token)
    {
        $res = array_filter(explode(',', $this->$token));
        $result = [];
        foreach ($res as $k => $g) {
            if (preg_match('/^(\d+)$/', $g, $match)) {
                $result[] = $g;
            }
        }
        return $result;
    }

    function getOnlyApplicableCategoryIds()
    {
        return $this->_getOnlyCategoryIds('product_ids');
    }

    function getOnlyNotApplicableCategoryIds()
    {
        return $this->_getOnlyCategoryIds('not_product_ids');
    }

    protected function _getOnlyCategoryIds($token)
    {
        $res = array_filter(explode(',', $this->$token));
        $result = [];
        foreach ($res as $k => $g) {
            if (preg_match('/^CATEGORY-(\d*)/', $g, $match)) {
                $result[] = $match[1];
            }
        }
        return $result;
    }

    function getOnlyApplicableBillingPlanIds()
    {
        return $this->_getOnlyBillingPlanIds('product_ids');
    }

    function getOnlyNotApplicableBillingPlanIds()
    {
        return $this->_getOnlyBillingPlanIds('not_product_ids');
    }

    protected function _getOnlyBillingPlanIds($token)
    {
        $res = array_filter(explode(',', $this->$token));
        $result = [];
        foreach ($res as $k => $g) {
            if (preg_match('/^BP-(\d*)/', $g, $match)) {
                $result[] = $match[1];
            }
        }
        return $result;
    }

    function getOnlyApplicableBillingPlanCategoryIds()
    {
        return $this->_getOnlyBillingPlanCategoryIds('product_ids');
    }

    function getOnlyNotApplicableBillingPlanCategoryIds()
    {
        return $this->_getOnlyBillingPlanCategoryIds('not_product_ids');
    }

    protected function _getOnlyBillingPlanCategoryIds($token)
    {
        $res = array_filter(explode(',', $this->$token));
        $result = [];
        foreach ($res as $k => $g) {
            if (preg_match('/BPCATEGORY-(\d*)/', $g, $match)) {
                $result[] = $match[1];
            }
        }
        return $result;
    }

    function getApplicableBpIds()
    {
        return $this->_getBpIds('product_ids');
    }

    function getNotApplicableBpIds()
    {
        return $this->_getBpIds('not_product_ids');
    }

    protected function _getBpIds($token)
    {
        $catBps = $this->getDi()->billingPlanCategoryTable->getCategoryBillingPlans();
        $res = array_filter(explode(',', $this->$token ?? ''));
        $result = [];
        foreach ($res as $k => $g) {
            if (preg_match('/^BP-(\d*)/', $g, $match)) {
                $result[] = $match[1];
            }
            if (preg_match('/^BPCATEGORY-(\d*)/', $g, $match)) {
                $catId = $match[1];
                foreach ($catBps[$catId] as $prId) {
                    $result[] = $prId;
                }
            }
        }
        return $result;
    }

    function getRequireProduct()
    {
        return array_unique(array_filter($this->parseRequirementsGroup($this->require_product)));
    }

    function getPreventIfProduct()
    {
        return array_unique(array_filter($this->parseRequirementsGroup($this->prevent_if_product)));
    }

    /**
     * @param string $req
     * @return array
     */
    protected function parseRequirementsGroup($req)
    {
        $catProducts = $this->getDi()->productCategoryTable->getCategoryProducts();
        $res = array_filter(explode(',',$req ?? ''));
        foreach ($res as $k => $g) {
            if (preg_match('/^CATEGORY-(\w*)-(\d*)/', $g, $match)) {
                unset($res[$k]);
                $status = $match[1];
                $catId = $match[2];
                foreach ($catProducts[$catId] as $prId) {
                    $res[] = sprintf('%s-%d', $status, $prId);
                }
            }
        }
        return $res;
    }
}

/** @extends Am_Table<CouponBatch> */
class CouponBatchTable extends Am_Table
{
    protected $_key = 'batch_id';
    protected $_table = '?_coupon_batch';
    protected $_recordClass = 'CouponBatch';

    function deleteByUserId($user_id)
    {
        if (!$user_id)
            throw new Am_Exception_InternalError("user_id is empty in " . __METHOD__);
        $list = $this->_db->selectCol("SELECT batch_id FROM ?_coupon_batch WHERE user_id=?d", $user_id);
        if ($list)
            $this->_db->query("DELETE FROM ?_coupon_batch, ?_coupon WHERE batch_id IN (?a)", $list);
    }

    function getOptions($onlyEnabled = true)
    {
        return array_map(['Am_Html', 'escape'], $this->_db->selectCol("SELECT batch_id as ARRAY_KEY,
            CONCAT('#', batch_id, ' ', IF(comment<>'', comment, CONCAT(discount, IF(discount_type='percent', '%', '$'), IF(begin_date, CONCAT(' (', begin_date, ' - ', expire_date, ')'), ''))))
            FROM ?_coupon_batch
            {WHERE is_disabled = ?}",
            $onlyEnabled ? 0 : DBSIMPLE_SKIP));
    }
}
