<?php
class ControllerShippingCorreios extends Controller
{
    private function loadLanguage()
    {
        $language = $this->load->language('shipping/correios');
        $this->data = array_merge($this->data, $language);
    }

    private function breadcrumbs()
    {
        $token = $this->session->data['token'];
        $type = $this->request->get['type'];

        $this->data['breadcrumbs'] = [
            [
                'href' => $this->url->link('common/home', 'token=' . $token, 'SSL'),
                'text' => $this->language->get('text_home'),
            ],
            [
                'href' => $this->url->linkAnchor('extension/module', 'token=' . $token, 'tab-info=' . $type, 'SSL'),
                'text' => $this->language->get('text_shipping'),
            ],
            [
                'href' => $this->url->link('shipping/correios', 'token=' . $token . '&type=' . $type, 'SSL'),
                'text' => $this->language->get('heading_title'),
            ]
        ];
    }

    private function removeMask()
    {
        extract($this->request->post);

        $this->request->post['correios_adicional'] = ftr_geral::removeMaskToDouble($correios_adicional);
        $this->request->post['correios_medida_para_val_adicional'] = ftr_geral::removeMaskToDouble($correios_medida_para_val_adicional);
        $this->request->post['correios_minimo_declarar'] = ftr_geral::removeMaskToDouble($correios_minimo_declarar);
        $this->request->post['correios_val_adicional_medida'] = ftr_geral::removeMaskToDouble($correios_val_adicional_medida);

        if (isset($this->request->post['correios_servicos'])) {
            $this->request->post['correios_servicos'] = array_map(
                function ($service) {
                    $service['codigo'] = trim($service['codigo']);
                    $service['pesomax'] = ftr_geral::removeMaskToDouble($service['pesomax']);
                    return $service;
                },
                $correios_servicos
            );
        }
    }

    public function index()
    {
        $this->loadLanguage();
        $this->breadcrumbs();

        $this->document->addScript('admin/public/js/shipping/correios.js');
        $this->document->setTitle($this->language->get('heading_title'));

        $this->load->model('setting/setting');
        $this->load->model('localisation/geo_zone');
        $this->load->model('localisation/order_status');
        $this->load->type('tipocomum');
        $this->load->helper('ftr_geral');

        $this->data['geo_zones'] = $this->model_localisation_geo_zone->getGeoZones();
        $this->data['order_statuses'] = $this->model_localisation_order_status->getOrderStatuses();

        $this->data['Type_Status'] = Type_Status::getEnumList();
        $this->data['Type_DsimDnao'] = Type_DsimDnao::getEnumList();
        $this->data['Type_DsDn'] = Type_DsDn::getEnumList();
        $this->data['Type_CorreiosTipoCalculo'] = Type_CorreiosTipoCalculo::getEnumList();

        $this->data['correios_url_tracking'] = $this->urlloja->link('common/tracking', '', 'SSL');

        $url_action = $this->url->link(
            'shipping/correios/save',
            'token=' . $this->session->data['token'] . '&type=' . $this->request->get['type'],
            'SSL'
        );

        $url_back = $this->url->linkAnchor(
            'extension/module',
            'token=' . $this->session->data['token'],
            'tab-info=' . $this->request->get['type'],
            'SSL'
        );

        $configurations = $this->model_setting_setting->getSetting('correios');

        if(!isset($configurations['correios_api_status'])){
            $configurations['correios_api_status'] = '0';
        }

        if (!isset($configurations['correios_servicos'])) {
            $configurations['correios_servicos'] = $this->getServicosDefault();
        }

        $this->data['data'] = [
            'tabs' => [
                ['text' => $this->language->get('tab_configuracoes')],
                ['text' => $this->language->get('tab_servicos')],
            ],
            'configurations' => $configurations,
            'action' => str_replace('&amp;', '&', $url_action),
            'back' => str_replace('&amp;', '&', $url_back),
            'token' => $this->session->data['token']
        ];

        $this->children = array(
            'common/header',
            'common/footer'
        );

        $this->response->setOutput($this->render('shipping/correios'));
    }

