<?php
namespace App\Http\Controllers;

use App\Custom\SQLConnection;
use App\Custom\Misc;

use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Request;

use DateTime;

class AsignacionCuitsController extends Controller {

	public static $params = [];
	public static $integrante = [];
	public static $sociedad = [];
	public static $process = [];

	public static function inicializarParametros($id, $es_sociedad = null) {
		self::$params['id_sociedades_constituciones'] = $id;
		self::$params['es_sociedad'] = $es_sociedad;
		self::$params['buscado_por_cuit'] = null;
		self::$params['buscado_por_dni'] = null;
		self::$params['buscado_por_nombre'] = null;
		self::$params['buscado_por_domicilio'] = null;
		self::$params['encontrado_por_cuit'] = null;
		self::$params['encontrado_por_dni'] = null;
		self::$params['encontrado_por_nombre'] = null;
		self::$params['encontrado_por_domicilio'] = null;
		self::$params['cuit_procesar'] = null;
		self::$params['documemto_limpio'] = null;
		self::$params['nombre_limpio'] = null;
		self::$params['domicilio_limpio'] = null;
		self::$params['procesado'] = null;
		self::$params['multiplicidad_por_cuit'] = null;
		self::$params['multiplicidad_por_dni'] = null;
		self::$params['multiplicidad_por_nombre'] = null;
		self::$params['multiplicidad_por_domicilio'] = null;
		self::$params['error'] = null;
		self::$params['mensaje'] = null;
	}

	public function AsignarCuits() {
		$datetime1 = new DateTime();
		$process['sociedades'] = self::AsignarCuitsSociedades();
		$process['integrantes'] = self::AsignarCuitsIntegrantes();
		$process['integrantes_2da_fase'] = self::AsignarCuitsIntegrantes(2);
		$datetime2 = new DateTime();
		$process['tiempo_de_ejecucion'] = $datetime1->diff($datetime2);
		// dd($process);
	}

	public static function AsignarCuitsSociedades() {
		$sociedades = [];
		self::$process['completados'] = 0;
		self::$process['no_completados_por_multiplicidad'] = 0;
		self::$process['no_encontrados'] = 0;
		self::$process['ya_procesados_anteriormente'] = 0;
		self::$process['total'] = 0;
		self::$process['errores'] = [];
		$sociedades = SQLConnection::backendStoreProcedure('backend_obtener_sociedades_SC', array());
		if (is_array($sociedades) && count($sociedades) > 0) {
			self::$process['total'] = count($sociedades);
			foreach ($sociedades as self::$sociedad) {
				self::inicializarParametros(self::$sociedad->id, 1);
				if (!empty(self::$sociedad->nombre && !isset(self::$sociedad->flag))) {
					$razon_social = self::$sociedad->nombre;
					$diccionario = Misc::diccionarioRazonesSociales(self::$sociedad->nombre);
					$diccionario = is_array($diccionario) ? $diccionario : [self::$sociedad->nombre];
					foreach ($diccionario as self::$sociedad->nombre) {
						if (self::$params['procesado'] != 1 && !empty(self::$sociedad->nombre)) {
							$busqueda = self::busquedaPorRazonSocial(self::$sociedad->nombre);
							self::procesarResultados($busqueda, 'nombre');
						}
						if (self::$params['procesado'] != 1 && self::$params['multiplicidad_por_nombre'] == 1 && !empty(self::$sociedad->nombre) && !empty(self::$sociedad->domicilio)) {
							$busqueda = self::busquedaPorRazonSocialYDomicilio(self::$sociedad->nombre, self::$sociedad->domicilio);
							self::procesarResultados($busqueda, 'domicilio');
						}
						if (self::$params['procesado'] != 1 && self::$params['multiplicidad_por_nombre'] == 1 && !empty(self::$sociedad->nombre) && !empty(self::$sociedad->provincia) && !empty(self::$sociedad->localidad)) {
							$localidad = Misc::limpiarString(self::$sociedad->localidad);
							$provincia = Misc::limpiarString(self::$sociedad->provincia);
							$busqueda = SQLConnection::backendStoreProcedure('backend_busqueda_padron_asociativa', array(self::$params['nombre_limpio'], null, $localidad, $provincia, null, null, null, null, null));
							self::procesarResultados($busqueda, 'otro');
						}
					}
					if (self::$params['procesado'] != 1) {
						$multiplicidad = self::$params['multiplicidad_por_cuit'] + self::$params['multiplicidad_por_dni'] + self::$params['multiplicidad_por_nombre'] + self::$params['multiplicidad_por_domicilio'];
						if ($multiplicidad > 0) {
							self::$params['nombre_limpio'] = Misc::limpiarString($razon_social);
							$res = SQLConnection::backendStoreProcedure('backend_procesar_log_en_asignar_cuits_SC', array_values(self::$params), true);
							if (isset($res->id)) {
								self::$process['no_completados_por_multiplicidad']++;
							} else {
								self::registrarError($res);
							}
						} else {
							self::$process['no_encontrados']++;
						}
					}
					$aux_params = [
						'id' => self::$sociedad->id,
						'flag_soc' => 'B',
						'flag_int' => null,
					];
					$exec = SQLConnection::backendStoreProcedure('backend_procesar_flag_SC', array_values($aux_params));
				}
			}
		}
		return self::$process;
	}

