<?php

namespace App\Http\Controllers;

use App\Models\GrupoSuministros;
use App\Models\Suministros;
use App\Models\AvanceModulos;
use Illuminate\Http\Request;

class SuministrosController extends Controller
{
    private $apiKey;

    function __construct() {
        $apiController = new ApiController();

        $this->apiKey = $apiController->getApiKey()["key"];
    }

    public function crearSuministro(Request $request) {
        $id = new \stdClass();

        \DB::transaction(function() use(&$id, $request) {
            $suministro = Suministros::on('costos_principal');

            $id = $suministro->create(
                [
                    "con_fk_id" => $request->input("con_fk_id"),
                    "ins_fk_id" => $request->input("ins_fk_id"),
                    "sum_ano" => $request->input("sum_ano"),
                    "grs_fk_id" => $request->input("grs_fk_id"),
                    "sum_codigo" => $request->input("sum_codigo"),
                    "sum_nombre" => $request->input("sum_nombre"),
                    "sum_unidad_medida" => $request->input("sum_unidad_medida")
                ]
            );

            
            $this->verificarAvance($request->input("con_fk_id"),
                                   $request->input("ins_fk_id"),
                                   $request->input("sum_ano"));
        });

        return array("response" => $id->sum_pk_id);
    }

    public function actualizarSuministro(Request $request) {
        Suministros::on('costos_principal')
                   ->where("con_fk_id", $request->input("con_fk_id"))
                   ->where("ins_fk_id", $request->input("ins_fk_id"))
                   ->where("sum_ano", $request->input("sum_ano"))
                   ->where("grs_fk_id", $request->input("grs_fk_id"))
                   ->where("sum_codigo", $request->input("sum_codigo"))
        ->update(
            [
                "sum_nombre" => $request->input("sum_nombre"),
                "sum_unidad_medida" => $request->input("sum_unidad_medida")
            ]
        );
    }

    public function borrarSuministro(Request $request) {
        \DB::transaction(function() use(&$id, $request) {
            Suministros::on('costos_principal')
                       ->where("sum_pk_id", $request->input("sum_pk_id"))
                       ->delete();

            $this->verificarAvance($request->input("con_fk_id"),
                                   $request->input("ins_fk_id"),
                                   $request->input("sum_ano"));
        });
    }

    public function getSuministros(Request $request) {
        return Suministros::on('costos_principal')
                          ->join('grupo_suministros', 'grs_pk_id', '=', 'grs_fk_id')
                          ->where('suministros.con_fk_id', $request->input('con_fk_id'))
                          ->where('suministros.ins_fk_id', $request->input('ins_fk_id'))
                          ->where('sum_ano', $request->input('sum_ano'))
                          ->orderBy('grs_codigo')
                          ->orderBy('grs_nombre')
                          ->orderBy('sum_codigo')
                          ->orderBy('sum_nombre')
                          ->get()->toArray();

    }

    public function getSuministrosCsv(Request $request) {
        return Suministros::on('costos_principal')
                          ->select('grs_codigo', 'grs_nombre', 'sum_codigo', 'sum_nombre', 'sum_unidad_medida')
                          ->join('grupo_suministros', 'grs_pk_id', '=', 'grs_fk_id')
                          ->where('suministros.con_fk_id', $request->input('con_fk_id'))
                          ->where('suministros.ins_fk_id', $request->input('ins_fk_id'))
                          ->where('sum_ano', $request->input('sum_ano'))
                          ->orderBy('grs_codigo')
                          ->orderBy('grs_nombre')
                          ->orderBy('sum_codigo')
                          ->orderBy('sum_nombre')
                          ->get()->toArray();

    }

    public function getSuministroEspecifico(Request $request) {
        return Suministros::on('costos_principal')
                          ->where('con_fk_id', $request->input('con_fk_id'))
                          ->where('ins_fk_id', $request->input('ins_fk_id'))
                          ->where('sum_ano', $request->input('sum_ano'))
                          ->where('sum_codigo', $request->input('sum_codigo'))
                          ->get()->toArray();

    }

    public function getSuministrosPorGrupo(Request $request) {
        return Suministros::on('costos_principal')
                          ->where('con_fk_id', $request->input('con_fk_id'))
                          ->where('ins_fk_id', $request->input('ins_fk_id'))
                          ->where('sum_ano', $request->input('sum_ano'))
                          ->where('grs_fk_id', $request->input('grs_fk_id'))
                          ->orderBy('sum_nombre')
                          ->get()->toArray();

    }

