<?php
require_once (DIR_SYSTEM . "library/Cielo/config.php");

class ModelPaymentCielo extends Model {

	public function getMethod($address, $total) {

		$this->load->language('payment/cielo');

		$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "zone_to_geo_zone WHERE geo_zone_id = '" . (int)$this->config->get('cielo_geo_zone_id') . "' AND country_id = '" . (int)$address['country_id'] . "' AND (zone_id = '" . (int)$address['zone_id'] . "' OR zone_id = '0')");

		if (strtoupper($this->currency->getCode()) != 'BRL') {
			$status = false;
		} elseif ($this->config->get('cielo_total') > round($total,2)) {
			$status = false;
		} elseif (!$this->config->get('cielo_geo_zone_id')) {
			$status = true;
		} elseif ($query->num_rows) {
			$status = true;
		} else {
			$status = false;
		}

		// verifica se existe algum cartao ativado
		$cartoes_ativados = $this->getCartoesAtivados($total);

		// nao exibe a opcao caso nao encontre cartoes ativados
		if(count($cartoes_ativados) == 0){
			$status = false;
		}

		$method_data = array();

		if ($status) {
			$this->session->data['cielo_total'] = $total;

			$language_id = $this->config->get('config_language_id');

			$titulo = $this->config->has('cielo_title') ? $this->config->get('cielo_title') : array();
			$titulo = isset($titulo[$language_id]) ? trim($titulo[$language_id]) : '';
			$titulo = ($titulo != '') ? $titulo : $this->language->get('text_title');

			$method_data = array(
				'code'       => 'cielo',
				'title'      => $titulo,
				'terms'      => '',
				'sort_order' => $this->config->get('cielo_sort_order')
			);
		}

