<?php
	if(!isset($_SESSION)) session_start();
	//require_once "modelos/cfdi.php";
	//require_once "modelos/pagos.php";
	require_once "modelos/bd.php";
	require_once "config.php";
	require_once "ws_conexion.php";
	header('Content-Type: application/json');
	
	//Se toman parametros recibidos
	$json = file_get_contents('php://input');
	$data = json_decode($json);
	
	if (strlen($json) > 5){
		$pAccion = $data->pAccion;
	} else {
		$pAccion = "0";
	}
	
	//Invocamos armado segun tipo de parametro recibido
	switch ($pAccion) {
		
		case 'cancelacion_emision':
		
			$pUUID = $data->pUUID;
			$pRFCEmisor = $data->pRFCEmisor;
			$pRFCReceptor = $data->pRFCReceptor;
			$pTotal = $data->pTotal;
			$pIdEmpresa = $data->pIdEmpresa;
			$pTipoSistema = $data->pTipoSistema;
			$pIdFactura = $data->pIdFactura;
			$pTipoFactura = $data->pTipoFactura;
		
			$response = cancelacion_emision($pUUID, $pRFCEmisor, $pRFCReceptor, $pTotal, $pIdEmpresa, $pTipoSistema, $pIdFactura, $pTipoFactura, $conn);
			echo json_encode($response);
			break;
			
		default:
			echo json_encode("La peticion recibida es incorrecta, intente nuevamente");
			break;
	}
	
	/////////////////////////////////////////////////////////////////////////////////
	////			1		CANCELACION EMISION									/////
	/////////////////////////////////////////////////////////////////////////////////
	
	
	function cancelacion_emision($uuid, $rfcemisor, $rfcreceptor, $total, $idempresa, $tiposistema, $idfactura, $tipofactura, $conn){
		$mensaje = "";
		try {		
			$ftotal = floatval($total);
			
			$mensaje = "Error al obtener los datos de configuración de timbrado de Base de Datos";
			//0 - Obtener parametros de configuración de BD
			$smt = $conn->prepare("call setivera_facturacion.obtener_parametros_pac()");
			$smt->execute();	
				
			$numRegistrosDetalle = $smt->rowCount();
			$datosPAC = [];
			
			if($numRegistrosDetalle > 0) {
				while($row = $smt->fetch(PDO::FETCH_ASSOC)) { 
					$respuesta = new respuesta_configuracion_pac();
					$respuesta->token = $row["token"];
					$respuesta->pem_cer = $row["pem_cer"];
					$respuesta->pem_key = $row["pem_key"];
					$respuesta->logo = $row["logo"];
					$respuesta->url_ws = $row["url_ws"];
					$respuesta->pem_pwd = $row["pem_pwd"];
					$datosPAC[] = $respuesta;
				};
				$smt->closeCursor();
			} else {
				return "No se pudieron obtener los datos del detalle del CFDI";
			}
			
			//1 - Consultar estado del comprobante
			$mensaje = "Error al consultar el estado del comprobante ante SAT";
			$objConexion = new Conexion($datosPAC[0]->url_ws);
			$consultaEstadoSAT = json_decode($objConexion->operacion_consultarEstadoSAT($datosPAC[0]->token, $uuid, $rfcemisor, $rfcreceptor, $ftotal));
			//return Utf8_ansi(json_encode($consultaEstadoSAT));
			
			//2 - Determinar el tipo de cancelacion a solicitar
			
			if ($consultaEstadoSAT->Estado == "Vigente"){
				if ($consultaEstadoSAT->EsCancelable == "Cancelable sin aceptación"){
					$respuestaCancelacion = SolicitarCancelacionCFDI($datosPAC, $uuid, $rfcemisor, $rfcreceptor, $ftotal);
					
					$responsews = new wsuniversalresponse();
					if ($respuestaCancelacion == null){
						
						$responsews->estado = 0;
						$responsews->datos = null;
						$responsews->mensaje = "Se intentó cancelar este comprobante CANCELABLE SIN ACEPTACIÓN pero no se obtuvo respuesta del PAC. Intente nuevamente";
						
						return json_encode($responsews);
					} else {
						if ($respuestaCancelacion->status == "success"){
							$resultadoActualizacionBD = emision_facturas_asignar_cancelada($uuid, 1, $respuestaCancelacion->acuse, date("d/m/Y H:i:s"), $conn);
							if ($resultadoActualizacionBD == 1){
									$responsews->estado = 1;
								$responsews->datos = $respuestaCancelacion->acuse;
								$responsews->mensaje = $respuestaCancelacion->message;
							} else {
								$responsews->estado = 0;
								$responsews->datos = $respuestaCancelacion->acuse;
								$responsews->mensaje = "Se canceló correctamente el comprobante sin aceptación, pero no se pudo guardar el resultado en Base de datos (emision_facturas_asignar_cancelada)";
							}
							return json_encode($responsews);
						} else {
							$responsews->estado = 0;
							$responsews->datos = null;
							$responsews->mensaje = $respuestaCancelacion->message;
							return json_encode($responsews);
						}
					}
					
				} else {
					if ($consultaEstadoSAT->EsCancelable == "Cancelable con aceptación"){
						$respuestaCancelacion = SolicitarCancelacionCFDI($datosPAC, $uuid, $rfcemisor, $rfcreceptor, $ftotal);
						
						$responsews = new wsuniversalresponse();
						if ($respuestaCancelacion == null){
							
							$responsews->estado = 0;
							$responsews->datos = null;
							$responsews->mensaje = "Se intentó cancelar este comprobante CANCELABLE CON ACEPTACIÓN pero no se obtuvo respuesta del PAC. Intente nuevamente";
							return json_encode($responsews);
						} else {
							if ($respuestaCancelacion->status == "success"){
								//confirmación de solicitud de cancelación
								$resultadoActualizacionBD = emision_facturas_asignar_cancelada($uuid, 2, $respuestaCancelacion->acuse, date("d/m/Y H:i:s"), $conn);
								
								if ($resultadoActualizacionBD == 1){
									$resultadoActualizacionBD2 = facturas_asignar_pendiente_cancelar($idempresa, $tiposistema, $idfactura, $tipofactura, $conn);
									
									if ($resultadoActualizacionBD2 == 1){
										$responsews->estado = 1;
										$responsews->datos = $respuestaCancelacion->acuse;
										$responsews->mensaje = $respuestaCancelacion->message;
									} else {
										$responsews->estado = 0;
										$responsews->datos = $respuestaCancelacion->acuse;
										$responsews->mensaje = "Se envió correctamente la solicitud de cancelación a buzón tributario del receptor, pero hubo un error al ejecutar (facturas_asignar_pendiente_cancelar)";
									}
								} else {
									$responsews->estado = 0;
									$responsews->datos = $respuestaCancelacion->acuse;
									$responsews->mensaje = "Se envió correctamente la solicitud de cancelación a buzón tributario del receptor, pero hubo un error al ejecutar (emision_facturas_asignar_cancelada)";
								}
								
								return json_encode($responsews);
							} else {
								//error de cancelación
								$responsews->estado = 0;
								$responsews->datos = null;
								$responsews->mensaje = $respuestaCancelacion->message;
								return json_encode($responsews);
							}
						}
					} else {
						if ($consultaEstadoSAT->EsCancelable == "No Cancelable"){
							//Comprobante no cancelable. Se envia estado 0 a BD
							$resultadoActualizacionBD = emision_facturas_asignar_cancelada($uuid, 0, "", date("d/m/Y H:i:s"), $conn);
							$responsews = new wsuniversalresponse();
							if ($resultadoActualizacionBD == 1){
								$responsews->estado = 0;
								$responsews->datos = null;
								$responsews->mensaje = "Según el SAT, el comprobante no es cancelable.";
							} else {
								$responsews->estado = 0;
								$responsews->datos = null;
								$responsews->mensaje = "Según el SAT, el comprobante no es cancelable. No se pudo revertir la solicitud de cancelación en BD (emision_facturas_asignar_cancelada)";
							}
							return json_encode($responsews);
						}
					}
				}
			} else {
				if ($consultaEstadoSAT->Estado == "Cancelado"){
					if ($consultaEstadoSAT->EstatusCancelacion == "Cancelado sin aceptación" || $consultaEstadoSAT->EstatusCancelacion == "Cancelado con aceptación"){
						//El comprobante se cancelo en un intento previo. Se actualiza BD para reflejar el cambio
							$resultadoActualizacionBD = emision_facturas_asignar_cancelada($uuid, 1, "", date("d/m/Y H:i:s"), $conn);
							$responsews = new wsuniversalresponse();
							if ($resultadoActualizacionBD == 1){
								$responsews->estado = 1;
								$responsews->datos = null;
								$responsews->mensaje = "El comprobante ya fue cancelado anteriormente o el receptor aceptó la cancelación por buzón tributario. Se actualiza estado de cancelación del CFDI";
							} else {
								$responsews->estado = 0;
								$responsews->datos = null;
								$responsews->mensaje = "El comprobante ya habia sido cancelado con anterioridad o el receptor aceptó la cancelación por buzón tributario, pero no se pudo actualizar el estado de cancelación del CFDI en BD (emision_facturas_asignar_cancelada)";
							}
							return json_encode($responsews);
					} else {						
						if ($consultaEstadoSAT->EstatusCancelacion == "Plazo vencido"){
							//Se canceló mediante buzón tributario a raiz de un intento anterior SIN RESPUESTA EN 3 DIAS HABILES
							$resultadoActualizacionBD = emision_facturas_asignar_cancelada($uuid, 1, "", date("d/m/Y H:i:s"), $conn);
							$responsews = new wsuniversalresponse();
							if ($resultadoActualizacionBD == 1){
								$responsews->estado = 1;
								$responsews->datos = null;
								$responsews->mensaje = "La solicitud de cancelación fue aprobada por el SAT a falta de respuesta del receptor en 3 días habiles";
							} else {
								$responsews->estado = 0;
								$responsews->datos = null;
								$responsews->mensaje = "La solicitud de cancelación fue aprobada por el SAT a falta de respuesta del receptor en 3 días habiles, pero no se pudo actualizar el estado de cancelación del CFDI en BD (emision_facturas_asignar_cancelada)";
							}
							return json_encode($responsews);
						}
					}
				} else {
					if ($consultaEstadoSAT->Estado == "No Encontrado"){
						////Se intentó cancelar un CFDI inexistente o que aun no aparece como timbrado ante el SAT.
						//Comprobante no cancelable. Se envia estado 0 a BD
						$resultadoActualizacionBD = emision_facturas_asignar_cancelada($uuid, 0, "", date("d/m/Y H:i:s"), $conn);
						$responsews = new wsuniversalresponse();
						if ($resultadoActualizacionBD == 1){
							$responsews->estado = 0;
							$responsews->datos = null;
							$responsews->mensaje = "El comprobante con el UUID y datos especificados NO fue encontrado por el SAT. Revise los valores enviados e intente de nuevo. Se revirtió la solicitud de cancelación";
						} else {
							$responsews->estado = 0;
							$responsews->datos = null;
							$responsews->mensaje = "El comprobante con el UUID y datos especificados NO fue encontrado por el SAT. Revise los valores enviados e intente de nuevo. No se pudo revertir la solicitud dec cancelación en BD (emision_facturas_asignar_cancelada)";
						}
						return json_encode($responsews);
					} else {
						//Otro tipo de error, revisar respuesta y mensaje personalizado
							return json_encode($consultaEstadoSAT);
					}
				}
				
			}
		} catch (Exception $e){
			return "Error en obtención de datos de BD para petición de timbrado: " . $e . ": " . $mensaje;
		}
	}
	
	function emision_facturas_asignar_cancelada($uuid, $estadoCancelacion, $acuseCancelacion, $fechaCancelacion, $conn){
		$stmt3 = $conn->prepare("call setivera_facturacion.emision_facturas_asignar_cancelada('$uuid','$estadoCancelacion','$acuseCancelacion','$fechaCancelacion')");
		$stmt3->execute();	
			
		$numRegistrosGuardado = $stmt3->rowCount();
		if($numRegistrosGuardado > 0) {
			while($row = $stmt3->fetch(PDO::FETCH_ASSOC)) {
				$pTransaccionGuardado = $row["Transaccion"];
				$pMensajeGuardado = $row["Mensaje"];
			};
			$stmt3->closeCursor();
			return intval($pTransaccionGuardado);
		} else {
			return 0;
		}
	}
	
	function SolicitarCancelacionCFDI($datosPAC, $uuid, $rfcEmisor, $rfcReceptor, $total){
		$objConexion = new Conexion($datosPAC[0]->url_ws);
		$token = $datosPAC[0]->token;
		$keyCSD = base64_encode( file_get_contents($datosPAC[0]->pem_key) );
		$cerCSD = base64_encode( file_get_contents($datosPAC[0]->pem_cer) );
		$passCSD = $datosPAC[0]->pem_pwd;
		$resultadoCancelacion = json_decode($objConexion->operacion_cancelar($token, $keyCSD, $cerCSD, $passCSD, $uuid, $rfcEmisor, $rfcReceptor, $total));
		return $resultadoCancelacion;
	}
	
	//funcion auxiliar para limpiar caracteres escapados de la respuesta de cancelación del WS
	function Utf8_ansi($valor='') {
		$utf8_ansi2 = array(
		"\u00c0" =>"À",
		"\u00c1" =>"Á",
		"\u00c2" =>"Â",
		"\u00c3" =>"Ã",
		"\u00c4" =>"Ä",
		"\u00c5" =>"Å",
		"\u00c6" =>"Æ",
		"\u00c7" =>"Ç",
		"\u00c8" =>"È",
		"\u00c9" =>"É",
		"\u00ca" =>"Ê",
		"\u00cb" =>"Ë",
		"\u00cc" =>"Ì",
		"\u00cd" =>"Í",
		"\u00ce" =>"Î",
		"\u00cf" =>"Ï",
		"\u00d1" =>"Ñ",
		"\u00d2" =>"Ò",
		"\u00d3" =>"Ó",
		"\u00d4" =>"Ô",
		"\u00d5" =>"Õ",
		"\u00d6" =>"Ö",
		"\u00d8" =>"Ø",
		"\u00d9" =>"Ù",
		"\u00da" =>"Ú",
		"\u00db" =>"Û",
		"\u00dc" =>"Ü",
		"\u00dd" =>"Ý",
		"\u00df" =>"ß",
		"\u00e0" =>"à",
		"\u00e1" =>"á",
		"\u00e2" =>"â",
		"\u00e3" =>"ã",
		"\u00e4" =>"ä",
		"\u00e5" =>"å",
		"\u00e6" =>"æ",
		"\u00e7" =>"ç",
		"\u00e8" =>"è",
		"\u00e9" =>"é",
		"\u00ea" =>"ê",
		"\u00eb" =>"ë",
		"\u00ec" =>"ì",
		"\u00ed" =>"í",
		"\u00ee" =>"î",
		"\u00ef" =>"ï",
		"\u00f0" =>"ð",
		"\u00f1" =>"ñ",
		"\u00f2" =>"ò",
		"\u00f3" =>"ó",
		"\u00f4" =>"ô",
		"\u00f5" =>"õ",
		"\u00f6" =>"ö",
		"\u00f8" =>"ø",
		"\u00f9" =>"ù",
		"\u00fa" =>"ú",
		"\u00fb" =>"û",
		"\u00fc" =>"ü",
		"\u00fd" =>"ý",
		"\u00ff" =>"ÿ");

		return strtr($valor, $utf8_ansi2);      

	}
		
?>