<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Carbon;

class DocumentManagementController extends Controller
{
    private $responseController;
    private $encryptionController;
    private $functionsController;

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

    public function downloadFile($token, $idUser, $line)
    {

        $tokenInfo = DB::table('S002V01TTODE')->where([
            ['TODE_NULI', '=', $line],
            ['TODE_TOKE', '=', $token]
        ])->first();

        if (is_null($tokenInfo)) {
            return $this->responseController->makeResponse(true, 'El token de descarga no existe.', [], 404);
        } else if ($tokenInfo->TODE_ESTA != 'Activo') {
            return $this->responseController->makeResponse(true, 'El token de descarga ya fue utilizado.', [], 401);
        }

        $token = $this->encryptionController->shortDec($token);
        if (!$token) {
            return $this->responseController->makeResponse(true, 'El token de descarga no está encriptado correctamente.', [], 400);
        }

        $tokenArr = explode("|", $token);
        if (count($tokenArr) != 3) {
            return $this->responseController->makeResponse(true, 'Estructura de token inválida.', [], 401);
        } else if (intval($tokenArr[1]) != $tokenInfo->TODE_LLAL) {
            return $this->responseController->makeResponse(true, 'Token inválido.', [], 401);
        } else if ($tokenArr[2] != 'syp') {
            return $this->responseController->makeResponse(true, 'Token inválido.', [], 401);
        }

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

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

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

        $id = $tokenArr[0];
        $codiArr = explode("=", $id);
        $prefArr = explode("-", $codiArr[0]);
        $suffArr = explode(".", $codiArr[2]);

        $nuli = intval($prefArr[0]);
        $como = $prefArr[1];
        $cldo = $prefArr[2];
        $fecr = $prefArr[3];
        $nuse = intval($prefArr[4]);
        $nuve = $codiArr[1];
        $noar = $suffArr[0];
        $exte = $suffArr[1];

        $nowStr = Carbon::now('America/Mexico_city')->toDateTimeString();
        DB::table('S002V01TTODE')->where([
            ['TODE_IDTO', '=', $tokenInfo->TODE_IDTO],
            ['TODE_NULI', '=', $line]
        ])->update([
            'TODE_ESTA' => 'Usado',
            'TODE_USDE' => $idUser,
            'TODE_FEDE' => $nowStr
        ]);

        $file = DB::table('S002V01TAFAL')->where([
            ['AFAL_NULI', '=', $nuli],
            ['AFAL_COMO', '=', $como],
            ['AFAL_CLDO', '=', $cldo],
            ['AFAL_FECR', '=', $fecr],
            ['AFAL_NUSE', '=', $nuse],
            ['AFAL_NUVE', '=', $nuve],
            ['AFAL_NOAR', '=', $noar],
            ['AFAL_EXTE', '=', $exte],
        ])->first();

        $aux = DB::getQueryLog();

        if (is_null($file)) {
            return $this->responseController->makeResponse(true, 'El archivo solicitado no existe.', [], 404);
        }
        return response()->download($file->AFAL_UBIC);
    }

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

        $idFile = $this->encryptionController->shortDec($idFile);
        if (!$idFile) {
            return $this->responseController->makeResponse(true, 'El ID del archivo requerido no está encriptado correctamente.', [], 400);
        }

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

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

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

        $codiArr = explode("=", $idFile);
        $prefArr = explode("-", $codiArr[0]);
        $suffArr = explode(".", $codiArr[2]);

        $nuli = intval($prefArr[0]);
        $como = $prefArr[1];
        $cldo = $prefArr[2];
        $fecr = $prefArr[3];
        $nuse = intval($prefArr[4]);
        $nuve = $codiArr[1];
        $noar = $suffArr[0];
        $exte = $suffArr[1];

        $file = DB::table('S002V01TAFAL')->where([
            ['AFAL_NULI', '=', $nuli],
            ['AFAL_COMO', '=', $como],
            ['AFAL_CLDO', '=', $cldo],
            ['AFAL_FECR', '=', $fecr],
            ['AFAL_NUSE', '=', $nuse],
            ['AFAL_NUVE', '=', $nuve],
            ['AFAL_NOAR', '=', $noar],
            ['AFAL_EXTE', '=', $exte],
        ])->first();

