<?php


class nc_payment_register_provider_schetmash extends nc_payment_register_provider {

    const SERVICE_URL = 'https://online.schetmash.com/lk/api/v1';
    const SERVICE_PORT = 443;   


    static protected $settings = array(
        'PaymentRegisterSchetmashLogin' => NETCAT_MODULE_PAYMENT_REGISTER_SCHETMASH_LOGIN,
        'PaymentRegisterSchetmashPassword' => NETCAT_MODULE_PAYMENT_REGISTER_SCHETMASH_PASSWORD,
        'PaymentRegisterSchetmashGroup' => NETCAT_MODULE_PAYMENT_REGISTER_SCHETMASH_GROUP,
        //'PaymentRegisterSchetmashPaymentAddress' => NETCAT_MODULE_PAYMENT_REGISTER_SCHETMASH_PAYMENT_ADDRESS,
    );

    static protected $schetmash_vat_enum = array(
        '' => 'none',
        0 => 'vat0',
        10 => 'vat10',
        18 => 'vat18',
    );

    static protected $schetmash_default_vat = 'vat18'; 

    /**
     * @param $site_id
     * @param $provider_id
     */
    public function __construct($site_id = null, $provider_id = null) {
        parent::__construct($site_id, $provider_id);
    }

    /**
     * Получение токена
     */
    protected function getToken($nc_core) {
        $token = false; 

        $result = $this->execute_request('token', array(
            'login' => $this->get_setting('PaymentRegisterSchetmashLogin'),
            'password' => $this->get_setting('PaymentRegisterSchetmashPassword'),
        ));

        if(is_object($result) && isset($result->token) && !empty($result->token)) {

            $nc_core->set_settings('token', $result->token, 'schetmash', $nc_core->catalogue->id() );
            $token = $result->token;
        }

        return $token; 
    }

    /**
     * Обработка нового чека
     *
     * @param nc_payment_receipt $receipt
     */
    public function process_receipt(nc_payment_receipt $receipt) { 
        $nc_core = nc_core::get_object();
        $invoice = $receipt->get_invoice();

        //$domain = $nc_core->catalogue->get_current('Domain');
        $site_id = $nc_core->catalogue->get_current('Catalogue_ID');
        //$payment_address = $this->get_setting('PaymentRegisterSchetmashPaymentAddress');

        $receipt_id = (string)$receipt->get_id();
        $callback_url = $nc_core->catalogue->get_url_by_id($site_id) . nc_module_path('payment') . 'register/callback.php?receipt_id=' . $receipt_id;

        $items = $receipt->get_items();
        $totals = (float)$items->sum('total_price');

        $data = array(
            'timestamp' => date("d.m.Y H:i:s"),
            'external_id' => $receipt_id,
            'service' => array(
                //'inn' => $this->get_setting('PaymentRegisterINN'),
                //'payment_address' => $payment_address ? $payment_address : $domain,
                'callback_url' => $callback_url,
            ),
            'receipt' => array(
                'attributes' => array(
                    'sno' => $this->get_setting('PaymentRegisterSN'),
                ),
                'items' => array(),
                'total' => $totals,
                'payments' => array(
                    array(
                        'type' => 1,
                        'sum' => $totals
                    )
                )
            )
        );

        // Передается без префикса «+7». Максимальная длина строки – 64 символа
        $phone = preg_replace('/^\+7/', '', nc_normalize_phone_number($invoice->get('customer_phone')));
        if ($phone) {
            $data['receipt']['attributes']['phone'] = $phone;
        }

        // Максимальная длина строки – 64 символа
        $email = nc_substr($invoice->get('customer_email'), 0, 64);
        if ($email || !$phone) {
            // В запросе обязательно должно присутствовать одно из полей: email или phone
            if (!$email) {
                $email = nc_payment_register::get_default_customer_email();
            }
            $data['receipt']['attributes']['email'] = $email;
        }

        // Список товаров
        /** @var nc_payment_invoice_item $item */
        foreach ($items as $item) {
            $data['receipt']['items'][] = array(
                'name' => nc_substr($item->get('name'), 0, 128), // Максимальная длина строки – 128 символов
                'price' => $this->formatFloat(  $item->get('item_price') ),
                'quantity' => $this->formatFloat(  $item->get('qty') ),
                'sum' => $this->formatFloat(  $item->get('total_price') ),
                'tax' => nc_array_value(self::$schetmash_vat_enum, $item->get('vat_rate'), self::$schetmash_default_vat),
                'tax_sum' => $this->formatFloat( $item->get('total_vat_amount'), 3)
            );
        }
        $operation = $receipt->get('operation') === 'sell' ? 'sell' : 'sell_refund';
        $path = $this->get_setting('PaymentRegisterSchetmashGroup') . '/' . $operation . '?token=';
      

        $token = $nc_core->get_settings('token', 'schetmash', false, $nc_core->catalogue->id() );      
        if(!isset($token) || empty($token)) { 
            $token = $this->getToken($nc_core);
            if($token === false) { return; }
        }

        $response = $this->execute_request($path.$token, $data);

        if(!is_object($response) )  { return false;  }

        if (isset($result->code) && ($result->code  ==  2 || $result->code == 4) )	{	
            $token = $this->getToken($nc_core);
            $response = $this->execute_request($path.$token, $data);
        }

        if(!is_object($response) || !isset($response->id)) { return false;  }
   

        $receipt->set('transaction_id', $response->id);
        $receipt->save_status(
            (!empty($response->error)) ? $receipt::STATUS_FAILED : $receipt::STATUS_PENDING,
            array(
                'path' => $path,
                'data' => $data,
                'response' => $response, 
            )
        );
    }