	public static function AsignarCuitsIntegrantes($fase = 1) {
		$stored_procedure = ($fase == 1) ? 'backend_busqueda_padron_asociativa' : 'backend_busqueda_padron_asociativa_2da_fase';
		$integrantes = [];
		self::$process['completados'] = 0;
		self::$process['no_completados_por_multiplicidad'] = 0;
		self::$process['no_encontrados'] = 0;
		self::$process['ya_procesados_anteriormente'] = 0;
		self::$process['total'] = 0;
		self::$process['errores'] = [];
		$integrantes = SQLConnection::backendStoreProcedure('backend_obtener_integrantes_SC', array());
		if (is_array($integrantes) && count($integrantes) > 0) {
			self::$process['total'] = count($integrantes);
			foreach ($integrantes as self::$integrante) {
				self::inicializarParametros(self::$integrante->id, 0);
				if (!isset(self::$integrante->flag)) {
					if (!empty(self::$integrante->cuit_1)) {
						$busqueda = self::busquedaPorCuit(self::$integrante->cuit_1);
						self::procesarResultados($busqueda, 'cuit');
					}
					if (self::$params['procesado'] != 1 && !empty(self::$integrante->cuit_2)) {
						$busqueda = self::busquedaPorCuit(self::$integrante->cuit_2);
						self::procesarResultados($busqueda, 'cuit');
					}
					if (self::$params['procesado'] != 1 && !empty(self::$integrante->documento_1)) {
						$busqueda = self::busquedaPorDNI(self::$integrante->documento_1);
						self::procesarResultados($busqueda, 'dni');
					}
					if (self::$params['procesado'] != 1 && !empty(self::$integrante->documento_2)) {
						$busqueda = self::busquedaPorDNI(self::$integrante->documento_2);
						self::procesarResultados($busqueda, 'dni');
					}
					if (self::$params['procesado'] != 1 && !empty(self::$integrante->nombre) && !empty(self::$integrante->domicilio)) {
						$busqueda = self::busquedaPorNombreYDomicilio(self::$integrante->nombre, self::$integrante->domicilio, $fase);
						self::procesarResultados($busqueda, 'domicilio');
					}
					if (self::$params['procesado'] != 1 && self::$params['multiplicidad_por_domicilio'] == 1 && !empty(self::$integrante->nombre) && !empty(self::$integrante->domicilio)) {
						if (!empty(self::$integrante->fecha_nac)) {
							$fecha_nac = self::limpiarParametro(self::$integrante->fecha_nac);
							$busqueda = SQLConnection::backendStoreProcedure($stored_procedure, array(null, self::$params['domicilio_limpio'], null, null, self::$params['nombre_limpio'], $fecha_nac, null, null, null));
							self::procesarResultados($busqueda, 'otro');
						}
						if (self::$params['procesado'] != 1 && !empty(self::$integrante->profesion)) {
							$profesion = strtoupper(Misc::limpiarString(self::$integrante->profesion));
							$busqueda = SQLConnection::backendStoreProcedure($stored_procedure, array(null, self::$params['domicilio_limpio'], null, null, self::$params['nombre_limpio'], null, $profesion, null, null));
							self::procesarResultados($busqueda, 'otro');
						}
					}
					if (self::$params['procesado'] != 1 && self::$params['multiplicidad_por_nombre'] == 1 && !empty(self::$integrante->nombre)) {
						if (!empty(self::$integrante->cargo_1) || !empty(self::$integrante->cargo_2)) {
							$sociedad = SQLConnection::backendStoreProcedure('backend_obtener_cuit_asignado_SC', array(self::$integrante->id, 1));
							if (is_array($sociedad) && sizeof($sociedad) > 0 && isset($sociedad[0]->cuit)) {
								if (!empty(self::$integrante->cargo_1)) {
									self::busquedaPorCargoYSociedad(self::$integrante->cargo_1, $sociedad[0]->cuit, $stored_procedure);
								}
								if (self::$params['procesado'] != 1 && !empty(self::$integrante->cargo_2)) {
									self::busquedaPorCargoYSociedad(self::$integrante->cargo_2, $sociedad[0]->cuit, $stored_procedure);
								}
							}
						}
						if (self::$params['procesado'] != 1
							&& !empty(self::$integrante->localidad)
							&& !empty(self::$integrante->profesion) && !empty(self::$integrante->fecha_nac)
							&& (!empty(self::$integrante->provincia_1) || !empty(self::$integrante->provincia_2))) {

							if (!empty(self::$integrante->provincia_1)) {
								self::busquedaPorRestantes(self::$integrante->localidad, self::$integrante->provincia_1, self::$integrante->profesion, self::$integrante->fecha_nac, $stored_procedure);
							}

							if (self::$params['procesado'] != 1 && !empty(self::$integrante->provincia_2)) {
								self::busquedaPorRestantes(self::$integrante->localidad, self::$integrante->provincia_2, self::$integrante->profesion, self::$integrante->fecha_nac, $stored_procedure);
							}

						}
					}

					if (self::$params['procesado'] != 1) {
						$multiplicidad = self::$params['multiplicidad_por_cuit'] + self::$params['multiplicidad_por_dni'] + self::$params['multiplicidad_por_nombre'] + self::$params['multiplicidad_por_domicilio'];
						if ($multiplicidad > 0) {
							$res = SQLConnection::backendStoreProcedure('backend_procesar_log_en_asignar_cuits_SC', array_values(self::$params), true);
							if (isset($res->id)) {
								self::$process['no_completados_por_multiplicidad']++;
							} else {
								self::registrarError($res);
							}
						} else {
							self::$process['no_encontrados']++;
						}
					}

					$aux_params = [
						'id' => self::$integrante->id,
						'flag_soc' => null,
						'flag_int' => 'B',
					];
					$exec = SQLConnection::backendStoreProcedure('backend_procesar_flag_SC', array_values($aux_params));
				}
			}
		}
		return self::$process;
	}

