<?php

namespace App\Http\Controllers;

use App\Models\CentrosUtilidad;
use App\Models\SubcentrosUtilidad;
use App\Models\AvanceModulos;
use Illuminate\Http\Request;

class SubcentrosUtilidadController extends Controller
{
    private $apiKey;

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

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

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

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

            $id = $subcentroUtilidad->create(
                [
                    "con_fk_id" => $request->input("con_fk_id"),
                    "ins_fk_id" => $request->input("ins_fk_id"),
                    "scu_ano" => $request->input("scu_ano"),
                    "cut_fk_id" => $request->input("cut_fk_id"),
                    "scu_codigo" => $request->input("scu_codigo"),
                    "scu_descripcion" => $request->input("scu_descripcion")
                ]
            );

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

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

    public function actualizarSubcentroUtilidad(Request $request) {
        SubcentrosUtilidad::on('costos_principal')
                          ->where("con_fk_id", $request->input("con_fk_id"))
                          ->where("ins_fk_id", $request->input("ins_fk_id"))
                          ->where("scu_ano", $request->input("scu_ano"))
                          ->where("cut_fk_id", $request->input("cut_fk_id"))
                          ->where("scu_codigo", $request->input("scu_codigo"))
        ->update(
            [
                "scu_descripcion" => $request->input("scu_descripcion")
            ]
        );
    }

    public function borrarSubcentroUtilidad(Request $request) {
        \DB::transaction(function() use($request) {
            SubcentrosUtilidad::on('costos_principal')
                            ->where("scu_pk_id", $request->input("scu_pk_id"))
                            ->delete();
            
            $this->verificarAvance($request->input("con_fk_id"),
                                   $request->input("ins_fk_id"),
                                   $request->input("scu_ano"));
        });
    }

    public function getSubcentrosUtilidad(Request $request) {
        return SubcentrosUtilidad::on('costos_principal')
                                 ->join('centros_utilidad', 'cut_pk_id', '=', 'cut_fk_id')
                                 ->where('subcentros_utilidad.con_fk_id', $request->input('con_fk_id'))
                                 ->where('subcentros_utilidad.ins_fk_id', $request->input('ins_fk_id'))
                                 ->where('scu_ano', $request->input('scu_ano'))
                                 ->orderBy('cut_codigo')
                                 ->orderBy('scu_codigo')
                                 ->get()->toArray();

    }

    public function getSubcentroUtilidadPorCodigo(Request $request) {
        return SubcentrosUtilidad::on('costos_principal')
                                 ->where('con_fk_id', $request->input('con_fk_id'))
                                 ->where('ins_fk_id', $request->input('ins_fk_id'))
                                 ->where('cut_fk_id', $request->input('cut_fk_id'))
                                 ->where('scu_codigo', $request->input('scu_codigo'))
                                 ->where('scu_ano', $request->input('scu_ano'))
                                 ->get()->toArray();
    }

    public function getSubcentroUtilidadPorCentroUtilidad(Request $request) {
        return SubcentrosUtilidad::on('costos_principal')
                                 ->where('con_fk_id', $request->input('con_fk_id'))
                                 ->where('ins_fk_id', $request->input('ins_fk_id'))
                                 ->where('cut_fk_id', $request->input('cut_fk_id'))
                                 ->where('scu_ano', $request->input('scu_ano'))
                                 ->orderBy('scu_codigo')
                                 ->orderBy('scu_descripcion')
                                 ->get()->toArray();
    }

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

