<?php

namespace App\Support;

use stdClass;

class NavClient
{
    protected $itemsClient;
    protected $pricesClient;
    protected $companiesClient;
    protected $contactsClient;
    protected $bomsClient;
    protected $optionsClient;
    protected $licensesClient;
    protected $salesClient;
    protected $resourcesClient;
    protected $params;

    public function __construct()
    {
        $this->params = [
            'username' => config('navision.auth.username'),
            'password' => config('navision.auth.password'),
            'domain' => config('navision.auth.domain'),
            'stream_context' => stream_context_create([
                'ssl' => [
                    'ciphers'=>'RC4-SHA',
                    'verify_peer'=>false,
                    'verify_peer_name'=>false,
                    'allow_self_signed'=>true,
                ]]),
            'soap_version' => SOAP_1_1,
            'connection_timeout' => 180,
            'features' => SOAP_SINGLE_ELEMENT_ARRAYS
        ];
    }

    public function getItems(array $filters, int $size = 20, $bookmarkKey = null)
    {
        return $this->_getMultiple('Items',  $filters, $size, $bookmarkKey);
    }

    public function getItem(string $itemNo)
    {
        $prices = $this->getItems([
            'No' => $itemNo
        ], 1);

        return empty($prices) ? null : $prices[0];
    }

    public function getPrices(array $filters = [], $size = 20, $bookmarkKey = null)
    {
        return $this->_getMultiple('Sales_Prices', $filters, $size, $bookmarkKey);
    }

    public function getPrice(string $itemNo, $salesCode = null, string $salesType = null)
    {
        if (is_null($salesCode)) {
            $salesCode = config('navision.sales_code');
        }
        if (is_null($salesType)) {
            $salesType = config('navision.sales_type');
        }

        $prices = $this->getPrices([
            'Item_No' => $itemNo,
            'Sales_Code' => $salesCode,
            'Sales_Type' => $salesType
        ]);

        return empty($prices) ? null : $prices[0];
    }

    public function getCompanies(array $filters, int $size = 20, $bookmarkKey = null)
    {
        return $this->_getMultiple('Companies',  $filters, $size, $bookmarkKey);
    }

    public function getCompany(string $companyNo)
    {
        $companies = $this->getCompanies([
            'No' => $companyNo
        ], 1);

        return empty($companies) ? null : $companies[0];
    }

    public function getContacts(array $filters, int $size = 20, $bookmarkKey = null)
    {
        return $this->_getMultiple('Contacts',  $filters, $size, $bookmarkKey);
    }

    public function getContact(string $contactNo)
    {
        $contacts = $this->getContacts([
            'No' => $contactNo
        ], 1);

        return empty($contacts) ? null : $contacts[0];
    }

    public function getResources(array $filters, int $size = 20, $bookmarkKey = null)
    {
        return $this->_getMultiple('Resources',  $filters, $size, $bookmarkKey);
    }

    public function getResource(string $resourceNo)
    {
        $resources = $this->getResources([
            'No' => $resourceNo
        ], 1);

        return empty($resources) ? null : $resources[0];
    }

    public function getBoms(array $filters = [], $size = 20, $bookmarkKey = null)
    {
        return $this->_getMultiple('BOM',  $filters, $size, $bookmarkKey);
    }

    public function getOptions(array $filters, int $size = 20, $bookmarkKey = null)
    {
        return $this->_getMultiple('Options',  $filters, $size, $bookmarkKey);
    }

    public function getLicenses(array $filters, int $size = 20, $bookmarkKey = null)
    {
        return $this->_getMultiple('Licenses',  $filters, $size, $bookmarkKey);
    }

    public function createSales(stdClass $salesHeader)
    {
        $client = $this->_getSalesClient();

        $document = new stdClass();
        $document->Webshop_Salesheaders = $salesHeader;

        $retVal = $client->Create($document);

        return $retVal->Webshop_Salesheaders;
    }

    protected function _getMultiple(string $type, array $filters, int $size = 20, $bookmarkKey = null)
    {
        $camelCaseType = str_replace('_', '', $type);
        $clientGetMethod = "_get{$camelCaseType}Client";
        $resultsField = "Webshop_{$type}";
        $client = $this->$clientGetMethod();

        $filterParam = [];
        foreach ($filters as $field => $filterValue) {
            $filterParam[] = [
                'Field' => $field,
                'Criteria' => $filterValue
            ];
        }

        $params = [
            'filter' => $filterParam,
            'setSize' => $size
        ];

        if ($bookmarkKey) {
            $params['bookmarkKey'] = $bookmarkKey;
        }

        $retVal = $client->ReadMultiple($params);

        return !empty($retVal->ReadMultiple_Result->$resultsField) ? $retVal->ReadMultiple_Result->$resultsField : [];
    }

    protected function _getItemsClient()
    {
        return $this->itemsClient
            ? $this->itemsClient
            : $this->itemsClient = new MySoapClient(config('navision.wsdl.items'), $this->params);
    }

    protected function _getSalesPricesClient()
    {
        return $this->pricesClient
            ? $this->pricesClient
            : $this->pricesClient = new MySoapClient(config('navision.wsdl.prices'), $this->params);
    }

    protected function _getCompaniesClient()
    {
        return $this->companiesClient
            ? $this->companiesClient
            : $this->companiesClient = new MySoapClient(config('navision.wsdl.companies'), $this->params);
    }

    protected function _getContactsClient()
    {
        return $this->contactsClient
            ? $this->contactsClient
            : $this->contactsClient = new MySoapClient(config('navision.wsdl.contacts'), $this->params);
    }

    protected function _getBOMClient()
    {
        return $this->bomsClient
            ? $this->bomsClient
            : $this->bomsClient = new MySoapClient(config('navision.wsdl.bom'), $this->params);
    }

    protected function _getOptionsClient()
    {
        return $this->optionsClient
            ? $this->optionsClient
            : $this->optionsClient = new MySoapClient(config('navision.wsdl.options'), $this->params);
    }

    protected function _getLicensesClient()
    {
        return $this->licensesClient
            ? $this->licensesClient
            : $this->licensesClient = new MySoapClient(config('navision.wsdl.licenses'), $this->params);
    }

    protected function _getSalesClient()
    {
        return $this->salesClient
            ? $this->salesClient
            : $this->salesClient = new MySoapClient(config('navision.wsdl.sales'), $this->params);
    }

    protected function _getResourcesClient()
    {
        return $this->resourcesClient
            ? $this->resourcesClient
            : $this->resourcesClient = new MySoapClient(config('navision.wsdl.resources'), $this->params);
    }
}