    public function save()
    {
        $this->loadLanguage();
        $this->removeMask();

        $response = [];

        if (!$this->user->hasPermission('modify', 'shipping/correios')) {
            $response['warning'] = $this->language->get('error_permission');
            return $this->response->setOutputJson($response);
        }

        $validate = $this->validate();
        if ($validate) {
            $response['errors'] = $validate;
            return $this->response->setOutputJson($response);
        }

        $this->load->model('setting/setting');
        unset($this->request->post['correios_invalid_credential']); //toda vez que salva se houver a notificacao que desabilitou o modulo por conta das credenciais ele remove a flag da base
        $this->model_setting_setting->editSetting('correios', $this->request->post);
        $response['success'] = $this->language->get('text_success');

        $this->response->setOutputJson($response);
    }

    private function validate()
    {
        $this->load->type('tipocomum');
        extract($this->request->post);

        $errors = [];

            if($correios_api_status == Type_Status::Tp_Habilitado) {
            $authValidate = $this->validateAuth($correios_contrato_user, $correios_contrato_senha, $correios_postCartao);
    
            if(!isset($authValidate)){
                $errors['correios_contrato_user'][] ='Usuario, Token ou Cartão de Postagem invalidos!';
                $errors['correios_contrato_senha'][] = 'Usuario, Token ou Cartão de Postagem invalidos!';
                $errors['correios_postCartao'][] = 'Usuario, Token ou Cartão de Postagem invalidos!';
    
                $this->data['data']['warning_correios_credential'] = $authValidate;
    
                return $errors;
            }
        }

        $errors = $this->validate->execute([
            'correios_tracking_status' => [
                'value' => $correios_tracking_status,
                'validates' => ['isEmpty', 'isEnabledOrDisabled']
            ],
            'correios_postcode' => [
                'value' => $correios_postcode,
                'validates' => ['isEmpty', 'isCep']
            ],
            'correios_mao_propria' => [
                'value' => $correios_mao_propria,
                'validates' => [
                    'isEmpty',
                    [
                        'method' => 'isYesOrNo',
                        'type' => 'Type_DsDn',
                    ]
                ]
            ],
            'correios_aviso_recebimento' => [
                'value' => $correios_aviso_recebimento,
                'validates' => [
                    'isEmpty',
                    [
                        'method' => 'isYesOrNo',
                        'type' => 'Type_DsDn',
                    ]
                ]
            ],
            'correios_declarar_valor' => [
                'value' => $correios_declarar_valor,
                'validates' => [
                    'isEmpty',
                    [
                        'method' => 'isYesOrNo',
                        'type' => 'Type_DsDn',
                    ]
                ]
            ],
            'correios_prazo_adicional' => [
                'value' => $correios_prazo_adicional,
                'validates' => ['isIntegerNumber']
            ],
            'correios_tipo_calculo' => [
                'value' => $correios_tipo_calculo,
                'validates' => ['isEmpty']
            ],
            'correios_status' => [
                'value' => $correios_status,
                'validates' => ['isEmpty', 'isEnabledOrDisabled']
            ],
            'correios_sort_order' => [
                'value' => $correios_sort_order,
                'validates' => ['isIntegerNumber']
            ],
        ]);

        $correiosTipoCalculo = Type_CorreiosTipoCalculo::getEnumList();
        $correiosTipoCalculoIsValid = false;
        foreach ($correiosTipoCalculo as $key => $value) {
            if ($correios_tipo_calculo == $key) {
                $correiosTipoCalculoIsValid = true;
            }
        }
        if (!$correiosTipoCalculoIsValid) {
            $errors['correios_tipo_calculo'][] = 'Tipo de calculo inválido';
        }

        $hasServiceWithContract = false;
        if (isset($correios_servicos)) {
            foreach ($correios_servicos as $serviceKey => $service) {
                if ($service['contrato'] == Type_DsimDnao::Tp_Sim && $service['status'] == Type_DsimDnao::Tp_Sim) {
                    $hasServiceWithContract = true;
                }

                $serviceErrors = $this->validate->execute([
                    'correios_servicos[' .  $serviceKey . '][codigo]' => [
                        'value' => $service['codigo'],
                        'validates' => ['isEmpty', 'isWithoutDot'],
                    ],
                    'correios_servicos[' .  $serviceKey . '][nome]' => [
                        'value' => $service['nome'],
                        'validates' => ['isEmpty'],
                    ],
                    'correios_servicos[' .  $serviceKey . '][pesomax]' => [
                        'value' => $service['pesomax'],
                        'validates' => ['isEmpty'],
                    ],
                    'correios_servicos[' .  $serviceKey . '][contrato]' => [
                        'value' => $service['contrato'],
                        'validates' => [
                            'isEmpty',
                            [
                                'method' => 'isYesOrNo',
                                'type' => 'Type_DsimDnao',
                            ]
                        ]
                    ],
                    'correios_servicos[' .  $serviceKey . '][status]' => [
                        'value' => $service['status'],
                        'validates' => ['isEmpty', 'isEnabledOrDisabled']
                    ],
                ]);

                if ($serviceErrors) {
                    $errors = array_merge($errors, $serviceErrors);
                }
            }
        }

        if ($hasServiceWithContract) {
            $contractErrors = $this->validate->execute([
                'correios_contrato_codigo' => [
                    'value' => $correios_contrato_codigo,
                    'validates' => ['isEmpty']
                ],
                'correios_contrato_senha' => [
                    'value' => $correios_contrato_senha,
                    'validates' => ['isEmpty']
                ]
            ]);

            $errors = array_merge($errors, $contractErrors);
        }

        return $errors;
    }

