<?php

use KupShop\KupShopBundle\Config;
use KupShop\KupShopBundle\Context\PriceLevelContext;
use Query\Operator;
use Symfony\Component\HttpFoundation\RequestStack;

class AliveCard
{
    protected $url;

    protected $connection;

    public $error;
    public static $errors_msg = [
        'INVALID_NUMBER' => 'Špatný formát karty.',
        'CARD_NOT_FOUND' => 'Karta neexistuje.',
        'CARD_CANCELLED' => 'Karta byla zrušena.',
        'CARD_EXPIRED' => 'Karta expirovala.',
        'CARD_VALID_IN_FUTURE' => 'Karta ještě nemůže být validována.',
        'NAME_MISMATCH' => 'Špatné jméno.',
        'OTHER' => 'Nedefinovaná chyba.',
    ];

    /** @required */
    public RequestStack $requestStack;

    public function __construct($url = null)
    {
        if ($url) {
            $this->url = $url;
        }

        if (!$this->url) {
            $this->url = getVal('url',
                Config::get()['Modules']['isic'] ?? null,
                'https://testbs:testbs@gts-ncdb.orchitech.net/ws/referral');
        }
    }

    public function validate($serialNumber, $cardHolder = null)
    {
        $serialNumber = str_replace(' ', '', $serialNumber);

        $connection = $this->connect();

        $request = [
            'cardNumber' => $serialNumber,
            'cardholderName' => $cardHolder,
        ];

        if (!empty(Config::get()['Modules']['isic']['discountId'])) {
            $request['discountId'] = Config::get()['Modules']['isic']['discountId'];
        }

        $result = (array) $connection->post($this->url.'/verifications', $request);

        if ($result['result'] == 'SUCCESSFUL') {
            return $result;
        } else {
            $this->error = $result['reason'];
        }

        return null;
    }

    public function sendTransaction(int $verificationId, Decimal $amountPaid): ?array
    {
        if (empty(Config::get()['Modules']['isic']['discountId'])) {
            return null;
        }

        $connection = $this->connect();

        $request = [
            'discountId' => Config::get()['Modules']['isic']['discountId'],
            'verificationId' => $verificationId,
            'amountPaid' => $amountPaid->value(2)->asFloat(),
        ];

        $result = $connection->post($this->url.'/receipts', $request);

        if ($result['id'] ?? false) {
            return $result;
        }

        return null;
    }

    public function getErrorMessage($error)
    {
        if (!empty(static::$errors_msg[$error])) {
            return static::$errors_msg[$error];
        }

        return null;
    }

    public function connect()
    {
        $cfg = Config::get();

        if (!$this->connection) {
            $this->connection = new PestJSON($this->url);

            if (!empty($cfg['Modules']['isic']['username']) && !empty($cfg['Modules']['isic']['password'])) {
                $this->connection->setupAuth($cfg['Modules']['isic']['username'], $cfg['Modules']['isic']['password']);
            }
        }

        return $this->connection;
    }

    public function getPriceLevel(): ?array
    {
        if (!$this->requestStack->getMainRequest()) {
            return null;
        }

        if ($priceLevelId = $this->requestStack->getSession()->get(PriceLevelContext::PERSISTENT_KEY)) {
            $priceLevel = sqlQueryBuilder()
                ->select('*')
                ->from('price_levels')
                ->where(
                    Operator::equals(
                        [
                            'id' => $priceLevelId,
                        ]
                    )
                )->execute()->fetchAssociative();

            if (!$priceLevel) {
                throw new RuntimeException('Není definována cenová hladina pro ISIC');
            }

            return $priceLevel;
        }

        return null;
    }

    public function activateDiscount(?array $info): void
    {
        if (!$info) {
            return;
        }

        if (!$this->requestStack->getMainRequest()) {
            return;
        }

        if (!empty(Config::get()['Modules']['isic']['priceLevel'])) {
            $this->requestStack->getSession()->set(PriceLevelContext::PERSISTENT_KEY,
                getVal('priceLevel', Config::get()['Modules']['isic'], 1));
        }
    }
}
