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

class ControllerPaymentPagseguroAPI extends ControllerPaymentPagseguroAPILib
{

    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 index()
    {
        if (!$this->user->isLogged()) {
            $this->redirect('error/not_found');
        }

        // Language
        $language = $this->language->load('payment/pagseguro_api');
        $this->data = array_merge($this->data, $language);

        // Breadcumbs
        $this->data['breadcrumbs'] = array();

        $this->data['breadcrumbs'][] = array(
            'text' => $this->language->get('text_home'),
            'href' => $this->url->link('common/home'),
            'separator' => false
        );

        $this->data['breadcrumbs'][] = array(
            'text' => $this->language->get('text_title'),
            'href' => $this->url->link('payment/pagseguro_api'),
            'separator' => $this->language->get('text_separator')
        );

        $this->breadcrumbs->setbreadcumbs($this->data['breadcrumbs']);

        // Title
        $this->document->setTitle($this->language->get('text_title'));

        $this->data['continue'] = $this->url->link('common/home');

        $this->data['auth_done'] = '' ;


        if ($this->config->get('pagseguro_api_refresh_token')) {
            if( $this->pagseguroapi->validateAccess() ) {
                $this->data['auth_done'] = '1';
                $this->data['text_auth'] = $this->language->get('text_reauth');
            } else {
                $this->data['text_auth'] = $this->language->get('text_auth');
            }
        }

        $this->data['login_url'] = $this->pagseguroapi->getLoginUrl();

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

        $this->children = array(
            'common/breadcrumbs',
            'common/column_left',
            'common/column_right',
            'common/content_top',
            'common/content_bottom',
            'common/footer',
            'common/header'
        );

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

    public function credit_card()
    {
        $order_info = $this->dmodel_checkout_order->getOrder($this->session->data['order_id']);
        $this->load->helper('ftr_geral');
        $credit_card_config = $this->config->get('pagseguro_api_credit_card');
        if ($this->config->get('pagseguro_api_config_parcelamento') != Type_ConfigParcelamento::PorBandeira){
            foreach ($credit_card_config as &$value){
                $value['valor_minimo'] = '';
            }
        }
        $this->data['credit_cards'] = ftr_geral::getPaymentMethods($credit_card_config, $order_info['total']);

        $setting = [
            'display_cpf' => true,
            'Type_PaymentOption' => Type_PaymentOption::Tp_CreditCard,
            'payment_name' => 'pagseguro_api'
        ];

        $this->data['pagseguroPublicKey'] = base64_encode(($this->config->get('pagseguro_api_ambiente') == Type_Environment::Tp_Sandbox
            ? $this->config->get('pagseguro_api_public_key_sandbox')
            : $this->config->get('pagseguro_api_public_key')));

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

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

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

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

    public function billet()
    {
        $setting = [
            'display_cpf' => true,
            'payment_name' => 'pagseguro_api',
            '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/pagseguro_api/billet.twig')) {
            $this->template = $this->config->get('config_template') . '/template/payment/pagseguro_api/billet.twig';
        } else {
            $this->template = 'default/template/payment/pagseguro_api/billet.twig';
        }

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

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

    }

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

            if (isset($this->request->get['bandeira'])) {
                $bandeira = Type_PagseguroBandeira::getConstFromNickValue($this->request->get['bandeira']);
            } else if ($flag_params['bandeira'] != '') {
                $bandeira = Type_PagseguroBandeira::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('pagseguro_api_credit_card');

            $bandeira = current(array_filter($credit_cards, function($item) use ($bandeira) {
                return $item['key'] == $bandeira;
            }));

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

    public function pay_credit_card()
    {

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

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

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

            try {

                $this->saveRequiedCustomerInfos();

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

                    $payment_method_id = Type_PagseguroBandeira::getConstFromNickValue($this->request->post['creditcard_cctype']);
                    $pagseguro_api_credit_card = $this->config->get('pagseguro_api_credit_card');
                    $qtd_parcela = $this->request->post['qtd_parcela'];

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

                        if (($this->config->get('pagseguro_api_config_parcelamento') == Type_ConfigParcelamento::PorBandeira)&&($this->request->post['qtd_parcela'] > $pagseguro_api_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::Pagseguro),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 pagseguro_api.');
                    }

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

                $order_info = parent::getOrder();

                //calcula novamente as parcelas para evitar que venha valor modificado do javascript
                $cartao_recalculo = $this->parcelamento(Type_CreditCardModule::getNickFromConstValue(Type_CreditCardModule::Pagseguro),false, array("bandeira" => $this->request->post['creditcard_cctype']));
                $valor = $cartao_recalculo[$qtd_parcela]['valor_parcela'];
                $valorPedido = number_format($valor * $qtd_parcela, 2, '.', '');
                $this->paymentInfo->setParam('amount', $valorPedido);

                //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 = number_format($total_parcelas - $order_info['total'], 2, '.', '');
                    }else if ($total_parcelas < $order_info['total']) {
                        $desconto_parcela = $order_info['total']-$total_parcelas;
                    }
                }

                $total_sobra = $order_info['total'] % $this->request->post['qtd_parcela'] / 100;

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

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

                if(isset($this->request->post['cpf'])){
                    $this->paymentInfo->setParam('cpf', $this->request->post['cpf']);
                }

                //seta a opção escolhida pelo usuario
                $this->paymentInfo->setParam('payment_method_id', $payment_method_id);
                //seta as opções de pagamentos disponiveis
                $this->paymentInfo->setParam('available_payment_methods', implode(',', Type_PagseguroBandeira::getEnumListConst()));

                $paymentData = parent::getTransactionInfo(Type_PaymentOption::Tp_CreditCard);

                $card = (Object)['encrypted' => $this->request->post['encryptedCard']];
                $paymentData['charges'][0]['payment_method']['card'] = $card;

                $result = $this->pagseguroapi->sendPayment($paymentData, $order_info['order_id']);

                $this->load->dmodel('payment/pagseguroapi');
                $this->dmodel_payment_pagseguroapi->setStatusOrder($order_info['order_id'], current($result->charges)->status);

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

                $data = new DateTime(substr($result->created_at, 0, 19));
                $data->setTimezone(new DateTimeZone('America/Sao_Paulo'));
                $creditcard_ccno = str_replace(' ', '', $this->request->post['creditcard_ccno']);

                $pagtoInfo = current($result->charges);

                $paymentinfo = array();
                $paymentinfo['tid'] = '';
                $paymentinfo['payment_id'] = $pagtoInfo->id;
                $paymentinfo['nsu'] = $pagtoInfo->payment_response->reference;
                $paymentinfo['mensagem_retorno'] = $pagtoInfo->payment_response->message;
                $paymentinfo['order_id'] = $order_info['order_id'];
                $paymentinfo['valor_pagamento'] = $pagtoInfo->amount->value/100;
                $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), substr($creditcard_ccno, 0, 6), substr($creditcard_ccno, 12, strlen($creditcard_ccno)));
                $paymentinfo['cartao_bandeira'] = Type_PagseguroBandeira::getConstFromNickValue(strtolower($this->request->post['creditcard_cctype']));
                $paymentinfo['cartao_bandeira_text'] = ucfirst($this->request->post['creditcard_cctype']);
                $paymentinfo['qtd_parcela'] = $qtd_parcela;
                $paymentinfo['valor_acrescimo'] = (isset($juros_parcela) && ($juros_parcela > 0)) ? $juros_parcela : null;
                $paymentinfo['moeda'] = $pagtoInfo->amount->currency;