	public static function busquedaPorRestantes($localidad, $provincia, $profesion, $fecha_nac, $stored_procedure) {
		$localidad = strtoupper(Misc::limpiarString($localidad));
		$provincia = strtoupper(Misc::limpiarString($provincia));
		$profesion = strtoupper(Misc::limpiarString($profesion));
		$fecha_nac = self::limpiarParametro($fecha_nac);
		$busqueda = SQLConnection::backendStoreProcedure($stored_procedure, array(null, null, $localidad, $provincia, self::$params['nombre_limpio'], $fecha_nac, $profesion, null, null));
		self::procesarResultados($busqueda, 'otro');
	  }

	public static function limpiarParametro($parametro) {
		$parametro = str_replace('"', '', $parametro);
		$parametro = str_replace("'", '', $parametro);
		return $parametro;
	}

	public static function busquedaPorCuit($cuit) {
		$cuit = filter_var($cuit, FILTER_SANITIZE_NUMBER_INT);
		self::$params['documemto_limpio'] = Misc::limpiarString($cuit);
		self::$params['buscado_por_cuit'] = 1;
		return SQLConnection::backendStoreProcedure('backend_busqueda_padron_personalizada',
			array(self::$params['documemto_limpio'], null, null, null, null));
	}

	public static function busquedaPorDNI($dni) {
		$dni = filter_var($dni, FILTER_SANITIZE_NUMBER_INT);
		self::$params['documemto_limpio'] = Misc::limpiarString($dni);
		self::$params['documemto_limpio'] = Misc::agregarCerosAlDNI(self::$params['documemto_limpio']);
		self::$params['buscado_por_dni'] = 1;
		return SQLConnection::backendStoreProcedure('backend_busqueda_padron_personalizada',
			array(null, self::$params['documemto_limpio'], null, null, null));
	}

