<?php

namespace Eadesigndev\GLS\Model\API;

use Eadesigndev\GLS\lib\Nusoapclient;
use Eadesigndev\GLS\Helper\Data as GLSHelper;

#[\AllowDynamicProperties]
class GLS {

    const STATUS_DELIVERED = '05-Delivered';
    const STATUS_IN_DELIVERY = '04-In delivery van';
    const STATUS_ARRIVING_TO_DEPOT = '03-Arriving in Depot';
    const STATUS_DEPOT_TRANSIT = '53-DEPOT TRANSIT';
    const STATUS_PICKED_UP = '86-Pacel picked up';
    const STATUS_CLIENT_DATA_RECEIVED = '51-Client data received';
    const STATUS_HOLD_IN_DEPOT = '07-Hold in depot';
    const STATUS_CLIENT_NOT_AT_HOME = '12-Consignee is not at home';

    protected $urls = [
        'HU' => 'http://online.gls-hungary.com/webservices/soap_server.php?wsdl&ver=14.05.20.01',
        'SK' => 'http://online.gls-slovakia.sk/webservices/soap_server.php?wsdl&ver=14.05.20.01',
        'CZ' => 'http://online.gls-czech.com/webservices/soap_server.php?wsdl&ver=14.05.20.01',
        'RO' => 'https://online.gls-romania.ro/webservices/soap_server.php?wsdl&ver=16.12.15.01',
        'SI' => 'http://connect.gls-slovenia.com/webservices/soap_server.php?wsdl&ver=14.05.20.01',
        'HR' => 'http://online.gls-croatia.com/webservices/soap_server.php?wsdl&ver=14.05.20.01',
    ];

    protected $data = array(
        'username' => '',
        'password' => '',
        'senderid' => '',
        'sender_name' => '',
        'sender_address' => '',
        'sender_city' => '',
        'sender_zipcode' => '',
        'sender_country' => 'RO',
        'sender_contact' => '',
        'sender_phone' => '',
        'sender_email' => '',
        'consig_name' => '',
        'consig_address' => '',
        'consig_city' => '',
        'consig_zipcode' => '',
        'consig_country' => 'RO',
        'consig_contact' => '',
        'consig_phone' => '',
        'consig_email' => '',
        'pcount' => 0,
        'pickupdate' => '',
        'content' => '',
        'clientref' => '',
        'codamount' => '',
        'codref' => '',
        'services' => array(),
        'printertemplate' => 'A4_2x2',
        'printit' => true,
        'timestamp' => '',
        'hash' => 'xsd:string' );
    private GLSHelper $_glsHelper;
    private string $countryCode;

    /**
     * API constructor
     *
     * @param string $countryCode HU/SK/CZ/RO/SI/HR
     */
    public function __construct(
        GLSHelper $GLSHelper
    ){
        $this->_glsHelper = $GLSHelper;
        $this->countryCode = strtoupper('RO');
    }

    /**
     * Initializate
     *
     * @param
     * @return
     * @throws
     */
    public function initializate($data = null) {
        // load data
        // var_dump($data);
        // $this->loadCompanyData($data['account']);
        // $this->loadClienrData($data['account']);
    }


    /**
     * Get all data
     *
     * @param
     * @return
     * @throws
     */
    public function getData() {
        return $this->data;
    }

    /**
     * Set masive data
     *
     * @param
     * @return
     * @throws
     */
    public function setData($data) {
        foreach ($data as $key => $value) {
            if(isset($this->data[$key])){
                $this->data[$key] = $value;
            }
        }
        $data = $this->getData();
        $hash = $this->getHash($data);
        $this->data['hash'] = $hash;

    }


    function getHash($data) {
        $hashBase = '';
        foreach($data as $key => $value) {
            if ($key != 'services'
                && $key != 'hash'
                && $key != 'timestamp'
                && $key != 'printit'
                && $key != 'printertemplate'
                && $key != 'customlabel') {
                $hashBase .= $value;
            }
        }
        return sha1($hashBase);
    }



    public function toArray(){
        $this->timestamp = (new \DateTime('now', new \DateTimeZone('Europe/Bucharest')))->format('YmdHis');
        $this->data["timestamp"] = $this->timestamp;
        $data = $this->data;

        // Calculate hash - based on GLS API specification
        // Exclude specific fields from hash calculation as per GLS documentation
        $hashBase = '';
        foreach ($data as $key => $value)
        {
            if ($key != 'services'
                && $key != 'hash'
                && $key != 'timestamp'
                && $key != 'printit'
                && $key != 'printertemplate'
                && $key != 'customlabel'
            )
            {
                $hashBase .= $value;
            }
        }
        $data['hash'] = sha1($hashBase);

        return $data;
    }


