<?php

class PayController extends Am_Mvc_Controller
{
    public function indexAction()
    {
        $invoice = $this->getInvoice();

        $form = $this->createForm($invoice, $this->getParam('secure_id'));

        $this->view->invoice = $invoice;
        $this->view->form = $form;

        if ($form->isSubmitted() && $form->validate()) {
            $vars = $form->getValue();

            $invoice = $this->buildInvoice($invoice, $vars);
            $invoice->save();

            $payProcess = new Am_Paysystem_PayProcessMediator($this, $invoice);
            $payProcess->process();

            throw new Am_Exception_InternalError(
                sprintf('Error occurred while trying process invoice [%s]',
                    filterId($invoice->public_id)));
        }

        $this->view->layoutNoMenu = true;
        $this->view->display('pay.phtml');
    }

    function previewAction()
    {
        $invoice = $this->getInvoice();
        $secure_id = $this->getParam('secure_id');
        $form = $this->createForm($invoice, $secure_id);
        $form->validate();
        $vars = $form->getValue();
        $invoice = $this->buildInvoice($invoice, $vars);
        $this->view->invoice = $invoice;
        $this->view->display('_receipt.phtml');
    }

    protected function buildInvoice(Invoice $invoice, array $vars): Invoice
    {
        if (!$invoice->paysys_id) {
            $invoice->setPaysystem($vars['paysys_id']);
        }

        return $this->getDi()->hook->filter($invoice, Am_Event::PAY_PAGE_INVOICE, ['vars' => $vars]);
    }

    protected function getPaysystems(Invoice $invoice): array
    {
        $psOptions = [];
        foreach ($this->getDi()->plugins_payment->getAllPublic() as $ps) {
            $psOptions[$ps->getId()] = $this->renderPaysys($ps);
        }

        //universal format for payload in all %_GET_PAYSYSTEMS events
        $_ = array_keys($psOptions);
        $_ = $this->getDi()->hook->filter($_, Am_Event::PAY_PAGE_GET_PAYSYSTEMS, ['invoice' => $invoice]);
        $psOptions = array_filter($psOptions, function($id) use ($_) {return in_array($id, $_);}, ARRAY_FILTER_USE_KEY);

        return $psOptions;
    }

    protected function createForm(Invoice $invoice, string $secure_id): Am_Form
    {
        $form = new Am_Form('pay-form');
        $form->addCsrf();

        $form->addHidden('secure_id')->setValue($secure_id);
        if (!$invoice->paysys_id) {
            $psOptions = $this->getPaysystems($invoice);

            if (count($psOptions) == 1) {
                reset($psOptions);
                $form->addHtml()
                    ->setLabel(___('Payment System'))
                    ->setHtml(current($psOptions));
                $form->addHidden('paysys_id')->setValue(key($psOptions));
            } else {
                $paysys = $form->addAdvRadio('paysys_id')
                    ->setLabel(___('Payment System'))
                    ->loadOptions($psOptions);
                $paysys->addRule('required', ___('Please choose a payment system'));
            }
        }

        $form = $this->getDi()->hook->filter($form, Am_Event::PAY_PAGE_FORM, ['invoice' => $invoice]);

        $form->addSaveButton(___('Pay'));

        return $form;
    }

    protected function getInvoice(): Invoice
    {
        /* @var $invoice Invoice */
        $invoice = $this->getDi()->invoiceTable->findBySecureId($this->getParam('secure_id'), 'payment-link');
        if (
            !$invoice
            || $invoice->status != Invoice::PENDING
        ) {
            throw new Am_Exception_QuietError(sprintf('Unknown invoice [%s] or invoice is already processed', filterId($this->getParam('secure_id'))));
        }
        if (
            !$invoice->due_date
            && sqlDate($invoice->tm_added) < sqlDate("-" . Invoice::DEFAULT_DUE_PERIOD . " days")
        ) {
            throw new Am_Exception_InputError(___('Invoice is expired'));
        } elseif (
            $invoice->due_date
            && $invoice->due_date < sqlDate('now')
        ) {
            throw new Am_Exception_InputError(___('Invoice is expired'));
        }

        return $invoice;
    }

    protected function renderPaysys(Am_Paysystem_Description $p)
    {
        return sprintf(
            '<span class="am-paysystem-title">%s</span> <span class="am-paysystem-desc">%s</span>',
            $p->getTitle(),
            $p->getDescription()
        );
    }
}