<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use App\Custom\Misc;
use App\Custom\SQLConnection;

use Carbon\Carbon;
use Session;
use DateTime;
use Validator;
use Exception;
use Log;

class ApiControllerV4 extends Controller
{

    private float $tiempo_afip_a13;
    private float $tiempo_afip_a5;
    private float $tiempo_renaper;
    private float $tiempo_facematch;
    private float $tiempo_worldsys;

    const CANTIDAD_DIAS_EXPIRADO_ARCA = 45;

    public function __construct()
    {
        $this->tiempo_afip_a13 = 0;
        $this->tiempo_afip_a5 = 0;
        $this->tiempo_renaper = 0;
        $this->tiempo_facematch = 0;
        $this->tiempo_worldsys = 0;
    }

    /*
        Funcion que maneja el endpoint de govcheck v4. Consulta a ARCA (mediante API interna) de ser necesario
    */
    public function govcheck(Request $request, $respuesta_final = true)
    {
        // Seleccion de identificacion. Preferimos tax_id si estan ambos
        $identificacion = '';

        if ($request->national_id) {
            $dni = $request->national_id;
            $identificacion = $dni;
        }

        if ($request->tax_id) {
            $tax_id = $request->tax_id;
            $identificacion = $tax_id;
        }

        $transaction_id = $this->consumirServicio($request, $identificacion)->transaction_id;

        // Validacion de entrada
        $parametros = ['national_id', 'tax_id'];

        if ($error = $this->validarFormatoParametros($request, $parametros, $transaction_id)) {
            return $error;
        }
        if ($error = $this->validarParametrosObligatoriosGovcheck($request, $parametros, $transaction_id)) {
            return $error;
        }

        try {
            $sp = 'api_get_govcheck_2024';
            $govcheck = SQLConnection::backendStoreProcedure($sp, array($identificacion), 'select');
        } catch (Exception $e) {
            Log::error("Error al ejecutar $sp", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->enviarMailError("govcheck - Error SP $sp", $identificacion, $transaction_id, $e);
            return $this->errorGenerico($request->only($parametros), $transaction_id);
        }

        $registro = array_first($govcheck) ?? null;
        if ($this->debeActualizarPadron($registro)) {
            try {
                // Consulta a la API interna de busqueda padron, que va a consultar ARCA y actualizar el padron
                $persona = $this->consultarApiPadron($identificacion);

                $govcheck = SQLConnection::backendStoreProcedure('api_get_govcheck_2024', array($identificacion), 'select');
            } catch (Exception $e) {
                Log::error("Error al consultar API Padron", [
                    'transaction_id' => $transaction_id,
                    'message' => $e->getMessage(),
                    'file' => $e->getFile(),
                    'line' => $e->getLine(),
                    'trace' => $e->getTraceAsString()
                ]);

                $this->enviarMailError('govcheck - Error API Padron', $identificacion, $transaction_id, $e);
                return $this->errorGenerico($request->only($parametros), $transaction_id);
            }
        }

        if (!empty($registro->fecha_nacimiento) && !self::esMayorDeEdad($registro->fecha_nacimiento)) {
            $codigo_resultado = '313';
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id
            );
        }

        $datos_bancarios = [];
        foreach ($govcheck as $govcheck_individuo) {
            $antiguedad_situacion_1 = '';
            $info_bancaria = [
                'cheques_rechazados' => '',
                'ultima_posicion' => '',
                'maxima_posicion' => '',
                'cantidad_bancos' => '0',
            ];
            try {
                $antiguedad_situacion_1 = $this->antiguedadSituacion1($govcheck_individuo->identificacion);
                $info_bancaria = $this->obtenerInfoBancaria($govcheck_individuo->identificacion);
            } catch (Exception $e) {
                Log::error("Error al obtener informacion bancaria", [
                    'transaction_id' => $transaction_id,
                    'message' => $e->getMessage(),
                    'file' => $e->getFile(),
                    'line' => $e->getLine(),
                    'trace' => $e->getTraceAsString()
                ]);
            }

            $chequesRechazados = $info_bancaria['cheques_rechazados'];
            $ultima_formateada = $info_bancaria['ultima_posicion'];
            $maxima_formateada = $info_bancaria['maxima_posicion'];
            $cantidadBancosUnicos = $info_bancaria['cantidad_bancos'];

            $datos_bancarios[$govcheck_individuo->identificacion] = [
                'Sit_1_since' => $antiguedad_situacion_1,
                'Banks' => $cantidadBancosUnicos,
                'Last_position' => $ultima_formateada,
                'Highest_position' => $maxima_formateada,
                'Rejected_checks' => $chequesRechazados
            ];
        }

        $govcheck_formateado = Misc::conversorApisGovcheckV4($govcheck, $datos_bancarios);

        if (empty($govcheck_formateado)) {
            $codigo_resultado = '401';
        }

        if (count($govcheck_formateado) === 1) {
            $codigo_resultado = '200';
        }

        if (count($govcheck_formateado) > 1) {
            $codigo_resultado = '201';
        }

        $notificacion_govcheck = [
            'Status' => $codigo_resultado,
            'Message' => Misc::error_query($codigo_resultado),
        ];

        $response_array = [
            'Parameters' => $request->only($parametros),
            'Results' => count($govcheck_formateado),
            'Notification' => $notificacion_govcheck,
            'Response' => $govcheck_formateado,
            'Transaction_id' => $transaction_id
        ];

        if (!$respuesta_final) {
            return response()->json($response_array);
        }

        $this->guardarResultadoApi(
            $identificacion,
            null,
            $transaction_id,
            $response_array,
            $codigo_resultado
        );

        return response()->json($response_array);
    }

