<?php

class ControllerCommonTracking extends Controller
{

    public function index()
    {
      $this->load->dmodel('setting/task');

      $this->ftrgeralregistry->permissaoAcessoUrl($this->dmodel_setting_task->getTaskByType(Type_TaskUrl::Tp_TaskRastreio));
      if ($this->config->get('correios_tracking_status') OR $this->config->get('melhorenvio_tracking_status') OR $this->config->get('kangu_tracking_status')){

        if ((($this->config->get('correios_status')) && ($this->config->get('correios_tracking_status'))) OR (($this->config->get('kangu_status')) && ($this->config->get('kangu_tracking_status')))) {

          if (isset($this->request->get['order_id'])) {
            ini_set("default_socket_timeout", 10);
          }

          $this->load->type('tipocomum');
          $this->load->type('tipofrete');
          $this->load->dmodel('tracking/tracking');
          $this->load->dmodel('mercadolivre/meliproduto');
          $this->load->helper('ftr_geral');

          $result = $this->dmodel_setting_task->getTaskByType(Type_TaskUrl::Tp_TaskRastreio);

          $time = (($result['time_execution'] * 60) - 60);

          $dataTask = array(
            'date_last_acting' => $this->db->dataAtual(),
            'type' => Type_TaskUrl::Tp_TaskRastreio
          );
          $this->dmodel_setting_task->editDateTaskByType($dataTask);

          $minutos = $time / 60;
          $tempoLimite = (new DateTime($this->db->dataAtual()))->add(new DateInterval('PT' . $minutos . 'M'));

          $json = array();

          $tracking_date_att = $this->db->dataAtual();

          $codeTracking = [];

          if($this->config->get('correios_tracking_status')){
            array_push($codeTracking, "'".Type_ShippingCode::Tp_ShippingCorreios."'");
          }

          if($this->config->get('kangu_tracking_status')){
            array_push($codeTracking, "'".Type_ShippingCode::Tp_ShippingKangu."'");
          }

          $data = array(
            'order_id' => (isset($this->request->get['order_id'])) ? $this->request->get['order_id'] : false,
            'origem_pedido' => Type_OrigemSistema::Tp_Ecommerce,
            'date_added_betwenn' => '(DATE(o.date_added) BETWEEN  CURDATE() - INTERVAL 60 DAY AND DATE(NOW()))',
            'tracking_complete' => Type_Status::Tp_Desabilitado,
            'shipping_code' => implode(',',$codeTracking),
            'sort' => 'ot.tracking_date_att',
            'order' => 'DESC',
            'start' => 0,
            'limit' => 20
          );

          $trackings = $this->dmodel_tracking_tracking->getTrackingsEcommerce($data);

          if ($trackings) {
            $trackingData = array();
            foreach ($trackings as $key => $tracking) {
              $shipping_code = ftr_geral::removeString($tracking['shipping_code'], '.');
              $trackingData[$shipping_code][$key] = ['tracking_code' => trim($tracking['tracking_code']), 'order_id' => $tracking['order_id']];
            }

            if ($trackingData) {
              foreach ($trackingData as $key => $tracking) {
                $status = $this->dmodel_tracking_tracking->verifyStatus($key);

                if ($status) {
                  $configTracking = $this->dmodel_tracking_tracking->getConfigTracking($key);
                  try {
                    if($key == Type_ShippingCode::Tp_ShippingCorreios){
                      $events = $this->correios->getObjectTracking(array_map(function ($array) {
                        return $array['tracking_code'];
                      }, $tracking));

                      $dataTracking = array();
                      
                      foreach ($tracking as $key => $value) {
                        $dataTracking['tracking_code'][$key] = $value['tracking_code'];
                        $dataTracking['order_id'][$value['order_id']] = $value['tracking_code'];
                      }

                      $events = $this->correios->getEvents($dataTracking);

                      if ($events || array_filter(array_values($events))) {
                        $events['tracking_date_att'] = $tracking_date_att;
  
                        $this->dmodel_tracking_tracking->addTrackingEcommerceEvent($events, $key);
  
                        $json['success'] = 'Status de envio atualizado com sucesso. A página será recarregada em breve!';
                      } else {
                        $json['error'] = 'Erro ao atualizar status de envio. Objeto não encontrado na base dos correios!';
                      }

                    }elseif ($key == Type_ShippingCode::Tp_ShippingKangu){
                      $trackingInstance = AbstractFactoryTrackingMethod::getInstance($key, $this->kangu);
                      $trackingInstance->autentication(['usuario' => $configTracking['usuario'], 'senha' => $configTracking['senha']]);
                     
                      $trackingInstance->getObjectTracking(array_map(function ($array) {
                        return $array['tracking_code'];
                      }, $tracking));

                      $dataTracking = array();
                      
                      foreach ($tracking as $key => $value) {
                        $dataTracking['tracking_code'][$key] = $value['tracking_code'];
                        $dataTracking['order_id'][$value['order_id']] = $value['tracking_code'];
                      }
  
                      $events = $trackingInstance->getEvents($dataTracking);
  
                      if ($events || array_filter(array_values($events))) {
                        $events['tracking_date_att'] = $tracking_date_att;
  
                        $this->dmodel_tracking_tracking->addTrackingEcommerceEvent($events, $key);
  
                        $json['success'] = 'Status de envio atualizado com sucesso. A página será recarregada em breve!';
  
                      } else {
                        $json['error'] = 'Erro ao atualizar status de envio. Objeto não encontrado na base dos correios!';
                      }
                    }

                  } catch (Exception $e) {
                    $error_message = $e->getMessage();
                    if (str_contains(strtolower($error_message), 'usuário e/ou senha inválidos')) {
                      $this->db->query("UPDATE oc_setting SET `value` = '0' WHERE `group` = 'correios' AND `key` = 'correios_tracking_status' AND store_id = '0'");
                      $this->db->query("INSERT INTO oc_setting SET store_id = '0', `group` = 'correios', `key` = 'correios_invalid_credential', `value` = '1'");
                    }

                    $trackingInstance->setErrorLog($this->config->get('config_error_filename'), $shipping_code, $e->getMessage());
                    $json['error'] = 'Erro ao atualizar status de envio. Tente novamente mais tarde ou consulte pelo site da transportadora!';
                    unset($trackingInstance);
                  }
                }

                if (($tempoLimite) && (new DateTime($this->db->dataAtual()) > $tempoLimite)) {
                  break;
                }
              }

            }

          }

          if (isset($this->request->get['order_id'])) {
            $this->response->setOutputJson($json);
          }
        }

        // Melhor envio - alterar status de pedidos entregues
        if (($this->config->get('melhorenvio_status')) && ($this->config->get('melhorenvio_tracking_status'))) {
          if (isset($this->request->get['order_id'])) {
            ini_set("default_socket_timeout", 10);
          }

          $this->load->type('tipocomum');
          $this->load->type('tipofrete');
          $this->load->dmodel('shipping/shippinglabel');
          $this->load->dmodel('checkout/order');
          $this->load->helper('ftr_geral');

          $result = $this->dmodel_setting_task->getTaskByType(Type_TaskUrl::Tp_TaskRastreio);
          $time = (($result['time_execution'] * 60) - 60);
          ini_set('max_execution_time', $time);

          $dataTask = array(
            'date_last_acting' => $this->db->dataAtual(),
            'type' => Type_TaskUrl::Tp_TaskRastreio
          );
          $this->dmodel_setting_task->editDateTaskByType($dataTask);

          $json = array();

          $tracking_date_att = $this->db->dataAtual();

          $data = array(
            'order_id' => (isset($this->request->get['order_id'])) ? $this->request->get['order_id'] : false,
            'date_added_betwenn' => '(DATE(o.date_added) BETWEEN  CURDATE() - INTERVAL 60 DAY AND DATE(NOW()))',
            'shipping_code' => Type_ShippingCode::Tp_ShippingMelhorEnvio,
            'label_complete' => Type_Status::Tp_Desabilitado,
            'sort' => 'sl.date_att',
            'order' => 'DESC',
            'start' => 0,
            'limit' => 20
          );

          $labels = $this->dmodel_shipping_shippinglabel->getShippingLabelsByFields($data);

          if ($labels) {

            try {
              $labelsTrackings = $this->melhorenvio->getTrackingInfo(array_column($labels, 'shipping_label'));
            } catch (Exception $e) {
              $this->log->write('Rota: common/tracking - Error: Não foi possível obter as informações de rastreio do melhor envio! - ' . $e->getMessage());
              return;
            }

            $orderLabels = array();
            foreach ($labels as $key => $label) {
              $orderLabels[$label['order_id']]['labels'][] = $label['shipping_label'];
            }

            foreach ($labels as $key => $label) {
              try {
                $labelTracking = $labelsTrackings->{$label['shipping_label']};

                if ($labelTracking) {
                  if (!empty($labelTracking->delivered_at)) {
                    // teste
//                if (!empty($labelTracking->posted_at)){
//                atualiza a etiqueta
                    $this->dmodel_shipping_shippinglabel->setShippingLabelComplete($label['order_id'], $label['shipping_code'], $label['shipping_label']);

                    $json['success'] = 'Status de envio atualizado com sucesso. A página será recarregada em breve!';
                  }
                } else {
                  $json['error'] = 'Erro ao atualizar status do pedido: ' . $label['order_id'] . '. Objeto: ' . $label['shipping_label'] . ' não encontrado na base do Melhor Envio!';
                }


              } catch (Exception $e) {
                $trackingInstance->setErrorLog($this->config->get('config_error_filename'), $label['shipping_label'], $e->getMessage());
                $json['error'] = 'Erro ao atualizar status de envio. Tente novamente mais tarde ou consulte pelo site da transportadora!';
                unset($trackingInstance);
              }
            }

//        atualiza o status dos pedido
            $orders = array_unique(array_column($labels, 'order_id'));
            $ordersInfo = $this->dmodel_shipping_shippinglabel->getOrdersShippingLabelInfo(array_values($orders));

            $dataStatus = array(
              'order_status_id' => $this->config->get('melhorenvio_tracking_delivered_status'),
              'cometario_html' => false,
              'comment' => ''
            );
            foreach ($ordersInfo as $orderInfo) {
              if (($orderInfo['complete'] == Type_Status::Tp_Habilitado)
                && ($orderInfo['order_status_id'] != $this->config->get('melhorenvio_tracking_delivered_status'))) {
                $this->dmodel_checkout_order->addOrderHistory($orderInfo['order_id'], $dataStatus);
              }
            }

          }

          if (isset($this->request->get['order_id'])) {
            $this->response->setOutputJson($json);
          }
        }

      }else {
        throw new Exception('Configuração de atualização dos status de envio dos pedido que utlizarem esta desabilitada!');
      }
    }
}