		return $method_data;
	}










	public function addTransaction($dados){
		$this->db->query("INSERT INTO " . DB_PREFIX . "cielo_transacoes(
			tid,
			code,
			order_id,
			valor,
			datahora,
			bandeira,
			produto,
			parcelas,
			autorizar,
			capturar,
			status,
			finalizada
		) VALUES(
			'". (string)$dados['tid'] ."',
			'". (string)$dados['code'] ."',
			". (int)$dados['order_id'] .",
			". (float)$dados['valor'] .",
			'". (string)$dados['datahora'] ."',
			'". (string)$dados['bandeira'] ."',
			'". (string)$dados['produto'] ."',
			". (int)$dados['parcelas'] .",
			". (int)$dados['autorizar'] .",
			". (int)$dados['capturar'] .",
			0,
			0
		)");
	}

	public function updateTransaction($tid, $status){
		$this->db->query("INSERT INTO " . DB_PREFIX . "cielo_consultas(tid, status, datahora) VALUES('". (string) $tid ."',". (int) $status .",'". date('Y-m-d H:i:s') ."')");
		$this->db->query("UPDATE " . DB_PREFIX . "cielo_transacoes SET status = ". (int) $status ." WHERE tid = '". (string) $tid ."'");
	}

	public function finalizaTransaction($tid){
		$this->db->query("UPDATE " . DB_PREFIX . "cielo_transacoes SET finalizada = 1 WHERE tid = '". (string) $tid ."'");
	}

	public function getTransactionByCode($code){
		$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "cielo_transacoes WHERE code = '". (string) $code ."'");
		return $query->row;
	}










	public function getCartoesAtivados($total = 0){
		$cartoes = array();

		foreach($GLOBALS['CIELO_BANDEIRAS_DISPONIVEIS'] as $cartao){
			// verifica se esta ativado
			if($this->config->get("cielo_{$cartao}_ativar") == '1'){
				// valida o valor minimo para ativacao
				if($this->validaValorMinimo($cartao, $total)){
					$cartoes[] = $cartao;
				}
			}
		}

		return $cartoes;
	}





	public function validaCartao($cartao){
		$cond = TRUE;

		// valida se o cartao escolhido existe
		if( !in_array($cartao, $GLOBALS['CIELO_BANDEIRAS_DISPONIVEIS']) ){
			$cond = FALSE;

		// valida se o cartao escolhido esta ativado
		}elseif($this->config->get("cielo_{$cartao}_ativar") != '1'){
			$cond = FALSE;
		}

		return $cond;
	}





	public function validaParcelamento($cartao, $parcelas){
		$cond = TRUE;

		if($this->config->get("cielo_{$cartao}_parcelamento") == '0'){
			// se o parcelamento estiver desativado aceita somente pagamento a vista
			// portanto o numero de parcelas nao pode ser diferente de 1
			if($parcelas != 1){
				$cond = FALSE;
			}
		}else{
			// se o parcelamento estiver ativado o numero de parcelas nao pode ser maior
			// que o numero maximo permitido e nem menor que o numero minimo permitido
			if($parcelas > $this->config->get("cielo_{$cartao}_max_parcelas") OR $parcelas < $GLOBALS['CIELO_MINIMO_PARCELAS'] OR $parcelas > $GLOBALS['CIELO_MAXIMO_PARCELAS']){
				$cond = FALSE;
			}
		}

		return $cond;
	}





	public function validaValorMinimo($cartao, $total){
		$cond = TRUE;

		if( !is_numeric($total) ){
			$cond = FALSE;
		}elseif( !is_numeric($this->config->get("cielo_{$cartao}_valor_minimo")) ){
			$cond = FALSE;
		}elseif($this->config->get("cielo_{$cartao}_valor_minimo") > $total){
			$cond = FALSE;
		}

		return $cond;
	}





	public function calculaParcelas($cartao, $total){
		$opcoes_parcelamento = array();

		$desconto = $this->config->get("cielo_{$cartao}_desconto");
		$parcelamento = $this->config->get("cielo_{$cartao}_parcelamento");
		$parcela_minima = $this->config->get("cielo_{$cartao}_parcela_minima");
		$max_parcelas = $this->config->get("cielo_{$cartao}_max_parcelas");
		$parcelas_sem_juros = $this->config->get("cielo_{$cartao}_parcelas_sem_juros");
		$parcelas_juros_loja = $this->config->get("cielo_{$cartao}_parcelas_juros_loja");
		$taxa_juros = $this->config->get("cielo_{$cartao}_juros");
		$calculo_juros = $this->config->get("cielo_{$cartao}_calculo_juros");

		if(!is_numeric($desconto)){ $desconto = 0; }
		if($max_parcelas < $GLOBALS['CIELO_MINIMO_PARCELAS']){ $max_parcelas = $GLOBALS['CIELO_MINIMO_PARCELAS']; }
		if($max_parcelas > $GLOBALS['CIELO_MAXIMO_PARCELAS']){ $max_parcelas = $GLOBALS['CIELO_MAXIMO_PARCELAS']; }

		if($parcelamento == '0'){
			$parcela_minima = $GLOBALS['CIELO_PARCELA_MINIMA'];
			$max_parcelas = 1;
			$parcelas_sem_juros = 1;
			$parcelas_juros_loja = 0;
			$taxa_juros = 0;
		}

		$this->language->load('payment/cielo');
		$text_opcao_parcela_d = $this->language->get('text_opcao_parcela_d');
		$text_opcao_parcela_sj = $this->language->get('text_opcao_parcela_sj');
		$text_opcao_parcelas_sj = $this->language->get('text_opcao_parcelas_sj');
		$text_opcao_parcela_cjl = $this->language->get('text_opcao_parcela_cjl');
		$text_opcao_parcelas_cjl = $this->language->get('text_opcao_parcelas_cjl');
		$text_opcao_parcela_cja = $this->language->get('text_opcao_parcela_cja');
		$text_opcao_parcelas_cja = $this->language->get('text_opcao_parcelas_cja');

		for($p=1; $p<=$max_parcelas; $p++){

			$descricao = '';
			$p_desconto = 0;
			$valor_desconto = 0;
			$p_juros = 0;
			$valor_juros = 0;
			$p_total = $total;

			if($p <= $parcelas_sem_juros){
				// sem juros
				$p_tipo = 'sj';

				$valor_parcela = $total / $p;

			}elseif($p <= $parcelas_juros_loja){
				// com juros pela loja
				$p_tipo = 'cjl';
				$p_juros = $taxa_juros;

				if ($calculo_juros == 1) {
					$p_total = $this->calcularJurosBacen($total, $p_juros, $p);
				}elseif ($calculo_juros == 3) {
					$p_total = $this->calcularJurosComposto($total, $p_juros, $p);
				}else{
					$p_total = $this->calcularJurosSimples($total, $p_juros, $p);
				}

				$valor_juros = $p_total - $total;
				$valor_parcela = $p_total / $p;


			}else{
				// com juros pela administradora
				$p_tipo = 'cja';

				$valor_parcela = $total / $p;
			}

			// cancela se o valor da parcela for menor que o permitido
			if($p > 1 AND ($valor_parcela < $parcela_minima OR $valor_parcela < $GLOBALS['CIELO_PARCELA_MINIMA'])){
				continue;
			}

			// verifica o desconto quando a vista
			if($p == 1){
				if($desconto > 0){
					$p_tipo = 'd';
					$p_desconto = $desconto;
					$valor_desconto = ($valor_parcela / 100) * $p_desconto;
					$valor_parcela -= $valor_desconto;
					if($valor_parcela < 0.01){ $valor_parcela = 0.01; }
					$p_total = $valor_parcela;
				}
			}

			// monta descricao da parcela
			$valor_formatado = $this->currency->format($valor_parcela, 'BRL');
			$p_desconto_formatado = number_format($p_desconto, 2, $this->language->get('decimal_point'), $this->language->get('thousand_point'));
			$p_juros_formatado = number_format($p_juros, 2, $this->language->get('decimal_point'), $this->language->get('thousand_point'));

			if($p == 1){
				if($p_tipo == 'd'){
					$descricao = sprintf($text_opcao_parcela_d, $p, $valor_formatado, $p_desconto_formatado);
				}elseif($p_tipo == 'sj'){
					$descricao = sprintf($text_opcao_parcela_sj, $p, $valor_formatado);
				}elseif($p_tipo == 'cjl'){
					$descricao = sprintf($text_opcao_parcela_cjl, $p, $valor_formatado, $p_juros_formatado);
				}elseif($p_tipo == 'cja'){
					$descricao = sprintf($text_opcao_parcela_cja, $p);
				}
			}else{
				if($p_tipo == 'sj'){
					$descricao = sprintf($text_opcao_parcelas_sj, $p, $valor_formatado);
				}elseif($p_tipo == 'cjl'){
					$descricao = sprintf($text_opcao_parcelas_cjl, $p, $valor_formatado, $p_juros_formatado);
				}elseif($p_tipo == 'cja'){
					$descricao = sprintf($text_opcao_parcelas_cja, $p);
				}
			}

			$opcoes_parcelamento[$p] = array(
				'tipo' => $p_tipo,
				'descricao' => $descricao,
				'valor' => $valor_parcela,
				'desconto' => $p_desconto,
				'valor_desconto' => $valor_desconto,
				'juros' => $p_juros,
				'valor_juros' => $valor_juros,
				'total' => $p_total
			);
		}

		return $opcoes_parcelamento;

	} // calculaParcelas





	public function calcularJurosSimples($valor_a_parcelar , $taxa_de_juros, $numero_de_parcelas) {
		$taxa_de_juros = $taxa_de_juros / 100;
		return $valor_a_parcelar * (1 + $taxa_de_juros * $numero_de_parcelas);
	}

	public function calcularJurosComposto($valor_a_parcelar, $taxa_de_juros, $numero_de_parcelas) {
		$taxa_de_juros = $taxa_de_juros / 100;
		return $valor_a_parcelar * pow((1 + $taxa_de_juros), $numero_de_parcelas);
	}

	public function calcularJurosBacen($valor_a_parcelar, $taxa_de_juros, $numero_de_parcelas) {
		// Utilizando a metodologia (formula) do Banco Central (tabela Price) disponivel em:
		// https://www3.bcb.gov.br/CALCIDADAO/publico/exibirMetodologiaFinanciamentoPrestacoesFixas.do?method=exibirMetodologiaFinanciamentoPrestacoesFixas
		// Desenvolvido por Eric Mariano Endo - Hotel da WEB
		$taxa_de_juros = $taxa_de_juros / 100;
		$valor_da_parcela = ($valor_a_parcelar * $taxa_de_juros) / (1 - pow((1 + $taxa_de_juros), -$numero_de_parcelas));
		return $valor_da_parcela * $numero_de_parcelas;
	}





	public function requisicaoTransacao($cartao, $parcelas, $total, $order_id, $url_retorno){
		require_once (DIR_SYSTEM . "library/Cielo/cielo.php");
		require_once (DIR_SYSTEM . "library/Cielo/pedido.php");
		require_once (DIR_SYSTEM . "library/Cielo/logger.php");

		$parcelas_sem_juros = $this->config->get("cielo_{$cartao}_parcelas_sem_juros");
		$parcelas_juros_loja = $this->config->get("cielo_{$cartao}_parcelas_juros_loja");
		$captura_automatica = $this->config->get("cielo_{$cartao}_captura_automatica");
		$tipo_autorizacao = $this->config->get("cielo_{$cartao}_tipo_autorizacao");

		// verifica se eh debito e retorna TRUE/FALSE
		$debito = cieloCheckIsDebit($cartao);

		// se for debito troca para a bandeira correspondente, ex: maestro = mastercard
		$cartao = cieloDebitToCredit($cartao);

		$Pedido = new Pedido();

		$Pedido->dadosEcNumero      = $this->config->get("cielo_afiliacao");
		$Pedido->dadosEcChave       = $this->config->get("cielo_chave");

		$Pedido->dadosPedidoNumero  = $order_id;
		$Pedido->dadosPedidoValor   = preg_replace('/[^0-9]/', '', number_format($total, 2, '', ''));

		$Pedido->capturar           = ($captura_automatica == '1') ? TRUE : FALSE;
		$Pedido->autorizar          = $tipo_autorizacao;

		$Pedido->formaPagamentoBandeira = $cartao;

		if($debito){
			$Pedido->formaPagamentoProduto = "A"; // A = debito
			$Pedido->formaPagamentoParcelas = 1;
		}else{
			if($parcelas == 1){
				$Pedido->formaPagamentoProduto = 1; // 1 = credito a vista
			}else{
				if($parcelas <= $parcelas_sem_juros OR $parcelas <= $parcelas_juros_loja){
					$Pedido->formaPagamentoProduto = 2; // 2 = parcelado loja
				}else{
					$Pedido->formaPagamentoProduto = 3; // 3 = parcelado administradora
				}
			}
			$Pedido->formaPagamentoParcelas = $parcelas;
		}

		$Pedido->urlRetorno = $url_retorno;

		return $Pedido->RequisicaoTransacao(FALSE);

	} // requisicaoTransacao





	public function requisicaoConsulta($tid) {
		require_once (DIR_SYSTEM . "library/Cielo/cielo.php");
		require_once (DIR_SYSTEM . "library/Cielo/pedido.php");
		require_once (DIR_SYSTEM . "library/Cielo/logger.php");

		$Pedido = new Pedido();
		$Pedido->dadosEcNumero  = $this->config->get("cielo_afiliacao");
		$Pedido->dadosEcChave   = $this->config->get("cielo_chave");
		$Pedido->tid            = $tid;

		return $Pedido->RequisicaoConsulta();

	} // requisicaoConsulta

}
