<?php

declare(strict_types=1);

namespace KupShop\OrderingBundle;

use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Exception\RedirectException;
use Omnipay\Common\GatewayInterface;
use Omnipay\Common\Message\ResponseInterface;
use Payment;

abstract class OmniPay extends \Payment
{
    abstract public static function getOmnipayName(): string;

    abstract public function configureGateway(GatewayInterface $gateway, \Order $order): GatewayInterface;

    public function getGatewayOptions(\Order $order): array
    {
        return [];
    }

    public function processStep_1()
    {
        $gateway = $this->getGateway();

        try {
            // Auth
            $response = $gateway->purchase($this->getGatewayOptions($this->order))->send();

            if ($response->isRedirect()) {
                $response->redirect();
            } else {
                echo $response->getMessage();
            }
        } catch (\Exception $e) {
            getRaven()->captureException($e);
            echo $e->getMessage();
        }

        exit;
    }

    public function processStep_5()
    {
        $gateway = $this->getGateway();

        try {
            $response = $gateway->completePurchase($this->getGatewayOptions($this->order))->send();

            if ($response->isSuccessful()) {
                $op_id_payment = $response->getTransactionReference();
                $this->status = \Payment::STATUS_FINISHED;

                // Ensure payment exists
                if (!$this->getStatus($op_id_payment)) {
                    $this->createPaymentFromResponse($response);
                }

                // change payment status to finished
                if (!$this->setStatus(\Payment::STATUS_FINISHED, $op_id_payment)) {
                    throw new \Exception('Omnipay::updatePaymentStatus: setStatus failed!');
                }

                $this->success(translate('paymentSuccess', 'payment'));
            } else {
                if (($response->getData()['ResponseCode'] ?? false) == 15) {
                    $this->error(translate('payment_storno', 'payment'));
                }

                $this->step(-3, 'storno');
            }
        } catch (RedirectException $e) {
            throw $e;
        } catch (\Exception $e) {
            getRaven()->captureException($e);

            $this->step(-3, 'Storno because some error happened');
        }
    }

    public function getGateway(): GatewayInterface
    {
        $gateway = \Omnipay\Omnipay::create(static::getOmnipayName());

        return $this->configureGateway($gateway, $this->order);
    }

    public static function isEnabled($className)
    {
        $cfg = Config::get();

        if (empty($cfg['Modules']['payments'][$className])) {
            return false;
        }

        return true;
    }

    protected function createPaymentFromResponse(ResponseInterface $response)
    {
        $this->createPayment(
            $response->getTransactionReference(),
            str_replace(',', '.', $response->getData()['Amount']),
            ['paymentClass' => static::class]
        );
    }

    public function hasOnlinePayment()
    {
        return true;
    }
}