	public static function busquedaPorNombreYDomicilio($nombre, $domicilio, $fase = 1) {
		self::$params['nombre_limpio'] = Misc::limpiarString($nombre);
		if ($fase == 2) {
			self::$params['nombre_limpio'] = self::asignarNear(self::$params['nombre_limpio']);
		}
		self::$params['domicilio_limpio'] = self::limpiarParametro($domicilio);
		self::$params['buscado_por_nombre'] = 1;
		self::$params['buscado_por_domicilio'] = 1;
		/*if ($fase == 2)
		  dd(array(null, null, self::$params['nombre_limpio'], self::$params['domicilio_limpio'], null));*/
		return SQLConnection::backendStoreProcedure('backend_busqueda_padron_personalizada',
			array(null, null, self::$params['nombre_limpio'], self::$params['domicilio_limpio'], null));
	}

	public static function busquedaPorRazonSocial($razon_social) {
		self::$params['nombre_limpio'] = Misc::parsearBusquedaPadron($razon_social);
		self::$params['buscado_por_nombre'] = 1;
		return SQLConnection::backendStoreProcedure('backend_busqueda_padron_personalizada',
			array(null, null, null, null, self::$params['nombre_limpio']));
	}

	public static function busquedaPorRazonSocialYDomicilio($razon_social, $domicilio) {
		self::$params['nombre_limpio'] = Misc::parsearBusquedaPadron($razon_social);
		self::$params['domicilio_limpio'] = self::limpiarParametro($domicilio);
		self::$params['buscado_por_nombre'] = 1;
		self::$params['buscado_por_domicilio'] = 1;
		return SQLConnection::backendStoreProcedure('backend_busqueda_padron_personalizada',
			array(null, null, null, self::$params['domicilio_limpio'], self::$params['nombre_limpio']));
	}

	public static function busquedaPorCargoYSociedad($cargo, $cuit_sociedad, $stored_procedure) {
		$cargo = strtoupper(Misc::limpiarString($cargo));
		$busqueda = SQLConnection::backendStoreProcedure($stored_procedure, array(null, null, null, null, self::$params['nombre_limpio'], null, null, $cargo, $cuit_sociedad));
		self::procesarResultados($busqueda, 'otro');
		if (self::$params['procesado'] != 1 && is_array($busqueda) && sizeof($busqueda) > 1) {
			if (!empty(self::$integrante->fecha_nac)) {
				$fecha_nac = self::limpiarParametro(self::$integrante->fecha_nac);
				$busqueda = SQLConnection::backendStoreProcedure($stored_procedure, array(null, null, null, null, self::$params['nombre_limpio'], $fecha_nac, null, $cargo, $cuit_sociedad));
				self::procesarResultados($busqueda, 'otro');
			}
			if (self::$params['procesado'] != 1 && !empty(self::$integrante->profesion)) {
				$profesion = strtoupper(Misc::limpiarString(self::$integrante->profesion));
				$busqueda = SQLConnection::backendStoreProcedure($stored_procedure, array(null, null, null, null, self::$params['nombre_limpio'], null, $profesion, $cargo, $cuit_sociedad));
				self::procesarResultados($busqueda, 'otro');
			}
		}
	}

