<?php 
 
namespace App\Controller; 
 
use App\Entity\Equipo; 
use App\Entity\Evento; 
use App\Entity\Grupo; 
use App\Entity\Grupomenu; 
use App\Entity\GrupomenuMenu; 
use App\Entity\Justificacion; 
use App\Entity\Menu; 
use App\Entity\Persona; 
use App\Entity\RegistroCasino; 
use App\Repository\PuertaRepository; 
use DateTimeZone; 
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; 
use Symfony\Component\Form\Extension\DataCollector\Proxy\ResolvedTypeFactoryDataCollectorProxy; 
use Symfony\Component\HttpFoundation\JsonResponse; 
use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; 
use Symfony\Component\Routing\Annotation\Route; 
use App\Repository\PersonaRepository; 
use ZipArchive; 
 
class ApiController extends AbstractController 
{ 
    /** 
     * @Route("/api/personas/{serial}/{timestamp}", name="api_get_personas") 
     */ 
    public function getAll($serial, $timestamp, PersonaRepository $personaRepository): JsonResponse 
    { 
 
        $personas = $personaRepository->findByTimestamp($timestamp); 
        $data = []; 
        foreach ($personas as $persona) { 
            $data[] = [ 
                'rut' => $persona->getRut(), 
                'dv' => $persona->getDv(), 
                'activo' => $persona->getActivo(), 
                'updatedat' => $persona->getUpdatedAt()->getTimestamp(), 
                'pin' => $persona->getPin(), 
 
            ]; 
 
        } 
 
        return new JsonResponse($data, Response::HTTP_OK); 
    } 
 
    /** 
     * @Route("/api/personasfoto/{ip}/{timestamp}", name="api_get_foto_personas") 
     */ 
    public function getAllFoto($ip, $timestamp, PersonaRepository $personaRepository): JsonResponse 
    { 
 
        $personas = $personaRepository->findByTimestamp($timestamp); 
        $data = []; 
        foreach ($personas as $persona) { 
            if ($ip == 'control') { 
                $porticos = $persona->getPorticos(); 
                $array_porticos = []; 
                foreach ($porticos as $portico) { 
                    $array_porticos[] = $portico->getNombre(); 
                } 
                if (in_array('cerezas', $array_porticos)) { 
                    $data[] = [ 
                        'rut' => $persona->getRut(), 
                        'dv' => $persona->getDv(), 
                        'activo' => $persona->getActivo(), 
                        'updatedat' => $persona->getUpdatedAt()->getTimestamp(), 
                        'foto' => $persona->getFoto(), 
                        'nombre' => $persona->getFullName(), 
                    ]; 
 
                } 
 
 
            } else { 
                $data[] = [ 
                    'rut' => $persona->getRut(), 
                    'dv' => $persona->getDv(), 
                    'activo' => $persona->getActivo(), 
                    'updatedat' => $persona->getUpdatedAt()->getTimestamp(), 
                    'foto' => $persona->getFoto(), 
                    'nombre' => $persona->getFullName(), 
                ]; 
            } 
 
        } 
 
        return new JsonResponse($data, Response::HTTP_OK); 
    } 
 
    /** 
     * @Route("/api/puertas/{serial}/{timestamp}", name="api_get_personas_en_puerta") 
     */ 
    public function getAllPuerta($serial, $timestamp, PersonaRepository $personaRepository, PuertaRepository $puertaRepository): JsonResponse 
    { 
        $puerta = $puertaRepository->findOneBySerial($serial); 
 
        $personas = $puerta->getPersonasAutorizadas(); 
        $data = []; 
        foreach ($personas as $persona) { 
            if ($persona->getPin() != "" && $persona->getActivo()) { 
                $data[] = [ 
                    'rut' => $persona->getRut(), 
                    'dv' => $persona->getDv(), 
                    'activo' => $persona->getActivo(), 
                    'updatedat' => $persona->getUpdatedAt()->getTimestamp(), 
                    'pin' => $persona->getPin(), 
                ]; 
            } 
 
        } 
        return new JsonResponse($data, Response::HTTP_OK); 
    } 
 