    private function formatFloat(float $int, $count = 2){
		return	round( $int , $count);
	}

    /**
     * Обработка колбека от кассового сервиса
     */
    public function process_callback() {    ;
        $receipt_id = nc_core::get_object()->input->fetch_get('receipt_id');    
        $response = json_decode(file_get_contents('php://input'));  

        if(!is_object($response) || !isset($response->id) || !isset($response->status)  || !isset($receipt_id) )  { return; }

        $receipt = new nc_payment_receipt($receipt_id);

        if(isset($response->error) && !empty($response->error)) {
            $receipt->save_status(         
                $receipt::STATUS_FAILED,
                array(
                    //'path' => $path,
                    'response' => $response,
                )
            );
        } elseif ($response->status === 'success' && !empty($response->payload)) {
            $payload = $response->payload;
            $receipt_datetime = DateTime::createFromFormat('d.m.Y H:i:s', $payload->receipt_datetime);
            $receipt->set_values(array(
                'fiscal_receipt_created' => $receipt_datetime->format("Y-m-d H:i:s"),
                'fiscal_receipt_number' => $payload->fiscal_receipt_number,
                'shift_number' => $payload->shift_number,
                'fiscal_storage_number' => $payload->fn_number,
                'register_registration_number' => $payload->ecr_registration_number,
                'fiscal_document_number' => $payload->fiscal_document_number,
                'fiscal_document_attribute' => $payload->fiscal_document_attribute,
            ));

            $receipt->save_status(
                $receipt::STATUS_REGISTERED,
                array(
                    //'path' => $path,
                    'response' => $response,    
                )
            );
        }

    }

