<?php
$loader = $this->registry->get('load');
$loader->controller('payment/wirecard_lib');

class ControllerPaymentWirecard extends ControllerPaymentWirecardLib
{

    public function __construct($registry)
    {
        parent::__construct($registry);
        parent::load();

        $this->paymentInfo = new PaymentInfo();
        $this->paymentInfo->clearParams();

        if (isset($this->session->data['payment_method']['code_type']) && isset($this->session->data['payment_method']['code'])) {
          $code_type = $this->session->data['payment_method']['code_type'];
          $code = $this->session->data['payment_method']['code']; // nome do controller

          $this->data['paymentRoute'] = "$code/pay_$code_type";
          $this->data['paymentName'] = $code;
        }
    }

    public function credit_card()
    {
        $order_info = $this->dmodel_checkout_order->getOrder($this->session->data['order_id']);
        $this->load->helper('ftr_geral');
        $this->data['credit_cards'] = ftr_geral::getPaymentMethods($this->config->get('wirecard_credit_card'), $order_info['total']);
        $this->data['public_key'] = $this->config->get('wirecard_key_public');

        $setting = [
          'Type_PaymentOption' => Type_PaymentOption::Tp_CreditCard,
          'payment_name' => 'wirecard',
          'load_customer_info' => true
        ];

        $this->data['payment_address'] = $this->getChild('payment/wirecard_payment_address', $setting);
        $this->data['captcha_tpl'] =  $this->getChild('payment/captcha');

        if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/payment/wirecard/credit_card.twig')) {
            $this->template = $this->config->get('config_template') . '/template/payment/wirecard/credit_card.twig';
        } else {
            $this->template = 'default/template/payment/wirecard/credit_card.twig';
        }

        if ($this->ftrgeralregistry->isApp()) {
            $this->document->addScriptApp(array(
                'https://assets.moip.com.br/v2/moip.min.js',
                'catalog/view/javascript/jquery.payment/jquery.payment.js',
                'catalog/view/theme/appmobile/js/payment.wirecard_credit_card.js'
            ));
            $this->data['scriptsApp'] = json_encode($this->document->getScriptsApp());
        }