    public function cargarArchivoSuministros(Request $request) {
        $apiKey = $request->apiKey;

        if ($apiKey === $this->apiKey) {
            $rutaDelArchivo = $request->suministros->path();
            $delimitador = $request->delimitador;
            $archivo = fopen($rutaDelArchivo, 'r');
            $suministros = array();
            $primeraLinea = true;

            // Extraer cada línea del archivo CSV y convertirlo en un arreglo
            while($linea = fgetcsv($archivo, 1000, $delimitador)) {
                if (!$primeraLinea) {
                    $registro = $linea;
                    array_push($suministros, $registro);
                } else {
                    $primeraLinea = false;
                }
            }

            fclose($archivo);

            return $this->procesarArchivoSuministros($suministros,
                                                     $request->con_fk_id,
                                                     $request->ins_fk_id,
                                                     $request->sum_ano);
        } else {
            throw new \Exception('Imposible completar la petición.');
        }
    }

    private function procesarArchivoSuministros($suministros, $con_fk_id, $ins_fk_id, $sum_ano) {
        $resultados = new \stdClass();
        $resultados->errores = "";

        \DB::transaction(function() use(&$resultados, $suministros, $con_fk_id, $ins_fk_id, $sum_ano) {
            if (count($suministros) === 0) {
                $resultados->correcto = false;
                $resultados->errores = 'El archivo está vacío. ';
                return json_encode($resultados);
            } else if (count($suministros[0]) !== 4) {
                $resultados->correcto = false;
                $resultados->errores = 'La cantidad de columnas no corresponde. ';
                return json_encode($resultados);
            } else {
                $grupoSuministrosBd = GrupoSuministros::on('costos_principal')
                                                    ->where('con_fk_id', $con_fk_id)
                                                    ->where('ins_fk_id', $ins_fk_id)
                                                    ->where('grs_ano', $sum_ano)
                                                    ->get()->toArray();

                $suministrosBd = Suministros::on('costos_principal')
                                            ->join('grupo_suministros', 'grs_pk_id', '=', 'grs_fk_id')
                                            ->where('suministros.con_fk_id', $con_fk_id)
                                            ->where('suministros.ins_fk_id', $ins_fk_id)
                                            ->where('sum_ano', $sum_ano)
                                            ->get()->toArray();

                $grupoSuministrosExistentes = [];
                $suministrosExistentes = [];

                // Crear las relaciones existentes en la base de datos
                foreach ($grupoSuministrosBd as $grsDb) {
                    $grupoSuministrosExistentes[$grsDb['grs_codigo']] = $grsDb['grs_pk_id'];
                }

                foreach ($suministrosBd as $sumDb) {
                    $suministrosExistentes[$sumDb['sum_codigo']] = new \stdClass();

                    $suministrosExistentes[$sumDb['sum_codigo']]->grs_fk_id = $sumDb['grs_fk_id'];
                    $suministrosExistentes[$sumDb['sum_codigo']]->sum_nombre = $sumDb['sum_nombre'];
                    $suministrosExistentes[$sumDb['sum_codigo']]->sum_unidad_medida = $sumDb['sum_unidad_medida'];
                }

                // Variables de control
                $registrosProcesados = 0;
                $grupoSuministrosInexistentes = "";
                $descripcionesLargas = false;
                $camposVacios = false;

                // Revisar el archivo respecto a las relaciones existentes
                foreach($suministros as $sumCsv) {
                    $grupoSuministros = strtoupper(utf8_encode(trim($sumCsv[0])));
                    $suministro = strtoupper(utf8_encode(trim($sumCsv[1])));
                    $nombre = utf8_encode(trim($sumCsv[2]));
                    $unidadMedida = utf8_encode(trim($sumCsv[3]));

                    // Campos vacios
                    if ($grupoSuministros != "" && $suministro != "" && $nombre != "" && $unidadMedida != "") {
                        // Descripcion largas
                        if (strlen($grupoSuministros) <= 10 && strlen($suministro) <= 25 && strlen($nombre) <= 300 && strlen($unidadMedida) <= 80) {
                            // Existe el grupo de suministros
                            if (isset($grupoSuministrosExistentes[$grupoSuministros])) {
                                // Existe el suministro
                                if (isset($suministrosExistentes[$suministro])) {
                                    // Actualizar si la descripcion es diferente
                                    if ($suministrosExistentes[$suministro]->grs_fk_id != $grupoSuministrosExistentes[$grupoSuministros] ||
                                        $suministrosExistentes[$suministro]->sum_nombre != $nombre ||
                                        $suministrosExistentes[$suministro]->sum_unidad_medida != $unidadMedida) {
                                        Suministros::on('costos_principal')
                                                ->where("con_fk_id", $con_fk_id)
                                                ->where("ins_fk_id", $ins_fk_id)
                                                ->where("sum_ano", $sum_ano)
                                                ->where("sum_codigo", $suministro)
                                        ->update(
                                            [
                                                "grs_fk_id" => $grupoSuministrosExistentes[$grupoSuministros],
                                                "sum_nombre" => $nombre,
                                                "sum_unidad_medida" => $unidadMedida
                                            ]
                                        );

                                        $registrosProcesados++;
                                    } else {
                                        $registrosProcesados++;
                                    }
                                } else { // Crear el suministro
                                    $suministrosNuevo = Suministros::on('costos_principal');

                                    $id = $suministrosNuevo->create(
                                        [
                                            "con_fk_id" => $con_fk_id,
                                            "ins_fk_id" => $ins_fk_id,
                                            "sum_ano" => $sum_ano,
                                            "grs_fk_id" => $grupoSuministrosExistentes[$grupoSuministros],
                                            "sum_codigo" => $suministro,
                                            "sum_nombre" => $nombre,
                                            "sum_unidad_medida" => $unidadMedida
                                        ]
                                    );

                                    $registrosProcesados++;

                                    $suministrosExistentes[$suministro] = new \stdClass();

                                    $suministrosExistentes[$suministro]->grs_fk_id = $grupoSuministrosExistentes[$grupoSuministros];
                                    $suministrosExistentes[$suministro]->sum_nombre = $nombre;
                                    $suministrosExistentes[$suministro]->sum_unidad_medida = $unidadMedida;
                                }
                            } else {
                                $grupoSuministrosInexistentes .= $grupoSuministros.", ";
                            }
                        } else {
                            $descripcionesLargas = true;
                        }
                    } else {
                        $camposVacios = true;
                    }
                }

                // Errores de grupo de suministros
                if ($grupoSuministrosInexistentes !== "") {
                    $grupoSuministrosInexistentes[strlen($grupoSuministrosInexistentes) - 1] = " ";
                    $grupoSuministrosInexistentes[strlen($grupoSuministrosInexistentes) - 2] = " ";
                    $grupoSuministrosInexistentes = "No existen los siguientes grupos de suministros: ".$grupoSuministrosInexistentes;

                    $resultados->errores = $grupoSuministrosInexistentes;
                }

                // Descripciones largas
                if ($descripcionesLargas) {
                    if ($resultados->errores !== "") {
                        $resultados->errores .= "-  ";
                    }

                    $resultados->errores .= "Hay descripciones con más caracteres de los permitidos. Son máximo 10 caracteres para el grupo de suministros, 25 para el suministro 300 para el nombre y 80 para la unidad de medida";
                }

                // Campos vacios
                if ($camposVacios) {
                    if ($resultados->errores !== "") {
                        $resultados->errores .= "-  ";
                    }

                    $resultados->errores .= "Hay campos vacíos";
                }

                if (!$descripcionesLargas && !$camposVacios && $grupoSuministrosInexistentes == "") {
                    $resultados->correcto = true;
                } else {
                    $resultados->correcto = false;
                }

                $resultados->registros = $registrosProcesados;
            }

            $this->verificarAvance($con_fk_id, $ins_fk_id, $sum_ano);
        });

        return json_encode($resultados);
    }

