<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Carbon;
use ElephantIO\Client;

class NotificationsController extends Controller{
    private $responseController;
    private $encryptionController;
    private $functionsController;
    private $documentManagementController;

    public function __construct(){
        $this->responseController = new ResponseController();
        $this->encryptionController = new EncryptionController();
        $this->functionsController = new FunctionsController();
        $this->documentManagementController = new DocumentManagementController();
    }

    public function emitNotification(
        string $module,
        string $title,
        string $content,
        array $actions,
        array $audience,
        string $idUser,
        int $line,
        object $socket,
        int $idOrder = null,
        string $orderType = null
    ) : bool {
        $moduleObj = DB::table('S002V01TMODU')->where([
            ['MODU_NULI', '=', $line],
            ['MODU_IDMO', '=', $module]
        ])->first();

        if(is_null($moduleObj)) return false;
        if(strlen($title) < 1 || strlen($title) > 150) return false;

        $scope = [];
        foreach($audience as $user){
            $scope[] = [
                'USUARIO' => $user,
                'ESTADO' => 'No leído'
            ];
        }

        $now = $this->functionsController->now();
        $nowStr = $now->toDateTimeString();
        $audienceStr = json_encode($audience);
        $idNotification = DB::table('S002V01TNOTI')->insertGetId([
            'NOTI_NULI' => $line,
            'NOTI_IDMO' => $module,
            'NOTI_ASUN' => $title,
            'NOTI_CONT' => $content,
            'NOTI_IDOT' => $idOrder,
            'NOTI_TIOR' => $orderType,
            'NOTI_ACCI' => json_encode($actions),
            'NOTI_AUDI' => $audienceStr,
            'NOTI_ALCA' => json_encode($scope),
            'NOTI_USRE' => $idUser,
            'NOTI_FERE' => $nowStr,
        ]);

        $idNotificationEnc = $this->encryptionController->encrypt($idNotification);
        $audienceEnc = $this->encryptionController->encrypt($audienceStr);

        $notificationData = ['idNotification' => $idNotificationEnc, 'audience' => $audienceEnc];
        $socket->emit('new_notification', $notificationData);

        return true;
    }

    public function getNotification($idNotification, $setRead, $idUser, $line) {
        DB::enableQueryLog();

        $idUser = $this->encryptionController->decrypt($idUser);
        if(!$idUser){
            return $this->responseController->makeResponse(true, 'El ID del usuario que realizó la solicitud no está encriptado correctamente', [], 400);
        }

        $usr = DB::table('S002V01TUSUA')->where([
            ['USUA_NULI', '=', $line],
            ['USUA_IDUS', '=', $idUser],
        ])->first();

        if(is_null($usr)){
            return $this->responseController->makeResponse(true, 'El usuario que realizó la consulta no está registrado', [], 404);
        }

        $idNotification = $this->encryptionController->decrypt($idNotification);
        if(!$idNotification){
            return $this->responseController->makeResponse(true, 'El ID de la notificación solicitada no está encriptado correctamente', [], 400);
        }

        $notification = DB::table('S002V01TNOTI')->select([
            'NOTI_IDNO AS ID_NOTIFICACION',
            'NOTI_IDMO AS ID_MODULO',
            'MODU_NOMO AS MODULO',
            'NOTI_ASUN AS TITULO',
            'NOTI_CONT AS CUERPO_NOTIFICACION',
            'NOTI_IDOT AS ID_ORDEN',
            'NOTI_TIOR AS TIPO_ORDEN',
            'NOTI_ACCI AS ACCIONES',
            'NOTI_AUDI AS AUDIENCIA',
            'NOTI_ALCA AS ALCANCE',
            'NOTI_USRE AS USRREG',
            'NOTI_FERE AS FECREG',
        ])->join('S002V01TMODU', 'MODU_IDMO', '=', 'NOTI_IDMO')->where([
            ['NOTI_NULI', '=', $line],
            ['NOTI_IDNO', '=', $idNotification]
        ])->first();

        if(is_null($notification)){
            return $this->responseController->makeResponse(true, 'La notificación consultada no está registrada.', [], 404);
        }

        $notification->ID_NOTIFICACION = $this->encryptionController->encrypt($notification->ID_NOTIFICACION);
        $notification->ID_MODULO = $this->encryptionController->encrypt($notification->ID_MODULO);

        if(!is_null($notification->ID_ORDEN)){
            $notification->ID_ORDEN = $this->encryptionController->encrypt($notification->ID_ORDEN);
        }

        $audienceArr = json_decode($notification->AUDIENCIA, true);
        if(!in_array($idUser, $audienceArr)){
            return $this->responseController->makeResponse(true, 'El usuario que realizó la consulta no puede leer la notificación.', [], 401);
        }

        foreach($audienceArr as $key=>$user){
            $audienceArr[$key] = $this->encryptionController->encrypt($user);
        }

        $notification->AUDIENCIA = json_encode($audienceArr);
        $scopeArr = json_decode($notification->ALCANCE, true);
        foreach($scopeArr as $key=>$item){
            $item['USUARIO'] = $this->encryptionController->encrypt($item['USUARIO']);
            $scopeArr[$key] = $item;
        }

        if($setRead == 'S'){
            $scopeArrUpd = json_decode($notification->ALCANCE, true);

            foreach($scopeArrUpd as $key=>$item){
                if($item['USUARIO'] == $idUser){
                    $item['ESTADO'] = 'Leído';
                    $scopeArrUpd[$key] = $item;
                }
            }

            $scopeStrUpd = json_encode($scopeArrUpd);
            DB::table('S002V01TNOTI')->where([
                ['NOTI_NULI', '=', $line],
                ['NOTI_IDNO', '=', $idNotification]
            ])->update([
                'NOTI_ALCA' => $scopeStrUpd,
            ]);
        }

        $notification->ALCANCE = json_encode($scopeArr);
        $usrReg = DB::table('S002V01TUSUA')->where([
            ['USUA_NULI', '=', $line],
            ['USUA_IDUS', '=', $notification->USRREG]
        ])->first();

        $nameReg = $this->functionsController->joinName($usrReg->USUA_NOMB, $usrReg->USUA_APPA, $usrReg->USUA_APMA);
        $notification->USRREG = $nameReg . ' (' . $notification->USRREG . ')';

        $now = $this->functionsController->now();
        $nowStr = $now->toDateTimeString();
        $actions = DB::getQueryLog();
        $name = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
        
        $idac = $this->functionsController->registerActivity(
            $line,
            '-',
            '-',
            '-',
            'Consulta',
            "El usuario $name (" . $usr->USUA_IDUS . ") consultó la notificación #$idNotification.",
            $idUser,
            $nowStr,
        );

        $this->functionsController->registerLog($actions, $idUser, $nowStr, $idac, $line);
        return $this->responseController->makeResponse(false, 'EXITO.', $notification);
    }