    /**
     * Запрос статуса чека
     *
     * @param nc_payment_receipt $receipt
     */
    protected function request_report(nc_payment_receipt $receipt) {
        $receipt_uuid = $receipt->get('transaction_id');
        if (!$receipt_uuid) {
            trigger_error(__METHOD__ . ": receipt with id={$receipt->get_id()}) has no 'transaction_id'", E_USER_WARNING);
            return;
        }

        $nc_core = nc_core::get_object();
        $token = $nc_core->get_settings('token', 'schetmash', false, $nc_core->catalogue->id() );
        if(!isset($token) || empty($token)) { 
            $token = $this->getToken($nc_core);
            if($token === false) { return; }
        }

        $path = $this->get_setting('PaymentRegisterSchetmashGroup') . '/report/' . $receipt_uuid . '?token=';
        $response = $this->execute_request($path.$token);

        if(!is_object($response) )  { return false;  }

        if (isset($result->code) &&  ( $result->code  ==  2 || $result->code == 4) )	{	
            $token = $this->getToken($nc_core);
            $response = $this->execute_request($path.$token);
            if(!is_object($response) )  { return false;  }
        }

        if(!isset($response->status)) { return false; }        

      
        if(isset($response->error) && !empty($response->error)) {
            $receipt->save_status(         
                $receipt::STATUS_FAILED,
                array(
                    'path' => $path,
                    'response' => $response,
                )
            );
        } elseif ($response->status === 'success' && !empty($response->payload)) {
            $payload = $response->payload;
            $receipt_datetime = DateTime::createFromFormat('d.m.Y H:i:s', $payload->receipt_datetime);
            $receipt->set_values(array(
                'fiscal_receipt_created' => $receipt_datetime->format("Y-m-d H:i:s"),
                'fiscal_receipt_number' => $payload->fiscal_receipt_number,
                'shift_number' => $payload->shift_number,
                'fiscal_storage_number' => $payload->fn_number,
                'register_registration_number' => $payload->ecr_registration_number,
                'fiscal_document_number' => $payload->fiscal_document_number,
                'fiscal_document_attribute' => $payload->fiscal_document_attribute,
            ));

            $receipt->save_status(
                $receipt::STATUS_REGISTERED,
                array(
                    'path' => $path,
                    'response' => $response,    
                )
            );
        } elseif ($status === 'wait') {
            // Z-z-z...
        }
    }

    /**
     * Функция для создания CURL-запроса
     *
     * @param $path
     * @param null|array $data
     * @return array
     */
    protected function execute_request($path, $data = null) {  


        $curl = curl_init(); 
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_URL, static::SERVICE_URL.'/'.$path);
        curl_setopt($curl, CURLOPT_PORT , static::SERVICE_PORT);         
        if(isset($data)) { 
			curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
        curl_setopt($curl, CURLOPT_POSTFIELDS, /*json_encode($data)*/ nc_array_json($data) );
            curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));  
		  }  
        curl_setopt($curl, CURLOPT_HEADER, false);
//        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
//        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($curl, CURLOPT_TIMEOUT, 30);
        $out = curl_exec($curl); #Инициируем запрос к API и сохраняем ответ в переменную
        $code = curl_getinfo($curl, CURLINFO_HTTP_CODE); #Получим HTTP-код ответа сервера
        $err = curl_error($curl);
        curl_close($curl);

        if (!$code) { return $err; }

        if ($code !== 200 ) { return $code; }
      
        return json_decode( $out );	

    }

    /**
     * Выполнение задач при периодическом запуске скрипта из планировщика:
     * запрос статуса по чекам, по которым не получен ответ (АТОЛ может не вызвать
     * callback, если чек содержал ошибку)
     */
    public function execute_cron_tasks() {
        $pending_receipts_query =
            "SELECT * 
               FROM `Payment_Receipt` 
              WHERE `RegisterProvider_Type` = '" . nc_payment_receipt::PROVIDER_TYPE_REGISTER . "'
                AND `RegisterProvider_ID` = '" . $this->get_id() . "'
                AND `Status` = '" . nc_payment_receipt::STATUS_PENDING . "'";

        $receipts = nc_payment_receipt_collection::load_records($pending_receipts_query);
        foreach ($receipts as $receipt) {
            $this->request_report($receipt);
        }
    }





}