<?php

require_once DIR_SYSTEM . 'library/PagSeguro/PagSeguroData.class.php';
require_once DIR_SYSTEM . 'library/PagSeguroLibrary/PagSeguroLibrary.php';
require_once DIR_SYSTEM . 'library/PagSeguroLibrary/utils/PagSeguroHttpConnection.class.php';
require_once DIR_SYSTEM . 'library/PagSeguroLibrary/utils/PagSeguroXmlParser.class.php';

class ControllerPaymentPagseguroBoleto extends Controller
{
	public function index()
	{
		$this->language->load('payment/pagseguro_boleto');

		$this->load->model('checkout/order');
		$order_info = $this->model_checkout_order->getOrder((int)$this->session->data['order_id']);

		$customer_name = trim(trim($order_info['payment_firstname']) .' '. trim($order_info['payment_lastname']));
		$space_pos = strpos($customer_name, ' ');

		if ($space_pos !== false) {
			$firstname = substr($customer_name, 0, $space_pos);
			$lastname = substr($customer_name, $space_pos + 1);
		} else {
			$firstname = $customer_name;
			$lastname = '';
		}

		$data['firstname'] = $firstname;
		$data['lastname']  = $lastname;
		$data['razao']     = isset($order_info['custom_field']['razao']) ? $order_info['custom_field']['razao'] : $customer_name;
		$data['pessoa']    = isset($order_info['custom_field']['tipo']) ? $order_info['custom_field']['tipo'] : 'f';
		$data['cpf']       = isset($order_info['custom_field']['cpf']) ? $order_info['custom_field']['cpf'] : '';
		$data['cnpj']      = isset($order_info['custom_field']['cnpj']) ? $order_info['custom_field']['cnpj'] : '';
		$data['telefone']  = $order_info['telephone'];

		$pagSeguroObject = new PagSeguroData(false, $this->config->get('pagseguro_boleto_email'), $this->config->get('pagseguro_boleto_token'));

		$data['pagseguro_js'] = $pagSeguroObject->getJavascriptURL();
		$data['pagseguro_session'] = $this->getSessionId($pagSeguroObject);

		if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/payment/pagseguro_boleto.tpl')) {
			return $this->load->view($this->config->get('config_template') . '/template/payment/pagseguro_boleto.tpl', $data);
		} else {
			return $this->load->view('default/template/payment/pagseguro_boleto.tpl', $data);
		}
	}

	public function payment()
	{
		// Adding parameters
		$pagSeguroObject = new PagSeguroData(false, $this->config->get('pagseguro_boleto_email'), $this->config->get('pagseguro_boleto_token'));

		$this->load->model('checkout/order');
		$order_info = $this->model_checkout_order->getOrder((int)$this->session->data['order_id']);
		// $this->log->write(print_r($order_info, true)); exit;

		/* Dados do cliente */

		$telefone = $this->getDDDNumero($this->request->post['senderPhone']);

		if ($this->request->post['pessoa'] == 'f') {
			$params['senderCPF']  = preg_replace('/[^0-9]/', '', $this->request->post['senderCPF']);
			$params['senderName'] = $this->mySubstr(trim($this->request->post['senderFirstName'] . ' ' . $this->request->post['senderLastName']), 0, 50);
		} else {
			$params['senderCNPJ'] = preg_replace('/[^0-9]/', '', $this->request->post['senderCNPJ']);
			$params['senderName'] = $this->mySubstr(trim($this->request->post['senderName']), 0, 50);
		}

		$params['senderEmail']    = $this->mySubstr(trim($order_info['email']), 0, 60);
		$params['senderAreaCode'] = $telefone[0];
		$params['senderPhone']    = $telefone[1];
		$params['senderHash']     = $this->request->post['senderHash'];
		// $this->log->write(json_encode($params)); exit;

		/* Frete */
		$this->load->model('localisation/zone');

		if ($this->cart->hasShipping()) {
			$shipping_custom_field_numero      = isset($order_info['shipping_custom_field']['numero'])      ? $order_info['shipping_custom_field']['numero']      : '';
			$shipping_custom_field_complemento = isset($order_info['shipping_custom_field']['complemento']) ? $order_info['shipping_custom_field']['complemento'] : '';

			$estado = $this->model_localisation_zone->getZone($order_info['shipping_zone_id']);
			$params['shippingAddressPostalCode'] = $this->mySubstr(preg_replace('/[^0-9]/', '', $order_info['shipping_postcode']), 0, 8);
			$params['shippingAddressStreet']     = $this->mySubstr($order_info['shipping_address_1'], 0, 80);
			$params['shippingAddressNumber']     = $this->mySubstr($shipping_custom_field_numero, 0, 20);
			$params['shippingAddressComplement'] = $this->mySubstr($shipping_custom_field_complemento, 0, 40);
			$params['shippingAddressDistrict']   = $this->mySubstr($order_info['shipping_address_2'], 0, 60);
			$params['shippingAddressCity']       = $this->mySubstr($order_info['shipping_city'], 0, 60);
			$params['shippingAddressState']      = strtoupper($estado['code']);
		} else {
			$payment_custom_field_numero      = isset($order_info['payment_custom_field']['numero'])      ? $order_info['payment_custom_field']['numero']      : '';
			$payment_custom_field_complemento = isset($order_info['payment_custom_field']['complemento']) ? $order_info['payment_custom_field']['complemento'] : '';

			$estado = $this->model_localisation_zone->getZone($order_info['payment_zone_id']);
			$params['shippingAddressPostalCode'] = $this->mySubstr(preg_replace('/[^0-9]/', '', $order_info['payment_postcode']), 0, 8);
			$params['shippingAddressStreet']     = $this->mySubstr($order_info['payment_address_1'], 0, 80);
			$params['shippingAddressNumber']     = $this->mySubstr($payment_custom_field_numero, 0, 20);
			$params['shippingAddressComplement'] = $this->mySubstr($payment_custom_field_complemento, 0, 40);
			$params['shippingAddressDistrict']   = $this->mySubstr($order_info['payment_address_2'], 0, 60);
			$params['shippingAddressCity']       = $this->mySubstr($order_info['payment_city'], 0, 60);
			$params['shippingAddressState']      = strtoupper($estado['code']);
		}

		if ($params['shippingAddressNumber'] == '' || $params['shippingAddressNumber'] == false) {
			$params['shippingAddressNumber'] = 's/n';
		}
		if ($params['shippingAddressDistrict'] == '' || $params['shippingAddressDistrict'] == false) {
			$params['shippingAddressDistrict'] = 'sem bairro';
		}

		$params['shippingAddressCountry'] = 'BRA';
		$params['shippingType'] = 3; // 1=pac; 2=sedex; 3=não especificado;

		/* Produtos */

		$i = 1;

		foreach ($this->cart->getProducts() as $product) {
			if ($product['price'] <= 0) { continue; }

			$options_names = array();
			foreach ($product['option'] as $option) {
				if (in_array($option['type'], array('select','radio','checkbox','image'))) {
					$options_names[] = $option['value'];
				}
			}
			$options_names = implode('/', $options_names);
			if ($options_names) { $options_names = " ({$options_names})"; }

			$params['itemId' . $i]          = $product['product_id'];
			$params['itemDescription' . $i] = $this->mySubstr($product['name'] . $options_names, 0, 90);
			$params['itemAmount' . $i]      = $this->currency->format($product['price'], $order_info['currency_code'], false, false);
			$params['itemQuantity' . $i]    = $product['quantity'];

			$i++;
		}



		// url para receber notificações sobre o status das transações
		$params['notificationURL'] = $this->url->link('payment/pagseguro_boleto/callback');

		// obtendo frete, descontos e taxas
		$total = $this->currency->format($order_info['total'] - $this->cart->getSubTotal(), $order_info['currency_code'], false, false);
		$params['extraAmount'] = $total;

		$params['paymentMethod'] = 'boleto';
		$params['paymentMode']   = 'default'; // paymentMode
		$params['currency']      = 'BRL'; // Currency (only BRL)
		$params['reference']     = $order_info['order_id']; // Setting the Application Order to Reference on PagSeguro

		$params += $pagSeguroObject->getCredentials(); // add credentials
		// $this->response->setOutput(json_encode($params)); exit;

		// treat parameters here!
		$httpConnection = new PagSeguroHttpConnection();
		$httpConnection->post($pagSeguroObject->getTransactionsURL(), $params);

		// Get Xml From response body
		$xmlArray = $this->paymentResultXml($httpConnection->getResponse());

		$json = array();

		if (array_key_exists('errors', $xmlArray)) {
			foreach ($xmlArray['errors'] as $error) {
				$this->log->write('Erro PagSeguro Boleto: ' . print_r($error, true));
			}
			$json['error'] = true;
		} else {
			$this->load->model('payment/pagseguro_boleto');
			$this->model_payment_pagseguro_boleto->addPaymentLink($this->session->data['order_id'], $xmlArray['transaction']['paymentLink']);
			$json['success'] = $xmlArray['transaction']['paymentLink'];
			$json['order_id'] = $this->session->data['order_id'];
		}

		$this->response->addHeader('Content-Type: application/json');
		$this->response->setOutput(json_encode($json));
	}

	public function confirm()
	{
		$this->load->model('checkout/order');

		$this->model_checkout_order->addOrderHistory($this->session->data['order_id'], $this->config->get('pagseguro_boleto_order_aguardando_pagamento'), '', true);

		$this->response->redirect($this->url->link('checkout/success'));
	}

	public function callback()
	{
		$code = isset($_REQUEST['notificationCode']) && trim($_REQUEST['notificationCode']) !== '' ? trim($_REQUEST['notificationCode']) : null;
		$type = isset($_REQUEST['notificationType']) && trim($_REQUEST['notificationType']) !== '' ? trim($_REQUEST['notificationType']) : null;
		// @mail('eric@hoteldaweb.com.br', 'PagSeguro Boleto Log 1', 'Post: '.print_r($_REQUEST,true)."\n\n".date('Y-m-d H:i:s'));
		// $this->log->write('PagSeguro Boleto: Log 1: Post: '.print_r($_REQUEST,true));

		if ($code && $type) {
			$notificationType = new PagSeguroNotificationType($type);
			$strType = $notificationType->getTypeFromValue();

			if ($strType == 'TRANSACTION') {
				try {
					$credentials = new PagSeguroAccountCredentials($this->config->get('pagseguro_boleto_email'), $this->config->get('pagseguro_boleto_token'));
					$transaction = PagSeguroNotificationService::checkTransaction($credentials, $code);
					// @mail('eric@hoteldaweb.com.br', 'PagSeguro Boleto Log 2', "transaction: ".print_r($transaction,true)."\n\n".date('Y-m-d H:i:s'));
					// $this->log->write('PagSeguro Boleto: Log 2: transaction: '.print_r($transaction,true));

					$status = $transaction->getStatus()->getTypeFromValue();
					$reference = $transaction->getReference();
					// @mail('eric@hoteldaweb.com.br', 'PagSeguro Boleto Log 3', "transactionStatus: {$status}\nid_pedido: {$reference}\n\n".date('Y-m-d H:i:s'));
					// $this->log->write("PagSeguro Boleto: Log 3: transactionStatus: {$status} / id_pedido: {$reference}");

					$order_id = explode('_', preg_replace('/_+/', '_', $reference));
					$order_id = $order_id[0];

					$this->load->model('checkout/order');
					$order = $this->model_checkout_order->getOrder($order_id);
					// @mail('eric@hoteldaweb.com.br', 'PagSeguro Boleto Log 4', "order: ".print_r($order,true)."\n\n".date('Y-m-d H:i:s'));
					// $this->log->write('PagSeguro Boleto: Log 4: order: '.print_r($order,true));

					$update_status_alert = false;
					if ($this->config->get('pagseguro_boleto_update_status_alert') == '1') {
						$update_status_alert = true;
					}

					if ($order['order_status_id'] == '0') {
						$this->model_checkout_order->addOrderHistory($order_id, $this->config->get('pagseguro_boleto_order_aguardando_pagamento'), '', true);
					}

					switch($status){

					// 'WAITING_PAYMENT' => 1
					case 'WAITING_PAYMENT':
						$order_aguardando_pagamento = $this->config->get('pagseguro_boleto_order_aguardando_pagamento');
						if (is_numeric($order_aguardando_pagamento) && $order_aguardando_pagamento > 0) {
							if ($order['order_status_id'] != $order_aguardando_pagamento) {
								$this->model_checkout_order->addOrderHistory($order_id, $order_aguardando_pagamento, '', $update_status_alert);
							}
						}
						break;

					// 'IN_ANALYSIS' => 2
					case 'IN_ANALYSIS':
						$order_analise = $this->config->get('pagseguro_boleto_order_analise');
						if (is_numeric($order_analise) && $order_analise > 0) {
							if ($order['order_status_id'] != $order_analise) {
								$this->model_checkout_order->addOrderHistory($order_id, $order_analise, '', $update_status_alert);
							}
						}
						break;

					// 'PAID' => 3
					case 'PAID':
						$order_paga = $this->config->get('pagseguro_boleto_order_paga');
						if (is_numeric($order_paga) && $order_paga > 0) {
							if ($order['order_status_id'] != $order_paga) {
								// $paymentMethod = $transaction->getPaymentMethod();
								// $paymentCode   = $paymentMethod->getCode()->getTypeFromValue();
								// $pagamento    = $paymentCode->getTypeFromValue();

								$pagamento = $transaction->getPaymentMethod()->getCode()->getTypeFromValue();
								$parcelas  = $transaction->getInstallmentCount();

								// Obtendo o tipo de pagamento escolhido
								$comment = "Tipo de pagamento escolhido: {$pagamento} / Número de parcelas: {$parcelas}";
								// @mail('eric@hoteldaweb.com.br', 'PagSeguro Boleto Log 5', "comment: {$comment}\n\n".date('Y-m-d H:i:s'));
								// $this->log->write("PagSeguro Boleto: Log 5: comment: {$comment}");

								$this->model_checkout_order->addOrderHistory($order_id, $order_paga, $comment, $update_status_alert);
							}
						}
						break;

					// 'AVAILABLE' => 4
					case 'AVAILABLE':
						$order_disponivel = $this->config->get('pagseguro_boleto_order_disponivel');
						if (is_numeric($order_disponivel) && $order_disponivel > 0) {
							if ($order['order_status_id'] != $order_disponivel) {
								$this->model_checkout_order->addOrderHistory($order_id, $order_disponivel, '', $update_status_alert);
							}
						}
						break;

					// 'IN_DISPUTE' => 5
					case 'IN_DISPUTE':
						$order_disputa = $this->config->get('pagseguro_boleto_order_disputa');
						if (is_numeric($order_disputa) && $order_disputa > 0) {
							if ($order['order_status_id'] != $order_disputa) {
								$this->model_checkout_order->addOrderHistory($order_id, $order_disputa, '', $update_status_alert);
							}
						}
						break;

					// 'REFUNDED' => 6
					case 'REFUNDED':
						$order_devolvida = $this->config->get('pagseguro_boleto_order_devolvida');
						if (is_numeric($order_devolvida) && $order_devolvida > 0) {
							if ($order['order_status_id'] != $order_devolvida) {
								$this->model_checkout_order->addOrderHistory($order_id, $order_devolvida, '', $update_status_alert);
							}
						}
						break;

					// 'CANCELLED' => 7
					case 'CANCELLED':
						$order_cancelada = $this->config->get('pagseguro_boleto_order_cancelada');
						if (is_numeric($order_cancelada) && $order_cancelada > 0) {
							if ($order['order_status_id'] != $order_cancelada) {
								$this->model_checkout_order->addOrderHistory($order_id, $order_cancelada, '', $update_status_alert);
							}
						}
						break;

					// 'SELLER_CHARGEBACK' => 8
					case 'SELLER_CHARGEBACK':
						$order_chargeback = $this->config->get('pagseguro_boleto_order_chargeback');
						if (is_numeric($order_chargeback) && $order_chargeback > 0) {
							if ($order['order_status_id'] != $order_chargeback) {
								$this->model_checkout_order->addOrderHistory($order_id, $order_chargeback, '', $update_status_alert);
							}
						}
						break;

					// 'CONTESTATION' => 9
					case 'CONTESTATION':
						$order_contestacao = $this->config->get('pagseguro_boleto_order_contestacao');
						if (is_numeric($order_contestacao) && $order_contestacao > 0) {
							if ($order['order_status_id'] != $order_contestacao) {
								$this->model_checkout_order->addOrderHistory($order_id, $order_contestacao, '', $update_status_alert);
							}
						}
						break;
					}

				} catch (PagSeguroServiceException $e) {
					// @mail('eric@hoteldaweb.com.br', 'PagSeguro Boleto', "Erro 1: ".$e->getMessage()."\n\n".print_r($transaction,true)."\n\n".date('Y-m-d H:i:s'));
					$this->log->write('PagSeguro Boleto: Erro 1: '.$e->getMessage()."\n\n".print_r($transaction,true));
				} catch (Exception $e) {
					// @mail('eric@hoteldaweb.com.br', 'PagSeguro Boleto', "Erro 2: ".$e->getMessage()."\n\n".print_r($transaction,true)."\n\n".date('Y-m-d H:i:s'));
					$this->log->write('PagSeguro Boleto: Erro 2: '.$e->getMessage()."\n\n".print_r($transaction,true));
				}

			} else {
				$this->log->write("PagSeguro Boleto: tipo de notificação desconhecido [{$type}]");
			}

		} else {
			$this->log->write('PagSeguro Boleto: Parâmetros de notificação inválidos. Request: '.print_r($_REQUEST,true));
		}
	}

	public function open()
	{
		$order_id = $this->request->get['order_id'];

		$this->load->model('checkout/order');
		$order = $this->model_checkout_order->getOrder((int)$order_id);

		$this->response->redirect($order['pagseguro_link']);
	}

	private function getSessionId(PagSeguroData $pagSeguroData)
	{
		// Creating a http connection (CURL abstraction)
		$httpConnection = new PagSeguroHttpConnection();

		// Request to PagSeguro Session API using Credentials
		$httpConnection->post($pagSeguroData->getSessionURL(), $pagSeguroData->getCredentials());

		// Request OK getting the result
		if ($httpConnection->getStatus() === 200) {
			$data = $httpConnection->getResponse();

			$sessionId = $this->parseSessionIdFromXml($data);

			return $sessionId;
		} else {
			throw new Exception("PagSeguro Boleto: API Request Error: " . $httpConnection->getStatus());
		}
	}

	private function parseSessionIdFromXml($data)
	{
		// Creating an xml parser
		$xmlParser = new PagSeguroXmlParser($data);

		// Verifying if is an XML
		if ($xml = $xmlParser->getResult("session")) {
			// Retrieving the id from "session node"
			return $xml['id'];
		} else {
			throw new Exception("PagSeguro Boleto: [{$data}] is not an XML");
		}
	}

	private function getDDDNumero($telefone)
	{
		$telefone = str_replace(array('(', ')', '-', '.', '/'), '', $telefone);
		$telefone = explode(' ', $telefone);
		return $telefone;
	}

	private function mySubstr($string, $start = 0, $limit = 10)
	{
		if (function_exists("mb_substr")) {
			$string = mb_substr($string, $start, $limit, 'UTF-8');
		} else {
			$string = utf8_encode(substr(utf8_decode($string), $start, $limit));
		}

		return $string;
	}

	private function paymentResultXml($data)
	{
		// Creating an xml parser
		$xmlParser = new PagSeguroXmlParser($data);

		// Verifying if is an XML
		if ($xml = $xmlParser->getResult()) {
			return $xml;
		} else {
			throw new Exception("PagSeguro Boleto: [{$data}] is not an XML");
		}
	}

}