    /** 
     * @Route("/api/eventos/{serial}", methods={"POST"}) 
     */ 
    public function newEventos($serial, Request $request) 
    { 
        $entityManager = $this->getDoctrine()->getManager(); 
        $data = json_decode($request->getContent(), true); 
        $equipo = $this->getDoctrine()->getRepository(Equipo::class)->findOneBySerial($serial); 
        $control = 0; 
        foreach ($data as $row) { 
            $persona = $this->getDoctrine()->getRepository(Persona::class)->findOneByRut($row[1]); 
            $evento = new Evento(); 
            if ($persona) 
                $evento->setPersona($persona); 
            if ($equipo) 
                $evento->setEquipo($equipo); 
            $evento->setFecha(\DateTime::createFromFormat("Y-m-d H:i:s.u", $row[2])); 
            $evento->setEntrada($row[4]); 
            $evento->setAutorizado($row[5]); 
            $evento->setQr($row[3]); 
            $evento->setIdInterno($row[0]); 
            $entityManager->persist($evento); 
            $control = $row[0]; 
 
 
        } 
        $entityManager->flush(); 
 
 
        return new JsonResponse($control, Response::HTTP_OK); 
 
 
    } 
 
 
 
    /** 
     * @Route("/api/eventos_realtime/{ip}", methods={"POST"}) 
     */ 
    public function newEventosRealtime($ip, Request $request) 
    { 
        $entityManager = $this->getDoctrine()->getManager(); 
        $data = json_decode($request->getContent(), true); 
        $equipo = $this->getDoctrine()->getRepository(Equipo::class)->findOneByIp($ip); 
        $control = 0; 
        $rut = $request->request->get('rut', null); 
        $timestamp = $request->request->get('timestamp', null); 
 
        $persona = $this->getDoctrine()->getRepository(Persona::class)->findOneByRut($rut); 
        $evento = new Evento(); 
        if ($persona) 
            $evento->setPersona($persona); 
        if ($equipo) 
            $evento->setEquipo($equipo); 
        $datetime = new \DateTime(); 
        $datetime->setTimestamp($timestamp); 
        $evento->setFecha($datetime); 
        //evaluar entrada 
        $evento->setEntrada(0); 
        $evento->setAutorizado(1); 
        $evento->setQr($rut); 
        $evento->setIdInterno($rut); 
        $entityManager->persist($evento); 
        $entityManager->flush(); 
        $control = $evento->getId(); 
        $nombre_completo = $persona->getFullName(); 
 
 
        //return new JsonResponse($control, Response::HTTP_OK); 
        return new JsonResponse(['evento' => $control, 'nombre_completo' => $nombre_completo, 'rut'=> $persona->getRut().'-'.$persona->getDv()], Response::HTTP_OK); 
 
 
    } 
 
 
    public function enviarBnovus($evento) 
    { 
        $persona = $evento->getPersona(); 
        $equipo = $evento->getEquipo(); 
        if ($persona && $equipo) { 
            //bnovus:conseguir token 
            $curl = curl_init(); 
 
            curl_setopt_array($curl, array( 
                CURLOPT_URL => 'https://webapiagenteasistencia.bnovus.cl/v1/Login', 
                CURLOPT_RETURNTRANSFER => true, 
                CURLOPT_ENCODING => '', 
                CURLOPT_MAXREDIRS => 10, 
                CURLOPT_TIMEOUT => 0, 
                CURLOPT_FOLLOWLOCATION => true, 
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, 
                CURLOPT_CUSTOMREQUEST => 'POST', 
                CURLOPT_POSTFIELDS => '{ 
                                          "semilla": "22D6A56B-DEEA-4E1E-91BB-56E4345E1B4D", 
                                          "servidorNombre": "SRV-PRUEBAS", 
                                          "servidorIP": "192.168.1.100", 
                                          "servidorDirectorio": "C:\\\\Pruebas", 
                                          "estado": 1 
                                        }', 
                CURLOPT_HTTPHEADER => array( 
                    'Content-Type: application/json' 
                ), 
            )); 
 
            $response = curl_exec($curl); 
 
            curl_close($curl); 
 
            $json = json_decode($response, true); 
 
            //bnovus:hacer marca 
 
            $curl = curl_init(); 
            //tipoMovimiento: 0=Entrada, 1=Salida, 255=Indeterminado 
            $params = ['dispositivoCodigo' => $equipo->getNombreBnovus(), 
                'identificador' => $persona->getRut() . $persona->getDv(), 
                'fechaMarcaje' => date_format($evento->getFecha(), 'Y-m-d\TH:i:s'), 
                'tipoMovimiento' => $equipo->getSentido(), 
                'modoIdentificacion' => 15 
            ]; 
            curl_setopt_array($curl, array( 
                CURLOPT_URL => 'https://webapiagenteasistencia.bnovus.cl/v1/Marcaje', 
                CURLOPT_RETURNTRANSFER => true, 
                CURLOPT_ENCODING => '', 
                CURLOPT_MAXREDIRS => 10, 
                CURLOPT_TIMEOUT => 0, 
                CURLOPT_FOLLOWLOCATION => true, 
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1, 
                CURLOPT_CUSTOMREQUEST => 'POST', 
                CURLOPT_POSTFIELDS => json_encode(array($params)), 
                CURLOPT_HTTPHEADER => array( 
                    'Authorization: Bearer ' . $json['token'], 
                    'Content-Type: application/json' 
                ), 
            )); 
            $response = curl_exec($curl); 
            echo json_encode(array($params)); 
 
            curl_close($curl); 
            return $response; 
        } 
    } 
 
    /** 
     * @Route("/api/eventos_ip/{ip}", methods={"POST"}) 
     */ 
    public function newEventosIP($ip, Request $request) 
    { 
        $bnovus = true; 
        $entityManager = $this->getDoctrine()->getManager(); 
        $data = json_decode($request->getContent(), true); 
        $equipo = $this->getDoctrine()->getRepository(Equipo::class)->findOneByIp($ip); 
        $control = 0; 
        foreach ($data as $row) { 
            $persona = $this->getDoctrine()->getRepository(Persona::class)->findOneByRut($row[1]); 
            $evento = new Evento(); 
            if ($persona) 
            { 
                $evento->setPersona($persona); 
 
 
                if($persona->getTurno()!=NULL){ 
                    $evento->setTurno($persona->getTurno()); 
                } 
 
                if($persona->getGrupo()!=NULL){ 
                    $evento->setGrupo($persona->getGrupo()); 
                } 
            } 
 
            if ($equipo) 
                $evento->setEquipo($equipo); 
            $evento->setFecha(\DateTime::createFromFormat("Y-m-d H:i:s.u", $row[2], new DateTimeZone('America/Santiago'))); 
            if ($equipo->getSentido() == 0) 
                $evento->setEntrada(true); 
            elseif ($equipo->getSentido() == 1) 
                $evento->setEntrada(false); 
            else 
                $evento->setEntrada($row[4]); 
            $evento->setAutorizado($row[5]); 
            $evento->setQr($row[1]); 
            $evento->setIdInterno($row[0]); 
            $evento->setIsJornada(!$equipo->getPortico()->getOperativo()); 
            $entityManager->persist($evento); 
 
            if ($persona) 
            { 
                $persona->setUltimoEvento($evento); 
                $persona->setUltimoEventoFecha($evento->getFecha()); 
            } 
            $control = $row[0]; 
            $entityManager->flush(); 
 
 
            //evento, equipo, persona 
 
            /* 
            try { 
                $respuesta = $this->enviarBnovus($evento, $persona); 
                $fechaactual = new \DateTime('now'); 
                $evento->setFechaBnovus($fechaactual); 
                $evento->setRespuestaBnovus($respuesta); 
                $entityManager->persist($evento); 
                $entityManager->flush(); 
 
            } catch (\Throwable $th) { 
                //throw $th; 
            } 
            */ 
 
        } 
 
 
        return new JsonResponse($control, Response::HTTP_OK); 
 
 
    } 
 
    /** 
     * @Route("/api/newvisita", name="api_visitas") 
     */ 
    public function newVisita(Request $request) 
    { 
        $entityManager = $this->getDoctrine()->getManager(); 
        $rut = $request->request->get('rut'); 
        $dv = $request->request->get('dv'); 
        $grupo_visita = $this->getDoctrine()->getRepository(Grupo::class)->findOneBy(['visitas' => true]); 
        $persona = new Persona(); 
        $persona->setRut($rut); 
        $persona->setDv($dv); 
        $persona->setActivo(true); 
        $persona->setGrupo($grupo_visita); 
        $entityManager->persist($persona); 
        $entityManager->flush(); 
        exec("mosquitto_pub -h localhost -t acceso -m 'update'"); 
        $qr = "QRTOTEM+https://portal.sidiv.registrocivil.cl/docstatus?RUN=" . $persona->getRut() . "-" . $persona->getDv() . "&type"; 
        return new JsonResponse(['qr' => $qr], Response::HTTP_OK); 
    } 
 
    /** 
     * @Route("/api/justificacion", name="api_justificacion") 
     */ 
    public function justificacion(Request $request) 
    { 
 
        $entityManager = $this->getDoctrine()->getManager(); 
        $rut = $request->request->get('rut'); 
        $motivo = $request->request->get('motivo'); 
        $persona = $this->getDoctrine()->getRepository(Persona::class)->findOneByRut($rut); 
        if ($persona) { 
            if ($persona->getActivo() == true) { 
                $justificacion = new Justificacion(); 
                $justificacion->setPersona($persona); 
                $justificacion->setMotivo($motivo); 
                $justificacion->setCreatedAt(new \DateTime()); 
                $entityManager->persist($justificacion); 
                $entityManager->flush(); 
 
                $qr = "QRTOTEM+https://portal.sidiv.registrocivil.cl/docstatus?RUN=" . $persona->getRut() . "-" . $persona->getDv() . "&type"; 
                return new JsonResponse(['qr' => $qr, 'nombre_completo' => $persona->__toString(), 'grupo' => $persona->getGrupo()->getNombre()], Response::HTTP_OK); 
            } else 
                return new JsonResponse(['error' => 'error'], Response::HTTP_OK); 
        } else 
            throw new NotFoundHttpException('Sorry not existing!'); 
 
 
    } 
 
    /** 
     * @Route("/api/registro_casino", name="api_registro_casino") 
     */ 
    public function registroCasino(Request $request): JsonResponse 
    { 
        $em = $this->getDoctrine()->getManager(); 
        $autorizado = false; 
        $ahora = new \DateTime(); 
 
        $rut = $request->request->get('rut', null); 
        $timestampEntregado = $request->request->get('timestamp', null); 
        $timestampConsumido = $request->request->get('timestampConsumido', null); 
 
        if (empty($rut) || empty($timestampEntregado)) { 
            return new JsonResponse(["Faltan parametros"], Response::HTTP_BAD_REQUEST); 
        } 
 
        $persona = $em->getRepository(Persona::class)->findOneBy(["rut" => $rut]); 
        $gruposmenu = $this->getDoctrine()->getRepository(GrupomenuMenu::class)->findBy(array('grupomenu' => $persona->getGrupomenu())); 
        $diasemana = date_format($ahora, 'N'); 
        //dd($gruposmenu); 
 
        foreach ($gruposmenu as $grupomenu) { 
            //validamos día de semana 
            if (in_array($diasemana, $grupomenu->getMenu()->getDiasSemana())) { 
                //ahora + horas 
                $horainicio = strtotime(date_format($grupomenu->getMenu()->getHorarioInicio(), 'G:i:s')) ; 
                $horafin = strtotime(date_format($grupomenu->getMenu()->getHorarioFin(), 'G:i:s')) ; 
                $horaactual = $timestampEntregado - 3600*3; 
                if($horaactual < $horainicio) $horaactual=$horaactual+24*3600; 
 
                //dd($horainicio,$horaactual,$horafin); 
                //dentro de la hora? 
                if ($horaactual < $horafin && $horaactual > $horainicio) { 
                    $autorizado = true; 
                    $menuId = $grupomenu->getMenu()->getId(); 
                } 
            } 
 
        } 
 
 
        if ($autorizado == false) { 
            return new JsonResponse(["No permitido en horario" . strtotime(date_format($ahora, 'G:i:s'))], Response::HTTP_NOT_FOUND); 
        } 
 
        $menu = $em->getRepository(Menu::class)->find($menuId); 
 
        //$registro = $this->getDoctrine()->getRepository(RegistroCasino::class)->findBy(array('menu' => $menu, 'persona' => $persona->getId()), array('id' => 'DESC')); 
        $registro = $this->getDoctrine()->getRepository(RegistroCasino::class)->findDelDia($menu,$persona); 
        if ($registro) { 
 
            if ($registro[0]->getTimestampConsumido() != null) { 
                return new JsonResponse(["Almuerzo ya consumido"], Response::HTTP_NOT_FOUND); 
            } 
 
        } 
 
        $qr = 'RUT)' . $persona->getRut() . '>MENU)' . $menuId; 
        $nombre_completo = $persona->getFullName(); 
 
        if (!$persona) { 
            return new JsonResponse(["No existe persona"], Response::HTTP_NOT_FOUND); 
        } 
 
        if (!$menu) { 
            return new JsonResponse(["No existe menu"], Response::HTTP_NOT_FOUND); 
        } 
 
 
        $registroCasino = $em->getRepository(RegistroCasino::class)->findOneBy(["persona" => $persona, "timestampEntregado" => $timestampEntregado]); 
 
        if (!$registroCasino) { 
            $registroCasino = new RegistroCasino(); 
            $registroCasino->setPersona($persona); 
            $registroCasino->setTimestampEntregado($timestampEntregado); 
            $registroCasino->setMenu($menu); 
        } 
        if ($timestampConsumido) { 
            $registroCasino->setTimestampConsumido($timestampConsumido); 
        } 
        $em->persist($registroCasino); 
        $em->flush(); 
 
        return new JsonResponse(['qr' => $qr, 'nombre_completo' => $nombre_completo, 'menu' => $menu->getNombre(), 'rut'=> $persona->getRut().'-'.$persona->getDv()], Response::HTTP_OK); 
    } 
 
    /** 
     * @Route("/api/registro_casino2", name="api_registro_casino2") 
     */ 
    public function registroCasino2(Request $request): JsonResponse 
    { 
        $em = $this->getDoctrine()->getManager(); 
        $autorizado = false; 
        $ahora = new \DateTime(); 
 
        $rut = $request->request->get('rut', null); 
        $timestampEntregado = $request->request->get('timestamp', null); 
        $timestampConsumido = $request->request->get('timestampConsumido', null); 
 
        if (empty($rut) || empty($timestampEntregado)) { 
            return new JsonResponse(["Faltan parametros"], Response::HTTP_BAD_REQUEST); 
        } 
 
        $persona = $em->getRepository(Persona::class)->findOneBy(["rut" => $rut]); 
        $gruposmenu = $this->getDoctrine()->getRepository(GrupomenuMenu::class)->findBy(array('grupomenu' => $persona->getGrupomenu())); 
        $diasemana = date_format($ahora, 'N'); 
        //dd($gruposmenu); 
 
        foreach ($gruposmenu as $grupomenu) { 
            //validamos día de semana 
            if (in_array($diasemana, $grupomenu->getMenu()->getDiasSemana())) { 
                //ahora + horas 
                $horainicio = strtotime(date_format($grupomenu->getMenu()->getHorarioInicio(), 'G:i:s')) ; 
                $horafin = strtotime(date_format($grupomenu->getMenu()->getHorarioFin(), 'G:i:s')) ; 
                $horaactual = $timestampEntregado - 3600*3; 
                //dd($horainicio,$horaactual,$horafin); 
                //dentro de la hora? 
                if ($horaactual < $horafin && $horaactual > $horainicio) { 
                    $autorizado = true; 
                    $menuId = $grupomenu->getMenu()->getId(); 
                } 
            } 
 
        } 
 
 
        if ($autorizado == false) { 
            return new JsonResponse(["No permitido en horario" . strtotime(date_format($ahora, 'G:i:s'))], Response::HTTP_NOT_FOUND); 
        } 
 
        $menu = $em->getRepository(Menu::class)->find($menuId); 
 
        //$registro = $this->getDoctrine()->getRepository(RegistroCasino::class)->findBy(array('menu' => $menu, 'persona' => $persona->getId()), array('id' => 'DESC')); 
        $registro = $this->getDoctrine()->getRepository(RegistroCasino::class)->findDelDia($menu,$persona); 
        if ($registro) { 
 
            if ($registro[0]->getTimestampConsumido() != null) { 
                return new JsonResponse(["Almuerzo ya consumido"], Response::HTTP_NOT_FOUND); 
            } 
 
        } 
 
        $qr = 'RUT)' . $persona->getRut() . '>MENU)' . $menuId; 
        $nombre_completo = $persona->getFullName(); 
 
        if (!$persona) { 
            return new JsonResponse(["No existe persona"], Response::HTTP_NOT_FOUND); 
        } 
 
        if (!$menu) { 
            return new JsonResponse(["No existe menu"], Response::HTTP_NOT_FOUND); 
        } 
 
 
        $registroCasino = $em->getRepository(RegistroCasino::class)->findOneBy(["persona" => $persona, "timestampEntregado" => $timestampEntregado]); 
 
        if (!$registroCasino) { 
            $registroCasino = new RegistroCasino(); 
            $registroCasino->setPersona($persona); 
            $registroCasino->setTimestampEntregado($timestampEntregado); 
            $registroCasino->setMenu($menu); 
        } 
        if ($timestampConsumido) { 
            $registroCasino->setTimestampConsumido($timestampConsumido); 
        } 
        $em->persist($registroCasino); 
        $em->flush(); 
 
        return new JsonResponse(['qr' => $qr, 'nombre_completo' => $nombre_completo, 'menu' => $menu->getNombre(), 'rut'=> $persona->getRut().'-'.$persona->getDv()], Response::HTTP_OK); 
    } 
 
    /** 
     * @Route("/api/get_menu", name="api_get_menu") 
     */ 
    public function getMenu() 
    { 
        $em = $this->getDoctrine()->getManager(); 
        $gruposMenu = $em->getRepository(Grupomenu::class)->findAll(); 
        $grupoMenuArray = []; 
        $menusArray = []; 
        foreach ($gruposMenu as $grupoMenu) { 
            $menusGrupoMenuArray = []; 
            /** @var GrupomenuMenu $grupomenuMenu */ 
            foreach ($grupoMenu->getGruposmenuMenu() as $grupomenuMenu) { 
                $menusGrupoMenuArray[] = $grupomenuMenu->getMenu()->getId(); 
            } 
            $grupoMenuArray[] = [ 
                "id" => $grupoMenu->getId(), 
                "nombre" => $grupoMenu->getNombre(), 
                "menus" => $menusGrupoMenuArray 
            ]; 
        } 
 
        $menus = $em->getRepository(Menu::class)->findAll(); 
        foreach ($menus as $menu) { 
            $menusArray[] = [ 
                "id" => $menu->getId(), 
                "nombre" => $menu->getNombre(), 
                "horarioInicio" => $menu->getHorarioInicio(), 
                "horarioFin" => $menu->getHorarioFin(), 
                "diasSemana" => $menu->getDiasSemana() 
            ]; 
        } 
 
        return new JsonResponse(["gruposMenu" => $grupoMenuArray, "menus" => $menusArray]); 
    } 
 
    /** 
     * @Route("/api/comprimir_foto_usuario/{grupo}/{timestamp}", methods={"GET"}) 
     */ 
    public function comprimirFotoUsuario($grupo, $timestamp, Request $request, PersonaRepository $personaRepository) 
    { 
        $personas = $personaRepository->findByFotoTimestamp($timestamp); 
        $zip = new ZipArchive(); 
        $path = $this->getParameter('kernel.project_dir') . '/public/' . $this->getParameter("app.path.foto_persona") . '/'; 
        if ($zip->open("foto_usuario_{$grupo}.zip", ZipArchive::CREATE) === true) { 
            foreach ($personas as $persona) { 
                $zip->addFile($path . $persona->getFoto(), $persona->getFoto()); 
            } 
            $zip->close(); 
        } 
        return new JsonResponse("foto_usuario_{$grupo}.zip"); 
    } 
}