<?php
/**
 * Class represents records from table billing_plan
 * {autogenerated}
 * @property int $plan_id PK
 * @property int $product_id FK product
 * @property string $title
 * @property string $terms
 * @property float $first_price
 * @property string $first_period
 * @property int $rebill_times
 * @property float|null $second_price
 * @property string|null $second_period
 * @property int $disabled
 * @property int $qty
 * @property int $variable_qty
 * @property string|null $currency
 * @property string|null $paysys_id
 * @property int|null $sort_order
 * {/autogenerated}
 */
class BillingPlan extends Am_Record_WithData
{
    /** @var Product cached */
    protected $_product;

    public function init()
    {
        parent::init();
        if (empty($this->currency))
            $this->currency = Am_Currency::getDefault();
    }

    /** @return Product */
    public function getProduct()
    {
        if ($this->_product && $this->_product->product_id == $this->product_id)
            return $this->_product;
        $this->_product = $this->getDi()->productTable->load($this->product_id, true);
        $this->_product->setBillingPlan($this);
        return $this->_product;
    }

    public function _setProduct(Product $p)
    {
        $this->_product = $p;
    }

    /** @return string saved or calculated billing terms */
    public function getTerms()
    {
        return $this->terms ? ___($this->terms) : $this->getTermsText();
    }

    /** @return string caclulated billing terms */
    public function getTermsText()
    {
        $tt = new Am_TermsText($this);
        $terms = $tt->getString();
        return $this->getDi()->hook->filter($terms, Am_Event::BILLING_PLAN_TERMS, ['billingPlan' => $this]);
    }

    public function getCurrency($value = null)
    {
        $c = new Am_Currency($this->currency);
        if ($value) $c->setValue($value);
        return $c;
    }

    public function isFree()
    {
        return !$this->first_price && !$this->second_price;
    }

    public function delete()
    {
        parent::delete();
        $this->_table->getAdapter()->query("DELETE FROM ?_product_upgrade WHERE
            to_billing_plan_id=?d OR from_billing_plan_id=?d",
                $this->plan_id, $this->plan_id);
    }

    /** param array $categories - array of id# */
    function setCategories(array $categories)
    {
        $this->getAdapter()->query("DELETE FROM ?_billing_plan_billing_plan_category WHERE billing_plan_id=?d 
            {AND billing_plan_category_id NOT IN (?a)}",
            $this->pk(), $categories ?: DBSIMPLE_SKIP);
        if (!$categories) return;
        $vals = [];
        foreach ($categories as $id)
            $vals[] = sprintf("(%d,%d)", $this->pk(), $id);
        $this->getAdapter()->query("INSERT IGNORE INTO ?_billing_plan_billing_plan_category
            (billing_plan_id, billing_plan_category_id)
            VALUES " . implode(", ", $vals));
    }

    /** @return array of id# */
    function getCategories()
    {
        if (!$this->isLoaded()) return [];
        return $this->getAdapter()->selectCol(
            "SELECT billing_plan_category_id, billing_plan_category_id AS ARRAY_KEY FROM ?_billing_plan_billing_plan_category WHERE billing_plan_id=?d",
            $this->pk()
        );
    }
}

/**
 * @package Am_Invoice
 * @extends Am_Table_WithData<BillingPlan>
 * @method void deleteByProductId($value, $useObjects = true)
 */
class BillingPlanTable extends Am_Table_WithData
{
    protected $_key = 'plan_id';
    protected $_table = '?_billing_plan';
    protected $_recordClass = 'BillingPlan';

    protected $productCache = [];
    protected $useProductCache = true; // disable in admin cp

    function toggleProductCache($flag)
    {
        $this->useProductCache = (bool)$flag;
    }

    function getForProduct($product_id, $limit = null, $onlyEnabled = false)
    {
        if ($this->useProductCache)
        {
            $key = "$product_id-$limit-$onlyEnabled";
            if (array_key_exists($key, $this->productCache))
                return $this->productCache[$key];
        }
        $ret = $this->selectObjects(
                "SELECT *
                 FROM ?_billing_plan
                 WHERE product_id=?d
                 {AND (disabled IS NULL OR disabled = ?d )}
                 ORDER BY sort_order, plan_id
                 {LIMIT ?d}",
                $product_id,
                !$onlyEnabled ? DBSIMPLE_SKIP : 0,
                $limit === null ? DBSIMPLE_SKIP : $limit
            );
        if ($this->useProductCache)
            $this->productCache[$key] = $ret;
        return $ret;
    }

    /**
     *  Select All billing plans respecting sort preferences from aMember CP -> Manage products
     * @return TRecord[]
     */
    function selectAllSorted()
    {
        return $this->selectObjects("SELECT bp.*, p.title as product_title
                                     FROM $this->_table bp
                                     INNER JOIN ?_product p USING (product_id)
                                     WHERE p.is_archived=0
                                     ORDER BY 0+p.sort_order,p.title,bp.sort_order");
    }

    /**
     * return array of product_id-billing_plan_id => Product Title (billing plan terms)
     */
    public function getProductPlanOptions()
    {
        $ret = [];
        foreach ($this->selectAllSorted() as $p)
        {
            $ret["{$p->product_id}-{$p->plan_id}"] = "({$p->product_id}) {$p->product_title} ({$p->getTerms()})";
        }
        return $ret;
    }

    public function getOptions()
    {
        $ret = [];
        foreach ($this->selectAllSorted() as $p) {
            $ret[$p->plan_id] = "{$p->product_title} ({$p->getTerms()})";
        }
        return $ret;
    }
}