	public static function procesarResultados($busqueda, $tipo_busqueda) {
		if (is_array($busqueda) && count($busqueda) == 1) {
			switch ($tipo_busqueda) {
				case 'cuit':
					self::$params['encontrado_por_cuit'] = 1;
					break;
				case 'dni':
					self::$params['encontrado_por_dni'] = 1;
					break;
				case 'nombre':
					self::$params['encontrado_por_nombre'] = 1;
					break;
				case 'domicilio':
					self::$params['encontrado_por_domicilio'] = 1;
					break;
			}
			self::$params['cuit_procesar'] = $busqueda[0]->cuit;
			self::$params['procesado'] = 1;
			self::$params['multiplicidad_por_cuit'] = null;
			self::$params['multiplicidad_por_dni'] = null;
			self::$params['multiplicidad_por_nombre'] = null;
			self::$params['multiplicidad_por_domicilio'] = null;
			$res = SQLConnection::backendStoreProcedure('backend_procesar_log_en_asignar_cuits_SC', array_values(self::$params), true);
			if (isset($res->id)) {
				self::$process['completados']++;
			} else {
				self::registrarError($res);
			}
		} elseif (is_array($busqueda) && count($busqueda) > 1) {
			switch ($tipo_busqueda) {
				case 'cuit':
					self::$params['multiplicidad_por_cuit'] = 1;
					break;
				case 'dni':
					self::$params['multiplicidad_por_dni'] = 1;
					break;
				case 'nombre':
					self::$params['multiplicidad_por_nombre'] = 1;
					break;
				case 'domicilio':
					self::$params['multiplicidad_por_domicilio'] = 1;
					break;
			}
		}
	}

	public static function registrarError($res) {
		self::$params['error'] = 1;
		self::$params['mensaje'] = $res->error ?? 'Error: el SP [backend_procesar_log_en_asignar_cuits_SC] no se completó de forma correcta.';
		self::$process['errores'][] = self::$params;
		self::limpiarVariablesDeError();
	}

	public static function limpiarVariablesDeError() {
		self::$params['error'] = null;
		self::$params['mensaje'] = null;
	}

	public static function asignarNear($string) {
		$words = explode(' ', $string);
		return "'NEAR(" . implode(',', $words) . ")'";
	}

	public static function compararStrings($string_1, $string_2) {
		$string_1 = str_replace(' ', '', Misc::limpiarString($string_1));
		$string_2 = str_replace(' ', '', Misc::limpiarString($string_2));
		return ($string_1 == $string_2);
	}

	public static function confirmacionDeAsignados() {
		$datetime1 = new DateTime();
		self::$process['confirmados'] = 0;
		self::$process['no_confirmados'] = 0;
		self::$process['total'] = 0;
		self::$process['errores'] = [];
		$procesados = SQLConnection::backendStoreProcedure('backend_obtener_cuits_asignados_SC', array());
		self::$process['total'] = sizeof($procesados);
		foreach ($procesados as $pos => $row) {
			self::$process['verificado'] = false;
			$domicilios = SQLConnection::backendStoreProcedure('obtener_domicilios_new', array($row->a_cuit_procesar, 0));
			$row = (object) Misc::convertirStringsVaciosEnNull((array) $row);
			if (is_array($domicilios) && sizeof($domicilios) > 0) {
				if (!self::$process['verificado'] && isset($row->a_nombre_limpio)) {
					self::verificarAsignacion($row->a_nombre_limpio, $row, $domicilios);
				}
				if (!self::$process['verificado'] && ($row->a_es_sociedad == 1) && isset($row->s_razon_social)) {
					$diccionario = Misc::diccionarioRazonesSociales($row->s_razon_social);
					$diccionario = is_array($diccionario) ? $diccionario : [$row->s_razon_social];
					foreach ($diccionario as $nombre) {
						if (!self::$process['verificado']) {
							self::verificarAsignacion($row->a_nombre_limpio, $row, $domicilios);
						} else {
							break;
						}
					}
				}
				if (!self::$process['verificado'] && ($row->a_es_sociedad == 0) && ($row->a_encontrado_por_cuit == null) && ($row->a_encontrado_por_dni == null) && isset($row->s_nombre_int)) {
					self::verificarAsignacion($row->s_nombre_int, $row, $domicilios);
				}
			}
			if (!self::$process['verificado'] && ($row->a_es_sociedad == 0) && (($row->a_encontrado_por_cuit == null) || ($row->a_encontrado_por_dni == 1))) {
				$params = [
					$row->a_id, 0, 0, 0, 1
				];
				$exec = SQLConnection::backendStoreProcedure('confirmar_asignacion_cuits_SC', $params, true);
				if (isset($exec->id)) {
					self::$process['confirmados']++;
					self::$process['verificado'] = true;
				} else {
					// ERROR SQL AL ACTUALIZAR EL ID ($row->a_id)
					self::$process['errores'][] = 'Error al procesar como "confirmado" el registro: ' . $row->a_id . ', verificar SP confirmar_asignacion_cuits_SC';
				}
			}
			if (!self::$process['verificado']) {
				$params = [
					$row->a_id, 0, 0, 0, 0
				];
				$exec = SQLConnection::backendStoreProcedure('confirmar_asignacion_cuits_SC', $params, true);
				if (isset($exec->id)) {
					self::$process['no_confirmados']++;
				} else {
					// ERROR SQL AL ACTUALIZAR EL ID ($row->a_id)
					self::$process['errores'][] = 'Error al procesar como "no confirmado" el registro: ' . $row->a_id . ', verificar SP confirmar_asignacion_cuits_SC';
				}
			}
		}
		unset(self::$process['verificado']);
		$datetime2 = new DateTime();
		self::$process['tiempo_de_ejecucion'] = $datetime1->diff($datetime2);
		// dd(self::$process);
	}