        $aux = DB::getQueryLog();
        if (is_null($file)) {
            return $this->responseController->makeResponse(true, 'El archivo solicitado no existe.', [], 404);
        }

        $rand = rand(0, 99999);
        $tokenArr = [$idFile, $rand, "syp"];
        $tokenStr = join('|', $tokenArr);

        $token = $this->encryptionController->shortEnc($tokenStr);
        $token = str_replace("+", "=P=", $token);
        $token = str_replace("/", "=S=", $token);
        $nowStr = Carbon::now('America/Mexico_city')->toDateTimeString();

        DB::table('S002V01TTODE')->insert([
            'TODE_NULI' => $line,
            'TODE_TOKE' => $token,
            'TODE_CODO' => $idFile,
            'TODE_LLAL' => $rand,
            'TODE_USRE' => $idUser,
            'TODE_FERE' => $nowStr
        ]);

        return $this->responseController->makeResponse(false, 'EXITO', ['TOKEN' => $token]);
    }

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

        $id = $this->encryptionController->shortDec($id);
        if (!$id) {
            return $this->responseController->makeResponse(true, 'El ID del archivo requerido no está encriptado correctamente.', [], 400);
        }

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

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

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

        $idArr = explode("=", $id);
        $codiArr = explode("-", $idArr[0]);

        $nuli = $line;
        $como = $codiArr[1];
        $cldo = $codiArr[2];
        $fecr = $codiArr[3];
        $nuse = intval($codiArr[4]);
        $nuve = intval($idArr[1]);

        $fileInfo = DB::table('S002V01TAFAL')->select([
            'AFAL_NOAR AS NOMBREARCHIVO',
            'AFAL_EXTE AS EXTENSION',
            'AFAL_TAMA AS PESO',
            'AFAL_USAC AS ACCESO',
            'AFAL_ESTA AS ESTADO'
        ])->where([
            ['AFAL_NULI', '=', $nuli],
            ['AFAL_COMO', '=', $como],
            ['AFAL_CLDO', '=', $cldo],
            ['AFAL_FECR', '=', $fecr],
            ['AFAL_NUSE', '=', $nuse],
            ['AFAL_NUVE', '=', $nuve],
        ])->first();

        if (is_null($fileInfo)) {
            return $this->responseController->makeResponse(true, 'El archivo solicitado no está registrado.', [], 404);
        } else if ($fileInfo->ESTADO != 'Activo') {
            return $this->responseController->makeResponse(true, 'El archivo solicitado no está disponible.', [], 404);
        }

        return $this->responseController->makeResponse(false, 'EXITO', $fileInfo);
    }

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

        $documents = DB::table('s002v01tafal')->select(
            'AFAL_NOAR as NOMBRE_ARC',
            'AFAL_EXTE as EXTENSION',
            'AFAL_TAMA as TAMANIO',
            'AFAL_NUVE as VERSION',
            'AFAL_FECR as FECHA_REGISTRO',
            'AFAL_USRE as PROPIETARIO',
            'AFAL_UBIC as URL',
            'AFAL_USAC AS ACCESO',
            'AFAL_ESTA AS ESTADO',
            'AFAL_NULI AS NUMERO_LINEA',
            'AFAL_CLDO AS CLASIFICACION',
            'AFAL_COMO AS MODULO',
            'AFAL_NUSE AS SECUENCIAL'
        )->where('AFAL_USRE', $idUser)->get()->all();

        $nowStr = Carbon::now('America/Mexico_city')->toDateTimeString();
        $actions = DB::getQueryLog();

        //$this->functionsController->registerActivity($actions, $idUser, $nowStr, $line);
        return $this->responseController->makeresponse(false, "EXITO", $documents);
    }

    public function getInfoDocument($idUser, $line, $idDocument)
    {
        DB::enableQueryLog();
        $idUser = $this->encryptionController->shortDec($idUser);
        if (!$idUser) {
            return $this->responseController->makeResponse(true, 'El ID del usuario que realizó la solicitud no está encriptado correctamente', [], 400);
        }

        $idDocument = $this->encryptionController->shortDec($idDocument);
        if (!$idDocument) {
            return $this->responseController->makeResponse(true, 'El ID del documento no está encriptado correctamente', [], 400);
        }

        $document = DB::table('s002v01tafal')->where('AFAL_USRE', $idUser)->where('AFAL_ID', $idDocument)->get();

        $nowStr = Carbon::now('America/Mexico_city')->toDateTimeString();
        $actions = DB::getQueryLog();

        //$this->functionsController->registerActivity($actions, $idUser, $nowStr, $line);
        return $this->responseController->makeresponse(false, "EXITO", $document);
    }

    /* public function moveFinalFile(Request $request)
    {
        DB::enableQueryLog();
        $validator = Validator::make($request->all(), [
            'id_user' => 'required|string',
            'linea' => 'required|integer',
            'audiencia' => 'required|json',
            'archivos' => 'required|json',
            'cldo' => 'required|string',
            ''
        ]);

        if($validator->fails()){
            return $this->responseController->makeResponse(
                true,
                "Se encontraron uno o más errores.",
                $this->responseController->makeErrors(
                    $validator->errors()->messages()
                ),
                401
            );
        }

        $advice = $request->all();
        $idUser = $this->encryptionController->decrypt($advice['id_user']);
        if(!$idUser){
            return $this->responseController->makeResponse(true, "El ID del usuario que realizó la petición no fue encriptado correctamente", [], 400);
        }

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

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

        $filesArr = json_decode($advice['archivos'], true);
        $nowStr = Carbon::now('America/Mexico_city')->toDateTimeString();
        $attachedArr = [];
        foreach($filesArr as $file){
            $idFile = $file['id'];
            $idFile = $this->encryptionController->decrypt($idFile);
            if(!$idFile){
                return $this->responseController->makeResponse(true, "El ID del archivo $file[name] no fue encriptado correctamente", [], 400);
            }

            $fileObj = DB::table('S002V01TARTE')->where([
                ['ARTE_IDAR', '=', $idFile],
                ['ARTE_NULI', '=', $advice['linea']]
            ])->first();

            if(is_null($fileObj)){
                return $this->responseController->makeResponse(true, "El ID del archivo $file[name] no existe", [], 404);
            }else if($fileObj->ARTE_ESTA == 'Eliminado'){
                return $this->responseController->makeResponse(true, "El archivo $file[name] está eliminado", [], 404);
            }

            $fileSaved = $this->moveFinalFile($advice['linea'], 'AV', $fileObj, 'S002V01M01ADSI', 'S002V01F03CRAV', 'S002V01P02CNAV');
            if(!$fileSaved[0]){
                return $this->responseController->makeResponse(true, "El archivo no pudo guardarse: $fileSaved[1]", [], 500);
            }

            $attachedArr[] = $this->encryptionController->encrypt($fileSaved[1]);

            DB::table('S002V01TARTE')->where([
                ['ARTE_IDAR', '=', $idFile],
                ['ARTE_NULI', '=', $advice['linea']],
            ])->update([
                'ARTE_ESTA' => 'Eliminado',
                'ARTE_USMO' => $idUser,
                'ARTE_FEMO' => $nowStr
            ]);
        }

        $ubiTempFile = $file->ARTE_UBTE;
        $ubiFileArr = explode('tempFiles', $ubiTempFile);
        $ubic = $ubiFileArr[0] . 'files' . $ubiFileArr[1];

        $como = substr($module, -4);
        $date = Carbon::now('America/Mexico_city')->toDateTimeString();
        $dateArr = explode(' ', $date);
        $dateStr = $dateArr[0];
        $dA = explode('-', $dateStr);
        $dA[0] = substr($dA[0], -2);
        $fecr = implode('', $dA);

        $nameStr = $file->ARTE_NOAR;
        $nameArr = explode('.', $nameStr);

        $nuve = 0;
        $nuse = 0;

        $lastSec = DB::table('S002V01TAFAL')->where([
            ['AFAL_NULI', '=', $line],
            ['AFAL_COMO', '=', $como],
            ['AFAL_CLDO', '=', $cldo]
        ])->orderBy('AFAL_NUSE', 'desc')->first();

        if (is_null($lastSec)) {
            $nuse = 1;
        } else {
            $nuse = $lastSec->AFAL_NUSE + 1;
        }

        $lastVersion = DB::table('S002V01TAFAL')->where([
            ['AFAL_NULI', '=', $line],
            ['AFAL_NOAR', '=', $nameArr[0]],
            ['AFAL_EXTE', '=', $nameArr[1]],
        ])->orderBy('AFAL_NUVE', 'desc')->first();

        if (is_null($lastVersion)) {
            $nuve = 1;
        } else {
            $nuve = $lastVersion->AFAL_NUVE + 1;
        }

        if ($nuve > 99) return [false, 'El archivo llegó al número máximo de versiones'];
        if ($nuse > 999999) return [false, 'El archivo llegó al número de secuencia máximo'];


        $noar = $nameArr[0];
        $exte = $nameArr[1];

        if (strlen($noar) > 100) return [false, 'El nombre del archivo tiene una longitud mayor a 100 caracteres'];
        $tama = $file->ARTE_TAMA;
        $usac = json_encode([$file->ARTE_USRE]);
        $usre = $file->ARTE_USRE;
        $fere = $file->ARTE_FERE;

        DB::table('S002V01TAFAL')->insert([
            'AFAL_NULI' => $line,
            'AFAL_COMO' => $como,
            'AFAL_CLDO' => $cldo,
            'AFAL_FECR' => $fecr,
            'AFAL_NUSE' => $nuse,
            'AFAL_NUVE' => $nuve,
            'AFAL_NOAR' => $noar,
            'AFAL_EXTE' => $exte,
            'AFAL_TAMA' => $tama,
            'AFAL_UBIC' => $ubic,
            'AFAL_USAC' => $usac,
            'AFAL_USRE' => $usre,
            'AFAL_FERE' => $fere
        ]);

        if (file_exists($file->ARTE_UBTE)) {
            rename($file->ARTE_UBTE, $ubic);
        }

        $codigo = "";
        if (strlen($line) < 2) {
            $codigo .= "0$line-";
        } else {
            $codigo .= "$line-";
        }

        $codigo .= "$como-$cldo-$fecr-";
        switch (strlen($nuse)) {
            case 1:
                $codigo .= "00000$nuse";
                break;
            case 2:
                $codigo .= "0000$nuse";
                break;
            case 3:
                $codigo .= "000$nuse";
                break;
            case 4:
                $codigo .= "00$nuse";
                break;
            case 5:
                $codigo .= "0$nuse";
                break;
            default:
                $codigo .= "$nuse";
                break;
        }

        if (strlen($nuve) < 2) {
            $codigo .= "=0$nuve=";
        } else {
            $codigo .= "=$nuve=";
        }

        $codigo .= "$noar.$exte";

        return [true, $codigo];
    } */


    public function getTypesDocuments($line) {
        try {
            $arrTypesDocuments = DB::table('S002V01TTIDO')
                ->where('TIDO_NULI', '=', $line)
                ->where('TIDO_ESTA', '=', 'Activo')
                ->get([
                    'TIDO_IDTI', // Identificador del Tipo
                    'TIDO_ACRO', // Acrónimo del tipo
                    'TIDO_TIPO', // Tipo
                    'TIDO_EXTE', // Extensiones
                ]);
        } catch (\Throwable $th) {
            return $this->responseController->makeResponse(true, 'ERR_TYPES_GET001: Ocurrió un error al obtener los tipos de documentos.', $th->getMessage(), 400);
        }

        return $this->responseController->makeresponse(false, "ÉXITO: Consulta Exitosa", $arrTypesDocuments);
    }
}