    public function validateAuth($user, $token, $postcard){
        $url = 'https://api.correios.com.br/token/v1/autentica/cartaopostagem';
        
        $basicAuth = base64_encode($user . ':' . $token);
        
        $param = json_encode(array(
            "numero"=> $postcard
        ));
      
        $header = array(
            'Accept: application/json;charset=UTF-8',
            'Content-Type: application/json',
            'Authorization: Basic '.$basicAuth
        );

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_POSTFIELDS, $param); 
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_close($ch);
        
        $response = json_decode(curl_exec($ch));
        $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        
        if($status_code == 201){
            return $response;
        }

        return null;
    }
    
    public function getServicosDefault()
    {
        $this->load->type('tipocomum');
        $this->load->helper('ftr_geral');
        $services = [];

        $typeServices = Type_CorreiosServico::getEnumList();
        foreach ($typeServices as $serviceKey => $serviceValue) {
            $service['codigo'] = $serviceKey;
            $service['nome'] = $serviceValue;

            if (strpos(strtoupper($service['nome']), 'SEM')) {
                $service['contrato'] = Type_DsimDnao::Tp_Nao;
            } else {
                $service['contrato'] = Type_DsimDnao::Tp_Sim;
            }

            if (
                (strpos($service['nome'], '10')) ||
                (strpos($service['nome'], '12')) ||
                (strpos(strtoupper($service['nome']), 'HOJE'))
            ) {
                $service['pesomax'] = 10;
            } else {
                $service['pesomax'] = 30;
            }

            $service['status'] = $this->validateOldCode($serviceKey);

            array_push($services, $service);
        }

        return $services;
    }

    private function validateOldCode($code)
    {
        $row = $this->db->query("Select * from " . DB_PREFIX . "setting where `key` = 'correios_" . $code . "' limit 1")->row;

        if ($row) {
            return 1;
        } else {
            return 0;
        }
    }

    function adminCodeTest()
    {

        $nCdEmpresa = $this->request->post['nCdEmpresa'];
        $sDsSenha = $this->request->post['sDsSenha'];
        $sCepOrigem = $this->request->post['sCepOrigem'];

        $url = "http://ws.correios.com.br/calculador/CalcPrecoPrazo.aspx?nCdEmpresa=$nCdEmpresa&sDsSenha=$sDsSenha&sCepOrigem=$sCepOrigem&sCepDestino=$sCepOrigem&nVlPeso=0,3&nCdFormato=1&nVlComprimento=16&nVlLargura=11&nVlAltura=9.1656564543302&sCdMaoPropria=N&nVlValorDeclarado=20.5&sCdAvisoRecebimento=S&nCdServico=41106&nVlDiametro=0&StrRetorno=xml";

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);

        $result = curl_exec($ch);

        curl_close($ch);

        $this->response->setOutput($result);
    }
}