    public function verificarAvance($contrato, $institucion, $ano) {
        // Verificar si existe registro del avance
        $conteo = AvanceModulos::on('costos_principal')
                               ->where('con_fk_id', $contrato)
                               ->where('ins_fk_id', $institucion)
                               ->where('avm_ano', $ano)
                               ->whereNull('avm_mes')
                               ->count();

        // Verificar el avance del modulo
        $sum = Suministros::on('costos_principal')
                          ->where('con_fk_id', $contrato)
                          ->where('ins_fk_id', $institucion)
                          ->where('sum_ano', $ano)
                          ->count();

        if ($conteo > 0) {
            if ($sum > 0) {
                AvanceModulos::on('costos_principal')
                                ->where('con_fk_id', $contrato)
                                ->where('ins_fk_id', $institucion)
                                ->where('avm_ano', $ano)
                                ->where('avm_mes', null)
                ->update(
                    [
                        "avm_suministros" => true
                    ]
                );
            } else {
               AvanceModulos::on('costos_principal')
                            ->where('con_fk_id', $contrato)
                            ->where('ins_fk_id', $institucion)
                            ->where('avm_ano', $ano)
                            ->where('avm_mes', null)
                ->update(
                    [
                        "avm_suministros" => false
                    ]
                ); 
            }
        } else {
            AvanceModulos::on('costos_principal')
            ->create(
                [
                    "con_fk_id" => $contrato,
                    "ins_fk_id" => $institucion,
                    "avm_ano" => $ano,
                    "avm_mes" => null,
                    "avm_suministros" => true
                ]
            );
        }            
    }
}