        $this->response->setOutput($this->render());

    }

    public function billet()
    {
        $setting = [
            'payment_name' => 'wirecard',
            'load_customer_info' => true
        ];
        $this->data['payment_address'] = $this->getChild('payment/payment_address', $setting);
        $this->data['captcha_tpl'] =  $this->getChild('payment/captcha');

        if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/payment/wirecard/billet.twig')) {
            $this->template = $this->config->get('config_template') . '/template/payment/wirecard/billet.twig';
        } else {
            $this->template = 'default/template/payment/wirecard/billet.twig';
        }

        if ($this->ftrgeralregistry->isApp()) {
            $this->document->addScriptApp(array(
                'catalog/view/theme/appmobile/js/payment.wirecard_billet.js'
            ));
            $this->data['scriptsApp'] = json_encode($this->document->getScriptsApp());
        }

        $this->response->setOutput($this->render());

    }

    public function bank_transfer()
    {
        $setting = ['payment_name' => 'wirecard'];
        $this->data['payment_address'] = $this->getChild('payment/payment_address', $setting);

        if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/payment/wirecard/bank_transfer.twig')) {
            $this->template = $this->config->get('config_template') . '/template/payment/wirecard/bank_transfer.twig';
        } else {
            $this->template = 'default/template/payment/wirecard/bank_transfer.twig';
        }

        if ($this->ftrgeralregistry->isApp()) {
            $this->document->addScriptApp(array(
                'catalog/view/theme/appmobile/js/payment.wirecard_bank_transfer.js'
            ));
            $this->data['scriptsApp'] = json_encode($this->document->getScriptsApp());
        }

        $this->response->setOutput($this->render());

    }

    public function parcelamento($module='wirecard',$html = true, $flag_params=array())
    {
      if ($this->config->get('wirecard_config_parcelamento') == Type_ConfigParcelamento::PorBandeira){
        $json = array();
        $this->load->helper('ftr_geral');

        if (isset($this->request->get['bandeira'])) {
          $bandeira = Type_FormPgtowirecardCartao::getConstFromNickValue($this->request->get['bandeira']);
        } else if ($flag_params['bandeira'] != '') {
          $bandeira = Type_FormPgtowirecardCartao::getConstFromNickValue($flag_params['bandeira']);
        } else {
          $json['bandeira'] = 'Não foi possivel fazer o cálculo da parcela pois nenhuma bandeira foi encontrada!';
        }
        $credit_cards = $this->config->get('wirecard_credit_card');

        $flag_params['juros'] = ftr_geral::isIsset($this->config->get('wirecard_porcentagem_juros')) ? $this->config->get('wirecard_porcentagem_juros') : 0;
        $flag_params['parcela_sem_juros']  = (isset($credit_cards[$bandeira]['parcela_juros']) && ($credit_cards[$bandeira]['parcela_juros'] != '')) ? $credit_cards[$bandeira]['parcela_juros'] : 0;
        $flag_params['parcela_maxima_qtd'] = (isset($credit_cards[$bandeira]['total_parcela']) && ($credit_cards[$bandeira]['total_parcela'] != '')) ? $credit_cards[$bandeira]['total_parcela'] : Type_wirecardConfigs::Tp_MaximoParcela;
        $flag_params['parcela_minima_val'] = $this->config->get('wirecard_parcela_minima');
      }
      return parent::parcelamento($module,$html,$flag_params);
    }

    public function pay_credit_card()
    {

        $this->load->helper('Ftr_sql');
        $this->language->load('payment/wirecard');

        $json['error'] = $this->validate();

        if (!$json['error']) {

            try {

                $this->saveRequiedCustomerInfos();

                $order_info = parent::getOrder();

                //validação feita somente para cartão de credito
                if (isset($this->request->post['creditcard_cctype'])) {

                    $payment_method_id = Type_FormPgtowirecardCartao::getConstFromNickValue($this->request->post['creditcard_cctype']);
                    $wirecard_credit_card = $this->config->get('wirecard_credit_card');

                    if (isset($wirecard_credit_card[$payment_method_id])) {

                        if (($this->config->get('wirecard_config_parcelamento') == Type_ConfigParcelamento::PorBandeira)&&($this->request->post['qtd_parcela'] > $wirecard_credit_card[$payment_method_id]['total_parcela'])) {
                            throw new exception('Quantidade de parcela não suportada para a bandeira' . $this->request->post['creditcard_cctype']);
                        }

                        $parcelas = $this->parcelamento(Type_CreditCardModule::getNickFromConstValue(Type_CreditCardModule::Wirecard),false, array("bandeira" => $this->request->post['creditcard_cctype']));

                        if (!in_array($this->request->post['qtd_parcela'], array_keys($parcelas))) {
                            throw new exception('Quantidade de parcela não suportada para a bandeira' . $this->request->post['creditcard_cctype']);
                        }

                    } else {
                        throw new exception('Bandeira ' . $this->request->post['creditcard_cctype'] . ' não habilitado para wirecard.');
                    }

                } else {
                    throw new exception('Bandeira não encontrada.');
                }

                if (isset($this->request->post['encrypted_value'])) {
                    $hash = $this->request->post['encrypted_value'];
                } else {
                    throw new exception('Hash não encontrado.');
                }

                //calcula o juros das parcelas
                $juros_parcela = 0;
                $desconto_parcela = 0;
                if (isset($parcelas[$this->request->post['qtd_parcela']])) {
                    $total_parcelas = $parcelas[$this->request->post['qtd_parcela']]['valor_parcela'] * $this->request->post['qtd_parcela'];
                    if ($total_parcelas > $order_info['total']) {
                        $juros_parcela = $total_parcelas - $order_info['total'];
                    }else if ($total_parcelas < $order_info['total']) {
                        $desconto_parcela = ($order_info['total']-$total_parcelas);
                    }
                }

                if (parent::setOrderIncrease($this->order_info['order_id'])||$juros_parcela) {
                    $juros_total = $juros_parcela+parent::getOrderIncreaseValue();
                    $this->paymentInfo->setParam('price_additional', (int)$this->currency->getValueCents($juros_total));
                }

                if (parent::setOrderDiscount($this->order_info['order_id'])||$desconto_parcela) {
                    $desconto_total = $desconto_parcela + parent::getOrderDiscountValue();
                    $this->paymentInfo->setParam('price_discount', (int)$this->currency->getValueCents($desconto_total));
                }

                $wirecardorder = parent::getWireCardOrder();
                $paymentData = $wirecardorder->create();

                $result = $paymentData->payments()
                    ->setCreditCardHash($hash, parent::getWireCardHolder())
                    ->setInstallmentCount($this->request->post['qtd_parcela'])
                    ->execute();

                $this->load->model('payment/wirecard');
                $this->model_payment_wirecard->setStatusOrder($order_info['order_id'], $result->getStatus());

                $sqlUpdParam = Ftr_sql::generateUpdate('oc_order', ['codigo_integracao_pagamento'], 'order_id = ' . $order_info['order_id']);
                $this->db->executeSql($sqlUpdParam, [$result->getOrder()->getOwnId()]);

                $data = new DateTime($this->db->dataAtual(), new DateTimeZone('America/Sao_Paulo'));
                $creditcard_ccno = str_replace(' ', '', $this->request->post['creditcard_ccno']);

                $paymentInfo = array();
                $paymentInfo['tid'] = $result->getId();
                $paymentInfo['numero_autorizacao'] = $result->getOrder()->getOwnId();
                $paymentInfo['cod_autorizacao'] = $result->getOrder()->getOwnId();
                $paymentInfo['mensagem_retorno'] = null;
                $paymentInfo['order_id'] = $order_info['order_id'];
                $paymentInfo['valor_pagamento'] = number_format(($result->getAmount()->total) / 100, 2, '.', '');
                $paymentInfo['data_pagamento'] = $data->format("Y-m-d H:i:s");
                $paymentInfo['tipo_cartao'] = Type_Card::Tp_Credito;
                $paymentInfo['cartao_mascara'] = ftr_geral::MaskCard(strlen($creditcard_ccno), $result->getFundingInstrument()->creditCard->first6, $result->getFundingInstrument()->creditCard->last4);
                $paymentInfo['cartao_bandeira'] = Type_FormPgtoWirecardCartao::getConstFromNickValue($this->request->post['creditcard_cctype']);
                $paymentinfo['cartao_bandeira_text'] = ucfirst($this->request->post['creditcard_cctype']);
                $paymentInfo['qtd_parcela'] = $result->getInstallmentCount();
                $paymentInfo['valor_acrescimo'] = (isset($juros_parcela) && ($juros_parcela > 0)) ? $juros_parcela : null;

                $this->load->dmodel('payment/payment_info');
                $this->dmodel_payment_payment_info->addPaymentCreditCard($paymentInfo);

                if ($juros_parcela) {
                    $valorPedido = $order_info['total'] + $juros_parcela;
                    $this->dmodel_checkout_order->InsertOrderTotal($this->session->data['order_id'], array(
                        'module_code' => 'wirecard_acrescimo',
                        'module_title' => 'Acréscimo Wirecard (' . $parcelas[$this->request->post['qtd_parcela']]['percentual_calculo'] . '% de juros ao mês no parcelamento)',
                        'value' => $juros_parcela,
                        'order' => '2'
                    ));
                    $this->dmodel_checkout_order->updateTotalOrder($this->session->data['order_id'], $valorPedido);
                    $this->dmodel_checkout_order->updateApportionment($this->session->data['order_id'],$juros_parcela,Type_Apportionment::Increase);
                }

                if ($desconto_parcela) {
                    $valorPedido = $order_info['total']-$desconto_parcela;
                    $this->dmodel_checkout_order->InsertOrderTotal($this->session->data['order_id'], array(
                        'module_code' => 'wirecard_desconto',
                        'module_title' => 'Desconto Wirecard (' . $parcelas[$this->request->post['qtd_parcela']]['percentual_calculo'] . '% de desconto)',
                        'value' => $desconto_parcela*-1,
                        'order' => '2'
                    ));
                    $this->dmodel_checkout_order->updateTotalOrder($this->session->data['order_id'], $valorPedido);
                    $this->dmodel_checkout_order->updateApportionment($this->session->data['order_id'],$desconto_parcela,Type_Apportionment::Discount);
                }

            } catch (Exception $e) {
                parent::setErrorLog('Erro ao finalizar pagamento com Cartão na Wirecard pedido ID: ' . $this->session->data['order_id'], $e->getErrors());
                $this->dmodel_checkout_order->update($this->session->data['order_id'], $this->config->get('wirecard_order_status_cancelled'), '');
            }

            $json['redirect'] = $this->url->link('checkout/success');

        }

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

    }

    public function pay_billet()
    {
        $this->load->helper('Ftr_sql');
        $this->load->dmodel('tool/image');
        $this->load->controller('payment/payment_address');
        $controllerPaymentPaymentAddress = new ControllerPaymentPaymentAddress($this->registry);
        $json['error'] = $controllerPaymentPaymentAddress->validate();

        if (!$json['error']) {
            try {

                $this->saveRequiedCustomerInfos();

                $order_info = parent::getOrder();

                $wirecardorder = parent::getWireCardOrder();

                if (parent::setOrderIncrease($this->order_info['order_id'])) {
                    $wirecardorder->setAddition((int)$this->currency->getValueCents(parent::getOrderIncreaseValue()));
                }

                if (parent::setOrderDiscount($this->order_info['order_id'])) {
                    $wirecardorder->setDiscount((int)$this->currency->getValueCents(parent::getOrderDiscountValue()));
                }

                $paymentData = $wirecardorder->create();

                $wirecard_billet = $this->config->get('wirecard_billet');
                $expiration_date = '';
                $instruction_lines = array();
                $logo_uri = false;
                array_walk($wirecard_billet, function ($array) use (&$expiration_date, &$instruction_lines, &$logo_uri) {
                    if (isset($array['validade']) && (!empty($array['validade']))) {
                        $date = new DateTime('+' . $array['validade'] . ' day');
                        $expiration_date = $date->format('Y-m-d');
                    } else {
                        $expiration_date = new DateTime('+4 day');
                    }

                    if (isset($array['instrucao']) && (!empty($array['instrucao']))) {
                        $instruction_lines[] = ucfirst(trim($array['instrucao']));
                        $instruction_lines[] = '';
                        $instruction_lines[] = '';
                    }

                    if (isset($array['logo']) && (!empty($array['logo']))) {
                        $logo_uri = $this->dmodel_tool_image->resize($array['logo'], 80, 25);
                    }

                });

                $result = $paymentData->payments()
                    ->setBoleto($expiration_date, $logo_uri, $instruction_lines)
                    ->execute();

                $this->load->model('payment/wirecard');
                $this->model_payment_wirecard->setStatusOrder($order_info['order_id'], $result->getStatus());

                $sqlUpdParam = Ftr_sql::generateUpdate('oc_order', ['codigo_integracao_pagamento'], 'order_id = ' . $order_info['order_id']);
                $this->db->executeSql($sqlUpdParam, [$result->getOrder()->getOwnId()]);

                $paymentInfo = array();
                $paymentInfo['numero_autorizacao'] = $result->getId();
                $paymentInfo['link_boleto'] = $result->getHrefBoleto();
                $paymentInfo['link_digitavel'] = $result->getLineCodeBoleto();
                $paymentInfo['order_id'] = $order_info['order_id'];

                $this->load->dmodel('payment/payment_info');
                $this->dmodel_payment_payment_info->addPaymentBillit($paymentInfo);

            } catch (Exception $e) {
                parent::setErrorLog('Erro ao finalizar pagamento com Boleto na Wirecard pedido ID: ' . $this->session->data['order_id'], $e->getErrors());
                $this->dmodel_checkout_order->update($this->session->data['order_id'], $this->config->get('wirecard_order_status_cancelled'), '');
            }

            $json['redirect'] = $this->url->link('checkout/success');
        }

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

    }

    public function pay_bank_transfer()
    {

        $this->load->helper('Ftr_sql');
        $this->load->controller('payment/payment_address');
        $controllerPaymentPaymentAddress = new ControllerPaymentPaymentAddress($this->registry);
        $json['error'] = $controllerPaymentPaymentAddress->validate();

        if (!$json['error']) {
            try {

                $this->saveRequiedCustomerInfos();

                $order_info = parent::getOrder();

                $wirecardorder = parent::getWireCardOrder();

                if (parent::setOrderIncrease($this->order_info['order_id'])) {
                    $wirecardorder->setAddition((int)$this->currency->getValueCents(parent::getOrderIncreaseValue()));
                }

                if (parent::setOrderDiscount($this->order_info['order_id'])) {
                    $wirecardorder->setDiscount((int)$this->currency->getValueCents(parent::getOrderDiscountValue()));
                }

                $paymentData = $wirecardorder->create();

                $result = $paymentData->payments()
                    ->setOnlineBankDebit(Type_WirecardConfigs::Tp_BankTransferItau, new DateTime(), $this->url->link('checkout/success'))
                    ->execute();

                $this->load->model('payment/wirecard');
                $this->model_payment_wirecard->setStatusOrder($order_info['order_id'], $result->getStatus());

                $sqlUpdParam = Ftr_sql::generateUpdate('oc_order', ['codigo_integracao_pagamento'], 'order_id = ' . $order_info['order_id']);
                $this->db->executeSql($sqlUpdParam, [$result->getOrder()->getOwnId()]);

                $paymentInfo = array();
                $paymentInfo['numero_autorizacao'] = $result->getOrder()->getOwnId();
                $paymentInfo['cod_autorizacao'] = $result->getOrder()->getOwnId();
                $paymentInfo['link_payment'] = $result->getLinks()->getLink('payOnlineBankDebitItau');
                $paymentInfo['order_id'] = $order_info['order_id'];

                $this->load->dmodel('payment/payment_info');
                $this->dmodel_payment_payment_info->addPaymentBankTransfer($paymentInfo);

            } catch (Exception $e) {
                parent::setErrorLog('Erro ao finalizar pagamento com Transferência Bancária na Wirecard pedido ID: ' . $this->session->data['order_id'], $e->getMessage());
                $this->dmodel_checkout_order->update($this->session->data['order_id'], $this->config->get('wirecard_order_status_cancelled'), '');
            }

            $json['redirect'] = $this->url->link('checkout/success');
        }

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

    }

    public function success()
    {

        if (isset($this->session->data['payment_session']['code']) && ($this->session->data['payment_session']['code'] == Type_wirecardConfigs::Tp_NameModule)) {

            $this->load->dmodel('payment/payment_info');
            $this->load->language('payment/' . $this->session->data['payment_session']['code']);

            switch ($this->session->data['payment_session']['code_type']) {
                case Type_PaymentOption::Tp_CreditCard :
                    $query = $this->db->query('SELECT pcc.tid, o.order_status_id  FROM oc_order o LEFT JOIN oc_payment_credit_card pcc ON (o.order_id = pcc.order_id) WHERE o.order_id = ' . $this->session->data['payment_session']['order_id'])->row;
                    if (!$query) {
                        return false;
                    }
                    $this->data['tid'] = $query['tid'];
                    $this->load->dmodel('checkout/order');
                    $status_info = $this->dmodel_checkout_order->getOrderStatus($query['order_status_id']);
                    $this->data['status_descricao'] = $status_info['descricao'];
                    if ($status_info['order_status_id'] == $this->config->get('wirecard_order_status_cancelled')) {
                        $this->session->data['orderPaymentCanceled'] = 'Não conseguimos realizar seu pedido';
                    }
                    break;
                case Type_PaymentOption::Tp_Billet:
                    $query = $this->db->query('SELECT * FROM oc_payment_billet WHERE order_id = ' . $this->session->data['payment_session']['order_id'])->row;
                    if (!$query) {
                        return false;
                    }
                    $this->data['link_boleto'] = $query['link_boleto'];
                    $this->data['link_digitavel'] = $query['link_digitavel'];
                    break;
                case Type_PaymentOption::Tp_BankTransfer:
                    $query = $this->db->query('SELECT * FROM oc_payment_bank_transfer WHERE order_id = ' . $this->session->data['payment_session']['order_id'])->row;
                    if (!$query) {
                        return false;
                    }
                    $this->data['link_payment'] = $query['link_payment'];
                    break;
            }

            $this->template = $this->config->get('config_template') . '/template/success/' . $this->session->data['payment_session']['code_type'] . '.twig';
            $this->response->setOutput($this->render());

        } else {
            return false;
        }

    }

    public function callback()
    {

        // Pega o RAW data da requisição
        $json = file_get_contents('php://input');

        // Converte os dados recebidos
        $response = json_decode($json, true);

        if ($response) {
            try {
                $payment = $response['resource']['payment'];
                $dados = $this->moip->payments()->get($payment['id']);

                if ($dados) {
                    $this->load->dmodel('payment/payment_info');

                    $payment_method = $payment['fundingInstrument']['method'];
                    switch ($payment_method){
                        case Type_FormPgtoWirecard::Tp_Billet:
                            $tipo_pagamento = Type_PagamentoTabela::Tp_Boleto;
                            $campo_chave = Type_FormPgtoWirecard::getNickFromConstValue($payment_method);
                            break;
                        case Type_FormPgtoWirecard::Tp_CreditCard:
                            $tipo_pagamento = Type_PagamentoTabela::Tp_Cartao;
                            $campo_chave = Type_FormPgtoWirecard::getNickFromConstValue($payment_method);
                            break;
                        default:
                            $campo_chave = false;
                            $tipo_pagamento = false;
                            break;
                    }

                    if ($tipo_pagamento){
                        $result = $this->dmodel_payment_payment_info->getPaymentInfoByTransactionId($campo_chave, $payment['id'], $tipo_pagamento);
                        $this->load->model('payment/wirecard');
                        $this->model_payment_wirecard->setStatusOrder($result['order_id'], $dados->getStatus());
                    }
                }
            } catch (Exception $e) {
                if ($this->config->get('wirecard_log_error')) {
                    $logData = [
                        'event'    => 'PaymentWirecard::callback',
                        'message'  => 'Erro retorno wirecard',
                        'payment-id' => $payment['id'],
                        'exception'=> [
                            'type'    => get_class($e),
                            'message' => $e->getMessage(),
                            'code'    => $e->getCode(),
                            'file'    => $e->getFile(),
                            'line'    => $e->getLine(),
                            'trace'   => $e->getTraceAsString()
                        ],
                        'datetime' => date('c'), // data/hora no padrão ISO
                    ];
                    $this->log->write(json_encode($logData, JSON_UNESCAPED_UNICODE));
                }
            }
        }

        http_response_code(200);
    }

    public function validate(){
        $error = parent::validate();
        $error = $error ? $error :  array() ;

        if (!isset($this->request->post['qtd_parcela']) || $this->request->post['qtd_parcela'] < 1   ) {
            $error['qtd_parcela'] = $this->language->get('error_parcelas');
        }

        if ($error) {
            return $error;
        } else {
            return false;
        }
    }

}
