<?php

namespace inpost_shipping\Model\Shipment;

use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Exception\ClientException;
use GuzzleHttp\Psr7\Response;
use inpost_shipping\Model\Helper\InpostHelper;

class InpostPrinter
{
    /**
     * @var \GuzzleHttp\Client $guzzleClient
     */
    protected $guzzleClient;

    /**
     * @var string
     */
    protected $idOrganization;

    /**
     * @var string
     */
    protected $baseUri;

    /**
     * @var string
     */
    protected $apiKey;

    public function __construct(Client $guzzleClient, string $idOrganization, string $baseUri, string $apiKey)
    {
        $this->guzzleClient = $guzzleClient;
        $this->idOrganization = $idOrganization;
        $this->baseUri = $baseUri;
        $this->apiKey = $apiKey;
    }

    /**
     * @param array $labelParams
     *
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function print(array $labelParams): array
    {
        $fileName = '';
        if (isset($labelParams['bulk'])) {
            $fileName = $this->getFileNameByServiceIncludingDate('inpost_labels', date('Y-m-d H:i:s'), $labelParams['format']);
        }

        try {
            $requestData = [
                'format' => $labelParams['format'],
                'type' => $labelParams['type'],
            ];

            $query = http_build_query($requestData);

            $fileName = !empty($fileName) ? $fileName : $this->getFileNameByServiceIncludingDate($labelParams['service'], $labelParams['created_at'], strtolower($labelParams['format']));

            $filePath = DIR_SYSTEM . '../inpostLabels/' . $fileName;

            if (file_exists($filePath)) {
                unlink($filePath);
            }

            $fileResource = \GuzzleHttp\Psr7\Utils::tryFopen($filePath, 'w+');
            $stream = \GuzzleHttp\Psr7\Utils::streamFor($fileResource);

            $uri = '';
            if (isset($labelParams['bulk'])) {
                $shipmentsQueryArray = [];
                foreach ($labelParams['shipmentIds'] as $idShipment) {
                    $shipmentsQueryArray[] = 'shipment_ids[]=' . $idShipment;
                }

                $shipmentsQuery = implode('&', $shipmentsQueryArray);
                $uri = $this->baseUri . '/v1/organizations/' . $this->idOrganization . '/shipments/labels?' . $shipmentsQuery . '&' . $query;
            } else {
                $uri = $this->baseUri . '/v1/shipments/' . $labelParams['idShipment'] . '/label?' . $query;
            }

            $this->guzzleClient
                ->request(
                    'GET',
                    $uri,
                    [
                        'sink' => $stream,
                    ],
                );
        } catch (ClientException $exception) {
            return [
                InpostHelper::decodeExceptionToArray($exception->getResponse()),
            ];
        }

        if (defined('HTTPS_CATALOG')) {
            return [
                'labelUrl' => HTTPS_CATALOG . 'inpostLabels/' . $fileName,
            ];
        } else {
            return [
                'labelUrl' => HTTPS_SERVER . 'inpostLabels/' . $fileName,
            ];
        }
    }

    /**
     * @param string $idDispatch
     *
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function printDispatch(string $idDispatch): array
    {
        try {
            $fileName = 'Dispatch_' . $idDispatch . '.pdf';
            $filePath = DIR_SYSTEM . '../inpostLabels/' . $fileName;

            if (file_exists($filePath)) {
                unlink($filePath);
            }

            $fileResource = \GuzzleHttp\Psr7\Utils::tryFopen($filePath, 'w+');
            $stream = \GuzzleHttp\Psr7\Utils::streamFor($fileResource);

            $this->guzzleClient
                ->request(
                    'GET',
                    $this->baseUri . '/v1/dispatch_orders/' . $idDispatch . '/printout',
                    [
                        'sink' => $stream,
                    ],
                );
        } catch (ClientException $exception) {
            return [
                InpostHelper::decodeExceptionToArray($exception->getResponse()),
            ];
        }

        if (defined('HTTPS_CATALOG')) {
            return [
                'labelUrl' => HTTPS_CATALOG . 'inpostLabels/' . $fileName,
            ];
        } else {
            return [
                'labelUrl' => HTTPS_SERVER . 'inpostLabels/' . $fileName,
            ];
        }
    }

    /**
     * @param array $idsDispatch
     *
     * @return array
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function printBulkDispatch(array $idsDispatch): array
    {
        try {
            $fileName = 'Dispatch_' . date('d_m_Y') . '.pdf';
            $filePath = DIR_SYSTEM . '../inpostLabels/' . $fileName;

            if (file_exists($filePath)) {
                unlink($filePath);
            }

            $fileResource = \GuzzleHttp\Psr7\Utils::tryFopen($filePath, 'w+');
            $stream = \GuzzleHttp\Psr7\Utils::streamFor($fileResource);

            $idsDispatchArray = [];
            foreach ($idsDispatch as $id) {
                $idsDispatchArray[] = 'shipment_ids[]=' . $id;
            }

            $idsDispatchQuery = implode('&', $idsDispatchArray);

            $this->guzzleClient
                ->request(
                    'GET',
                    $this->baseUri . '/v1/organizations/' . $this->idOrganization . '/dispatch_orders/printouts?' . $idsDispatchQuery,
                    [
                        'sink' => $stream,
                    ],
                );
        } catch (ClientException $exception) {
            return [
                InpostHelper::decodeExceptionToArray($exception->getResponse()),
            ];
        }

        if (defined('HTTPS_CATALOG')) {
            return [
                'labelUrl' => HTTPS_CATALOG . 'inpostLabels/' . $fileName,
            ];
        } else {
            return [
                'labelUrl' => HTTPS_SERVER . 'inpostLabels/' . $fileName,
            ];
        }
    }

    /**
     * @param string $service
     * @param string $created_at
     * @param string $extension
     *
     * @return string
     */
    public function getFileNameByServiceIncludingDate(string $service, string $created_at, string $extension): string
    {
        return sprintf('%s_%s.%s', $service, date('d_m_Y', strtotime($created_at)), $extension);
    }
}