    /**
     * Get parcel/s number/s
     *
     * @param Form\ParcelGeneration $form
     * @return array <pre> {
     *      tracking_code: '123', // or ['123', '124']
     *      raw_pdf: => 'pdfrawdatastring'
     * } </pre>
     * @throws Exception\ParcelGeneration
     */
    public function generateParcel($form = array()) {
        $data = $this->requestNuSOAP('printlabel', $form);
        return $data;
    }

    /**
     * Get parcel status
     *
     * @param $tracking_code
     * @return mixed
     * @throws Exception
     */
    public function getParcelStatus($tracking_code) {

        //
        //   Aici mai trebuie lucrat
        //
        $html = $this->request($this->getTrackingUrl($tracking_code));
        $dom = new Crawler($html);
        $row = $dom->filter('table tr.colored_0, table tr.colored_1')->first();

        if (!count($row)) throw new Exception('Tracking code wasn`t registered or error occured!');

        $data = array_map('trim', [
            'date' => $row->filter('td')->eq(0)->text(),
            'status' => $row->filter('td')->eq(1)->text(),
            'depot' => $row->filter('td')->eq(2)->text(),
            'info' => $row->filter('td')->eq(3)->text()
        ]);

        return $data['status'];
    }

    /**
     * Delete parcel
     *
     * @param $tracking_code
     * @return mixed
     * @throws Exception
     */
    public function deleteParcel($pclids) {
        if(!is_array($pclids)){
            $pclids = array($pclids);
        }

        $data = $this->toArray();
        $form = array(
            'username' => $data['username'],
            'password' => $data['password'],
            'senderid' => $data['senderid'],
            'pclids'   => $pclids,
        );
        $data = $this->requestNuSOAP('deletelabels', $form);
        return $data;
    }

    public function getTrackingUrl($parcelNumber, $language = 'en') {
        return "http://online.gls-hungary.com/tt_page.php?tt_value=$parcelNumber&lng=$language";
    }

    /**
     * @param string $method
     * @param array|Form $data
     * @throws \SoapFault
     * @return mixed
     */
    protected function requestNuSOAP($method, $data = array()) {
        if(empty($data)){
            $data = $this->toArray();
        }

        // require_once(getcwd().'/app/code/GLS/Moduleshipping/lib/Nusoapclient.php');

        $client = new Nusoapclient($this->getApiUrl());

        // Workaround " <b>Notice</b>: Array to string conversion in fergusean/nusoap/lib/class.wsdl.php:1550"
        ob_start();
        $result = $client->call($method, $data);
        ob_end_clean();

        return $result;
    }

    protected function request($url, $data = array(), $method = 'GET', array $headers = array()) {
        if (empty($data)) $data = $this->toArray();

        require_once(dirname(__FILE__).'/Curl.php');
        $client = new Curl();
        // $client = new Curl();
        // $client->setVerifyPeer(FALSE);
        // $browser  = new Browser($client);
        // $response = $browser->submit($url, $data, $method, $headers);
        // $client->create('');
        if($method == 'post'){
            $client->post($data);
        }else{
            $client->get($data);
        }

        return $client->error_code();
        // return $response->getContent();
    }

    /**
     * Get api url based on country code
     *
     * @throws Exception
     * @return string
     */
    protected function loadApiData(){

    }
    /**
     * Load Company details on library
     *
     * @throws
     * @return
     */
    protected function loadCompanyData($config) {

        $data = array(
            'username'       => isset($config['username']) ? $config['username'] : '',
            'password'       => isset($config['password']) ? $config['password'] : '',
            'senderid'       => isset($config['senderid']) ? $config['senderid'] : '',
            'sender_name'    => isset($config['sender_name']) ? $config['sender_name'] : '',
            'sender_address' => isset($config['sender_address']) ? $config['sender_address'] : '',
            'sender_city'    => isset($config['sender_city']) ? $config['sender_city'] : '',
            'sender_zipcode' => isset($config['sender_zipcode']) ? $config['sender_zipcode'] : '',
            'sender_country' => 'RO',
            'sender_contact' => isset($config['sender_contact']) ? $config['sender_contact'] : '',
            'sender_phone'   => isset($config['sender_phone']) ? $config['sender_phone'] : '',
            'sender_email'   => isset($config['sender_email']) ? $config['sender_email'] : '',
        );
        $this->data = array_replace($this->data, $data);
    }



    /**
     * Get api url based on country code
     *
     * @throws Exception
     * @return string
     */
    protected function getApiUrl(){
        if (empty($this->urls[$this->countryCode])) {
            die('Wrong country code - ' . $this->countryCode);
        }
        return $this->urls[$this->countryCode];
    }
}