        if ($apiKey === $this->apiKey) {
            $rutaDelArchivo = $request->subcentrosUtilidad->path();
            $delimitador = $request->delimitador;
            $archivo = fopen($rutaDelArchivo, 'r');
            $subcentrosUtilidad = 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($subcentrosUtilidad, $registro);
                } else {
                    $primeraLinea = false;
                }
            }

            fclose($archivo);

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

    private function procesarArchivoSubcentrosUtilidad($subcentrosUtilidad, $con_fk_id, $ins_fk_id, $scu_ano) {
        $resultados = new \stdClass();
        $resultados->errores = "";

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

                $subcentrosUtilidadBd = SubcentrosUtilidad::on('costos_principal')
                                                        ->join('centros_utilidad', 'cut_pk_id', '=', 'cut_fk_id')
                                                        ->where('subcentros_utilidad.con_fk_id', $con_fk_id)
                                                        ->where('subcentros_utilidad.ins_fk_id', $ins_fk_id)
                                                        ->where('scu_ano', $scu_ano)
                                                        ->get()->toArray();

                $centrosUtilidadExistentes = [];
                $subcentrosUtilidadExistentes = [];
                $registrosProcesados = 0;

                // Crear las relaciones existentes en la base de datos
                foreach ($centrosUtilidadBd as $cutDb) {
                    $centrosUtilidadExistentes[$cutDb['cut_codigo']] = $cutDb['cut_pk_id'];
                }

                foreach ($subcentrosUtilidadBd as $scuDb) {
                    $subcentrosUtilidadExistentes[$scuDb['cut_codigo']][$scuDb['scu_codigo']] = $scuDb['scu_descripcion'];
                }

                // Almacenar centros de utilidad no existentes
                $centrosUtilidadInexistentes = "";
                $codSubcentroErroneo = "";
                $descripcionesLargas = false;
                $camposVacios = false;

                // Revisar el archivo respecto a las relaciones existentes
                foreach($subcentrosUtilidad as $scuCsv) {
                    $cenUt = strtoupper(utf8_encode(trim($scuCsv[0])));
                    $subcenUt = strtoupper(utf8_encode(trim($scuCsv[1])));
                    $descripcion = utf8_encode(trim($scuCsv[2]));

                    // Campos vacios
                    if ($descripcion != "") {
                        // Existe el subcentro de utilidad
                        if (isset($subcentrosUtilidadExistentes[$cenUt][$subcenUt])) {
                            // Actualizar si el nombre el diferente
                            if ($subcentrosUtilidadExistentes[$cenUt][$subcenUt] != $descripcion) {
                                // Descripciones largas
                                if (strlen($descripcion) <= 80) {
                                    SubcentrosUtilidad::on('costos_principal')
                                                    ->where("con_fk_id", $con_fk_id)
                                                    ->where("ins_fk_id", $ins_fk_id)
                                                    ->where("scu_ano", $scu_ano)
                                                    ->where("cut_fk_id", $centrosUtilidadExistentes[$cenUt])
                                                    ->where("scu_codigo", $subcenUt)
                                    ->update(
                                        [
                                            "scu_descripcion" => $descripcion
                                        ]
                                    );

                                    $registrosProcesados++;
                                } else {
                                    $descripcionesLargas = true;
                                }
                            } else {
                                $registrosProcesados++;
                            }
                        } else { // No existe, es necesario crearlo
                            // Existe el centro de utilidad
                            if (isset($centrosUtilidadExistentes[$cenUt])) {
                                // Codigo del subcentro de utilidad correcto
                                if (strlen($subcenUt) == 2 && is_numeric($subcenUt)) {
                                    // Descripciones largas
                                    if (strlen($descripcion) <= 80) {
                                        $subcentroUtilidad = SubcentrosUtilidad::on('costos_principal');

                                        $id = $subcentroUtilidad->create(
                                            [
                                                "con_fk_id" => $con_fk_id,
                                                "ins_fk_id" => $ins_fk_id,
                                                "scu_ano" => $scu_ano,
                                                "cut_fk_id" => $centrosUtilidadExistentes[$cenUt],
                                                "scu_codigo" => $subcenUt,
                                                "scu_descripcion" => $descripcion
                                            ]
                                        );

                                        $registrosProcesados++;

                                        $subcentrosUtilidadExistentes[$cenUt][$subcenUt] = $descripcion;
                                    } else {
                                        $descripcionesLargas = true;
                                    }
                                } else {
                                    $codSubcentroErroneo .= $subcenUt.", ";
                                }
                            } else {
                                $centrosUtilidadInexistentes .= $cenUt.", ";
                            }
                        }
                    } else {
                        $camposVacios = true;
                    }
                }

                // Errores de centros de utilidad
                if ($centrosUtilidadInexistentes !== "") {
                    $centrosUtilidadInexistentes[strlen($centrosUtilidadInexistentes) - 1] = " ";
                    $centrosUtilidadInexistentes[strlen($centrosUtilidadInexistentes) - 2] = " ";
                    $centrosUtilidadInexistentes = "No existen los siguientes centros de utilidad: ".$centrosUtilidadInexistentes;

                    $resultados->errores .= $centrosUtilidadInexistentes;
                }

                // Errores de subcentros de utilidad
                if ($codSubcentroErroneo !== "") {
                    $codSubcentroErroneo[strlen($codSubcentroErroneo) - 1] = " ";
                    $codSubcentroErroneo[strlen($codSubcentroErroneo) - 2] = " ";
                    $codSubcentroErroneo = "Los siguientes códigos de subcentros de utilidad no son numéricos o no tienen 2 caracteres: ".$codSubcentroErroneo;

                    if ($resultados->errores !== "") {
                        $resultados->errores .= "-  ";
                    }

                    $resultados->errores .= $codSubcentroErroneo;
                }

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

                    $resultados->errores .= "Hay descripciones de más de 80 caracteres";
                }

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

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

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

            $this->verificarAvance($con_fk_id, $ins_fk_id, $scu_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
        $scu = SubcentrosUtilidad::on('costos_principal')
                                 ->where('con_fk_id', $contrato)
                                 ->where('ins_fk_id', $institucion)
                                 ->where('scu_ano', $ano)
                                 ->count();

        if ($conteo > 0) {
            if ($scu > 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_scu" => 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_scu" => false,
                        "avm_cco" => false
                    ]
                ); 
            }
        } else {
            AvanceModulos::on('costos_principal')
            ->create(
                [
                    "con_fk_id" => $contrato,
                    "ins_fk_id" => $institucion,
                    "avm_ano" => $ano,
                    "avm_mes" => null,
                    "avm_scu" => true
                ]
            );
        }          
    }
}
