<?php

namespace KupShop\PohodaBundle\Utils\Importers;

use KupShop\AdminBundle\Util\ActivityLog;
use KupShop\PohodaBundle\Exceptions\PohodaException;
use KupShop\PohodaBundle\Utils\PohodaBase;
use Query\Operator;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;

class InvoicesDownloader
{
    use PohodaBase;

    public $fullDataPath = '';
    protected $requestTemplate = 'requests/invoicePDFCreate.tpl';
    protected $invoiceFolderPath = '';

    /**
     * @throws \KupShop\PohodaBundle\Exceptions\PohodaException
     */
    public function processData($numberRequested, $prefix = '')
    {
        $filePath = $this->invoiceFolderPath.$prefix.$numberRequested;

        return $this->pohodaConnector->getPohodaFile($filePath);
    }

    public function getInvoiceExists($order_id, $id_invoice = null)
    {
        $qb = sqlQueryBuilder()->select('*')->from('orders_pohoda_invoices')->where(
            Operator::equals([
                'id_order' => $order_id,
            ])
        );

        if ($id_invoice) {
            $qb->andWhere(Operator::equals([
                'id_pohoda_invoice' => $id_invoice,
            ]));
        }

        return $qb->execute()->fetch();
    }

    public function getInvoice(string $id_order, array $invoiceRow)
    {
        try {
            $order = new \Order();

            $this->pohodaConnector->setActiveConfigByOrderId($id_order);

            if (!$order->createFromDB($id_order)) {
                throw new NotFoundHttpException("Order '{$id_order}' does not exists");
            }

            if (!$this->pohodaConnector->checkConnection()) {
                throw new ServiceUnavailableHttpException('System down, please try again later');
            }

            $filePath = $this->createPDFFile($invoiceRow, $order);
            $pdfResponse = $this->processData($filePath);

            if ($this->pohodaConnector->getCurrent()['issuedInvoiceIn']['enable_history'] == 'Y' && !$pdfResponse && $invoiceRow['pohoda_sync_date']) {
                $year = date('Y', strtotime($invoiceRow['pohoda_sync_date']));
                $pdfResponse = $this->processData($invoiceRow['number_requested'].'.pdf', $year.'/');
            }

            if ($pdfResponse) {
                $response = new StreamedResponse(function () use ($pdfResponse) {
                    echo $pdfResponse;
                });
                $response->headers->set('Content-Type', 'application/pdf; charset=utf8');
            } else {
                throw new NotFoundHttpException("Order '{$id_order}' does not have invoice '{$invoiceRow['number_requested']}'");
            }
        } catch (NotFoundHttpException $exception) {
            addUserMessage('Stažení dokladu selhalo, zkuste to prosím později.');

            return new RedirectResponse(path('account'));
        } catch (ServiceUnavailableHttpException|PohodaException $exception) {
            addActivityLog(ActivityLog::SEVERITY_ERROR,
                ActivityLog::TYPE_COMMUNICATION,
                'Nepodařilo se stáhnout PDF fakturu.',
                ['error' => $exception->getMessage()]);
            addUserMessage('Stažení dokladu selhalo, zkuste to prosím později.');

            return new RedirectResponse(path('account'));
        } catch (\Exception $exception) {
            throw $exception;
        }

        return $response;
    }

    /**
     * @param $order \Order
     *
     * @return bool
     *
     * @throws \KupShop\PohodaBundle\Exceptions\PohodaException
     * @throws \SmartyException
     */
    public function createPDFFile($invoiceRow, $order)
    {
        if (!$invoiceRow['invoice_prefix'] && !$invoiceRow['number_requested']) {
            throw new \Exception("Undefined OrderPrefix - {$order->id}");
        }

        $printSetId = $this->getInvoicePrefix($invoiceRow['invoice_prefix'] ?: $invoiceRow['number_requested'], $order);

        if (!$printSetId) {
            addActivityLog(ActivityLog::SEVERITY_ERROR,
                ActivityLog::TYPE_COMMUNICATION,
                'Nepodařilo se stáhnout PDF fakturu. Pro fakturační řadu '.($invoiceRow['invoice_prefix'] ?: $invoiceRow['number_requested']).' není vyplněné Id tiskové sestavy, doplňte v Nastavení: Pohoda: Nastavení pro mServer: Fakturační řady');
        }

        $requestData = [
            'idPohodaInvoice' => $invoiceRow['id_pohoda_invoice'],
            'printSetId' => $printSetId,
            'filePath' => $this->getFullDataPath().$invoiceRow['number_requested'].'.pdf',
        ];

        $this->addRequestField($requestData, $printSetId);

        $request = $this->pohodaConnector->getRequestContent($this->requestTemplate, $requestData);

        $request = $this->replace($request);

        $response = $this->pohodaConnector->sendRequest($request);

        $xml = simplexml_load_string($response);

        $this->pohodaConnector->checkValidResponse($xml);

        if (!$xml->xpath("rsp:responsePackItem/prn:printResponse[@state = 'ok']")) {
            $note = $xml->xpath('rsp:responsePackItem/prn:printResponse/rdc:importDetails/rdc:detail/rdc:note')[0] ?? '';
            $errno = $xml->xpath('rsp:responsePackItem/prn:printResponse/rdc:importDetails/rdc:detail/rdc:errno')[0] ?? '';
            throw new NotFoundHttpException("Create pdf file failed  - {$order->id}, error '{$errno}', '{$note}'");
        }

        if (($filePath = $xml->xpath('rsp:responsePackItem/prn:printResponse/rdc:importDetails/rdc:detail/rdc:valueProduced')[0]
            ?? $xml->xpath('rsp:responsePackItem/prn:printResponse/rdc:importDetails/rdc:detail/rdc:valueRequested')[0] ?? false)
            && $filePathArray = explode('\\', $filePath)
        ) {
            return end($filePathArray);
        }

        return $invoiceRow['number_requested'].'.pdf';
    }

    /**
     * @param $order \Order
     *
     * @return bool
     */
    public function getInvoicePrefix($invoicePrefix, $order = null)
    {
        foreach ($this->pohodaConnector->getCurrent()['issuedInvoiceIn']['invoicePrefix'] ?? [] as $value) {
            if ($value['prefix'] == $invoicePrefix) {
                return $value['printOut'];
            }
        }

        return false;
    }

    /**
     * @return bool
     */
    public function checkInvoicePrefix($invoicePrefix)
    {
        if (empty($this->pohodaConnector->getCurrent()['issuedInvoiceIn']['invoicePrefix'])) {
            return true;
        }
        foreach ($this->pohodaConnector->getCurrent()['issuedInvoiceIn']['invoicePrefix'] ?? [] as $value) {
            if ($value['prefix'] == $invoicePrefix) {
                return true;
            }
        }

        return false;
    }

    protected function addRequestField(&$requestData, $field)
    {
        $requestData['setType'] = 'vydane_faktury';
    }

    public function getFullDataPath(): string
    {
        return $this->fullDataPath;
    }
}