    /*
        Funcion que maneja el endpoint de personal credit validation v4.
        Consulta a ARCA (mediante API interna) y RENAPER de ser necesario
    */
    public function personalCred(Request $request)
    {
        $dni = $request->national_id;

        $transaction_id = $this->consumirServicio($request, $dni)->transaction_id;

        $parametros = ['national_id', 'gender', 'id_main_issue', 'copy', 'issue_date', 'expiry_date'];

        if ($error = $this->validarFormatoParametros($request, $parametros, $transaction_id, false)) {
            return $error;
        }

        if ($error = $this->validarParametrosObligatoriosPersonalCred($request, $parametros, $transaction_id)) {
            return $error;
        }

        $genero = $request->gender;
        $issue_date = $request->issue_date;
        $expiry_date = $request->expiry_date;
        $copy = $request->copy;
        $id_main_issue = $request->id_main_issue;

        try {
            $persona = $this->consultarApiPadron($dni, $genero);
        } catch (Exception $e) {
            Log::error("Error al consultar API Padron", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->enviarMailError('personalCred - Error API Padron', $dni, $transaction_id, $e);
            return $this->errorGenerico($request->only($parametros), $transaction_id, false);
        }

        if (!empty($persona->fecha_nacimiento) && !self::esMayorDeEdad($persona->fecha_nacimiento)) {
            $codigo_resultado = '313';
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        try {
            $res_renaper = $this->obtenerResRenaper($dni, $genero);

            $codigo_resultado = $this->statusResRenaper($res_renaper);
        } catch (Exception $e) {
            Log::error("Error al consultar a Renaper", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->enviarMailError('personalCred - Error Renaper', $dni, $transaction_id, $e);
            return $this->errorGenerico($request->only($parametros), $transaction_id, false);
        }

        if ($codigo_resultado == '407') {
            // DNI carta de ciudadania
            return $this->responderDniCiudadania(
                $request->only($parametros),
                $dni,
                $genero,
                $transaction_id,
                $res_renaper,
                false
            );
        }

        if ($codigo_resultado != '200' && $codigo_resultado != '315') {
            // Tratamiento demas errores de validacion de respuesta de renaper
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        $info_persona_renaper = $res_renaper->Response ?? null;

        $fecha_nacimiento = isset($info_persona_renaper->fechaNacimiento) ? Misc::convertirFormatoFecha($info_persona_renaper->fechaNacimiento) : $persona->fecha_nacimiento;

        if (!empty($fecha_nacimiento) && !self::esMayorDeEdad($fecha_nacimiento)) {
            $codigo_resultado = '313';
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        $fecha_defuncion = isset($info_persona_renaper->fechaf) ? Misc::convertirFormatoFecha($info_persona_renaper->fechaf) : '';

        // info bancaria
        $tax_id = $info_persona_renaper->cuil ?? $persona->identificacion;
        $tax_id_type = $persona->identificador ?? '';

        $antiguedad_situacion_1 = '';
        $info_bancaria = [
            'cheques_rechazados' => '',
            'ultima_posicion' => '',
            'maxima_posicion' => '',
            'cantidad_bancos' => '0',
        ];
        try {
            $antiguedad_situacion_1 = $this->antiguedadSituacion1($tax_id ? $tax_id : $dni);
            $info_bancaria = $this->obtenerInfoBancaria($tax_id);
        } catch (Exception $e) {
            Log::error("Error al obtener datos bancarios", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);
        }

        $chequesRechazados = $info_bancaria['cheques_rechazados'];
        $ultima_formateada = $info_bancaria['ultima_posicion'];
        $maxima_formateada = $info_bancaria['maxima_posicion'];
        $cantidadBancosUnicos = $info_bancaria['cantidad_bancos'];

        $datos_generales = Misc::respuestaRenaperGenerica(
            $info_persona_renaper,
            $tax_id_type,
            $antiguedad_situacion_1,
            $fecha_defuncion,
            $ultima_formateada,
            $maxima_formateada,
            $chequesRechazados,
            $cantidadBancosUnicos,
            $fecha_nacimiento
        );

        $datos_validados = Misc::validacionDatosRenaper(
            $info_persona_renaper,
            $genero,
            $issue_date,
            $expiry_date,
            $copy,
            $id_main_issue
        );

        if ($codigo_resultado == '315') {
            [$datos_validados, $datos_generales] = $this->respuestaPersonalCredParcial(
                $dni, $tax_id, $tax_id_type, $persona,
                $fecha_nacimiento, $fecha_defuncion,
                $antiguedad_situacion_1, $cantidadBancosUnicos,
                $ultima_formateada, $maxima_formateada, $chequesRechazados,
                $transaction_id
            );
        }

        $respuestaFormateada = [$datos_validados, $datos_generales];
        $response_array = [
            'Parameters' => $request->only($parametros),
            'Status' => $codigo_resultado,
            'Message' => Misc::error_query($codigo_resultado),
            'Response' => $respuestaFormateada,
            'Transaction_id' => $transaction_id
        ];

        $this->guardarResultadoApi(
            $dni,
            $genero,
            $transaction_id,
            $response_array,
            $codigo_resultado
        );

        return response()->json($response_array);
    }

    /*
        Funcion que maneja el endpoint de personal credit validation extended ("facematch")
        Consulta a ARCA (mediante API interna) y RENAPER de ser necesario. 
        Consulta la API de Facematch de RENAPER siempre para reconocimiento facial
    */
    public function facematch(Request $request)
    {
        $parametros = ['national_id', 'gender', 'selfie_image'];

        $dni = $request->national_id;

        $consumo = $this->consumirServicio($request, $dni);
        $transaction_id = $consumo->transaction_id;
        $fecha_consumo = $consumo->transaction_date;

        if ($error = $this->validarFormatoParametros($request, $parametros, $transaction_id, false)) {
            return $error;
        }

        if ($error = $this->validarParametrosObligatoriosPersonalCred($request, $parametros, $transaction_id)) {
            return $error;
        }

        $genero = $request->gender;
        $selfie_image = $request->selfie_image;

        try {
            $persona = $this->consultarApiPadron($dni, $genero);
        } catch (Exception $e) {
            Log::error("Error al consultar API Padron", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->enviarMailError('facematch - Error API Padron', $dni, $transaction_id, $e);
            return $this->errorGenerico($request->only($parametros), $transaction_id, false);
        }

        if (empty($persona) || empty($persona->fecha_nacimiento)) {
            // Consulta a renaper-datos al no tener datos de la persona. Actualiza padron
            try {
                $res_renaper = $this->obtenerResRenaper($dni, $genero);
            } catch (Exception $e) {
                Log::error("Error al consultar a Renaper", [
                    'transaction_id' => $transaction_id,
                    'message' => $e->getMessage(),
                    'file' => $e->getFile(),
                    'line' => $e->getLine(),
                    'trace' => $e->getTraceAsString()
                ]);

                $this->enviarMailError('facematch - Error Renaper', $dni, $transaction_id, $e);
                return $this->errorGenerico($request->only($parametros), $transaction_id, false);
            }

            $codigo_resultado = $this->statusResRenaper($res_renaper);

            if ($codigo_resultado == '407') { // DNI carta de ciudadania
                return $this->responderDniCiudadania(
                    $request->only($parametros),
                    $dni,
                    $genero,
                    $transaction_id,
                    $res_renaper,
                    false
                );
            }

            if ($codigo_resultado != '200') {
                return $this->responderError(
                    $request->only($parametros),
                    $codigo_resultado,
                    $transaction_id,
                    false
                );
            }
            // Reconsulta padrón con los datos actualizados por renaper

            try {
                $persona = $this->consultarApiPadron($dni, $genero);
            } catch (Exception $e) {
                Log::error("Error al consultar API Padron", [
                    'transaction_id' => $transaction_id,
                    'message' => $e->getMessage(),
                    'file' => $e->getFile(),
                    'line' => $e->getLine(),
                    'trace' => $e->getTraceAsString()
                ]);

                $this->enviarMailError('facematch - Error API Padron (reconsulta)', $dni, $transaction_id, $e);
                return $this->errorGenerico($request->only($parametros), $transaction_id, false);
            }
        }

        if (!empty($persona->fecha_nacimiento) && !self::esMayorDeEdad($persona->fecha_nacimiento)) {
            $codigo_resultado = '313';
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        $tax_id = $persona->identificacion;
        $tipo_clave = $persona->identificador;
        $nombres_persona = $persona->nombres;
        $apellidos_persona = $persona->apellidos;
        $DOB = $persona->fecha_nacimiento;
        $DOD = $persona->fecha_defuncion;

        //$datos_persona = SQLConnection::backendStoreProcedure('api_get_govcheck_2024',array($persona[0]->identificacion),'select');

        $antiguedad_situacion_1 = '';
        $info_bancaria = [
            'cheques_rechazados' => '',
            'ultima_posicion' => '',
            'maxima_posicion' => '',
            'cantidad_bancos' => '0',
        ];
        try {
            $antiguedad_situacion_1 = $this->antiguedadSituacion1($tax_id ? $tax_id : $dni);
            $info_bancaria = $this->obtenerInfoBancaria($tax_id);
        } catch (Exception $e) {
            Log::error("Error al obtener datos bancarios", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);
        }

        $chequesRechazados = $info_bancaria['cheques_rechazados'];
        $ultima_formateada = $info_bancaria['ultima_posicion'];
        $maxima_formateada = $info_bancaria['maxima_posicion'];
        $cantidadBancosUnicos = $info_bancaria['cantidad_bancos'];

        $forzar_login = 'N';
        $datos = RenaperController::obtenerDatosLoginFace(env('RENAPER_FACE_SERVICIO'), $forzar_login);
        $this->tiempo_facematch = RenaperController::$tiempo_facematch ?? 0;
        
        if (isset($datos->error) || !isset($datos->token)) {
            $codigo_resultado = '307';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        $respuesta = RenaperController::obtenerDatosRenaperFace($selfie_image, $dni, $genero, $datos->token);
        $this->tiempo_facematch = RenaperController::$tiempo_facematch ?? 0;

        $decoded = json_decode($respuesta);

        if (empty($respuesta) || json_last_error() !== JSON_ERROR_NONE || !isset($decoded->data) || isset($decoded->error)) {
            $codigo_resultado = '306';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        if ($decoded->codigo_http != 200) {
            $codigo_resultado = '307'; //

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        $data = $decoded->data;

        if (isset($data->codigo) && $data->codigo == 1) { // Token expirado
            $codigo_resultado = '307';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        if (isset($data->codigo) && $data->codigo == 400) { // No se pudo procesar imagen
            $codigo_resultado = '405';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        if (!empty($data->notificacion) && !empty($data->notificacion->errorArray)) {
            $codigo_resultado = '306';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        if ((isset($data->codigo) && $data->codigo !== 200) || is_null($data->codigo)) {
            $codigo_resultado = '307';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        $notificacion = $data->notificacion;
        $notificacion_fase1 = $data->notificacion;
        $errorArray = $notificacion->errorArray;

        try {
            $id = SqlConnection::backendStoreProcedure('RENAPER_FACE_INSERTAR', array(
                $dni,
                $genero,
                $decoded->codigo_http ?? null,
                $decoded->mensaje_http ?? null,
                $data->codigo ?? null,
                $data->mensaje ?? null,
                $notificacion->transactionControlNumber ?? null,
                $notificacion->typeOfTransaction ?? null,
                $notificacion->dateOfTransaction ?? null,
                $errorArray[0]->code ?? null,
                $errorArray[0]->description ?? null,
                $errorArray[0]->name ?? null,
                null
            ), 'selectOne');
        } catch (Exception $e) {
            Log::error("Error al ejecutar RENAPER_FACE_INSERTAR", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            return $this->errorGenerico($request->only($parametros), $transaction_id, false);
        }

        if (!isset($id->transaccion)) {
            $codigo_resultado = '306';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        $final = RenaperController::obtenerDatosRenaperFaceFinal($id->transaccion, $datos->token);
        $this->tiempo_facematch += RenaperController::$tiempo_facematch ?? 0;

        $decoded = json_decode($final);

        if (empty($final) || json_last_error() !== JSON_ERROR_NONE || !isset($decoded->data) || isset($decoded->error)) {
            $codigo_resultado = '306';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        $data = $decoded->data;

        if ($decoded->codigo_http !== 200) {
            $codigo_resultado = '307';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        if (isset($data->codigo) && $data->codigo !== 0) {
            $facematch_data = new \stdClass();
            $facematch_data->tcnid = $notificacion_fase1->transactionControlNumber ?? '';
            $facematch_data->status = '';
            $facematch_data->score = '';
            $facematch_data->facematch_datetime = $fecha_consumo ?? '';
            $facematch_data->national_id = $dni ?? '';
            $facematch_data->facematch_id = $notificacion_fase1->transactionControlNumber ?? '';

            $credit_data = new \stdClass();
            $credit_data->name = $nombres_persona ?? '';
            $credit_data->surname = $apellidos_persona ?? '';
            $credit_data->tax_id_type = $tipo_clave ?? '';
            $credit_data->tax_id = $tax_id ?? '';
            $credit_data->sit_1_since = $antiguedad_situacion_1 ?? '';
            $credit_data->banks = $cantidadBancosUnicos ?? '';
            $credit_data->last_position = $ultima_formateada ?? '';
            $credit_data->highest_position = $maxima_formateada ?? '';
            $credit_data->rejected_checks = $chequesRechazados ?? '';
            $credit_data->DOB = $DOB ?? '';
            $credit_data->DOD = $DOD ?? '';

            $response_array = [[$facematch_data], [$credit_data]];
            $codigo_resultado = '315';

            $this->guardarResultadoApi($dni, $genero, $transaction_id, $response_array, $codigo_resultado);

            return response()->json([
                'Parameters' => self::recortarParametros($request->only($parametros)),
                'Status' => $codigo_resultado,
                'Message' => Misc::error_query($codigo_resultado),
                'Response' => $response_array,
                'Transaction_id' => $transaction_id,
            ]);
        }

        $notificacion = $data->notificacion;

        try {
            $ok = SqlConnection::backendStoreProcedure(
                'RENAPER_FACE_INSERTAR_FINAL',
                array(
                    $id->id,
                    $decoded->codigo_http ?? null,
                    $decoded->mensaje_http ?? null,
                    $notificacion->TCN ?? null,
                    $notificacion->status ?? null,
                    $notificacion->score ?? null,
                    $notificacion->matchtype ?? null,
                    $notificacion->comments ?? null,
                    $notificacion->fechanoti ?? null,
                    $notificacion->horanoti ?? null,
                    $data->codigo ?? null,
                    $data->mensaje ?? null
                ),
                'selectOne'
            );
        } catch (Exception $e) {
            Log::error("Error al ejecutar RENAPER_FACE_INSERTAR_FINAL", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            return $this->errorGenerico($request->only($parametros), $transaction_id, false);
        }

        if (isset($notificacion->status) && $notificacion->status === 'HIT' && !empty($selfie_image)) {
            $directorio = env('FACEMATCH_PATH');

            if (!empty($directorio) && is_dir($directorio)) {
                try {
                    file_put_contents("{$directorio}/{$id->id}_{$transaction_id}.txt", $selfie_image);
                } catch (Exception $e) {
                    Log::error("Error facematch:" . $e->getMessage());
                }
            }
        }

        $score = $notificacion->score ?? '';

        if (is_numeric($score)) {
            $score = intdiv($score, 100);
            $score = strval($score);
        }

        if (!$score) {
            $codigo_resultado = '406';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        $facematch_data = new \stdClass();

        $facematch_data->tcnid = $notificacion->TCN ?? '';
        $facematch_data->status = $notificacion->status ?? '';
        $facematch_data->score = $score;
        $facematch_data->facematch_datetime = $fecha_consumo ?? '';
        $facematch_data->national_id = $dni ?? '';
        $facematch_data->facematch_id = $id->transaccion;

        $credit_data = new \stdClass();

        $credit_data->name = $nombres_persona ?? '';
        $credit_data->surname = $apellidos_persona ?? '';
        $credit_data->tax_id_type = $tipo_clave ?? '';
        $credit_data->tax_id = $tax_id ?? '';
        $credit_data->sit_1_since = $antiguedad_situacion_1 ?? '';

        $credit_data->banks = isset($cantidadBancosUnicos) ? $cantidadBancosUnicos : "";
        $credit_data->last_position = isset($ultima_formateada) ? $ultima_formateada : "";
        $credit_data->highest_position = isset($maxima_formateada) ? $maxima_formateada : "";
        $credit_data->rejected_checks = isset($chequesRechazados) ? $chequesRechazados : "";

        $credit_data->DOD = $DOD ?? '';
        $credit_data->DOB = $DOB ?? '';

        $response_array = [
            [
                $facematch_data
            ],
            [
                $credit_data
            ]
        ];

        $codigo_resultado = '200';

        $this->guardarResultadoApi(
            $dni,
            $genero,
            $transaction_id,
            $response_array,
            $codigo_resultado
        );

        return response()->json(
            [
                'Parameters' => self::recortarParametros($request->only($parametros)),
                'Status' => $codigo_resultado,
                'Message' => Misc::error_query($codigo_resultado),
                'Response' => $response_array,
                'Transaction_id' => $transaction_id
            ]
        );
    }

    /*
        Funcion que maneja el endpoint de govcheck extended.
        Consulta a ARCA (mediante API interna), RENAPER y Worldsys de ser necesario.
    */
    public function extended(Request $request)
    {
        // Seleccion de identificacion. Preferimos tax_id si estan ambos
        $identificacion = '';
        $dni = null;
        $tax_id = null;
        
        if ($request->national_id) {
            $dni = $request->national_id;
            $identificacion = $dni;
        }

        if ($request->tax_id) {
            $tax_id = $request->tax_id;
            $identificacion = $tax_id;
        }

        $transaction_id = $this->consumirServicio($request, $identificacion)->transaction_id;

        $parametros = ['national_id', 'tax_id', 'gender', 'id_main_issue', 'copy', 'issue_date', 'expiry_date'];

        if ($error = $this->validarFormatoParametros($request, $parametros, $transaction_id)) {
            return $error;
        }

        if ($error = $this->validarParametrosObligatoriosGovcheck($request, $parametros, $transaction_id)) {
            return $error;
        }

        $genero = $request->gender;
        $issue_date = $request->issue_date;
        $expiry_date = $request->expiry_date;
        $copy = $request->copy;
        $id_main_issue = $request->id_main_issue;

        try {
            $persona = $this->consultarApiPadron($identificacion, $genero);
        } catch (Exception $e) {
            Log::error("Error al consultar API Padron", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->enviarMailError('extended - Error API Padron', $identificacion, $transaction_id, $e);
            return $this->errorGenerico($request->only($parametros), $transaction_id);
        }

        if (empty($persona)) {
            $codigo_resultado = '401';
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id
            );
        }

        if (!empty($persona->fecha_nacimiento) && !self::esMayorDeEdad($persona->fecha_nacimiento)) {
            $codigo_resultado = '313';
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id
            );
        }

        $dni = $persona->cuerpo_clave ?? $dni;

        try {
            $res_renaper = $this->obtenerResRenaper($dni, $genero);
        } catch (Exception $e) {
            Log::error("Error al consultar a Renaper", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->enviarMailError('extended - Error Renaper', $identificacion, $transaction_id, $e);
            return $this->errorGenerico($request->only($parametros), $transaction_id);
        }

        $codigo_resultado = $this->statusResRenaper($res_renaper);

        if ($codigo_resultado == '407') { // DNI carta de ciudadania
            return $this->responderDniCiudadania(
                $request->only($parametros),
                $dni,
                $genero,
                $transaction_id,
                $res_renaper
            );
        }

        if ($codigo_resultado == '315') {
            // Respuesta parcial de Renaper: datos del padrón local, sin validaciones de documento
            try {
                $govcheck = SQLConnection::backendStoreProcedure('api_get_govcheck_2024', array($identificacion), 'select');
            } catch (Exception $e) {
                Log::error("Error al ejecutar api_get_govcheck_2024", [
                    'transaction_id' => $transaction_id,
                    'message' => $e->getMessage(),
                    'file' => $e->getFile(),
                    'line' => $e->getLine(),
                    'trace' => $e->getTraceAsString()
                ]);

                $this->enviarMailError('extended (315) - Error SP api_get_govcheck_2024', $identificacion, $transaction_id, $e);
                return $this->errorGenerico($request->only($parametros), $transaction_id);
            }

            $fidecheck = ApiControllerV1::resFidecheckExtend($dni, $persona->nombre_persona, $persona->identificacion, $transaction_id ?? null);
            $this->tiempo_worldsys += ApiControllerV1::$tiempo_curl_api;

            $response = Misc::conversorApisExtendedParcial($govcheck, null, $fidecheck, 'no importa', $genero, $issue_date, $expiry_date, $id_main_issue, $copy);

            $notificacion_govcheck = [
                'Status' => $codigo_resultado,
                'Message' => Misc::error_query($codigo_resultado),
            ];

            $parametros = $request->only($parametros);

            $response_array = [
                'Parameters' => $parametros,
                'Results' => count($govcheck),
                'Notification' => $notificacion_govcheck,
                'Response' => $response,
                'Transaction_id' => $transaction_id
            ];

            $this->guardarResultadoApi(
                $dni,
                $genero,
                $transaction_id,
                $response_array,
                $codigo_resultado
            );

            return response()->json($response_array);
        }

        if ($codigo_resultado != '200') {
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id
            );
        }

        // Reconsulta padrón con los datos actualizados por renaper
        try {
            $persona = $this->consultarApiPadron($identificacion, $genero);
        } catch (Exception $e) {
            Log::error("Error al consultar API Padron", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->enviarMailError('extended - Error API Padron (reconsulta)', $identificacion, $transaction_id, $e);
            return $this->errorGenerico($request->only($parametros), $transaction_id);
        }

        if (!empty($persona->fecha_nacimiento) && !self::esMayorDeEdad($persona->fecha_nacimiento)) {
            $codigo_resultado = '313';
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id
            );
        }

        $info_persona_renaper = $res_renaper->Response ?? null;
        $identificacion = $persona->identificacion ?? $identificacion; // preferimos el identificador del padron actualizado por renaper

        try {
            $govcheck = SQLConnection::backendStoreProcedure('api_get_govcheck_2024', array($identificacion), 'select');
        } catch (Exception $e) {
            Log::error("Error al ejecutar api_get_govcheck_2024", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->enviarMailError('extended - Error SP api_get_govcheck_2024', $identificacion, $transaction_id, $e);
            return $this->errorGenerico($request->only($parametros), $transaction_id);
        }

        // Registro de tiempo worldsys en fidecheck
        // Está implementado reutilizando la funcion de ApiControllerV1 ya que va a haber un proyecto separado para Fidecheck
        $fidecheck = ApiControllerV1::resFidecheckExtend($dni, $persona->nombre_persona, $persona->identificacion, $transaction_id ?? null);
        $this->tiempo_worldsys += ApiControllerV1::$tiempo_curl_api;

        $response = Misc::conversorApisExtended_v3($govcheck, $info_persona_renaper, $fidecheck, 'no importa', $genero, $issue_date, $expiry_date, $id_main_issue, $copy);

        $notificacion_govcheck = [
            'Status' => $codigo_resultado,
            'Message' => Misc::error_query($codigo_resultado),
        ];

        $parametros = $request->only($parametros);

        $response_array = [
            'Parameters' => $parametros,
            'Results' => count($govcheck),
            'Notification' => $notificacion_govcheck,
            'Response' => $response,
            'Transaction_id' => $transaction_id
        ];

        $this->guardarResultadoApi(
            $dni,
            $genero,
            $transaction_id,
            $response_array,
            $codigo_resultado
        );

        return response()->json($response_array);
    }

    /**
     * Procesa la verificación de domicilio gubernamental.
     *
     * Esta función realiza los siguientes pasos:
     * 1. Valida que el tax_id sea correcto
     * 2. Consulta a renaper para actualizar domicilio
     * 3. Devuelve los domicilios asociados al tax_id
     *
     * @param \Illuminate\Http\Request $request Solicitud HTTP con los datos de entrada.
     * @return \Illuminate\Http\JsonResponse
     */
    public function domiciliosGovcheck(Request $request)
    {
        $tax_id = $request->tax_id;

        $transaction_id = $this->consumirServicio($request, $tax_id)->transaction_id;

        $parametros = ['tax_id'];

        if (empty($tax_id)) {
            $codigo_resultado = '302';
            $this->guardarResultadoApi($tax_id, null, $transaction_id, [], $codigo_resultado);

            return response()->json([
                'Parameters' => $request->only($parametros),
                'Status' => $codigo_resultado,
                'Message' => Misc::error_query($codigo_resultado),
                'Response' => [],
                'Transaction_id' => $transaction_id
            ]);
        }

        if ($response = $this->validarFormatoParametros($request, $parametros, $transaction_id, false)) {
            return $response;
        }

        try {
            $persona = $this->consultarApiPadron($tax_id);
        } catch (Exception $e) {
            Log::error("Error al consultar API Padron", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->enviarMailError('domiciliosGovcheck - Error API Padron', $tax_id, $transaction_id, $e);
            return $this->errorGenerico($request->only($parametros), $transaction_id, false);
        }

        if (!empty($persona->fecha_nacimiento) && !self::esMayorDeEdad($persona->fecha_nacimiento)) {
            $codigo_resultado = '313';
            $this->guardarResultadoApi($tax_id, null, $transaction_id, [], $codigo_resultado);

            return response()->json([
                'Parameters' => $request->only($parametros),
                'Status' => $codigo_resultado,
                'Message' => Misc::error_query($codigo_resultado),
                'Response' => [],
                'Transaction_id' => $transaction_id
            ]);
        }

        if ($persona) {
            $dni = $persona->cuerpo_clave;
            $sexo = $persona->sexo;

            // Consulta a renaper para actualizar padron de domicilios
            if ($dni && $sexo) {
                $this->obtenerResRenaper($dni, $sexo);
            }
        }

        try {
            $sp = 'sp_obtener_domicilios_general';
            $domicilios = SQLConnection::backendStoreProcedure($sp, array($tax_id));
        } catch (Exception $e) {
            Log::error("Error al ejecutar $sp", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->enviarMailError("domiciliosGovcheck - Error SP $sp", $tax_id, $transaction_id, $e);
            $codigo_resultado = '306';
            $this->guardarResultadoApi($tax_id, null, $transaction_id, [], $codigo_resultado);

            return response()->json([
                'Parameters' => $request->only($parametros),
                'Status' => $codigo_resultado,
                'Message' => Misc::error_query($codigo_resultado),
                'Response' => [],
                'Transaction_id' => $transaction_id
            ]);
        }

        if (empty($domicilios)) {
            $codigo_resultado = '401';
            $this->guardarResultadoApi($tax_id, null, $transaction_id, [], $codigo_resultado);

            return response()->json([
                'Parameters' => $request->only($parametros),
                'Status' => $codigo_resultado,
                'Message' => Misc::error_query($codigo_resultado),
                'Response' => [],
                'Transaction_id' => $transaction_id
            ]);
        }

        $domiciliosFiltrados = $this->filtrarYAgruparDomicilios($domicilios);

        if (empty($domiciliosFiltrados)) {
            $codigo_resultado = '401';
            $this->guardarResultadoApi($tax_id, null, $transaction_id, [], $codigo_resultado);

            return response()->json([
                'Parameters' => $request->only($parametros),
                'Status' => $codigo_resultado,
                'Message' => Misc::error_query($codigo_resultado),
                'Response' => [],
                'Transaction_id' => $transaction_id
            ]);
        }

        $respuesta = Misc::respuestaDomiciliosGovcheck($domiciliosFiltrados);
        $codigo_resultado = '200';

        $response_array = [
            'Parameters' => $request->only($parametros),
            'Status' => $codigo_resultado,
            'Message' => Misc::error_query($codigo_resultado),
            'Response' => $respuesta,
            'Transaction_id' => $transaction_id
        ];

        $this->guardarResultadoApi(
            $tax_id,
            null,
            $transaction_id,
            $response_array,
            $codigo_resultado
        );

        return response()->json($response_array);
    }

    public function idValidation(Request $request)
    {
        $usuario = Session::get('usuario');
        $user_id = $usuario->user_id;
        $name = trim($request->input('name'));
        $surname = trim($request->input('surname'));
        $dni = trim($request->input('dni'));
        $tax_id = trim($request->input('tax_id'));
        $birthdate = trim($request->input('birthdate'));
        $address = trim($request->input('address'));
        $telephone = trim($request->input('telephone'));
        $gender = trim($request->input('gender'));
        //--- Modificacion 24/09/2021
        $street_name = trim($request->input('street_name'));
        $street_number = trim($request->input('street_number'));
        $floor = trim($request->input('floor'));
        $apartment = trim($request->input('apartment'));
        $city = trim($request->input('city'));
        $state = trim($request->input('state'));
        $country_code = trim($request->input('country_code'));
        $idReg = trim($request->input('idReg'));

        //---

        $enviados_originales['name'] = $name;
        $enviados_originales['surname'] = $surname;
        $enviados_originales['dni'] = $dni;
        $enviados_originales['tax_id'] = $tax_id;
        $enviados_originales['birthdate'] = $birthdate;
        $enviados_originales['address'] = $address;
        $enviados_originales['telephone'] = $telephone;
        $enviados_originales['gender'] = $gender;
        $enviados_originales['street_name'] = $street_name;
        $enviados_originales['street_number'] = $street_number;
        $enviados_originales['floor'] = $floor;
        $enviados_originales['apartment'] = $apartment;
        $enviados_originales['city'] = $city;
        $enviados_originales['state'] = $state;
        $enviados_originales['country_code'] = $country_code;

        $dni = ApiControllerV1::normalizador_dni($dni);

        $enviados['name'] = ApiControllerV1::nombre_formateo($name);
        $enviados['surname'] = ApiControllerV1::nombre_formateo($surname);
        $enviados['dni'] = ApiControllerV1::normalizador_dni($dni);
        $enviados['tax_id'] = $tax_id;
        $tax_id = (isset($tax_id) && ApiControllerV1::tax_id_valido($tax_id)) ? $tax_id : '';
        $enviados['birthdate'] = $birthdate;
        $enviados['address'] = ApiControllerV1::acentos_enies($address);
        $enviados['telephone'] = ApiControllerV1::acentos_enies($telephone);
        $enviados['gender'] = ApiControllerV1::acentos_enies($gender);
        //------Modificacion 24/09/2021
        $enviados['street_name'] = ApiControllerV1::acentos_enies($street_name);
        $enviados['street_number'] = ApiControllerV1::acentos_enies($street_number);
        $enviados['floor'] = ApiControllerV1::acentos_enies($floor);
        $enviados['apartment'] = ApiControllerV1::acentos_enies($apartment);
        $enviados['city'] = ApiControllerV1::acentos_enies($city);
        $enviados['state'] = ApiControllerV1::acentos_enies($state);
        $enviados['country_code'] = ApiControllerV1::acentos_enies($country_code);

        //------
        $integridad = 0;
        $name_validation = 'FALSE';
        $surname_validation = 'FALSE';

        $p_url = $_SERVER['REQUEST_URI'];

        $array_txt = [];
        $consulta = SQLConnection::backendStoreProcedure('guardar_parametros_API', array($user_id, $name, $surname, $dni, $tax_id, $birthdate, $address, $telephone, $gender, $p_url), 'selectOne');


        // $producto = $usuario->producto ?? 71;
        $producto = $usuario->producto;

        if (!ApiControllerV1::tax_id_valido($enviados['tax_id'])) {
            $identificacion = !empty($tax_id) ? $tax_id : $dni;
            $resp = $this->consumirServicio($request, $identificacion);
            $status_code = '302';
            $data = [
                'Parameters' => $enviados_originales,
                'Status' => $status_code,
                'Message' => Misc::error_query($status_code),
                'Response' => [],
                'Transaction_id' => $resp->transaction_id,
            ];
            $this->guardarResultadoApi($enviados_originales['dni'], $enviados_originales['gender'], $resp->transaction_id, $data, $status_code);
            return response()->json($data);
        }

        if (!ApiControllerV1::dni_valido($enviados['dni'])) {
            $identificacion = !empty($tax_id) ? $tax_id : $dni;
            $resp = $this->consumirServicio($request, $identificacion);
            $status_code = '300';
            $data = [
                'Parameters' => $enviados_originales,
                'Status' => $status_code,
                'Message' => Misc::error_query($status_code),
                'Response' => [],
                'Transaction_id' => $resp->transaction_id,
            ];
            $this->guardarResultadoApi($enviados_originales['dni'], $enviados_originales['gender'], $resp->transaction_id, $data, $status_code);
            return response()->json($data);
        }

        if (!ApiControllerV1::fecha_valida($enviados['birthdate'])) {
            $identificacion = !empty($tax_id) ? $tax_id : $dni;
            $resp = $this->consumirServicio($request, $identificacion);
            $status_code = '317';
            $data = [
                'Parameters' => $enviados_originales,
                'Status' => $status_code,
                'Message' => Misc::error_query($status_code),
                'Response' => [],
                'Transaction_id' => $resp->transaction_id,
            ];
            $this->guardarResultadoApi($enviados_originales['dni'], $enviados_originales['gender'], $resp->transaction_id, $data, $status_code);
            return response()->json($data);
        }

        if (empty($tax_id) && empty($dni)) {
            $resp = $this->consumirServicio($request, $tax_id);
            $status_code = '310';
            $data = [
                'Parameters' => $enviados_originales,
                'Status' => $status_code,
                'Message' => Misc::error_query($status_code),
                'Response' => [],
                'Transaction_id' => $resp->transaction_id,
            ];
            $this->guardarResultadoApi($enviados_originales['dni'], $enviados_originales['gender'], $resp->transaction_id, $data, $status_code);
            return response()->json($data);
        }

        $identificacion = !empty($tax_id) ? $tax_id : $dni;

        if (strlen($name) < 2 || strlen($surname) < 2) {
            $resp = $this->consumirServicio($request, $identificacion);
            $status_code = '316';
            $data = [
                'Parameters' => $enviados_originales,
                'Status' => $status_code,
                'Message' => Misc::error_query($status_code),
                'Response' => [],
                'Transaction_id' => $resp->transaction_id,
            ];
            $this->guardarResultadoApi($enviados_originales['dni'], $enviados_originales['gender'], $resp->transaction_id, $data, $status_code);
            return response()->json($data);
        }

        if (!empty($tax_id)) {
            $taxid_dni = $tax_id;
        } else {
            $taxid_dni = $dni;
        }
        /* 06/12/2023 */

        // El producto 109 va a renaper, los demas van a afip.
        if ($producto == 109) {

            try {
                $persona_padron = $this->consultarApiPadron($dni, $gender);
            } catch (Exception $e) {
                $persona_padron = null;
            }
            if (!empty($persona_padron->fecha_nacimiento) && !self::esMayorDeEdad($persona_padron->fecha_nacimiento)) {
                $resp = $this->consumirServicio($request, $identificacion);
                $status_code = '313';
                $data = [
                    'Parameters' => $enviados_originales,
                    'Status' => $status_code,
                    'Message' => Misc::error_query($status_code),
                    'Response' => [],
                    'Transaction_id' => $resp->transaction_id,
                ];
                $this->guardarResultadoApi($enviados_originales['dni'], $enviados_originales['gender'], $resp->transaction_id, $data, $status_code);
                return response()->json($data);
            }

            // soloRenaperGBG NO GENERA CONSUMO (lo hace la función principal)
            $renaper = json_decode(ApiControllerV1::soloRenaperGBG($dni, $gender, false));

            if (empty($renaper)) {
                $resp = $this->consumirServicio($request, $identificacion);
                $status_code = '401';
                $data = [
                    'Parameters' => $enviados_originales,
                    'Status' => $status_code,
                    'Message' => Misc::error_query($status_code),
                    'Response' => [],
                    'Transaction_id' => $resp->transaction_id,
                ];
                $this->guardarResultadoApi($enviados_originales['dni'], $enviados_originales['gender'], $resp->transaction_id, $data, $status_code);
                return response()->json($data);
            }

            if (isset($renaper->Status) && $renaper->Status == '301') {
                $resp = $this->consumirServicio($request, $dni);
                $status_code = '401';
                $data = [
                    'Parameters' => $enviados_originales,
                    'Status' => $status_code,
                    'Message' => $renaper->Message ?? Misc::error_query($status_code),
                    'Response' => [],
                    'Transaction_id' => $resp->transaction_id,
                ];
                $this->guardarResultadoApi($enviados_originales['dni'], $enviados_originales['gender'], $resp->transaction_id, $data, $status_code);
                return response()->json($data);
            }

            $tiempo_curl = $renaper->tiempo_curl ?? 0;
            $proveedor = $renaper->proveedor ?? 'noCurl';
            $renaper_datos = $renaper->Response;

            $fecha_nacimiento_renaper = isset($renaper_datos->fechaNacimiento) ? Misc::convertirFormatoFecha($renaper_datos->fechaNacimiento) : null;
            if (!empty($fecha_nacimiento_renaper) && !self::esMayorDeEdad($fecha_nacimiento_renaper)) {
                $resp = $this->consumirServicio($request, $identificacion);
                $status_code = '313';
                $data = [
                    'Parameters' => $enviados_originales,
                    'Status' => $status_code,
                    'Message' => Misc::error_query($status_code),
                    'Response' => [],
                    'Transaction_id' => $resp->transaction_id,
                ];
                $this->guardarResultadoApi($enviados_originales['dni'], $enviados_originales['gender'], $resp->transaction_id, $data, $status_code);
                return response()->json($data);
            }

            if (!$gender || ($renaper_datos && $gender != $renaper_datos->gender)) {
                $gender = $renaper_datos->gender;
            }

            $datos_renaper = SQLConnection::backendStoreProcedure('RENAPER_BUSCAR', array($dni, $gender), 'select');
            $datos = [];
            if ($datos_renaper) {
                $datos[0] = $datos_renaper[0];
            }
        } else {

            try {
                $persona_padron = $this->consultarApiPadron(!empty($tax_id) ? $tax_id : $dni, $gender);
            } catch (Exception $e) {
                $persona_padron = null;
            }
            if (!empty($persona_padron->fecha_nacimiento) && !self::esMayorDeEdad($persona_padron->fecha_nacimiento)) {
                $resp = $this->consumirServicio($request, $identificacion);
                $status_code = '313';
                $data = [
                    'Parameters' => $enviados_originales,
                    'Status' => $status_code,
                    'Message' => Misc::error_query($status_code),
                    'Response' => [],
                    'Transaction_id' => $resp->transaction_id,
                ];
                $this->guardarResultadoApi($enviados_originales['dni'], $enviados_originales['gender'], $resp->transaction_id, $data, $status_code);
                return response()->json($data);
            }

            // GENERA UN CONSUMO
            if (!empty($tax_id) && strlen($tax_id) == 11) {

                $afip = json_decode(AFIPController::obtenerPadron($tax_id, true, 'AR', false));
                $tiempo_curl = $afip->tiempo_curl ?? 0;
                $proveedor = $afip->proveedor_curl ?? 'noCurl';

            } elseif (!empty($taxid_dni) && strlen($taxid_dni) == 8) {
                $cuitss = ApiControllerV1::BuscarCuit($taxid_dni, 'S');  /* Busca CUITs para el dni solicitado, y los pasa por AFIP */
                $tax_id = $cuitss[0]->cuit ?? $tax_id;

            }


            $datos = SQLConnection::backendStoreProcedure('validar_gbg_nombre', array($dni, $tax_id), 'select');

            if (count($datos) == 0) {
                list($cuitss, $tiempo_curl, $proveedor_curl) = ApiControllerV1::BuscarCuit_Forzado($dni, 'S');  /* Busca CUITs para el dni solicitado, y los pasa por AFIP */
                $datos = SQLConnection::backendStoreProcedure('validar_gbg_nombre', array($dni, $cuitss[0]->cuit), 'select');
            }
            /* 26/07/2021 Si no devuelve nada, guardamos con lo que busco, sino Lo hacemos dentro del foreach, para guardar la consulta por el cuit */
            if (sizeOf($datos) < 1) {
                $resp = $this->consumirServicio($request, $taxid_dni);
            }
        }

        $result = [];
        //----------------------------------------------------
        $address_validation = 'FALSE';
        $address_complete_validation = 'FALSE';
        $dni_validation = 'FALSE';
        $tax_id_validation = 'FALSE';
        $birthdate_validation = 'FALSE';
        $telephone_validation = 'FALSE';
        $gender_validation = 'FALSE';
        $pcia_validation = 'FALSE';
        //----------------------------------------------------

        foreach ($datos as $key => $persona) {
            /* 06/12/2023 */
            $info = new \stdClass();
            if ($producto == 109) {

                $persona->nombres = ApiControllerV1::nombre_formateo($persona->nombres);
                $persona->apellidos = ApiControllerV1::nombre_formateo($persona->apellido);

                if ($persona->fechaNacimiento) {
                    $fecha_nacimiento = substr($persona->fechaNacimiento, 6, 4) . '-' . substr($persona->fechaNacimiento, 3, 2) . '-' . substr($persona->fechaNacimiento, 0, 2);
                } else {
                    $fecha_nacimiento = '';
                }
                //$fecha_nacimiento = substr($persona->fechaNacimiento,6,4) . '-' . substr($persona->fechaNacimiento,3,2) . '-' . substr($persona->fechaNacimiento,0,2);
                $persona->fecha_nacimiento = $fecha_nacimiento;
                //$persona->sexo = $persona->sexo;
                $persona->cuit = $persona->identificacion;
                //$persona->dni = $persona->dni;
                if ($persona->fechaf) {
                    $fecha_fallecimiento = substr($persona->fechaf, 6, 4) . '-' . substr($persona->fechaf, 3, 2) . '-' . substr($persona->fechaf, 0, 2);
                } else {
                    $fecha_fallecimiento = '';
                }
                $persona->fecha_fallecimiento = $fecha_fallecimiento;

                $info->taxid = $persona->identificacion;
                $info->tipo = null;
                $info->nombre = $persona->apellidos ?? '' . ' ' . $persona->nombres ?? '';
                $calle = $persona->calle ?? '';
                $numero = $persona->numero ?? '';
                $piso = $persona->piso ?? '';
                $departamento = $persona->departamento ?? '';
                $domicilio = $calle . ' ' . $numero . ' ' . $piso . ' ' . $departamento;
                $domicilio = str_replace('    ', ' ', $domicilio);
                $domicilio = str_replace('   ', ' ', $domicilio);
                $domicilio = trim($domicilio);

                $info->domicilio = str_replace('  ', ' ', $domicilio);
                $info->localidad = ($persona->ciudad && $persona->ciudad !== NULL) ? $persona->ciudad : ($persona->municipio ?? '');
                $info->provicia = $persona->provincia;
                $info->codpos = $persona->cpostal;
                $info->telefonos = null;
                $info->actividades = null;
                $info->empleadores = null;
                $info->monotributo = null;
                $info->autonomo = null;
                $info->emails = null;
                $info->es_empleador = null;
                $info->facturas_apocrifas = null;

                $info->domicilio = ApiControllerV1::eliminar_acentos($info->domicilio);
                $info->provicia = ApiControllerV1::eliminar_acentos($info->provicia);
                $info->localidad = ApiControllerV1::eliminar_acentos($info->localidad);

                // El registro elegido es este que trajo Renaper
                $registro_elegido = new \stdClass();
                $registro_elegido->street_name = $persona->calle;
                $registro_elegido->state = $info->provicia;
                $registro_elegido->city = $info->localidad;
                $registro_elegido->country_code = $persona->pais ?? 'AR';
                $registro_elegido->street_number = $persona->numero;
                $registro_elegido->floor = $persona->piso;
                $registro_elegido->appartment = $persona->departamento;

            } else {
                /* 05/12/2023 */
                $persona->nombres = ApiControllerV1::nombre_formateo($persona->nombres);
                $persona->apellidos = ApiControllerV1::nombre_formateo($persona->apellidos);
                //$info = SQLConnection::backendStoreProcedure('[sp_procesos_cuit_enrichment_api_datos]',array(1,$persona->cuit),'selectOne');
                //No se usa mas el SP de arriba, ahora se llama al de telefonos y al de domicilios

                $datos_domicilios = SQLConnection::backendStoreProcedure('api_domicilios', array($persona->cuit));

                //----- El registro elegido es el de tipo RENAPER, si no hay sera el Fiscal, y sino el Legal
                $registro_elegido = new \stdClass();

                foreach ($datos_domicilios as $key => $value) {
                    if ($value->nombre_fuente == 'RENAPER') { // Es el mas importante, si lo tiene pisa lo que sea y sale
                        $registro_elegido = $datos_domicilios[$key];
                        break;
                    }
                    if ($value->address_type == 'F') { // El Fiscal puede pisar al Legal
                        $registro_elegido = $datos_domicilios[$key];
                    }
                    if ($value->address_type == 'L' && !isset($registro_elegido->domicilio)) { // solo toma el Legal si no tengo ninguno de los otros 2
                        $registro_elegido = $datos_domicilios[$key];
                    }
                }
                if (empty($registro_elegido)) { // Si esta vacio toma el primero
                    $registro_elegido = (count($datos_domicilios) == 0 || is_null($datos_domicilios)) ? '' : $datos_domicilios[0];
                }

                //$info->domicilio = ApiControllerV1::eliminar_acentos($registro_elegido->domicilio) ?? '';
                $info->domicilio = isset($registro_elegido->domicilio) ? ApiControllerV1::eliminar_acentos($registro_elegido->domicilio) : '';

                //$info->provicia = ApiControllerV1::eliminar_acentos($registro_elegido->state) ?? '';
                $info->provicia = isset($registro_elegido->state) ? ApiControllerV1::eliminar_acentos($registro_elegido->state) : '';

                //$info->localidad = ApiControllerV1::eliminar_acentos($registro_elegido->city) ?? '';
                $info->localidad = isset($registro_elegido->city) ? ApiControllerV1::eliminar_acentos($registro_elegido->city) : '';

                $info->codpos = $registro_elegido->zip_code ?? '';

            }


            /* 26/07/2021 Lo hacemos dentro del foreach, para guardar la consulta por el cuit */
            $resp = $this->consumirServicio($request, $persona->cuit);

            if (!empty($persona->nombres)) {
                $name_validation = ApiControllerV1::validacionNombre($enviados, $persona);
            }

            if (!empty($persona->apellidos)) {
                $surname_validation = ApiControllerV1::validacionApellido($enviados, $persona);
            }

            $localidad = '';
            $provincia = '';
            $pais = '';
            $address_validation = 'FALSE';


            $full_address = explode(',', $enviados['address']);

            if (sizeOf($full_address) > 0) {

                //$domicilio = $info->domicilio; //-> SE COMENTA Y AGREGA LA LINEA DE ABAJO PARA SOLUCIONAR PROBLEMA E RESPUESTA DE AFIP
                $domicilio = html_entity_decode($info->domicilio); //-> ESTO SE AGREGO PARA CONVERTIR CODIGO HTML QUE ENVIA AFIP EN LA RESPUESTA, GENRABA PROBLEMAS EN LA RESPUESTA JSON
                // Elimino blancos 
                $domicilio = trim($domicilio);
                while (strpos($domicilio, '  ') !== false) {
                    $domicilio = str_replace('  ', ' ', $domicilio);
                }

                $full_address[0] = trim($full_address[0]);
                while (strpos($full_address[0], '  ') !== false) {
                    $full_address[0] = str_replace('  ', ' ', $full_address[0]);
                }

                // Comparo si el domicilio es exactamente igual
                if ($full_address[0] == $domicilio && $domicilio != '') {
                    $address_validation = 'TRUE';
                } else {
                    // Comparamos que no haya palabras o partes distintas 
                    $address_contains = explode(' ', $full_address[0]);
                    foreach ($address_contains as $address_value) {
                        if ($address_value == '') {
                            continue;
                        }

                        if (stripos($domicilio, $address_value) !== false && strlen($address_value) > 1) {
                            if ($address_validation !== 'PARTIALLY TRUE') {
                                $address_validation = 'TRUE';
                            }
                            $domicilio = str_ireplace($address_value, '', $domicilio);
                        } else {
                            // Tiene algo distinto y era verdadero, pasa a ser parcialmente 
                            if ($address_validation == 'TRUE') {
                                $address_validation = 'PARTIALLY TRUE';
                            }
                        }
                    }
                    // Si termina de comparar y en domicilio todavia le queda algo, es porque el de la BD tiene mas cosas
                    $domicilio = trim($domicilio);
                    if ($address_validation == 'TRUE' && $domicilio !== '') {
                        $address_validation = 'PARTIALLY TRUE';
                    }
                }

                $localidad = (isset($full_address[1])) ? strtoupper(trim($full_address[1])) : '';
                $provincia = (isset($full_address[2])) ? strtoupper(trim($full_address[2])) : '';
                $pais = (isset($full_address[3])) ? trim($full_address[3]) : 'ARGENTINA';


                if (isset($info->provicia)) {
                    if ($info->provicia == 'CIUDAD AUTONOMA DE BUENOS AIRES' || $info->provicia == 'CIUDAD AUTONOMA BUENOS AIRES' || $info->provicia == 'CIUDAD DE BUENOS AIRES' || $info->provicia == 'CIUDAD BUENOS AIRES' || $info->provicia == 'CABA' || $info->provicia == 'C.A.B.A.' || $info->provicia == 'CAPITAL FEDERAL') {
                        $info->provicia = 'CIUDAD AUTONOMA DE BUENOS AIRES';
                    }
                }

                //$registro_elegido->state = strtoupper($info->provicia);
                $registro_elegido->state = isset($info->provicia) ? strtoupper($info->provicia) : '';
                //$registro_elegido->city = strtoupper($info->localidad);
                $registro_elegido->city = isset($info->localidad) ? strtoupper($info->localidad) : '';


                if ($provincia == 'CIUDAD AUTONOMA DE BUENOS AIRES' || $provincia == 'CIUDAD AUTONOMA BUENOS AIRES' || $provincia == 'CIUDAD DE BUENOS AIRES' || $provincia == 'CIUDAD BUENOS AIRES' || $provincia == 'CABA' || $provincia == 'C.A.B.A.' || $provincia == 'CAPITAL FEDERAL') {
                    $provincia = 'CIUDAD AUTONOMA DE BUENOS AIRES';
                }

                /*
                if( ($provincia == 'CIUDAD AUTONOMA DE BUENOS AIRES' && $info->provicia == 'CIUDAD AUTONOMA DE BUENOS AIRES' ) || 
                        $info->provicia == $provincia  ){
                    $pcia_validation = 'TRUE';
                } 
                */
                if (isset($info->provicia) && $info->provicia == $provincia) {
                    $pcia_validation = 'TRUE';
                }

                if ($address_validation == 'TRUE') {
                    if (($provincia == 'CIUDAD AUTONOMA DE BUENOS AIRES' && $info->provicia == 'CIUDAD AUTONOMA DE BUENOS AIRES') || ($info->provicia == $provincia && $info->localidad == $localidad) && ($pais = 'ARGENTINA' or $pais == 'AR')) {
                        $address_validation = 'TRUE';
                    } else {
                        $address_validation = 'PARTIALLY TRUE';
                    }
                }
            }

            //$birthdate_validation = 'FALSE'; //--> esto se lleva mas arriba.
            if ($enviados['birthdate'] == $persona->fecha_nacimiento) {
                $birthdate_validation = 'TRUE';
                $integridad += 100;
            }

            //$dni_validation = 'FALSE';  //--> esto se lleva mas arriba.
            if ($enviados['dni'] == $persona->dni) {
                $dni_validation = 'TRUE';
                $integridad += 100;
            }

            //$tax_id_validation = 'FALSE'; //--> esto se lleva mas arriba.
            if ($enviados['tax_id'] == $persona->cuit) {
                $tax_id_validation = 'TRUE';
            }

            //$telephone_validation = 'FALSE'; //--> esto se lleva mas arriba.
            $telephone = SQLConnection::backendStoreProcedure('api_info_telefonos_cuit', array($persona->cuit));

            foreach ($telephone as $key2 => $telefonos) {
                $value = $telefonos->telefono;
                if ($value == $enviados['telephone'] && $enviados['telephone'] != '') {
                    $telephone_validation = 'TRUE';
                } else if (stripos(trim($value), $enviados['telephone']) !== false || stripos('11' . trim($value), $enviados['telephone']) !== false) {
                    $telephone_validation = 'PARTIALLY TRUE';
                } else {
                    $telephone_validation = 'FALSE';
                }
            }
            //$gender_validation = 'FALSE';  //--> esto se lleva mas arriba.
            if (!empty($persona->ID_TRAMITE_PRINCIPAL)) {
                if (strtoupper($enviados['gender']) == strtoupper($persona->sexo)) {
                    $gender_validation = 'TRUE';
                }
            }

            $address_complete_validation = 'FALSE';

            //---- EN ESTE CONDICION CAMBIA EL NOMBRE SI ES CIUDAD AUTONOMA DE BUENOS AIRES, PARA PODER HACER LA COMPARACION CON EL REGISTRO OBTENIDO
            if (
                strtoupper($enviados['state']) == 'CABA' || strtoupper($enviados['state']) == 'C.A.B.A.' ||
                strtoupper($enviados['state']) == 'CAPITAL FEDERAL' ||
                strtoupper($enviados['state']) == 'CIUDAD BUENOS AIRES' ||
                strtoupper($enviados['state']) == 'CIUDAD AUTONOMA DE BUENOS AIRES' ||
                strtoupper($enviados['state']) == 'CIUDAD AUTONOMA BUENOS AIRES'
            ) {
                $enviados['state'] = 'CIUDAD AUTONOMA DE BUENOS AIRES';
            }

            try {
                //---- DEFENIENDO LAS FUNCION LEVENSHTEIN
                $levenshtein_nombre_calle = levenshtein(strtoupper((strlen($enviados['street_name']) > 0) ? $enviados['street_name'] : 'null'), $registro_elegido->street_name);
                $levenshtein_provincia = levenshtein(strtoupper($enviados['state']), $registro_elegido->state);
                $levenshtein_localidad = levenshtein(strtoupper($enviados['city']), $registro_elegido->city);
            } catch (\Throwable $th) {
                $levenshtein_nombre_calle = 2;
                $levenshtein_provincia = 2;
                $levenshtein_localidad = 2;
                $objTemporal = new \stdClass();
                $objTemporal->country_code = 'FALSE';
                $objTemporal->street_number = 'FALSE';
                $objTemporal->floor = 'FALSE';
                $objTemporal->appartment = 'FALSE';
                $registro_elegido = $objTemporal;
            }
            //---- COMIENZO DE LA VALIDACION DEL DOMICILIO COMPLETO
            //----- SI EL PAIS ES VALIDO
            if (strtoupper($enviados['country_code']) == $registro_elegido->country_code) {
                //---- SI EL NOMBRE DE LA CALLE ES VALIDO
                if ($levenshtein_nombre_calle == 1 || $levenshtein_nombre_calle == 0) {
                    //----- SI LA PROVINCIA ES VALIDA 
                    if ($levenshtein_provincia == 0 || $levenshtein_provincia == 1) {
                        //---- SI LA LOCALIDAD ES VALIDA
                        if ($levenshtein_localidad == 0 || $levenshtein_localidad == 1 || (strtoupper($enviados['state']) == 'CIUDAD AUTONOMA BUENOS AIRES')) {
                            //---- SI LA ALTURA ES VALIDA
                            if (strtoupper($enviados['street_number']) == $registro_elegido->street_number) {
                                //---- SI TIENE PISO
                                if ($registro_elegido->floor != NULL) {
                                    //---- SI EL PISO ES VALIDO
                                    if (strtoupper($enviados['floor']) == $registro_elegido->floor) {
                                        //---- SI TIENE DEPARTAMENTO
                                        if ($registro_elegido->appartment != NULL) {
                                            //---- SI EL DEPARTAMENTO ES VALIDO O NO
                                            if (strtoupper($enviados['apartment']) == $registro_elegido->appartment) {
                                                $address_complete_validation = 'TRUE';
                                            } else {
                                                $address_complete_validation = 'PARTIALLY TRUE';
                                            }
                                        } else {
                                            //---- SI NO TIENE DEPARTAMENTO
                                            $address_complete_validation = 'TRUE';
                                        }
                                    } else {
                                        //--- SI EL PISO ES INVALIDO
                                        $address_complete_validation = 'PARTIALLY TRUE';
                                    }
                                } else {
                                    //--- SI NO TIENE PISO
                                    $address_complete_validation = 'TRUE';
                                }
                            } else {
                                //---- SI LA ALTURA ES INVALIDA
                                $address_complete_validation = 'PARTIALLY TRUE';
                            }
                        } else {
                            //------ SI LA LOCALIDAD ES INVALIDA
                            $address_complete_validation = 'FALSE';
                        }
                    } else {
                        //--- SI LA PROVINCIA ES INVALIDA
                        $address_complete_validation = 'FALSE';
                    }
                } else {
                    //--- SI LA CALLE NO ES INVALIDA
                    $address_complete_validation = 'FALSE';
                }
            } else {
                //--- SI EL PAIS ES INVALIDO
                $address_complete_validation = 'FALSE';
            }

            //-------------------------------------- FIN DE MODIFICACION 24/09/2021
            //---------MODIFICACION 02/12/2021
            //------- COMIENZO DE VALIDACION INDIVIDUAL DEL DOMICILIO
            //-- VALIDACION DE CODIGO PAIS
            $country_code_validation = 'FALSE';
            $street_name_validation = 'FALSE';
            $state_validation = 'FALSE';
            $city_validation = 'FALSE';
            $street_number_validation = 'FALSE';
            $floor_validation = 'FALSE';
            $apartment_validation = 'FALSE';

            if ($enviados['country_code'] && $enviados['country_code'] !== '') {
                $country_code_validation = ((strtoupper($enviados['country_code']) == $registro_elegido->country_code) ||
                    (strtoupper($enviados['country_code']) == 'AR' && $registro_elegido->country_code == 'ARGENTINA') ||
                    (strtoupper($enviados['country_code']) == 'ARGENTINA' && $registro_elegido->country_code == 'AR')) ? 'TRUE' : 'FALSE';
            }
            //-- VALIDACION DEL NOMBRE DE CALLE
            if ($enviados['street_name'] && $enviados['street_name'] !== '') {
                $street_name_validation = ($levenshtein_nombre_calle == 1) ? 'TRUE' : (($levenshtein_nombre_calle == 0) ? 'TRUE' : 'FALSE');
            }

            //-- VALIDACION DEL NOMBRE DE PROVINCIA
            if ($enviados['state'] && $enviados['state'] !== '') {
                $state_validation = ($levenshtein_provincia == 0 || $levenshtein_provincia == 1) ? 'TRUE' : 'FALSE';
            }
            //-- VALIDACION DE NOMBRE DE LOCALIDAD
            if ($enviados['city'] && $enviados['city'] !== '') {
                $city_validation = ($levenshtein_localidad == 0 || $levenshtein_localidad == 1) ? 'TRUE' : 'FALSE';
            }
            //-- VALIDACION DE ALTURA DE CALLE
            if ($enviados['street_number'] && $enviados['street_number'] !== '') {
                $street_number_validation = (strtoupper($enviados['street_number']) == $registro_elegido->street_number) ? 'TRUE' : 'FALSE';
            }
            //-- VALIDACION DE PISO , SI EXISTE
            if ($enviados['floor'] && $enviados['floor'] !== '') {
                if ($registro_elegido->floor != NULL) {
                    $floor_validation = (strtoupper($enviados['floor']) == $registro_elegido->floor) ? 'TRUE' : 'FALSE';
                }
            } else {
                if (($registro_elegido->floor == NULL || $registro_elegido->floor == '') && ($enviados['street_name'] && $enviados['street_name'] !== '')) {
                    $floor_validation = 'TRUE';
                }
            }

            //-- VALIDACION DE DEPARTAMENTO
            if ($enviados['apartment'] && $enviados['apartment'] !== '') {
                if ($registro_elegido->appartment != NULL) {
                    $apartment_validation = (strtoupper($enviados['apartment']) == $registro_elegido->appartment) ? 'TRUE' : 'FALSE';
                }
            } else {
                if (($registro_elegido->appartment == NULL || $registro_elegido->appartment == '') && ($enviados['street_name'] && $enviados['street_name'] !== '')) {
                    $apartment_validation = 'TRUE';
                }
            }

            //--------- FIN DE MODIFICACION
            $result[2] = new \stdClass();
            $result[2]->dni = $dni_validation;
            $result[2]->tax_id = $tax_id_validation;
            $result[2]->birthdate = $birthdate_validation;
            $result[2]->name = $name_validation;
            $result[2]->surname = $surname_validation;
            $result[2]->address = $address_validation;
            //$result[2]->stateV            = $pcia_validation;
            $result[2]->telephone = $telephone_validation;
            $result[2]->gender = $gender_validation;
            $result[2]->deceased = ($persona->fecha_fallecimiento !== '') ? 'TRUE' : 'FALSE';
            $result[2]->transaction_id = $resp->transaction_id;
            $result[2]->legal_address = html_entity_decode($info->domicilio) ?? 'SIN DATOS'; //-> SE AGREGA PARA CONVERTIR CODIFICACION HTML QUE DEVUELVE AFIP
            $result[2]->state = $info->provicia ?? 'SIN DATOS';
            $result[2]->city = $info->localidad ?? 'SIN DATOS';
            $result[2]->zip = $info->codpos ?? 'SIN DATOS';
            //---- MODIFICACION 24/09/2021
            $result[2]->complete_address = $address_complete_validation;
            $result[2]->country_code = $registro_elegido->country_code ?? 'SIN DATOS';
            $result[2]->street_name = $registro_elegido->street_name ?? 'SIN DATOS';
            $result[2]->street_number = $registro_elegido->street_number ?? 'SIN DATOS';
            $result[2]->floor = $registro_elegido->floor ?? 'SIN DATOS';
            $result[2]->apartment = $registro_elegido->appartment ?? 'SIN DATOS';
            //---- FIN DE MODIFICACION 
            //---- MODIFICACION 02/12/2021


            if ($enviados['state'] && $enviados['state'] !== '') {
                $pcia_validation = $state_validation;
            }

            $result[2]->individual_address_validations = array(
                'country_code_validation' => $country_code_validation,
                'street_name_validation' => $street_name_validation,
                'state_validation' => $pcia_validation,
                'city_validation' => $city_validation,
                'street_number_validation' => $street_number_validation,
                'floor_validation' => $floor_validation,
                'apartment_validation' => $apartment_validation

            );
            //--- FIN DE MODIFICACION
            SQLConnection::backendStoreProcedure('guardar_parametros_API_2', array($consulta->id, $resp->transaction_id), 'selectOne');
        }

        if ($name_validation == 'TRUE') {
            $integridad += 100;
        } else if ($name_validation == 'PARTIALLY TRUE') {
            $integridad += 48;
        }

        if ($surname_validation == 'TRUE') {
            $integridad += 100;
        } else if ($surname_validation == 'PARTIALLY TRUE') {
            $integridad += 48;
        }

        if ($address_validation == 'TRUE') {
            $integridad += 100;
        } else if ($address_validation == 'PARTIALLY TRUE') {
            $integridad += 48;
        }

        if ($pcia_validation == 'TRUE') {
            $integridad += 100;
        } else if ($pcia_validation == 'PARTIALLY TRUE') {
            $integridad += 48;
        }


        //---- MODIFICACION 24/09/2021
        if ($address_complete_validation == 'TRUE') {
            $integridad += 100;
        } else if ($address_complete_validation == 'PARTIALLY TRUE') {
            $integridad += 48;
        }
        //----

        $resultado_integridad = round(($integridad / 6), 2);
        $status_code = '200';
        $data = [
            'Parameters' => $enviados_originales,
            'Status' => $status_code,
            'Message' => Misc::error_query($status_code),
            'Response' => $result,
            'Integrity' => $resultado_integridad . ' %',
        ];
        $this->guardarResultadoApi($enviados_originales['dni'], $enviados_originales['gender'], $resp->transaction_id ?? null, $data, $status_code);
        return response()->json($data);

    }

    public function obtenerInfoDniCuitAmpliada(Request $request) {
        $cuit = $request->input('cuit');
        $nombre = trim($request->input('nombre'));
        $nombre_contains = '';
        
        if ($nombre) {
            $nombre_contains = Misc::parsearBusquedaPadron($nombre);
        }
        
        $usuario = Session::get('usuario');
        $respuesta = new \stdClass();

        $consumo = $this->consumirServicio($request, $cuit);
        $id_consumo = $consumo->transaction_id;
        $respuesta->Transaction_id = $id_consumo;

        if (isset($cuit[0]) && $cuit[0] != '2' && strlen($cuit) == 11) {
            $respuesta->identificacion_buscada = $cuit;
            $respuesta->nombre_buscado = $nombre;
            $respuesta->fecha = date("Y-m-d h:i:s");
            $respuesta->codigo_error = '318';
            $respuesta->mensaje_error = Misc::error_query('318');
            $respuesta->fidelitas_response = [];

            $this->guardarResultadoApi($cuit, '', $id_consumo, $respuesta, '318');

            return response()->json($respuesta);
        }

        $validacion = SQLConnection::backendStoreProcedure('api_validacion_dni_cuit', array($cuit, $nombre, $nombre_contains), false);
        
        if (empty($validacion)) {
            $respuesta->identificacion_buscada = $cuit;
            $respuesta->nombre_buscado = $nombre;
            $respuesta->fecha = date("Y-m-d h:i:s");
            $respuesta->codigo_error = '401';
            $respuesta->mensaje_error = Misc::error_query('401');
            $respuesta->fidelitas_response = [];

            $this->guardarResultadoApi($cuit, '', $id_consumo, $respuesta, '401');

            return response()->json($respuesta);
        }

        foreach ($validacion as $key => $value) {
            $respuesta->identificacion_buscada = $cuit;
            $respuesta->nombre_buscado = $nombre;
            $respuesta->fecha = date("Y-m-d h:i:s");

            if ($value->error > 0) {
                // Mapeo los codigos de error del SP a codigos de error api
                $codigo_v4 = match((int)$value->error) {
                    1 => '310',
                    2 => '319',
                    3 => '401',
                    4 => '416',
                    default => strval($value->error),
                };
                $respuesta->codigo_error = $codigo_v4;
                $respuesta->mensaje_error = Misc::error_query($codigo_v4);
                $respuesta->fidelitas_response = [];

                $this->guardarResultadoApi($cuit, '', $id_consumo, $respuesta, $codigo_v4);

                return response()->json($respuesta);
            }

            if ($key == 0) {
                $respuesta->codigo_error = '200';
                $respuesta->mensaje_error = Misc::error_query('200');
                $respuesta->fidelitas_response = [];
            }

            $respuesta->fidelitas_response[$key]['mensaje'] = $value->mensaje_validacion;
            $respuesta->fidelitas_response[$key]['validacion'] = $value->validacion;
            $respuesta->fidelitas_response[$key]['nombre_correcto'] = trim($value->nombre_correcto);
            $respuesta->fidelitas_response[$key]['cuit_buscado'] = trim($value->cuit_buscado);

            $afip = json_decode(AFIPController::obtenerPadron($value->cuit_buscado, false, 'AR', false));
            $this->acumularTiempoAfip($afip);

            $afip = SQLConnection::backendStoreProcedure('api_info_afip_cuit', array($value->cuit_buscado), true);
            
            if (!empty($afip->fecha_nacimiento) && !self::esMayorDeEdad($afip->fecha_nacimiento)) {
                $respuesta->identificacion_buscada = $cuit;
                $respuesta->nombre_buscado = $nombre;
                $respuesta->fecha = date("Y-m-d h:i:s");
                $respuesta->codigo_error = '313';
                $respuesta->mensaje_error = Misc::error_query('313');
                $respuesta->fidelitas_response = [];

                $this->guardarResultadoApi($cuit, '', $id_consumo, $respuesta, '313');

                return response()->json($respuesta);
            }

            /* Si no tenemos la fecha de nacimiento en la BD (el campo buscar_fecha_nac viene con valor 1)
            entonces, buscamos en Renaper */

            if ($afip->buscar_fecha_nac == 1) {
                if ($afip->sexo == null) {
                    $renaper = $this->obtenerResRenaper($afip->dni, 'M');
                    if (!isset($renaper->Status) || $renaper->Status !== 'OK') {
                        $renaper = $this->obtenerResRenaper($afip->dni, 'F');
                    }
                    if (!isset($renaper->Status) || $renaper->Status !== 'OK') {
                        $renaper = $this->obtenerResRenaper($afip->dni, 'X');
                    }
                } else {
                    $renaper = $this->obtenerResRenaper($afip->dni, $afip->sexo);
                }
            }

            $res_renaper = $renaper->Response ?? null;

            /* FIN RENAPER */
             
            $fecha_nacimiento = isset($res_renaper->fechaNacimiento) ? Misc::convertirFormatoFecha($res_renaper->fechaNacimiento) : $afip->fecha_nacimiento;
            
            if (!empty($fecha_nacimiento) && !self::esMayorDeEdad($fecha_nacimiento)) {
                $respuesta->identificacion_buscada = $cuit;
                $respuesta->nombre_buscado = $nombre;
                $respuesta->fecha = date("Y-m-d h:i:s");
                $respuesta->codigo_error = '313';
                $respuesta->mensaje_error = Misc::error_query('313');
                $respuesta->fidelitas_response = [];

                $this->guardarResultadoApi($cuit, '', $id_consumo, $respuesta, '313');

                return response()->json($respuesta);
            }

            $respuesta->fidelitas_response[$key]['afip'] = new \stdClass();
            /* 23/07/2021: El sp api_info_afip_cuit devuelve mas datos, entonces tomamos solo los campos que necesitamos */
            
            $respuesta->fidelitas_response[$key]['afip']->responsable_inscripto = $afip->responsable_inscripto;
            $respuesta->fidelitas_response[$key]['afip']->monotributo = $afip->monotributo;
            $respuesta->fidelitas_response[$key]['afip']->fecha_nacimiento = $fecha_nacimiento;
            $respuesta->fidelitas_response[$key]['afip']->persona_fallecida = $afip->persona_fallecida;

            $domicilios = SQLConnection::backendStoreProcedure('api_info_domicilios_cuit', array($value->cuit_buscado), false);

            /* 22/04/2021: Se pidio que solo devuelva un domicilio (prefenrentemente el fiscal) */
            if (sizeof($domicilios) > 0) {
                $domiclio_fiscal = $domicilios[0];
                foreach ($domicilios as $dom) {
                    if ($dom->tipo_de_domicilio == 'Fiscal') {
                        $domiclio_fiscal = $dom;
                    }
                }
                $respuesta->fidelitas_response[$key]['domicilios'] = $domiclio_fiscal;
            }
        }
        

        $this->guardarResultadoApi($cuit, '', $id_consumo, $respuesta, '200');

        return response()->json($respuesta);
    }

    /*
        Funcion para recortar los parametros devueltos al cliente que sean muy largos
    */
    private static function recortarParametros(array $parametros)
    {
        if (isset($parametros['selfie_image']) && gettype($parametros['selfie_image']) === 'string') {
            $parametros['selfie_image'] = substr($parametros['selfie_image'], 0, 15) . '...';
        }
        return $parametros;
    }

    /*
        Funcion generica para responder un error en la consulta, guarda el resultado en la base de datos.
        $usarNodoNotification=true: formato govcheck con nodo Notification envolviendo Status/Message.
        $usarNodoNotification=false: Status/Message sueltos en la raiz (resto de APIs).
    */
    private function responderError(
        array $parametros,
        string $codigo_resultado,
        int $transaction_id = null,
        bool $usarNodoNotification = true
    ) {
        $response_array = ['Parameters' => self::recortarParametros($parametros)];

        if ($usarNodoNotification) {
            $response_array['Notification'] = [
                'Status' => $codigo_resultado,
                'Message' => Misc::error_query($codigo_resultado),
            ];
        } else {
            $response_array['Status'] = $codigo_resultado;
            $response_array['Message'] = Misc::error_query($codigo_resultado);
        }

        $response_array['Response'] = [];

        if ($transaction_id) {
            $response_array['Transaction_id'] = $transaction_id;
        }

        $this->guardarResultadoApi(
            $parametros['tax_id'] ?? $parametros['national_id'] ?? null,
            $parametros['gender'] ?? null,
            $transaction_id,
            $response_array,
            $codigo_resultado
        );

        return response()->json($response_array);
    }

    /*
        Funcion para responder errores de validacion de parametros
    */
    private function validarFormatoParametros(Request $request, $parametros, $transaction_id = null, bool $usarNodoNotification = true)
    {
        $reglas_formato = collect([
            'national_id' => ['digits_between:7,8'],
            'tax_id' => ['digits:11'],
            'gender' => ['string', 'in:m,f,x,M,F,X'],
            'id_main_issue' => ['string'],
            'copy' => ['string'],
            'issue_date' => ['date_format:Y-m-d'],
            'expiry_date' => ['date_format:Y-m-d']
        ])->only($parametros)->toArray();

        $validator = Validator::make($request->all(), $reglas_formato);

        if ($validator->errors()->has('tax_id')) {
            $codigo_resultado = '302';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                $usarNodoNotification
            );
        }

        if ($validator->errors()->has('national_id')) {
            $codigo_resultado = '300';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                $usarNodoNotification
            );
        }

        if ($validator->errors()->has('gender')) {
            $codigo_resultado = '304';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                $usarNodoNotification
            );
        }

        if ($validator->errors()->has('expiry_date') || $validator->errors()->has('issue_date')) {
            $codigo_resultado = '317';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                $usarNodoNotification
            );
        }
    }

    /*
        Funcion para validar los parametros obligatorios en las APIs de govcheck.
    */
    private function validarParametrosObligatoriosGovcheck(Request $request, $parametros, $transaction_id)
    {
        $rules = collect([
            'national_id' => ['required_without:tax_id',],
            'tax_id' => ['required_without:national_id',],
            'gender' => ['required',],
        ])->only($parametros)->toArray();

        $validator = Validator::make($request->all(), $rules);
        $errors = $validator->errors();

        if ($errors->has('national_id') || $errors->has('tax_id')) {
            $codigo_resultado = '310';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id
            );
        }

        if ($validator->errors()->has('gender')) {
            $codigo_resultado = '304';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id
            );
        }
    }

    /**
     * Valida los parámetros obligatorios requeridos por las APIs de PersonalCred y FaceMatch.
     *
     * Construye dinámicamente las reglas de validación a partir de un conjunto base
     * (`national_id`, `gender`, `selfie_image`) y solo aplica aquellas incluidas en
     * `$parametros`. Luego ejecuta la validación sobre todos los datos del request.
     *
     * @param \Illuminate\Http\Request $request        Solicitud HTTP con los datos de entrada.
     * @param array<int, string>       $parametros     Lista de nombres de parámetros a validar como obligatorios.
     * @param string|null              $transaction_id Identificador de transacción para trazabilidad (opcional).
     *
     * @return mixed Resultado del proceso de validación según la implementación del método.
     */
    private function validarParametrosObligatoriosPersonalCred(Request $request, $parametros, $transaction_id = null)
    {
        $rules = collect([
            'national_id' => ['required',],
            'gender' => ['required',],
            'selfie_image' => ['required',]
        ])->only($parametros)->toArray();

        $validator = Validator::make($request->all(), $rules);
        $errors = $validator->errors();

        if ($errors->has('national_id')) {
            $codigo_resultado = '300';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        if ($errors->has('gender')) {
            $codigo_resultado = '304';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        if ($errors->has('selfie_image')) {
            $codigo_resultado = '303';

            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }
    }

    private function consumirServicio(Request $request, $identificacion, $id_externo = null)
    {
        $p_ip = $request->ip();
        $p_url = str($request->path())->start('/');

        $usuario = Session::get('usuario');
        $user_id = $usuario->user_id;
        $producto = $usuario->producto;

        $consumo = SQLConnection::backendStoreProcedure('consumir_servicio_API', array($user_id, $identificacion, $producto, $p_ip, $p_url, $id_externo), 'selectOne');
        return $consumo;
    }

    private function acumularTiempoAfip(?object $afip): void
    {
        if (empty($afip)) return;

        $funciones = $afip->tiempos_funciones_afip ?? null;

        if (is_array($funciones) && !empty($funciones)) {
            foreach ($funciones as $entry) {
                $funcion = $entry->funcion ?? '';
                $tiempo  = $entry->tiempo  ?? 0;
                if (str_contains($funcion, 'A4')) {
                    $this->tiempo_afip_a13 += $tiempo;
                } else {
                    $this->tiempo_afip_a5 += $tiempo;
                }
            }
        }
    }

    private function guardarResultadoApi($dni, $sexo, $transaction_id, $json, $codigo_resultado = null)
    {
        $json_encoded = json_encode($json);

        $tiempoRespuesta = Misc::medirTiempoRespuesta();
        if (!is_null($tiempoRespuesta)) {
            $tiempoRespuesta = floatval(str_replace(',', '.', $tiempoRespuesta));
        }

        $usuario = Session::get('usuario');

        $tiemposProveedores = array_filter([
            4 => $this->tiempo_afip_a13,
            3 => $this->tiempo_afip_a5,
            6 => $this->tiempo_renaper,
            7 => $this->tiempo_facematch,
            8 => $this->tiempo_worldsys,
        ], fn($tiempo) => $tiempo > 0);

        $nombresProveedores = [
            4 => 'AFIP', // afip a13
            3 => 'AFIP', // afip a5
            6 => 'RENAPER',
            7 => 'FaceMatch',
            8 => 'WorldSys'
        ];

        $proveedorConcat = !empty($tiemposProveedores) ? implode('|', array_unique(array_map(fn($p) => $nombresProveedores[$p], array_keys($tiemposProveedores)))) : 'noCurl';
        $tiempoProveedorTotal = !empty($tiemposProveedores) ? strval(array_sum($tiemposProveedores)) : '0';

        $exec = SQLConnection::backendStoreProcedure('resultados_api_', array($usuario->user_id, $usuario->producto, $dni, $sexo, $transaction_id, $json_encoded, $codigo_resultado, $tiempoRespuesta, $proveedorConcat, $tiempoProveedorTotal));

        foreach ($tiemposProveedores as $proveedor => $tiempo) {
            SQLConnection::backendStoreProcedure('resultados_api_tiempos_', array($transaction_id, $proveedor, $tiempo));
        }

        // ....
    }

    private static function esMayorDeEdad($fecha_nacimiento)
    {
        $fechaNacimientoDt = new DateTime($fecha_nacimiento);
        $fechaActualDt = new DateTime();

        $diferencia = $fechaNacimientoDt->diff($fechaActualDt);
        $edad = $diferencia->y;

        return $edad >= 18;
    }

    private static function debeActualizarPadron($persona) {
        return empty($persona) ||
            (!isset($persona->fecha_nacimiento) && (isset($persona->tipo_persona_1) && $persona->tipo_persona_1 == 'F')) ||
            !isset($persona->ismodified) ||
            Misc::cantidadDias($persona->ismodified) >= self::CANTIDAD_DIAS_EXPIRADO_ARCA;
    }

    /*
        Esta funcion consulta a la API interna de busquedaPadron, la misma decide si actualizar los datos
        del padron con una consulta a ARCA.
    */
    private function consultarApiPadron($identificacion, $genero = null)
    {
        $persona = array_first(SQLConnection::backendStoreProcedure('api_padrones', [$identificacion, null, 'AR', 30, $genero]));

        if (!self::debeActualizarPadron($persona)) {
            return $persona;
        }

        $esCuit = strlen($identificacion) === 11;

        if ($esCuit) {
            return $this->fetchPadronDeAfip($identificacion) ?? $persona;
        }

        $cuits = is_object($persona)
            ? [$persona->identificacion]
            : array_map(fn ($res) => $res->cuit, SQLConnection::backendStoreProcedure('dni_buscar_cuit_segun_dni', [$identificacion]));
        
        foreach ($cuits as $cuit) {
            $afip = $this->fetchPadronDeAfip($cuit);
            if ($afip !== null) {
                return $afip;
            }
        }

        return $persona;
    }

    private function fetchPadronDeAfip(string $cuit)
    {
        $afip = json_decode(AFIPController::obtenerPadron($cuit, true, 'AR', false));
        
        if (empty($afip)) {
            return null;
        }

        $this->acumularTiempoAfip($afip);
        return $afip;
    }

    private function enviarMailError(string $contexto, $identificacion, ?int $transaction_id, \Throwable $e): void
    {
        $usuario = Session::get('usuario');
        $mensaje = 'Ver este caso API V4 fidelitas - ' . $contexto
            . '<br>Identificacion: ' . $identificacion
            . '<br>Transaction_id: ' . ($transaction_id ?? '-')
            . '<br>Producto: ' . ($usuario->producto ?? '-')
            . '<br>Cliente: ' . ($usuario->cliente['client_id'] ?? '-')
            . '<br>User_Id: ' . ($usuario->user_id ?? '-')
            . '<br>Error: ' . $e->getMessage()
            . '<br>Archivo: ' . basename($e->getFile()) . ' - Linea: ' . $e->getLine();

        Misc::enviarMail_errores_api($mensaje);
    }

    private function errorGenerico($parametros, $transaction_id, bool $usarNodoNotification = true)
    {
        $codigo_resultado = '306';
        $response_array = ['Parameters' => $parametros];

        if ($usarNodoNotification) {
            $response_array['Notification'] = [
                'Status' => $codigo_resultado,
                'Message' => Misc::error_query($codigo_resultado),
            ];
        } else {
            $response_array['Status'] = $codigo_resultado;
            $response_array['Message'] = Misc::error_query($codigo_resultado);
        }

        $response_array['Response'] = [];
        $response_array['Transaction_id'] = $transaction_id;

        $this->guardarResultadoApi(
            $parametros['tax_id'] ?? $parametros['national_id'] ?? null,
            null,
            $transaction_id,
            $response_array,
            $codigo_resultado
        );

        return response()->json($response_array);
    }

    private function antiguedadSituacion1($identificacion)
    {
        $antiguedad_situacion_1 = SQLConnection::backendStoreProcedure('obtener_cendeu_sit1_desde', array($identificacion), true);
        $antiguedad_situacion_1 = !empty($antiguedad_situacion_1) ? $antiguedad_situacion_1->fecha_desde : "";

        if (!empty($antiguedad_situacion_1)) {
            $date = DateTime::createFromFormat('m/Y', $antiguedad_situacion_1);
            $antiguedad_situacion_1 = $date->format('Y-m');
        }

        return $antiguedad_situacion_1;
    }

    private function obtenerInfoBancaria(string $tax_id)
    {
        $cardStatusBancario = SQLConnection::obtenerStatusBancario($tax_id);
        $obtenerBancos = SQLConnection::obtenerBancos($tax_id);

        $chequesRechazados = '';
        $ultimaFormateada = '';
        $maximaFormateada = '';
        $cantidadBancosUnicos = '0';

        if (!empty($cardStatusBancario->cheques_rechazados)) {
            $chequesRechazados = $cardStatusBancario->cheques_rechazados > 0 ? 'SI' : 'NO';
        }

        if (!empty($cardStatusBancario->ultima_posicion) && $cardStatusBancario->ultima_posicion > 0) {
            $ultimaFormateada = '$ ' . number_format($cardStatusBancario->ultima_posicion, 0, ',', ' ');
        }

        if (!empty($cardStatusBancario->maxima_posicion) && $cardStatusBancario->maxima_posicion > 0) {
            $maximaFormateada = '$ ' . number_format($cardStatusBancario->maxima_posicion, 0, ',', ' ');
        }

        if (!empty($obtenerBancos)) {
            $nombresUnicos = array_unique(
                array_map(fn($banco) => trim($banco->nombre), $obtenerBancos)
            );
            $cantidadBancosUnicos = strval(count($nombresUnicos));
        }

        return [
            'cheques_rechazados' => $chequesRechazados,
            'ultima_posicion' => $ultimaFormateada,
            'maxima_posicion' => $maximaFormateada,
            'cantidad_bancos' => $cantidadBancosUnicos,
        ];
    }

    /*
        Obtener codigo resultado apropiado segun codigo de respuesta de Renaper
    */
    private function statusResRenaper($res_renaper): string
    {
        if (!is_object($res_renaper) || empty($res_renaper) || !isset($res_renaper->Status)) {
            return '307';
        }

        return match ($res_renaper->Status) {
            12 => '305',
            'NE' => '305',
            11 => '407',
            '407' => '407',
            // 3 => ERROR EN LOS DATOS INGRESADOS
            'ERROR' => '315',
            'OK' => '200',
            default => '307',
        };
    }

    private function obtenerResRenaper($dni, $genero)
    {
        $res_renaper = RenaperController::obtenerUltimoEjemplarCompleto($dni, $genero);
        $this->tiempo_renaper += RenaperController::$tiempo_curl;

        if ($res_renaper) {
            $res_renaper = json_decode($res_renaper);
        } else {
            $res_renaper = [];
        }

        return $res_renaper;
    }

    private static function parsearDniMensajeCiudadania($res_renaper)
    {
        $string = $res_renaper->Message ?? '';
        $matches = [];
        preg_match('/DNI es:\s*(\d+)/', $string, $matches);

        $dni = count($matches) > 1 ? $matches[1] : '';

        return $dni;
    }

    private function responderDniCiudadania(
        array $parametros,
        string $dni,
        ?string $genero,
        int $transaction_id,
        $res_renaper,
        bool $usarNodoNotification = true
    ) {
        $dni_nuevo = self::parsearDniMensajeCiudadania($res_renaper);

        $response_array = ['Parameters' => $parametros];

        if ($usarNodoNotification) {
            $response_array['Notification'] = [
                'Status' => '407',
                'Message' => Misc::error_query('407'),
            ];
        } else {
            $response_array['Status'] = '407';
            $response_array['Message'] = Misc::error_query('407');
        }

        $response_array['Response'] = ['national_id' => $dni_nuevo];
        $response_array['Transaction_id'] = $transaction_id;

        $this->guardarResultadoApi(
            $dni,
            $genero,
            $transaction_id,
            $response_array,
            '407'
        );

        return response()->json($response_array);
    }

    private function respuestaPersonalCredParcial(
        string $dni,
        ?string $tax_id,
        string $tax_id_type,
        ?object $persona,
        ?string $fecha_nacimiento,
        ?string $fecha_defuncion,
        string $antiguedad_situacion_1,
        string $cantidadBancosUnicos,
        string $ultima_formateada,
        string $maxima_formateada,
        string $chequesRechazados,
        int $transaction_id
    ): array {
        $datos_generales = new \stdClass();

        $datos_generales->national_id      = $dni;
        $datos_generales->tax_id           = $tax_id ?? '';
        $datos_generales->tax_id_type      = $tax_id_type;
        $datos_generales->Name             = $persona->nombres ?? '';
        $datos_generales->Lastname         = $persona->apellidos ?? '';
        $datos_generales->DOB              = $fecha_nacimiento ?? '';
        $datos_generales->DOD              = $fecha_defuncion ?? '';

        $datos_generales->sit_1_since      = $antiguedad_situacion_1;
        $datos_generales->banks            = $cantidadBancosUnicos;
        $datos_generales->last_position    = $ultima_formateada;
        $datos_generales->highest_position = $maxima_formateada;
        $datos_generales->rejected_checks  = $chequesRechazados;

        $datos_generales->nationality   = isset($persona->nacionalidad)
            ? (strtoupper($persona->nacionalidad) === 'ARGENTINA' ? $persona->nacionalidad : 'EXTRANJERO')
            : '';
        $datos_generales->address       = '';
        $datos_generales->street_name   = '';
        $datos_generales->street_number = '';
        $datos_generales->floor         = '';
        $datos_generales->apartment     = '';
        $datos_generales->zip           = '';
        $datos_generales->city          = '';
        $datos_generales->state         = '';
        $datos_generales->country       = '';

        try {
            $domicilios_raw = SQLConnection::backendStoreProcedure('sp_obtener_domicilios_general', array($tax_id));
            $domicilios_filtrados = $this->filtrarYAgruparDomicilios($domicilios_raw ?? []);

            if (!empty($domicilios_filtrados)) {
                $dom = $domicilios_filtrados[0];
                $datos_generales->street_name   = $dom->calle      ?? '';
                $datos_generales->street_number = $dom->altura     ?? '';
                $datos_generales->floor         = $dom->piso       ?? '';
                $datos_generales->apartment     = $dom->depto      ?? '';
                $datos_generales->zip           = $dom->codpos     ?? '';
                $datos_generales->city          = $dom->loc_nombre ?? '';
                $datos_generales->state         = $dom->prv_nombre ?? '';
                $datos_generales->country       = $dom->pai_nombre ?? '';
            }
        } catch (Exception $e) {
            Log::warning("No se pudo enriquecer domicilio 315 en personalCred", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
            ]);
        }

        $datos_validados = new \stdClass();
        $datos_validados->gender       = '';
        $datos_validados->id_main_issue = '';
        $datos_validados->copy         = '';
        $datos_validados->issue_date   = '';
        $datos_validados->expiry_date  = '';

        return [$datos_validados, $datos_generales];
    }

    /*
        Filtra domicilios por fuente (AFIP/RENAPER) y agrupa por dirección única,
        unificando los tipos de domicilio.
    */
    private function filtrarYAgruparDomicilios(array $domicilios): array
    {
        $domiciliosFiltrados = array_filter($domicilios, function ($dom) {
            return isset($dom->nombre_fuente) && ($dom->nombre_fuente === 'AFIP' || $dom->nombre_fuente === 'RENAPER');
        });

        $resultado = [];

        foreach ($domiciliosFiltrados as $item) {
            $key = $item->domicilio . "|" . $item->pai_nombre . "|" . $item->prv_nombre . "|" . $item->loc_nombre . "|" . $item->codpos;

            $tipos = array_map('trim', explode(',', $item->tipo_domicilio));

            if (!isset($resultado[$key])) {
                $resultado[$key] = $item;
                $resultado[$key]->type_address = $tipos;
                unset($resultado[$key]->tipo_domicilio);
            } else {
                $resultado[$key]->type_address = array_merge($resultado[$key]->type_address, $tipos);
            }
        }

        foreach ($resultado as $key => $item) {
            $resultado[$key]->type_address = array_values(array_unique($item->type_address));
        }

        return array_values($resultado);
    }

    public function govcheckWork(Request $request) {
        $govcheck_response = $this->govcheck($request, false);
        $govcheck = $govcheck_response->getData();
        $status = $govcheck->Notification->Status;

        if ($status !== '200' && $status !== '201') {
            return $govcheck_response;
        }

        $personas = $status === '200'
            ? [array_first($govcheck->Response)]
            : $govcheck->Response;

        foreach ($personas as $persona) {
            $cuit = $persona->Tax_id_number;

            $empleado_de = SQLConnection::backendStoreProcedure('obtener_empleado_de', array($cuit), 'selectOne');
            $inscripciones = SQLConnection::backendStoreProcedure('obtener_inscripciones', array($cuit), 'selectOne');

            /* $persona->Employee = false;
            if (!empty($empleado_de?->periodo)) {
                try {
                    $persona->Employee = Carbon::createFromFormat('m/Y', $empleado_de->periodo)
                        ->greaterThan(Carbon::now()->subMonths(6));
                } catch (Exception $e) {
                    // periodo con formato inválido, dejamos false
                }
            }*/
            $persona->Employee = !empty($empleado_de);

            $persona->Self_employed = $inscripciones?->monotributo !== null;
        }

        $identificacion = $govcheck->Parameters->tax_id ?? $govcheck->Parameters->national_id ?? null;
        $transaction_id = $govcheck->Transaction_id;

        $this->guardarResultadoApi(
            $identificacion,
            null,
            $transaction_id,
            $govcheck,
            $status
        );

        return response()->json($govcheck);
    }

    /*
        Api de IC. Se modifico el formato de salida para que sea acorde con las demas apis.
    */
    public function ObtenerInformeComercialCompleto_v4(Request $request, $cuit = '', $apikey = '', $idioma = 'ENG')
    {
        //datos básicos y declaraciones de clases y arrays, para que no fallen
        if (!$cuit) {
            $cuit = $request->input('tax_id');
        }

        $parametros = ['tax_id'];

        /* 22/07/2021 Agregamos que pase por afip */
        if (!empty($cuit) && strlen($cuit) == 11) {
            $afip = json_decode(AFIPController::obtenerPadron($cuit, true, 'AR', false));
            $this->acumularTiempoAfip($afip);
        }
        // $idioma = ($request->input('idioma') !== NULL ) ? $request->input('idioma') : 'ESP';

        $consumo = $this->consumirServicio($request, $cuit);
        $transaction_id = $consumo->transaction_id;

        if (!$apikey) {
            $apikey = $request->input('apikey');
        }
        $persona = new \stdClass();
        $configuracion = [];
        $cuit_validado = Misc::validarCuit($cuit);

        if (!$cuit_validado) {
            $codigo_resultado = '302';
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        try {
            $persona_padron = $this->consultarApiPadron($cuit);
        } catch (Exception $e) {
            Log::error("Error al consultar API Padron", [
                'transaction_id' => $transaction_id,
                'message' => $e->getMessage(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'trace' => $e->getTraceAsString()
            ]);

            $this->enviarMailError('informeComercial - Error API Padron', $cuit, $transaction_id, $e);
            return $this->errorGenerico($request->only($parametros), $transaction_id, false);
        }

        if (!empty($persona_padron->fecha_nacimiento) && !self::esMayorDeEdad($persona_padron->fecha_nacimiento)) {
            $codigo_resultado = '313';
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        $respuesta = json_decode(ApiControllerV1::obtenerServicioScore($cuit, true, false));
        $idp = SQLConnection::obtenerIdPadron($cuit);

        if (is_null($idp) || empty($idp)) {
            $codigo_resultado = '401';
            return $this->responderError(
                $request->only($parametros),
                $codigo_resultado,
                $transaction_id,
                false
            );
        }

        $id_padron = $idp->id_padron;

        //obtengo la configuración para este cliente/usuario y veo que secciones le habilito
        if ($apikey) {
            $configuracion = SQLConnection::backendStoreProcedure('api_obtener_configuracion_secciones', array($apikey), true);

        }

        // Información Score
        if ($configuracion->score_ic == 1) {
            $score = $respuesta->score;
            if ($idioma == 'ESP') {
                $persona->score = new \stdClass();
                $persona->score->valor = $score;
            } elseif ($idioma == 'ENG') {
                $persona->score = new \stdClass();
                $persona->score->value = $score;
            }
        }

        //si tiene la configuración de formales, tomamos todos los datos posibles del formales. (defunción, domicilios, datos personales. etc.)
        if ($configuracion->formales == 1) {

            $nombre = '';
            $defuncion = SQLConnection::backendStoreProcedure('obtener_defuncion', array($cuit), true);
            $fisica_juridica = Misc::tipoPersona($cuit);
            $p_fisica = ($fisica_juridica == 'F') ? 'FISICA' : 'JURIDICA';

            $legalForm = "";
            if ("F" != $p_fisica) {
                $cardScore = SQLConnection::obtenerCardScore($cuit);
                if (!empty($cardScore) && property_exists($cardScore, 'forma_juridica')) {
                    $legalForm = $cardScore->forma_juridica ?? "";
                }
            } else {
                $cardScorePF = SQLConnection::obtenerCardScorePF($cuit);
                if (!empty($cardScorePF) && property_exists($cardScorePF, 'forma_juridica')) {
                    $legalForm = $cardScorePF->forma_juridica ?? "";
                }
            }

            if ($idioma == 'ESP') {
                $persona->formales = new \stdClass();
                $persona->formales->tipo_persona = $p_fisica;
                $persona->formaldata->forma_legal = $legalForm;
            } elseif ($idioma == 'ENG') {
                $persona->formaldata = new \stdClass();
                $persona->formaldata->legal_type = $p_fisica;
                $persona->formaldata->legal_form = $legalForm;
            }

            $telefonos = SQLConnection::backendStoreProcedure('obtener_telefono', array($id_padron));

            if ($idioma == 'ESP') {
                $persona->formales->identificacion = $cuit;
            } elseif ($idioma == 'ENG') {
                $persona->formaldata->taxid = $cuit;
            }

            if ($fisica_juridica == 'F') {
                $datos_persona = SQLConnection::backendStoreProcedure('obtener_persona', array($cuit), true);
                $nombre = $datos_persona->nombre_persona;
                $dni = (int) substr($cuit, 2, -1);
                $empleado_de = SQLConnection::backendStoreProcedure('obtener_empleado_de', array($cuit));
                if ($idioma == 'ESP') {
                    $persona->formales->dni = (string) $dni;
                    $persona->formales->telefonos = $telefonos;
                    $persona->formales->sexo = $datos_persona->sexo;
                    $persona->formales->anio_nacimiento = $datos_persona->anio_nacimiento;
                    //$persona->formales->nacionalidad    = ''; // en www2 estaba sacada esta linea
                    //$persona->formales->ejemplar        = '';
                    $persona->formales->defuncion = new \stdClass();
                } elseif ($idioma == 'ENG') {
                    $persona->formaldata->national_id = (string) $dni;
                    $persona->formaldata->phone = $telefonos;
                    $persona->formaldata->gender = $datos_persona->sexo;
                    $persona->formaldata->YOB = $datos_persona->anio_nacimiento;
                    //$persona->formaldata->nacionalidad    = ''; // en www2 estaba sacada esta linea
                    //$persona->formaldata->ejemplar        = '';
                    $persona->formaldata->death_info = new \stdClass();
                }

                if (!empty($datos_persona->fecha_nacimiento)) {
                    $edad = Misc::calcularEdad($datos_persona->fecha_nacimiento);
                    if ($edad) {
                        if ($idioma == 'ESP') {
                            $persona->formales->edad = $edad;
                        } elseif ($idioma == 'ENG') {
                            $persona->formaldata->age = $edad;
                        }
                    }
                }
                //
                if ($idioma == 'ESP') {
                    $persona->formales->empleado_de = $empleado_de;
                    $persona->formales->profesion = $datos_persona->profesion;
                    $persona->formales->fecha_nacimiento = $datos_persona->fecha_nacimiento;
                    $persona->formales->estado_civil = $datos_persona->estado_civil;
                    //
                    $persona->formales->defuncion->fuente = !empty($defuncion->fuente) ? $defuncion->fuente : '-';
                    $persona->formales->defuncion->fecha_deceso = !empty($defuncion->fecha_deceso) ? $defuncion->fecha_deceso : '-';
                    $persona->formales->defuncion->defuncion = !empty($defuncion->defuncion) ? $defuncion->defuncion : '-';
                } elseif ($idioma == 'ENG') {
                    // FALTA TRADUCIR
                    $persona->formaldata->employee_of = $empleado_de;
                    $persona->formaldata->profession = $datos_persona->profesion;
                    $persona->formaldata->DOB = $datos_persona->fecha_nacimiento;
                    $persona->formaldata->marital_status = $datos_persona->estado_civil;
                    //
                    $persona->formaldata->death_info->source = !empty($defuncion->fuente) ? $defuncion->fuente : '-';
                    $persona->formaldata->death_info->DOD = !empty($defuncion->fecha_deceso) ? $defuncion->fecha_deceso : '-';
                    $persona->formaldata->death_info->isdead = !empty($defuncion->defuncion) ? $defuncion->defuncion : '-';
                }
            } else {
                $nombre = SQLConnection::obtenerRazonSocial($cuit)->nombre_persona;
                $sociedades = SQLConnection::backendStoreProcedure('obtener_sociedades', array($cuit));
                $info_empresa_formales = [];
                $card_empleados = SQLConnection::backendStoreProcedure('obtener_empleados', array($cuit), 'selectOne');
                //
                if (isset($card_empleados->total)) {
                    if ($idioma == 'ESP') {
                        $card_empleados->total = (int) $card_empleados->total;
                    } elseif ($idioma == 'ENG') {
                        $card_empleados->perc_men = $card_empleados->cantidad_hombres;
                        $card_empleados->perc_women = $card_empleados->cantidad_mujeres;
                        $card_empleados->total_employees = (int) $card_empleados->total;
                        $card_empleados->period = $card_empleados->fecha;
                        //
                        unset($card_empleados->cantidad_mujeres);
                        unset($card_empleados->cantidad_hombres);
                        unset($card_empleados->total);
                        unset($card_empleados->fecha);
                    }
                }
                //
                if ($idioma == 'ESP') {
                    $persona->formales->empleados = $card_empleados;
                } elseif ($idioma == 'ENG') {
                    $persona->formaldata->employees = $card_empleados;
                }
                //
                if ($idioma == 'ESP') {
                    foreach ($sociedades as $key => $value) {
                        $info_empresa_formales[$key] = new \stdClass();
                        $info_empresa_formales[$key]->ramo = $value->ramo;
                        $info_empresa_formales[$key]->subramo = $value->subramo;
                        $info_empresa_formales[$key]->fecha_contrato_social = $value->fecha_cons;
                        $info_empresa_formales[$key]->capital = (int) $value->capital;
                    }
                    $persona->formales->mas_info = $info_empresa_formales;
                } elseif ($idioma == 'ENG') {
                    foreach ($sociedades as $key => $value) {
                        $info_empresa_formales[$key] = new \stdClass();
                        $info_empresa_formales[$key]->ramo = $value->ramo;
                        $info_empresa_formales[$key]->subramo = $value->subramo;
                        $info_empresa_formales[$key]->social_contract_date = $value->fecha_cons;
                        $info_empresa_formales[$key]->capital = (int) $value->capital;
                    }
                    $persona->formaldata->more_info = $info_empresa_formales;
                }
                //
                $claes_info = SQLConnection::backendStoreProcedure('obtener_clae', array($cuit));
                $claes = [];
                //
                if ($idioma == 'ESP') {
                    foreach ($claes_info as $key => $value) {
                        $claes[$key] = new \stdClass();
                        $claes[$key]->cod_clae = $value->cod_clae;
                        $claes[$key]->descripcion = $value->descripcion;
                    }
                    $persona->formales->claes = $claes;
                } elseif ($idioma == 'ENG') {
                    foreach ($claes_info as $key => $value) {
                        $claes[$key] = new \stdClass();
                        $claes[$key]->clae_code = $value->cod_clae;
                        $claes[$key]->description = $value->descripcion;
                    }
                    $persona->formaldata->economic_activity = $claes;
                }
            }
            //
            if ($idioma == 'ESP') {
                $persona->formales->nombre = $nombre;
                $persona->formales->domicilios = new \stdClass();
            } elseif ($idioma == 'ENG') {
                $persona->formaldata->legal_name = $nombre;
                $persona->formaldata->addresses = new \stdClass();
            }
            //
            $domicilios = SQLConnection::backendStoreProcedure('sp_obtener_domicilios', array($cuit));
            //
            if (!empty($domicilios)) {
                if ($idioma == 'ESP') {
                    foreach ($domicilios as $key => $value) {
                        // $domicilios[$key]->domicilio  = $domicilios[$key]->domicilio;
                        $domicilios[$key]->provincia = $domicilios[$key]->prv_nombre;
                        $domicilios[$key]->localidad = $domicilios[$key]->loc_nombre;
                        $domicilios[$key]->pais = $domicilios[$key]->pai_nombre;
                        $domicilios[$key]->cp = $domicilios[$key]->codpos;
                        // unset($domicilios[$key]->domicilio);
                        unset($domicilios[$key]->prv_nombre);
                        unset($domicilios[$key]->loc_nombre);
                        unset($domicilios[$key]->pai_nombre);
                        unset($domicilios[$key]->codpos);
                        unset($domicilios[$key]->id);
                        unset($domicilios[$key]->tipo_domicilio);
                        unset($domicilios[$key]->created);
                    }
                    //
                    $persona->formales->domicilios = $domicilios;
                } elseif ($idioma == 'ENG') {
                    // nahu
                    foreach ($domicilios as $key => $value) {
                        /* 
                            html_entity_decode: Esta funcion convierte las entidades HTML (como &#209;) en sus caracteres correspondientes (por ejemplo, Ñ).
                            ENT_QUOTES | ENT_HTML5: Estas banderas aseguran que tanto las comillas simples como las dobles se decodifiquen, y que la funcion utilice HTML5.
                            'UTF-8': Esto especifica la codificacion de caracteres que se debe utilizar (en este caso, UTF-8)
                        */
                        $domicilios[$key]->address = html_entity_decode($domicilios[$key]->domicilio ?? null, ENT_QUOTES | ENT_HTML5, 'UTF-8');
                        $domicilios[$key]->state = $domicilios[$key]->prv_nombre;
                        $domicilios[$key]->city = $domicilios[$key]->loc_nombre;
                        $domicilios[$key]->country = $domicilios[$key]->pai_nombre;
                        $domicilios[$key]->zip_code = $domicilios[$key]->codpos;
                        //
                        unset($domicilios[$key]->domicilio);
                        unset($domicilios[$key]->prv_nombre);
                        unset($domicilios[$key]->loc_nombre);
                        unset($domicilios[$key]->pai_nombre);
                        unset($domicilios[$key]->codpos);
                        unset($domicilios[$key]->id);
                        unset($domicilios[$key]->tipo_domicilio);
                        unset($domicilios[$key]->created);
                    }
                    //
                    $persona->formaldata->addresses = $domicilios;
                }
            }
        }

        //Información socios/directores/sociedades.
        if ($configuracion->relaciones == 1) {
            //
            if ($idioma == 'ESP') {
                $persona->relaciones = new \stdClass();
                $persona->relaciones->socios = [];
                $persona->relaciones->participaciones = [];
                $persona->relaciones->vinculaciones = [];
                //
                if ($fisica_juridica == 'F') {
                    $relaciones = SQLConnection::backendStoreProcedure('obtener_socios_directores', array($cuit, $fisica_juridica));
                    $participaciones = SQLConnection::backendStoreProcedure('obtener_participacion_socios_directores', array($cuit));
                    $vinculaciones = SQLConnection::backendStoreProcedure('obtener_vinculaciones', array($cuit));

                } else {
                    $relaciones = SQLConnection::backendStoreProcedure('obtener_socios_directores', array($cuit, $fisica_juridica));
                    $participaciones = SQLConnection::backendStoreProcedure('obtener_participacion_socios_directores', array($cuit));
                    $vinculaciones = SQLConnection::backendStoreProcedure('obtener_vinculaciones', array($cuit));
                }
                //
                $i = 0;
                foreach ($participaciones as $key => $value) {
                    $persona->relaciones->participaciones[$i] = new \stdClass();
                    $persona->relaciones->participaciones[$i]->razon_social_sociedad = $value->nombre_sociedad;
                    $persona->relaciones->participaciones[$i]->cuit_sociedad = $value->cuit_sociedad;
                    $persona->relaciones->participaciones[$i]->cuit_socio = $value->cuit_socio;
                    $persona->relaciones->participaciones[$i]->nombre_socio = $value->nombre_socio;
                    $persona->relaciones->participaciones[$i]->cargo = $value->cargo;
                    $i++;
                }
                //
                $i = 0;
                foreach ($relaciones as $key => $value) {
                    $persona->relaciones->socios[$i] = new \stdClass();
                    $persona->relaciones->socios[$i]->cuit = $value->cuit;
                    $persona->relaciones->socios[$i]->pais = $value->country_name;
                    $persona->relaciones->socios[$i]->nombre_persona = $value->nombre_persona;
                    $persona->relaciones->socios[$i]->cargo = $value->car_nombre;
                    $persona->relaciones->socios[$i]->desde = $value->c04_periodo_desde;
                    $persona->relaciones->socios[$i]->hasta = $value->c04_periodo_hasta;
                    $i++;
                }
                //
                $i = 0;
                foreach ($vinculaciones as $key => $value) {
                    $persona->relaciones->vinculaciones[$i] = new \stdClass();
                    $persona->relaciones->vinculaciones[$i]->cuit = $value->cuit_vinculada;
                    $persona->relaciones->vinculaciones[$i]->nombre_persona = $value->nombre_persona;
                    $persona->relaciones->vinculaciones[$i]->tipo = $value->nombre;
                    $persona->relaciones->vinculaciones[$i]->detalle = $value->detalle;
                    $i++;
                }

            } elseif ($idioma == 'ENG') {
                $persona->corporate_realationships = new \stdClass();
                $persona->corporate_realationships->partners = [];
                $persona->corporate_realationships->shareholding_activity = [];
                $persona->corporate_realationships->linkages = [];
                //
                if ($fisica_juridica == 'F') {
                    $relaciones = SQLConnection::backendStoreProcedure('obtener_socios_directores', array($cuit, $fisica_juridica));
                    $participaciones = SQLConnection::backendStoreProcedure('obtener_participacion_socios_directores', array($cuit));
                    $vinculaciones = SQLConnection::backendStoreProcedure('obtener_vinculaciones', array($cuit));
                } else {
                    $relaciones = SQLConnection::backendStoreProcedure('obtener_socios_directores', array($cuit, $fisica_juridica));
                    $participaciones = SQLConnection::backendStoreProcedure('obtener_participacion_socios_directores', array($cuit));
                    $vinculaciones = SQLConnection::backendStoreProcedure('obtener_vinculaciones', array($cuit));
                }
                //
                $i = 0;
                foreach ($participaciones as $key => $value) {
                    $persona->corporate_realationships->shareholding_activity[$i] = new \stdClass();
                    $persona->corporate_realationships->shareholding_activity[$i]->legal_name = $value->nombre_sociedad;
                    $persona->corporate_realationships->shareholding_activity[$i]->taxid = $value->cuit_sociedad;
                    $persona->corporate_realationships->shareholding_activity[$i]->taxid_sharheolder = $value->cuit_socio;
                    $persona->corporate_realationships->shareholding_activity[$i]->legal_name_shareholder = $value->nombre_socio;
                    $persona->corporate_realationships->shareholding_activity[$i]->role = $value->cargo;
                    $i++;
                }
                //
                $i = 0;
                foreach ($relaciones as $key => $value) {
                    $persona->corporate_realationships->partners[$i] = new \stdClass();
                    $persona->corporate_realationships->partners[$i]->taxid = $value->cuit;
                    $persona->corporate_realationships->partners[$i]->country = $value->country_name;
                    $persona->corporate_realationships->partners[$i]->legal_name = $value->nombre_persona;
                    $persona->corporate_realationships->partners[$i]->position = $value->car_nombre;
                    $persona->corporate_realationships->partners[$i]->from_date = $value->c04_periodo_desde;
                    $persona->corporate_realationships->partners[$i]->to_date = $value->c04_periodo_hasta;
                    $i++;
                }
                //
                $i = 0;
                foreach ($vinculaciones as $key => $value) {
                    $persona->corporate_realationships->linkages[$i] = new \stdClass();
                    $persona->corporate_realationships->linkages[$i]->tax_id = $value->cuit_vinculada;
                    $persona->corporate_realationships->linkages[$i]->legal_name = $value->nombre_persona;
                    $persona->corporate_realationships->linkages[$i]->tipo = $value->nombre;
                    $persona->corporate_realationships->linkages[$i]->description = $value->detalle;
                    $i++;
                }
            }
        }

        //Información Comercial.
        if ($configuracion->comerciales == 1) {
            if ($idioma == 'ESP') {
                $persona->comerciales = new \stdClass();
            } elseif ($idioma == 'ENG') {
                $persona->commercial_data = new \stdClass();
                ;
            }
            //
            $consultas_ramos = SQLConnection::backendStoreProcedure('obtener_consulta_por_ramos', array($cuit, 12));
            $seguros = SQLConnection::backendSeguros($cuit);
            $marcas = SQLConnection::backendStoreProcedure('obtener_marcas', array($cuit));
            $consultas = [];
            //
            if ($consultas_ramos) {
                if ($idioma == 'ESP') {
                    foreach ($consultas_ramos as $key_ramo => $consulta) {
                        $consultas[$key_ramo]['nombre'] = $consulta->descripcion;
                        $consultas[$key_ramo][$consulta->antiguedad] = $consulta->cantidad;
                    }
                    //
                    foreach ($consultas as $key => $consulta) {
                        if (!isset($consultas[$key]['entre_0_1'])) {
                            $consultas[$key]['entre_0_1'] = 0;
                        }
                        //
                        if (!isset($consultas[$key]['entre_1_2'])) {
                            $consultas[$key]['entre_1_2'] = 0;
                        }
                        //
                        if (!isset($consultas[$key]['entre_2_5'])) {
                            $consultas[$key]['entre_2_5'] = 0;
                        }
                        //
                        ksort($consultas[$key]);
                    }
                } elseif ($idioma == 'ENG') {
                    foreach ($consultas_ramos as $key_ramo => $consulta) {
                        $consultas[$key_ramo]['name'] = $consulta->descripcion;
                        $consultas[$key_ramo][$consulta->antiguedad] = $consulta->cantidad;
                    }
                    //
                    foreach ($consultas as $key => $consulta) {
                        if (!isset($consultas[$key]['between_0_1'])) {
                            $consultas[$key]['between_0_1'] = 0;
                        }
                        //
                        if (!isset($consultas[$key]['between_1_2'])) {
                            $consultas[$key]['between_1_2'] = 0;
                        }
                        //
                        if (!isset($consultas[$key]['between_2_5'])) {
                            $consultas[$key]['between_2_5'] = 0;
                        }
                        //
                        ksort($consultas[$key]);
                    }
                }
            }
            //
            if (!empty($marcas)) {
                if ($idioma == 'ESP') {
                    foreach ($marcas as $key => $value) {
                        unset($value->num_boletin);
                        unset($value->directorio);
                        unset($value->web);
                        unset($value->fecha_publicacion);
                        unset($value->encontrada);
                    }
                } elseif ($idioma == 'ENG') {
                    foreach ($marcas as $key => $value) {
                        $marcas[$key]->num_acta = $marcas[$key]->num_acta;
                        $marcas[$key]->type = $marcas[$key]->tipo;
                        $marcas[$key]->brand = $marcas[$key]->marca;
                        $marcas[$key]->class = $marcas[$key]->clase;
                        //
                        unset($marcas[$key]->tipo);
                        unset($marcas[$key]->marca);
                        unset($marcas[$key]->clase);
                        //
                        unset($value->num_boletin);
                        unset($value->directorio);
                        unset($value->web);
                        unset($value->fecha_publicacion);
                        unset($value->encontrada);
                    }
                }
            }
            //
            if (!empty($seguros)) {
                if ($idioma == 'ESP') {
                    foreach ($seguros as $key => $value) {
                        unset($seguros[$key]->seg_codigo);
                        unset($seguros[$key]->rie_codigo);
                        unset($seguros[$key]->id_seguros);
                        unset($seguros[$key]->id_padron);
                        unset($seguros[$key]->visible);
                        unset($seguros[$key]->estado);
                    }
                } elseif ($idioma == 'ENG') {
                    foreach ($seguros as $key => $value) {
                        $seguros[$key]->company_name = $seguros[$key]->seg_nombre;
                        $seguros[$key]->type = $seguros[$key]->rie_nombre;
                        //
                        unset($seguros[$key]->seg_nombre);
                        unset($seguros[$key]->rie_nombre);
                        //
                        unset($seguros[$key]->seg_codigo);
                        unset($seguros[$key]->rie_codigo);
                        unset($seguros[$key]->id_seguros);
                        unset($seguros[$key]->id_padron);
                        unset($seguros[$key]->visible);
                        unset($seguros[$key]->estado);
                    }
                }
            }
            //
            if ($idioma == 'ESP') {
                $persona->comerciales->consultas = $consultas;
                $persona->comerciales->seguros = $seguros;
                $persona->comerciales->marcas = $marcas;
            } elseif ($idioma == 'ENG') {
                $persona->commercial_data->qtyqueries = $consultas;
                $persona->commercial_data->insurances = $seguros;
                $persona->commercial_data->brands = $marcas;
            }
        }

        //Información Contables.
        if ($configuracion->contables == 1) {
            // $MainController = new MainController();
            // $contables      = json_decode($MainController->obtenerContables(true,'','','','','','','','','','',$cuit)->getContent())->info;
            //
            $persona->balance_sheets = new \stdClass();
            if ($idioma == 'ESP') {
                $persona->balances = [];
                $persona->balances = SQLConnection::backendStoreProcedure('api_obtener_balances', array($cuit));
                //
                foreach ($persona->balance_sheets as $key => $value) {
                    unset($persona->balance_sheets[$key]->id_balance);
                    unset($persona->balance_sheets[$key]->cuit);
                    unset($persona->balance_sheets[$key]->fecha_balance);
                    unset($persona->balance_sheets[$key]->ejercicio);
                    unset($persona->balance_sheets[$key]->periodo);
                    unset($persona->balance_sheets[$key]->bal_manifestacion);
                    unset($persona->balance_sheets[$key]->comentarios);
                }
            } elseif ($idioma == 'ENG') {
                //
                $persona->balance_sheets = [];
                $persona->balance_sheets = SQLConnection::backendStoreProcedure('api_obtener_balances', array($cuit));
                //
                foreach ($persona->balance_sheets as $key => $value) {
                    $persona->balance_sheets[$key]->currency = $persona->balance_sheets[$key]->moneda;
                    $persona->balance_sheets[$key]->date = $persona->balance_sheets[$key]->fecha_balance_dmy;
                    //
                    unset($persona->balance_sheets[$key]->moneda);
                    unset($persona->balance_sheets[$key]->fecha_balance_dmy);
                    //
                    unset($persona->balance_sheets[$key]->id_balance);
                    unset($persona->balance_sheets[$key]->cuit);
                    unset($persona->balance_sheets[$key]->fecha_balance);
                    unset($persona->balance_sheets[$key]->ejercicio);
                    unset($persona->balance_sheets[$key]->periodo);
                    unset($persona->balance_sheets[$key]->bal_manifestacion);
                    unset($persona->balance_sheets[$key]->comentarios);
                }
            }
        }

        //Información Fiscal.
        if ($configuracion->fiscales == 1) {
            if ($idioma == 'ESP') {
                $persona->fiscales = new \stdClass();
            } elseif ($idioma == 'ENG') {
                $persona->fiscal_data = new \stdClass();
            }
            //
            $claes = SQLConnection::backendStoreProcedure('obtener_clae', array($cuit));
            $inscripciones = SQLConnection::backendStoreProcedure('obtener_inscripciones', array($cuit));
            $impuestos = SQLConnection::backendStoreProcedure('obtener_padron_impuestos', array($id_padron));
            $apocrifas = SQLConnection::backendStoreProcedure('obtener_apocrifas', array($cuit));
            $sircreb = SQLConnection::backendStoreProcedure('obtener_sircreb', array($cuit));
            $arba = SQLConnection::backendStoreProcedure('obtener_arba', array($cuit));
            $aportes = SQLConnection::backendStoreProcedure('backend_mis_aportes', array($cuit, NULL, 12, 1), false);
            //
            if ($idioma == 'ESP') {
                $persona->fiscales->aportes = $aportes;
                $persona->fiscales->clae = $claes;
                $persona->fiscales->inscripciones = $inscripciones;
                $persona->fiscales->impuestos = $impuestos;
                $persona->fiscales->facturas_apocrifas = $apocrifas;
                $persona->fiscales->sircreb = $sircreb;
                $persona->fiscales->arba = $arba;
                //
            } elseif ($idioma == 'ENG') {
                $persona->fiscal_data->social_security_contributions = $aportes;//AGB VER CON DATOS
                $persona->fiscal_data->economic_activity_code = $claes;
                //
                foreach ($persona->fiscal_data->economic_activity_code as $key => $clae) {
                    $persona->fiscal_data->economic_activity_code[$key]->code = $clae->cod_clae;
                    $persona->fiscal_data->economic_activity_code[$key]->description = $clae->descripcion;
                    $persona->fiscal_data->economic_activity_code[$key]->start_date = $clae->fecha_inicio_actividad;
                    unset($persona->fiscal_data->economic_activity_code[$key]->cod_clae);
                    unset($persona->fiscal_data->economic_activity_code[$key]->descripcion);
                    unset($persona->fiscal_data->economic_activity_code[$key]->fecha_inicio_actividad);
                }
                //
                foreach ($inscripciones as $key => $value) {
                    $inscripciones[$key]->social_contract_date = $inscripciones[$key]->fecha_contrato_social;
                    $inscripciones[$key]->registration_number = $inscripciones[$key]->numero_inscripcion;
                    $inscripciones[$key]->registration_date = $inscripciones[$key]->fecha_inscripcion;
                    $inscripciones[$key]->monotributo = $inscripciones[$key]->monotributo;
                    $inscripciones[$key]->activity_start_date = $inscripciones[$key]->inicio_actividad;
                    $inscripciones[$key]->employer = $inscripciones[$key]->empleador;
                    //
                    unset($inscripciones[$key]->fecha_contrato_social);
                    unset($inscripciones[$key]->numero_inscripcion);
                    unset($inscripciones[$key]->fecha_inscripcion);
                    unset($inscripciones[$key]->inicio_actividad);
                    unset($inscripciones[$key]->empleador);
                }
                $persona->fiscal_data->registered_taxes = $inscripciones;
                //
                foreach ($impuestos as $key => $value) {
                    $impuestos[$key]->tax_code = $impuestos[$key]->codigo_impuesto;
                    $impuestos[$key]->tax_name = $impuestos[$key]->nombre_impuesto;
                    $impuestos[$key]->registration_date = $impuestos[$key]->fecha_inscripcion;
                    $impuestos[$key]->state = $impuestos[$key]->estado;
                    //
                    unset($impuestos[$key]->codigo_impuesto);
                    unset($impuestos[$key]->nombre_impuesto);
                    unset($impuestos[$key]->fecha_inscripcion);
                    unset($impuestos[$key]->estado);
                }
                //
                $persona->fiscal_data->taxes = $impuestos;
                $persona->fiscal_data->apocryphal_invoices = $apocrifas;
                $persona->fiscal_data->sircreb = $sircreb;
                $persona->fiscal_data->arba = $arba;
            }
        }

        //informacion de bancos
        if ($configuracion->bancos_y_cheques == 1) {
            //
            $bancos = SQLConnection::backendStoreProcedure('backend_central_deudores', array($cuit, 24, 1));
            $periodo = SQLConnection::backendStoreProcedure('obtener_periodo_maximo', array($cuit), 'selectOne');
            if ($idioma == 'ESP') {
                $persona->periodos = new \stdClass();
                $persona->periodos->bancos = Misc::convertirFormatoFecha($periodo->periodo_maximo, 'Y-m-d', 'Ym');
                $persona->bancos = [];
                //
                foreach ($bancos as $key => $value) {
                    $persona->bancos[$key] = new \stdClass();
                    $persona->bancos[$key]->codigo_entidad = $value->codigo_ent;
                    $persona->bancos[$key]->nombre_entidad = $value->nombre;
                    $persona->bancos[$key]->periodo = $value->fec_inf;
                    $persona->bancos[$key]->situacion = $value->situacion;
                    $persona->bancos[$key]->monto = $value->total;
                    $persona->bancos[$key]->dias_atraso = $value->dia_atraso;
                }
            } elseif ($idioma == 'ENG') {
                $persona->max_bank_information = new \stdClass();
                $persona->max_bank_information->period = Misc::convertirFormatoFecha($periodo->periodo_maximo, 'Y-m-d', 'Ym');
                $persona->banks = [];
                //
                foreach ($bancos as $key => $value) {
                    $persona->banks[$key] = new \stdClass();
                    $persona->banks[$key]->bank_code = $value->codigo_ent;
                    $persona->banks[$key]->bank_name = $value->nombre;
                    $persona->banks[$key]->period = $value->fec_inf;
                    $persona->banks[$key]->status = $value->situacion;
                    $persona->banks[$key]->amount = $value->total;
                    $persona->banks[$key]->days_late = $value->dia_atraso;
                }
            }
            //
            if ($idioma == 'ESP') {
                $persona->vinculados_segun_bcra = [];
            } elseif ($idioma == 'ENG') {
                $persona->representatives_with_banking_system = [];
            }
            //informacion de cheques
            $cheques = SQLConnection::backendStoreProcedure('obtener_cheques', array($cuit));
            $i = 0;
            foreach ($cheques as $key => $value) {
                if ($value->tipo == 'vinculaciones') {
                    if ($idioma == 'ESP') {
                        $persona->vinculados_segun_bcra[$i] = new \stdClass();
                        $persona->vinculados_segun_bcra[$i]->nombre_persona_firmante = $value->nombre_persona_firmante;
                        $persona->vinculados_segun_bcra[$i]->cuit_firmante = $value->cuit_firmante;
                        $persona->vinculados_segun_bcra[$i]->nombre_persona_relacionado = $value->nombre_persona_relacionado;
                        $persona->vinculados_segun_bcra[$i]->cuit_relacionado = $value->Cuit_relacionado;
                        $persona->vinculados_segun_bcra[$i]->cantidad_cheques_firmados = $value->cantidad;
                        $persona->vinculados_segun_bcra[$i]->cantidad_cheques_totales = $value->total_cheques;
                        unset($cheques[$i]);
                        $i += 1;
                    } elseif ($idioma == 'ENG') {
                        //
                        $persona->representatives_with_banking_system[$i] = new \stdClass();
                        $persona->representatives_with_banking_system[$i]->signer = $value->nombre_persona_firmante;
                        $persona->representatives_with_banking_system[$i]->signer_tax_id = $value->cuit_firmante;
                        $persona->representatives_with_banking_system[$i]->related = $value->nombre_persona_relacionado;
                        $persona->representatives_with_banking_system[$i]->related_tax_id = $value->Cuit_relacionado;
                        $persona->representatives_with_banking_system[$i]->signed_checks = $value->cantidad;
                        $persona->representatives_with_banking_system[$i]->total_checks = $value->total_cheques;
                        unset($cheques[$i]);
                        $i += 1;
                    }
                } else {
                    unset($cheques[$key]->idp);
                    unset($cheques[$key]->idppr);
                    unset($cheques[$key]->cantidad);
                    unset($cheques[$key]->total_cheques);
                }
            }
            //
            if ($idioma == 'ESP') {
                $persona->cheques = array_values($cheques);
            } elseif ($idioma == 'ENG') {
                $persona->bounced_checks = array_values($cheques);
                //
                foreach ($persona->bounced_checks as $key => $value) {
                    $persona->bounced_checks[$key]->signer = $persona->bounced_checks[$key]->nombre_persona_firmante;
                    $persona->bounced_checks[$key]->signer_tax_id = $persona->bounced_checks[$key]->cuit_firmante;
                    $persona->bounced_checks[$key]->related = $persona->bounced_checks[$key]->nombre_persona_relacionado;
                    $persona->bounced_checks[$key]->related_tax_id = $persona->bounced_checks[$key]->Cuit_relacionado;
                    $persona->bounced_checks[$key]->check_number = $persona->bounced_checks[$key]->nro_cheque;
                    $persona->bounced_checks[$key]->rejection_date = $persona->bounced_checks[$key]->fecha_rechazo;
                    $persona->bounced_checks[$key]->cover_payment_date = $persona->bounced_checks[$key]->fecha_levantamiento;
                    $persona->bounced_checks[$key]->import = $persona->bounced_checks[$key]->importe;
                    $persona->bounced_checks[$key]->cause = $persona->bounced_checks[$key]->causa;
                    $persona->bounced_checks[$key]->type = $persona->bounced_checks[$key]->tipo;
                    $persona->bounced_checks[$key]->payment_date = $persona->bounced_checks[$key]->fecha_pago;
                    //
                    unset($persona->bounced_checks[$key]->fecha_pago);
                    unset($persona->bounced_checks[$key]->nombre_persona_firmante);
                    unset($persona->bounced_checks[$key]->cuit_firmante);
                    unset($persona->bounced_checks[$key]->nombre_persona_relacionado);
                    unset($persona->bounced_checks[$key]->Cuit_relacionado);
                    unset($persona->bounced_checks[$key]->nro_cheque);
                    unset($persona->bounced_checks[$key]->fecha_rechazo);
                    unset($persona->bounced_checks[$key]->fecha_levantamiento);
                    unset($persona->bounced_checks[$key]->importe);
                    unset($persona->bounced_checks[$key]->causa);
                    unset($persona->bounced_checks[$key]->tipo);
                }
            }
        }

        //Información Comex.
        if ($configuracion->comex == 1) {
            if ($idioma == 'ESP') {
                $persona->comex = new \stdClass();
            } elseif ($idioma == 'ENG') {
                $persona->comex = new \stdClass();
            }
            //
            $impo = SQLConnection::backendStoreProcedure('obtener_comex', array($cuit), 'select');
            $pais = SQLConnection::backendStoreProcedure('obtener_comex_pais', array($cuit), 'select');
            $rubros = SQLConnection::backendStoreProcedure('obtener_comex_rubros', array($cuit), 'select');
            $totales = SQLConnection::backendStoreProcedure('obtener_comex_totales', array($cuit), 'selectOne');
            //
            if ($idioma == 'ESP') {
                $persona->comex->importaciones = [];
                if (!empty($impo)) {
                    foreach ($impo as $key => $value) {
                        $persona->comex->importaciones[$key] = new \stdClass();
                        $persona->comex->importaciones[$key]->fecha = $value->date;
                        $persona->comex->importaciones[$key]->consumo = $value->consumo;
                        $persona->comex->importaciones[$key]->deposito = $value->deposito;
                        $persona->comex->importaciones[$key]->zonafranca = $value->zonafranca;
                        $persona->comex->importaciones[$key]->temporal = $value->temporal;
                        $persona->comex->importaciones[$key]->total = $value->total;
                    }
                }
            } elseif ($idioma == 'ENG') {
                //
                $persona->comex->imports = [];
                if (!empty($impo)) {
                    foreach ($impo as $key => $value) {
                        $persona->comex->imports[$key] = new \stdClass();
                        $persona->comex->imports[$key]->date = $value->date;
                        $persona->comex->imports[$key]->consumption = $value->consumo;
                        $persona->comex->imports[$key]->deposit = $value->deposito;
                        $persona->comex->imports[$key]->free_trade_zone = $value->zonafranca;
                        $persona->comex->imports[$key]->temporary = $value->temporal;
                        $persona->comex->imports[$key]->total = $value->total;
                    }
                }
            }
            //
            if (!empty($pais)) {
                //
                if ($idioma == 'ESP') {
                    foreach ($pais as $key => $value) {
                        $persona->comex->pais[$key] = new \stdClass();
                        $persona->comex->pais[$key]->tipo_operacion = $value->tipo_operacion;
                        $persona->comex->pais[$key]->fob = $value->fob;
                    }
                } elseif ($idioma == 'ENG') {
                    foreach ($pais as $key => $value) {
                        $persona->comex->country[$key] = new \stdClass();
                        $persona->comex->country[$key]->operation = $value->tipo_operacion;
                        $persona->comex->country[$key]->fob = $value->fob;
                    }
                }
            }
            //
            if (!empty($rubros)) {
                // FALTA TRADUCIR
                if ($idioma == 'ESP') {
                    foreach ($rubros as $key => $value) {
                        $persona->comex->rubros[$key] = new \stdClass();
                        $persona->comex->rubros[$key]->tipo_operacion = $value->tipo_operacion;
                        $persona->comex->rubros[$key]->descripcion = $value->descripcion;
                        $persona->comex->rubros[$key]->fob = $value->fob;
                        $persona->comex->rubros[$key]->posicion = $value->posicion;
                    }
                } elseif ($idioma == 'ENG') {
                    foreach ($rubros as $key => $value) {
                        $persona->comex->category[$key] = new \stdClass();
                        $persona->comex->category[$key]->operation = $value->tipo_operacion;
                        $persona->comex->category[$key]->description = $value->descripcion;
                        $persona->comex->category[$key]->fob = $value->fob;
                        $persona->comex->category[$key]->position = $value->posicion;
                    }
                }
            }
            // 
            if (!empty($totales)) {
                if ($idioma == 'ESP') {
                    $persona->comex->totales = new \stdClass();
                    $persona->comex->totales->total_impo = $totales->total_impo;
                    $persona->comex->totales->total_expo = $totales->total_expo;
                } elseif ($idioma == 'ENG') {
                    $persona->comex->total = new \stdClass();
                    $persona->comex->total->total_imports = $totales->total_impo;
                    $persona->comex->total->total_exports = $totales->total_expo;
                }
            }
        }

        //Información Legales.
        if ($configuracion->legales == 1) {
            $actor = SQLConnection::backendStoreProcedure('obtener_juicios_demandado_actor', array(null, 'A', $cuit, 60, 1), 'select');
            $demandado = SQLConnection::backendStoreProcedure('obtener_juicios_demandado_actor', array(null, 'D', $cuit, 60, 1), 'select');
            if ($idioma == 'ESP') {
                $persona->legales = new \stdClass();
                $persona->legales->actor = [];
                $persona->legales->demandado = [];
                //
                foreach ($actor as $key => $value) {
                    $persona->legales->actor[$key] = new \stdClass();
                    $persona->legales->actor[$key]->fecha_causa = $value->fecha_causa;
                    $persona->legales->actor[$key]->nombre_causa = $value->nombre_causa;
                    $persona->legales->actor[$key]->cuit = $value->cuit_otra_parte;
                    $persona->legales->actor[$key]->nombre = $value->nombre_padron_otra_parte;
                    $persona->legales->actor[$key]->juzgado = $value->juzgado;
                    $persona->legales->actor[$key]->secretaria = $value->secretaria;
                }
                //
                foreach ($demandado as $key => $value) {
                    $persona->legales->demandado[$key] = new \stdClass();
                    $persona->legales->demandado[$key]->fecha_causa = $value->fecha_causa;
                    $persona->legales->demandado[$key]->nombre_causa = $value->nombre_causa;
                    $persona->legales->demandado[$key]->cuit = $value->cuit_otra_parte;
                    $persona->legales->demandado[$key]->nombre = $value->nombre_padron_otra_parte;
                    $persona->legales->demandado[$key]->expediente = $value->expediente;
                    $persona->legales->demandado[$key]->juzgado = $value->juzgado;
                    $persona->legales->demandado[$key]->secretaria = $value->secretaria;
                }
            } elseif ($idioma == 'ENG') {
                $persona->legal = new \stdClass();
                $persona->legal->plaintiff = [];
                $persona->legal->defendant = [];
                //
                foreach ($actor as $key => $value) {
                    $persona->legal->plaintiff[$key] = new \stdClass();
                    $persona->legal->plaintiff[$key]->case_date = $value->fecha_causa;
                    $persona->legal->plaintiff[$key]->process_type = $value->nombre_causa;
                    $persona->legal->plaintiff[$key]->tax_id = $value->cuit_otra_parte;
                    $persona->legal->plaintiff[$key]->name = $value->nombre_padron_otra_parte;
                    $persona->legal->plaintiff[$key]->court = $value->juzgado;
                    $persona->legal->plaintiff[$key]->court_clerk = $value->secretaria;
                }
                //
                foreach ($demandado as $key => $value) {
                    $persona->legal->defendant[$key] = new \stdClass();
                    $persona->legal->defendant[$key]->case_date = $value->fecha_causa;
                    $persona->legal->defendant[$key]->process_type = $value->nombre_causa;
                    $persona->legal->defendant[$key]->tax_id = $value->cuit_otra_parte;
                    $persona->legal->defendant[$key]->name = $value->nombre_padron_otra_parte;
                    $persona->legal->defendant[$key]->process_number = $value->expediente;
                    $persona->legal->defendant[$key]->court = $value->juzgado;
                    $persona->legal->defendant[$key]->court_clerk = $value->secretaria;
                }
            }
        }
        //        
        $codigo_resultado = '200';

        $response_array = [
            'Parameters' => $request->only($parametros),
            'Status' => $codigo_resultado,
            'Message' => Misc::error_query($codigo_resultado),
            'Response' => $persona,
            'Transaction_id' => $transaction_id
        ];

        $this->guardarResultadoApi(
            $cuit,
            null,
            $transaction_id,
            $response_array,
            $codigo_resultado
        );

        return response()->json($response_array);
    }
}