	public static function verificarAsignacion($nombre, $row, $domicilios) {
		if (self::compararStrings($nombre, $row->p_nombre_persona)) {
			foreach ($domicilios as $i => $dom) {
				if (self::$process['verificado']) {
					break;
				}
				if (($row->a_es_sociedad == 0) && (strtoupper($dom->tipo_domicilio) != 'F')) {
					continue;
				}
				$dom = (object) Misc::convertirStringsVaciosEnNull((array) $dom);
				if (isset($row->s_domicilio_soc))
					$row->s_domicilio_soc = Misc::reemplazarAcentosPorEquivalentes($row->s_domicilio_soc);
				if (isset($row->s_localidad_soc))
					$row->s_localidad_soc = Misc::reemplazarAcentosPorEquivalentes($row->s_localidad_soc);
				if (isset($row->s_provincia_soc))
					$row->s_provincia_soc = Misc::reemplazarAcentosPorEquivalentes($row->s_provincia_soc);
				if (isset($dom->domicilio))
					$dom->domicilio = Misc::reemplazarAcentosPorEquivalentes($dom->domicilio);
				if (isset($dom->loc_nombre))
					$dom->loc_nombre = Misc::reemplazarAcentosPorEquivalentes($dom->loc_nombre);
				if (isset($dom->prv_nombre))
					$dom->prv_nombre = Misc::reemplazarAcentosPorEquivalentes($dom->prv_nombre);
				if (
					(isset($row->s_domicilio_soc) && isset($dom->domicilio) && ($row->s_domicilio_soc == $dom->domicilio))
					||
					(isset($row->s_localidad_soc) && isset($dom->loc_nombre) && ($row->s_localidad_soc == $dom->loc_nombre))
					||
					(isset($row->s_provincia_soc) && isset($dom->prv_nombre) && ($row->s_provincia_soc == $dom->prv_nombre))
				) {
					$params = [
						$row->a_id,
						(isset($row->s_domicilio_soc) && isset($dom->domicilio)) ? (Integer) ($row->s_domicilio_soc == $dom->domicilio) : 0,
						(isset($row->s_localidad_soc) && isset($dom->loc_nombre)) ? (Integer) ($row->s_localidad_soc == $dom->loc_nombre) : 0,
						(isset($row->s_provincia_soc) && isset($dom->prv_nombre)) ? (Integer) ($row->s_provincia_soc == $dom->prv_nombre) : 0,
						1
					];
					$exec = SQLConnection::backendStoreProcedure('confirmar_asignacion_cuits_SC', $params, true);
					if (isset($exec->id)) {
						self::$process['confirmados']++;
						self::$process['verificado'] = true;
					} else {
						// ERROR SQL AL ACTUALIZAR EL ID ($row->a_id)
						self::$process['errores'][] = 'Error al confirmar el registro: ' . $row->a_id . ', verificar SP confirmar_asignacion_cuits_SC';
					}
				}
			}
		}
	}

}