<?php
/**
 * Class represents records from table invoice_refund
 * {autogenerated}
 * @property int $invoice_refund_id PK
 * @property int $invoice_id FK invoice
 * @property string $invoice_public_id
 * @property int|null $invoice_payment_id FK invoice_payment
 * @property int $user_id FK user
 * @property string|null $paysys_id
 * @property string $receipt_id
 * @property string $transaction_id
 * @property datetime $dattm
 * @property string $currency
 * @property float $amount
 * @property float|null $tax
 * @property string|null $tax_rate
 * @property int|null $tax_address_id
 * @property int $refund_type
 * @property float|null $base_currency_multi
 * @property string|null $display_invoice_id
 * {/autogenerated}
 * @package Am_Invoice
 */
class InvoiceRefund extends Am_Record_WithData
{
    /** @var User */
    protected $_user;
    /** @var Invoice */
    protected $_invoice;
    /** by customer request - ACCESS does not stopped */
    const REFUND = 0;
    /** chargeback */
    const CHARGEBACK = 1;
    /** quickly after the order - ACCESS will be revoked */
    const VOID = 2;

    public function setFromTransaction(Invoice $invoice, Am_Paysystem_Transaction_Interface $transaction, $refundType)
    {
        $this->dattm = $transaction->getTime()->format('Y-m-d H:i:s');
        $this->invoice_id = $invoice->invoice_id;
        $this->invoice_public_id = $invoice->public_id;
        $this->user_id = $invoice->user_id;
        $this->currency = $invoice->currency;
        $this->amount = $transaction->getAmount();
        $this->paysys_id = $transaction->getPaysysId();
        $this->receipt_id = $transaction->getReceiptId();
        $this->transaction_id = $transaction->getUniqId();
        $this->refund_type = $refundType;
        return $this;
    }

    public function insert($reload = true)
    {
        if ($this->currency == Am_Currency::getDefault()) {
            $this->base_currency_multi = 1.0;
        } else {
            $this->base_currency_multi = $this->getDi()->currencyExchangeTable->getRate($this->currency, sqlDate($this->dattm));
        }

        $ret = parent::insert($reload);
        $this->setDisplayInvoiceId();
        $this->getDi()->hook->call(Am_Event::REFUND_AFTER_INSERT, [
            'invoice' => $this->getInvoice(),
            'refund'  => $this,
            'user'    => $this->getInvoice()->getUser(),
        ]);
        return $ret;
    }

    public function delete()
    {
        parent::delete();
        $this->getDi()->hook->call(Am_Event::REFUND_AFTER_DELETE, ['refund' => $this]);
        return $this;
    }

    public function getInvoice(): Invoice
    {
        if (empty($this->_invoice))
            $this->_invoice = $this->getDi()->invoiceTable->load($this->invoice_id);
        return $this->_invoice;
    }

    public function getUser(): User
    {
        if (empty($this->_user))
            $this->_user = $this->getDi()->userTable->load($this->user_id);
        return $this->_user;
    }

    /**
     * Set Invoice ID wich will be displayed in pdf invoice
     */
    protected function setDisplayInvoiceId()
    {
        $this->display_invoice_id = $this->getDi()->hook->filter(
            "{$this->getInvoice()->public_id}/R{$this->getInvoice()->getRefundsCount()}",
            Am_Event::SET_DISPLAY_INVOICE_REFUND_ID,
            ['record' => $this]);
        $this->updateSelectedFields('display_invoice_id');
    }

    function getDisplayInvoiceId()
    {
        return $this->display_invoice_id ?: ($this->getInvoice()->public_id . '/' . $this->receipt_id);
    }

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

    function setTax(Invoice $invoice, ?InvoicePayment $p = null)
    {
        if (!empty($p)) {
            $this->tax_rate = $p->tax_rate;
            $this->tax_address_id = $p->tax_address_id;
        }
        if (empty($this->tax_rate)) {
            foreach ($this->getDi()->plugins_tax->getAllEnabled() as $plugin) {
                if ($rate = $plugin->getRate($invoice, $invoice->getItem(0))) {
                    $this->tax_rate = $rate;
                }
            }
        }
        if (!empty($this->tax_rate)) {
            if ($p->amount == $this->amount) {
                $this->tax = $p->tax;
            } else {
                $price = moneyRound($this->amount / (1 + ($this->tax_rate / 100)));
                $this->tax = $this->amount - $price;
            }
        }

        if (empty($this->tax_address_id)) {
            $this->tax_address_id = $this->getDi()->addressTable->getTaxAddressId($invoice->getUser());
        }
    }
}

/**
 * @package Am_Invoice
 * @extends Am_Table_WithData<InvoiceRefund>
 * @method void deleteByInvoiceId($value, $useObjects = true)
 * @method InvoiceRefund[] findByInvoiceId($value, $start = null, $count = null, $orderBy = null)
 * @method InvoiceRefund[] findByInvoicePaymentId($value, $start = null, $count = null, $orderBy = null)
 * @method InvoiceRefund[] findByUserId($value, $start = null, $count = null, $orderBy = null)
 */
class InvoiceRefundTable extends Am_Table_WithData
{
    protected $_key = 'invoice_refund_id';
    protected $_table = '?_invoice_refund';
    protected $_recordClass = 'InvoiceRefund';

    public function insert(array $values, $returnInserted = false)
    {
        if (empty($values['dattm']))
            $values['dattm'] = $this->getDi()->sqlDateTime;
        return parent::insert($values, $returnInserted);
    }

    /** @return TRecord[] */
    function selectLast($num, $dateThreshold = null)
    {
        return $this->selectObjects("SELECT ir.*,
            (SELECT GROUP_CONCAT(item_title SEPARATOR ', ') FROM ?_invoice_item WHERE invoice_id=ir.invoice_id) AS items,
            u.login, u.email, CONCAT(u.name_f, ' ', u.name_l) AS name, u.name_f, u.name_l,
            ir.invoice_public_id AS public_id
            FROM ?_invoice_refund ir
            LEFT JOIN ?_user u USING (user_id)
            {WHERE ir.dattm > ?}
            ORDER BY ir.dattm DESC LIMIT ?d",
            $dateThreshold ?: DBSIMPLE_SKIP, $num);
    }

    function getRefundsCount($invoiceId)
    {
        return $this->_db->selectCell("SELECT COUNT(*) FROM ?_invoice_refund WHERE invoice_id=?d", $invoiceId);
    }
}