<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ResourcesController extends Controller
{
    private $responseController;
    public function __construct() {
        $this->responseController = new ResponseController();
    }


    public function formatSecuence($cont, $length){
        $longigud = strlen($cont);
        $aumentar = $length - $longigud;
        $contador = '';
        for ($i = 0; $i < $aumentar; $i++) {
            $contador .= '0';
        }
        $contador .= $cont === 0 ? 1 : $cont;
        return $contador;
    }

    // Establece la duracion entre dos fechas
    public function durationDate($date)
    {
        if ($date->d > 29) {
            if ($date->m > 11) {
                $date->y++;
            } else {
                $date->m++;
            }
        }else{
            $date->d++;
        }

        if ($date->y > 0) {

            if ($date->y > 1) {
                $duration = $date->y . " años, ";
            } else {
                $duration = $date->y . " año, ";
            }

            if ($date->m > 1) {
                $duration .= $date->m . " meses, ";
            } else if ($date->m == 1) {
                $duration .= $date->m . " mes, ";
            }

            if ($date->d > 1) {
                $duration .= $date->d . " dias";
            } else if ($date->d == 1) {
                $duration .= $date->d . " dia";
            }

        } else if ($date->m > 0) {

            if ($date->m > 1) {
                $duration = $date->m . " meses, ";
            } else {
                $duration = $date->m . " mes, ";
            }

            if ($date->d > 1) {
                $duration .= $date->d . " dias";
            } else if ($date->d == 1) {
                $duration .= $date->d . " dia";
            }

        } else if ($date->d > 0) {

            if ($date->d > 1) {
                $duration = $date->d . " dias";
            } else {
                $duration = $date->d . " dia";
            }

        } else {
            $duration = "Menos de 1 dia";
        }

        return $duration;
    }

    public function saveImage($img, $pathSave, $nameImage, $line) {

        $ruta = storage_path().$pathSave;
        $secuenceNumber = 0;
        if ( !is_dir($ruta) ) {
            $arrResponseCreate = $this->createRouteSave($pathSave);
            if ($arrResponseCreate['error']) {
                return $arrResponseCreate;
            }else{
                $this->saveImage($img, $pathSave, $nameImage, $line);
            }
        }else{
            $gestor = opendir($ruta);
            while (($archivo = readdir($gestor)) !== false)  {
                if ($archivo != '.' && $archivo != '..') {
                    $secuenceNumber++;
                }
            }

            $numeroLinea = $this->formatSecuence($line, 2);
            $numeroSecuencia = $this->formatSecuence($secuenceNumber, 6);

            $image = str_replace('data:image/jpeg;base64,', '', $img);
            $image = str_replace(' ', '+', $image);

            $currentDate = date("ymd");

            $imageName = "$numeroLinea-GEAD-FO-$currentDate-$numeroSecuencia-01=$nameImage";
            try {
                $validate = \File::put( storage_path(). $pathSave . '/' . $imageName, base64_decode($image) );
            } catch (\Throwable $th) {
                return $this->responseController->makeResponse(true, "ERR_PATH_CRE000: Ocurrió un error al crear la carpeta.", $th->getMessage(), 500);
            }

            return [
                "error" => false,
                "msg" => "ÉXITO: Imagen Creada Exitosamente",
                "response" => $imageName
            ];

        }
    }

    public function saveDocument($documentBase, $pathSave, $nameDocument, $typeDocument, $line) {
        try {
            // Se obtiene la ruta en donde se guardará el archivo
            $routeSaveDocument = "/app/public/$pathSave";
            // Se obtiene la ruta completa del archivo a guardar
            $pathRoute = storage_path().$routeSaveDocument;

            // Se pregunta si la ruta del archivo a guardar existe
            if ( !is_dir($pathRoute) ) {
                // Si no existe, entonces se intentará crear la ruta del archivo
                $arrResponseCreate = $this->createRouteSave($routeSaveDocument);
                // Si no se pudo crear la ruta del archivo, entonces regresa una respuesta negativa
                if ($arrResponseCreate['error']) {
                    return $arrResponseCreate;
                }else{
                    // Si si se pudo crear la ruta, entonces se vuelve a ejecutar el método
                    return $this->saveDocument($documentBase, $pathSave, $nameDocument, $typeDocument, $line);
                }
            } else {
                // Se abré la ruta del archivo
                $management = opendir($pathRoute);
                // Se inicializa el número de secuencia
                $secuenceNumber = 0;
                // Se obtienen todos los archivos guardados en la ruta donde se guardará el archivo
                while ( ($file = readdir($management)) !== false) {
                    if ($file != '.' && $file != '..') {
                        // Se va incrementando el número de secuencia según los archivos obtenidos en la ruta
                        $secuenceNumber++;
                    }
                }
                // Si no se encontró ningún archivo, entonces se inicializa en 1
                if ( $secuenceNumber === 0 ) {
                    $secuenceNumber = 1;
                }
                // Se obtiene el número de línea en el formato deseado (XX)
                $lineNumber = $this->formatSecuence($line, 2);
                // Se obtiene el número de secuencia en el formato deseado (XXXXXX)
                $secuenceNumber = $this->formatSecuence($secuenceNumber, 6);
                // Se obtiene la fecha actual en el formato deseado (YYMMDD)
                $currentDate = date("ymd");
                // Se obtiene el nombre del documento en el formato deseado (mayuscula y sin espacios en blanco)
                $nameDocument = strtoupper(str_replace(' ', '_', trim($nameDocument)));

                // Se genera el código del documento
                $codeDocument = "$lineNumber-$pathSave-$typeDocument-$currentDate-$secuenceNumber-01=$nameDocument";

                // Se obtiene la información del documento en base64
                $document = explode(',', $documentBase)[1];
                $document = str_replace(' ', '+', $document);

                try {
                    // Se guarda el documento en la ruta deseada con el nombre del código generado
                    $validate = \File::put( storage_path(). $routeSaveDocument . '/' . $codeDocument, base64_decode($document) );
                } catch (\Throwable $th) {
                    return [ "error" => true, "msg" =>  "ERR_RESOURCE_DOCUMENT_CRE001: Ocurrió un error al crear la carpeta.", "response" => $th->getMessage() ];
                }

                // Se valida que se haya guardado correctamente el documento
                if ( !$validate ) {
                    return [ "error" => true, "msg" =>  "ERR_RESOURCE_DOCUMENT_CRE002: No se pudo crear la carpeta.", "response" => [] ];
                }

                // Se envía el código del documento
                return [ "error" => false, "msg" => "ÉXITO: Documento Creado Exitosamente", "response" => $codeDocument ];
            }
        } catch (\Throwable $th) {
            return [ "error" => true, "msg" =>  "ERR_RESOURCE_DOCUMENT_CRE000: Ocurrió un error al guardar el documento.", "response" => $th->getMessage() ];
        }
    }

    public function updateDocument($codeDocument, $documentBase, $pathSave, $nameDocument, $typeDocument, $line) {
        try {
            // Se obtiene la ruta en donde se guardará el archivo
            $routeSaveDocument = "/app/public/$pathSave";
            // Se obtiene la ruta completa del archivo a guardar
            $pathRoute = storage_path().$routeSaveDocument;

            // Se pregunta si la ruta del archivo a guardar existe
            if ( !is_dir($pathRoute) ) {
                // Si no existe, entonces se intentará crear la ruta del archivo
                $arrResponseCreate = $this->createRouteSave($routeSaveDocument);
                // Si no se pudo crear la ruta del archivo, entonces regresa una respuesta negativa
                if ($arrResponseCreate['error']) {
                    return $arrResponseCreate;
                }else{
                    // Si si se pudo crear la ruta, entonces se vuelve a ejecutar el método
                    return $this->updateDocument($codeDocument, $documentBase, $pathSave, $nameDocument, $typeDocument, $line);
                }
            } else {

                // Se obtiene la escrutura del código
                $arrResponseStructure = $this->getStrucutreCode( $codeDocument );
                if ( $arrResponseStructure['error'] ) {
                    return [ "error" => true, "msg" =>  $arrResponseStructure['msg'], "response" => [] ];
                }
                $arrStructureCode = $arrResponseStructure['response'];

                // Se abré la ruta del archivo
                $routeGetDocument = "/app/public/$pathSave";
                $management = opendir( storage_path() . $routeGetDocument );

                // Se inicializa la variable si el archivo es encontrado
                $isFound = false;
                // Se obtienen todos los archivos guardados en la ruta donde se guardará el archivo
                while ( ($file = readdir($management)) !== false) {
                    $codeDocumentSave = explode('=', $file)[0];
                    if ($codeDocumentSave == $codeDocument) {
                        // Se va incrementando el número de secuencia según los archivos obtenidos en la ruta
                        $isFound = true;
                    }
                }

                // Si el documento es encontrado en la base de datos documental, entonces...
                if ( !$isFound ) {
                    return [
                        "error" => true,
                        "msg" =>  "ERR_RESOURCE_DOCUMENT_UPD001: No se pudo encontrar el documento en la base de datos documental",
                        "response" => []
                    ];
                }

                // Se obtiene el número de línea en el formato deseado (XX)
                $lineNumber = $arrStructureCode['LINE'];
                // Se obtiene el número de secuencia en el formato deseado (XXXXXX)
                $secuenceNumber = $arrStructureCode['SECUENCE'];
                // Se obtiene la fecha actual en el formato deseado (YYMMDD)
                $currentDate = $arrStructureCode['DATE'];
                // Se obtiene el nombre del documento en el formato deseado (mayuscula y sin espacios en blanco)
                $nameDocument = strtoupper(str_replace(' ', '_', trim($nameDocument)));
                // Se obtiene la versión del documento y se le incrementa uno más
                $versionNumber = $this->formatSecuence( intval($arrStructureCode['VERSION']) + 1 , 2);

                // Se genera el código del documento
                $codeDocument = "$lineNumber-$pathSave-$typeDocument-$currentDate-$secuenceNumber-$versionNumber=$nameDocument";
                // Se obtiene la información del documento en base64
                $document = explode(',', $documentBase)[1];
                $document = str_replace(' ', '+', $document);
                try {
                    // Se guarda el documento en la ruta deseada con el nombre del código generado
                    $validate = \File::put( storage_path() . $routeSaveDocument . '/' . $codeDocument, base64_decode($document) );
                } catch (\Throwable $th) {
                    return [ "error" => true, "msg" =>  "ERR_RESOURCE_DOCUMENT_UPD002: Ocurrió un error al crear la carpeta.", "response" => $th->getMessage() ];
                }

                // Se valida que se haya guardado correctamente el documento
                if ( !$validate ) {
                    return [ "error" => true, "msg" =>  "ERR_RESOURCE_DOCUMENT_UPD003: No se pudo crear la carpeta.", "response" => [] ];
                }
                // Se envía el código del documento
                return [ "error" => false, "msg" => "ÉXITO: Documento Creado Exitosamente", "response" => $codeDocument ];
            }
        } catch (\Throwable $th) {
            return [ "error" => true, "msg" =>  "ERR_RESOURCE_DOCUMENT_UPD000: Ocurrió un error al crear la carpeta.", "response" => $th->getMessage() ];
        }
    }

    public function nameFormatDocument($nameDocument){

        $nameDocument = str_replace(' ', '_', $nameDocument);
        $nameDocument = str_replace('-', '', $nameDocument);
        $nameDocument = str_replace('/', '', $nameDocument);
        $nameDocument = str_replace('\\', '', $nameDocument);
        $nameDocument = str_replace('@', '', $nameDocument);
        $nameDocument = str_replace('&', '', $nameDocument);
        $nameDocument = str_replace('|', '', $nameDocument);
        $nameDocument = str_replace('!', '', $nameDocument);
        $nameDocument = str_replace('"', '', $nameDocument);
        $nameDocument = str_replace("'", '', $nameDocument);
        $nameDocument = str_replace('%', '', $nameDocument);
        $nameDocument = str_replace('(', '', $nameDocument);
        $nameDocument = str_replace(')', '', $nameDocument);
        $nameDocument = str_replace('+', '', $nameDocument);
        $nameDocument = str_replace('+', '', $nameDocument);
        $nameDocument = str_replace('[', '', $nameDocument);
        $nameDocument = str_replace(']', '', $nameDocument);
        $nameDocument = str_replace('?', '', $nameDocument);
        $nameDocument = str_replace('¿', '', $nameDocument);
        $nameDocument = str_replace('!', '', $nameDocument);
        $nameDocument = str_replace('#', '', $nameDocument);
        $nameDocument = str_replace('$', '', $nameDocument);
        $nameDocument = str_replace(':', '', $nameDocument);
        $nameDocument = str_replace('{', '', $nameDocument);
        $nameDocument = str_replace('}', '', $nameDocument);
        $nameDocument = str_replace('°', '', $nameDocument);
        $nameDocument = str_replace('¬', '', $nameDocument);
        $nameDocument = str_replace('=', '', $nameDocument);

        return $nameDocument;
    }

    private function getStrucutreCode($codeDocument) {
        $arrCodeDocument = explode('-', $codeDocument);
        if ( count($arrCodeDocument) < 6) {
            return [ "error" => true, "msg" =>  "ERR_RESOURCE_STRUCTURE_CRE000: No se pudo generar la estructura del código", "response" => [] ];
        }

        $arrStructure = [
            'LINE' => $arrCodeDocument[0],
            'MODULE' => $arrCodeDocument[1],
            'TYPE' => $arrCodeDocument[2],
            'DATE' => $arrCodeDocument[3],
            'SECUENCE' => $arrCodeDocument[4],
            'VERSION' => $arrCodeDocument[5],
        ];

        return [
            "error" => false,
            "msg" =>  "",
            "response" => $arrStructure
        ];

    }

    private $index = 0;

    public function createRouteSave ($path, $savePath = '') {
        try {
            // Se obtiene cada carpeta de la ruta en un arreglo
            $arrPath = explode('/',$path);
            // Se obtiene la cantidad de iteraciones que tendrá el método
            $maxPath = count($arrPath);

            // Si existe el direcctorio y aún se tienen iteraciones disponibles, entonces...
            if ( is_dir( storage_path() . '/' . $savePath . $arrPath[$this->index] ) && $maxPath > $this->index){
                // Se agrega una nueva carpeta a la ruta
                $savePath .= $arrPath[$this->index] . '/';
                // Se incrementa el index para buscar en el arreglo de rutas
                $this->index += 1;
                // Si aún hay iteraciones disponibles, entonces se ejecutará el método de nuevo
                if ($maxPath > $this->index) {
                    $this->createRouteSave($path, $savePath);
                }
            // Si no exite la carpeta, entonces
            } else if (  ! is_dir( storage_path() . '/' . $savePath . $arrPath[$this->index] ) ) {
                try {
                    // Se creará la carpeta
                    if ( ! mkdir( storage_path() . '/' . $savePath . $arrPath[$this->index] ) ) {

                        // En caso de haber un error en la creación de la carpeta, mandará una respuesta negativa
                        return [
                            "error" => true,
                            "msg" => "ERR_RESOURCE_ROUTE_CRE001: Ocurrió un error al crear la carpeta " . $arrPath[$this->index],
                            "response" => storage_path() . '/' . $savePath . $arrPath[$this->index]
                        ];
                    }else{
                        // Si la carpeta se pudo crear de manera exitosa, entonces se ejecutará el método de nuevo
                        $this->createRouteSave($path, $savePath);
                    }
                } catch (\Throwable $th) {
                    return [
                        "error" => true,
                        "msg" => "ERR_RESOURCE_ROUTE_CRE002: Ocurrió un error inesperado al crear la ruta del archivo",
                        "response" => $th->getMessage()
                    ];
                }

            }
            // En caso de crear todas las carpetas, se reinicia las iteraciones a 0
            $this->index = 0;
            // Se envía una respuesta positiva
            return [
                "error" => false,
                "msg" => "Creación de Ruta Exitosa",
                "response" => storage_path() . '/' . $savePath . $arrPath[$this->index]
            ];
        } catch (\Throwable $th) {
            return [
                "error" => true,
                "msg" => "ERR_RESOURCE_ROUTE_CRE000: Ocurrió un error inesperado al generar la ruta del archivo",
                "response" => $th->getMessage()
            ];
        }

    }

}