                $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' => 'pagseguro_api_acrescimo',
                        'module_title' => 'Acréscimo Pagseguro (' . $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' => 'pagseguro_api_desconto',
                        'module_title' => 'Desconto Pagseguro (' . $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) {
                $this->dmodel_checkout_order->update($this->session->data['order_id'], $this->config->get('pagseguro_api_order_status_canceled'), '');
            }

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

        }

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

    }

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

        if (!$json['error']) {
            try {
                $order_info = parent::getOrder();

                //seta as opções de pagamentos disponiveis
                if(isset($this->request->post['cpf'])){
                    $this->paymentInfo->setParam('cpf', $this->request->post['cpf']);
                }

                if (parent::setOrderIncrease($order_info['order_id'])) {
                    $this->paymentInfo->setParam('price_additional', number_format(parent::getOrderIncreaseValue(), 2, '.', ''));
                }

                if (parent::setOrderDiscount($order_info['order_id'])) {
                    $this->paymentInfo->setParam('price_discount', number_format(parent::getOrderDiscountValue(), 2, '.', ''));
                }

                $valor = $order_info['total'];
                $valorPedido = number_format($valor, 2, '.', '');
                $this->paymentInfo->setParam('amount', $valorPedido);

                $paymentData = parent::getTransactionInfo(Type_PaymentOption::Tp_Billet);

                $result = $this->pagseguroapi->sendPayment($paymentData, $order_info['order_id']);

                $pagtoInfo = current($result->charges);

                $this->load->dmodel('payment/pagseguroapi');
                $this->dmodel_payment_pagseguroapi->setStatusOrder($order_info['order_id'], $pagtoInfo->status);

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

                $paymentInfo = array();
                $paymentInfo['data_criacao'] = str_replace('T', ' ',substr($pagtoInfo->created_at, 0, 19));
                $paymentInfo['data_vencimento'] = $pagtoInfo->payment_method->boleto->due_date . ' 23:59:59';
                $paymentInfo['link_boleto'] = $pagtoInfo->links[0]->href;
                $paymentInfo['link_digitavel'] = $pagtoInfo->payment_method->boleto->formatted_barcode;
                $paymentInfo['order_id'] = $order_info['order_id'];

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

            } catch (Exception $e) {
                $this->dmodel_checkout_order->update($this->session->data['order_id'], $this->config->get('pagseguro_api_order_status_canceled'), '');
            }

            $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_PagseguroConfigs::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 (isset($query['tid'])) {
                        $this->data['tid'] = $query['tid'];
                    }
                    break;
                case Type_PaymentOption::Tp_Billet:
                    $query = $this->db->query('SELECT pb.link_boleto, pb.link_digitavel, o.order_status_id  FROM oc_order o LEFT JOIN oc_payment_billet pb ON (o.order_id = pb.order_id) WHERE o.order_id = ' . $this->session->data['payment_session']['order_id'])->row;
                    if (isset($query['link_boleto'])) {
                        $this->data['link_boleto'] = $query['link_boleto'];
                    }
                    if (isset($query['link_digitavel'])) {
                        $this->data['link_digitavel'] = $query['link_digitavel'];
                    }
                    $this->data['link_order'] = $this->url->link('account/order/info', 'order_id=' . $this->session->data['payment_session']['order_id']);
                    break;
                case Type_PaymentOption::Tp_BankTransfer:
                    $query = $this->db->query('SELECT pbt.link_payment, o.order_status_id  FROM oc_order o LEFT JOIN oc_payment_bank_transfer pbt ON (o.order_id = pbt.order_id) WHERE o.order_id = ' . $this->session->data['payment_session']['order_id'])->row;
                    if (isset($query['link_payment'])) {
                        $this->data['link_payment'] = $query['link_payment'];
                    }
                    break;
            }

            $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('pagseguro_api_order_status_canceled')) {
                $this->session->data['orderPaymentCanceled'] = 'Pedido cancelado';
            }

            $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 validate()
    {

        $this->load->controller('payment/payment_address');

        $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;
        }

    }

    public function callback()
    {
        // parte de recuperar o code da autorização
        if ($this->request->server['REQUEST_METHOD'] == 'GET'){
            $this->data['error'] = '';
            if (isset($this->request->get['error'])) {
                $this->data['error'] = 'Error: ' . $this->request->get['error'] . (($this->request->get['error_description']) ? ' - ' . $this->request->get['error_description'] : '');
            }

            if (isset($this->request->get['code'])) {
                if (!$this->user->isLogged()) {
                    $this->redirect('error/not_found');
                } else {
                    $this->pagseguroapi->getRefreshToken($this->request->get['code']);
                    $urlAuth = $this->urlloja->link('', '', 'NONSSL', false) . 'pagseguroapiauth';
                    $this->redirect($urlAuth);
                }
            }
        // parte de atualizar os pagamentos
        } else if ($this->request->server['REQUEST_METHOD'] == 'POST'){
            $paymentData = json_decode(file_get_contents("php://input"), true);

            if (isset($paymentData['id']) && isset($paymentData['charges'])) {
                $this->load->dmodel('payment/payment_info');

                $charges = current($paymentData['charges']);

                $paymentId = $charges['id'];

                $data = array('codigo_integracao_pagamento' => $paymentId);

                $results = $this->dmodel_payment_payment_info->getOrderByToken($data);

                if ($results) {
                    try {
                        $this->load->dmodel('payment/pagseguroapi');
                        $this->dmodel_payment_pagseguroapi->setStatusOrder($results['order_id'], $charges['status']);

                        ob_start();
                        header($_SERVER["SERVER_PROTOCOL"] . " 200 OK");
                        ob_end_flush();
                    } catch (Exception $e) {
                        $this->log->write('Erro retorno callback pagseguro_api. Erro: ' . $e->getMessage() . '. Pedido ' . $results['order_id']);
                    }
                }
            }
        }

        if (headers_sent()) {
            echo "Header Sent to Pagseguro";
        } else {
            echo "Header Not Sent to Pagseguro";
        }
    }
}