    public function getNotificationsByUser($idUser, $line) {
        DB::enableQueryLog();

        $idUser = $this->encryptionController->decrypt($idUser);
        if(!$idUser){
            return $this->responseController->makeResponse(true, 'El ID del usuario que realizó la solicitud no está encriptado correctamente', [], 400);
        }

        $usr = DB::table('S002V01TUSUA')->where([
            ['USUA_NULI', '=', $line],
            ['USUA_IDUS', '=', $idUser],
        ])->first();

        if(is_null($usr)){
            return $this->responseController->makeResponse(true, 'El usuario que realizó la consulta no está registrado', [], 404);
        }

        $notifications = DB::table('S002V01TNOTI')->select([
            'NOTI_IDNO AS ID_NOTIFICACION',
            'NOTI_IDMO AS ID_MODULO',
            'MODU_NOMO AS MODULO',
            'NOTI_ASUN AS TITULO',
            'NOTI_CONT AS CUERPO_NOTIFICACION',
            'NOTI_IDOT AS ID_ORDEN',
            'NOTI_TIOR AS TIPO_ORDEN',
            'NOTI_AUDI AS AUDIENCIA',
            'NOTI_ALCA AS ALCANCE',
            'NOTI_USRE AS USRREG',
            'NOTI_FERE AS FECREG',
        ])->join('S002V01TMODU', 'MODU_IDMO', '=', 'NOTI_IDMO')
        ->where('NOTI_NULI', '=', $line)
        ->whereJsonContains('NOTI_AUDI', $idUser)
        ->orderBy('NOTI_FERE', 'desc')->get()->all();

        foreach($notifications as $key=>$notification){
            $notification->ID_NOTIFICACION = $this->encryptionController->encrypt($notification->ID_NOTIFICACION);
            $notification->ID_MODULO = $this->encryptionController->encrypt($notification->ID_MODULO);

            if(!is_null($notification->ID_ORDEN)){
                $notification->ID_ORDEN = $this->encryptionController->encrypt($notification->ID_ORDEN);
            }

            $audienceArr = json_decode($notification->AUDIENCIA, true);
            foreach($audienceArr as $k=>$v){
                $audienceArr[$k] = $this->encryptionController->encrypt($v);
            }

            $notification->AUDIENCIA = json_encode($audienceArr);
            $scopeArr = json_decode($notification->ALCANCE, true);
            foreach($scopeArr as $k=>$v){
                $v['USUARIO'] = $this->encryptionController->encrypt($v['USUARIO']);
                $scopeArr[$k] = $v;
            }

            $notification->ALCANCE = json_encode($scopeArr);
            $usrReg = DB::table('S002V01TUSUA')->where([
                ['USUA_NULI', '=', $line],
                ['USUA_IDUS', '=', $notification->USRREG]
            ])->first();

            $nameReg = $this->functionsController->joinName($usrReg->USUA_NOMB, $usrReg->USUA_APPA, $usrReg->USUA_APMA);
            $notification->USRREG = $nameReg . " (" . $notification->USRREG . ")";
            $notifications[$key] = $notification;
        }

        $now = $this->functionsController->now();
        $nowStr = $now->toDateTimeString();
        $actions = DB::getQueryLog();
        $name = $this->functionsController->joinName($usr->USUA_NOMB, $usr->USUA_APPA, $usr->USUA_APMA);
        
        $idac = $this->functionsController->registerActivity(
            $line,
            '-',
            '-',
            '-',
            'Consulta',
            "El usuario $name (" . $usr->USUA_IDUS . ") consultó su feed de notificaciones.",
            $idUser,
            $nowStr,
        );

        $this->functionsController->registerLog($actions, $idUser, $nowStr, $idac, $line);
        return $this->responseController->makeResponse(false, 'EXITO.', $notifications);
    }
}