<?php

namespace App\Http\Controllers;

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

class CentrosCostoController extends Controller
{
    private $apiKey;

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

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

    public function crearCentroCosto(Request $request) {
        $centroCosto = CentrosCosto::on('costos_principal');
        $codigoHomologado = "";

        if ($request->input("cco_cod_homologado") === "") {
            $codigoHomologado = $request->input("cco_codigo_completo");
        } else {
            $codigoHomologado = $request->input("cco_cod_homologado");
        }

        $id = $centroCosto->create(
            [
                "con_fk_id" => $request->input("con_fk_id"),
                "ins_fk_id" => $request->input("ins_fk_id"),
                "sed_fk_id" => $request->input("sed_fk_id"),
                "cco_ano" => $request->input("cco_ano"),
                "cut_fk_id" => $request->input("cut_fk_id"),
                "scu_fk_id" => $request->input("scu_fk_id"),
                "cco_codigo" => $request->input("cco_codigo"),
                "cco_codigo_completo" => $request->input("cco_codigo_completo"),
                "cco_cod_homologado" => $codigoHomologado,
                "cco_descripcion" => $request->input("cco_descripcion"),
                "cco_final" => $request->input("cco_final"),
                "cco_unidad_medida" => $request->input("cco_unidad_medida")
            ]
        );

        // Cuando se crea un centro de costo no final
        if (!$request->input("cco_final")) {
            AvanceModulos::on('costos_principal')
                        ->where('con_fk_id', $request->input('con_fk_id'))
                        ->where('ins_fk_id', $request->input('ins_fk_id'))
                        ->where('avm_ano', $request->input('cco_ano'))
                        ->whereNull('avm_mes')
            ->update(["avm_dist_costos" => false]);
        }

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

    public function actualizarCentroCosto(Request $request) {
        CentrosCosto::on('costos_principal')->where("cco_pk_id", $request->input("cco_pk_id"))
        ->update(
            [
                "sed_fk_id" => $request->input("sed_fk_id"),
                "cco_codigo" => $request->input("cco_codigo"),
                "cco_codigo_completo" => $request->input("cco_codigo_completo"),
                "cco_cod_homologado" => $request->input("cco_cod_homologado"),
                "cco_descripcion" => $request->input("cco_descripcion"),
                "cco_final" => $request->input("cco_final"),
                "cco_unidad_medida" => $request->input("cco_unidad_medida")
            ]
        );
        

        return $request;
    }

    public function borrarCentroCosto(Request $request) {
        CentrosCosto::on('costos_principal')
                    ->where("cco_pk_id", $request->input("cco_pk_id"))
                    ->delete();
    }

    public function getCentrosCosto(Request $request) {
        return CentrosCosto::on('costos_principal')
                           ->join('centros_utilidad', 'cut_pk_id', '=', 'cut_fk_id')
                           ->join('subcentros_utilidad', 'scu_pk_id', '=', 'scu_fk_id')
                           ->join('sedes', function($join) {
                               $join->on('sed_pk_id', '=', 'sed_fk_id');
                               $join->on('sedes.con_fk_id', '=', 'centros_costo.con_fk_id');
                           })
                           ->where('centros_costo.con_fk_id', $request->input('con_fk_id'))
                           ->where('centros_costo.ins_fk_id', $request->input('ins_fk_id'))
                           ->where('cco_ano', $request->input('cco_ano'))
                           ->orderBy('cut_codigo')
                           ->orderBy('scu_codigo')
                           ->orderBy('cco_cod_homologado')
                           ->get()->toArray();

    }

    public function getCentrosCostoCsv(Request $request) {
        return CentrosCosto::on('costos_principal')
                           ->select('sed_nombre_sede', 'cco_cod_homologado', 'cco_descripcion')
                           ->join('sedes', function($join) {
                               $join->on('sed_pk_id', '=', 'sed_fk_id');
                               $join->on('sedes.con_fk_id', '=', 'centros_costo.con_fk_id');
                           })
                           ->where('centros_costo.con_fk_id', $request->input('con_fk_id'))
                           ->where('centros_costo.ins_fk_id', $request->input('ins_fk_id'))
                           ->where('cco_ano', $request->input('cco_ano'))
                           ->orderBy('cco_codigo')
                           ->get()->toArray();

    }

    public function getCentrosCostoPorCodigo(Request $request) {
        return CentrosCosto::on('costos_principal')
                           ->where('con_fk_id', $request->input('con_fk_id'))
                           ->where('ins_fk_id', $request->input('ins_fk_id'))
                           ->where('cco_ano', $request->input('cco_ano'))
                           ->where('cut_fk_id', $request->input('cut_fk_id'))
                           ->where('scu_fk_id', $request->input('scu_fk_id'))
                           ->where('cco_codigo', $request->input('cco_codigo'))
                           ->get()->toArray();
    }

    public function getCentrosCostoPorCodigoHomologado(Request $request) {
        return CentrosCosto::on('costos_principal')
                           ->where('con_fk_id', $request->input('con_fk_id'))
                           ->where('ins_fk_id', $request->input('ins_fk_id'))
                           ->where('cco_ano', $request->input('cco_ano'))
                           ->where('cco_cod_homologado', $request->input('cco_cod_homologado'))
                           ->get()->toArray();
    }

    public function getCentrosCostoPorSubcentroUtilidad(Request $request) {
        return CentrosCosto::on('costos_principal')
                           ->where('con_fk_id', $request->input('con_fk_id'))
                           ->where('ins_fk_id', $request->input('ins_fk_id'))
                           ->where('cco_ano', $request->input('cco_ano'))
                           ->where('cut_fk_id', $request->input('cut_fk_id'))
                           ->where('scu_fk_id', $request->input('scu_fk_id'))
                           ->orderBy('cco_codigo')
                           ->orderBy('cco_descripcion')
                           ->get()->toArray();
    }

    public function getCentrosCostoPorSede(Request $request) {
        return CentrosCosto::on('costos_principal')
                           ->where('con_fk_id', $request->input('con_fk_id'))
                           ->where('ins_fk_id', $request->input('ins_fk_id'))
                           ->where('cco_ano', $request->input('cco_ano'))
                           ->where('sed_fk_id', $request->input('sed_fk_id'))
                           ->orderBy('cco_codigo')
                           ->orderBy('cco_descripcion')
                           ->get()->toArray();
    }

    public function getCentrosCostosMultipleSede(Request $request) {
        return CentrosCosto::on('costos_principal')
                           ->where('con_fk_id', $request->input('con_fk_id'))
                           ->where('ins_fk_id', $request->input('ins_fk_id'))
                           ->where('cco_ano', $request->input('cco_ano'))
                           ->whereIn('sed_fk_id', explode(',', $request->input('sedes')))
                           ->orderBy('cco_descripcion')
                           ->get()->toArray();
    }

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

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

            fclose($archivo);

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

    private function procesarArchivoCentrosCosto($centrosCosto, $con_fk_id, $ins_fk_id, $cco_ano) {
        $resultados = new \stdClass();
        $resultados->errores = "";

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

                $centrosUtilidadBd = CentrosUtilidad::on('costos_principal')
                                                    ->where('con_fk_id', $con_fk_id)
                                                    ->where('ins_fk_id', $ins_fk_id)
                                                    ->where('cut_ano', $cco_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', $cco_ano)
                                                        ->get()->toArray();

                $centrosCostoBd = CentrosCosto::on('costos_principal')
                                            ->join('centros_utilidad', 'cut_pk_id', '=', 'cut_fk_id')
                                            ->join('subcentros_utilidad', 'scu_pk_id', '=', 'scu_fk_id')
                                            ->where('centros_costo.con_fk_id', $con_fk_id)
                                            ->where('centros_costo.ins_fk_id', $ins_fk_id)
                                            ->where('cco_ano', $cco_ano)
                                            ->get()->toArray();

                $sedesExistentes = [];
                $centrosUtilidadExistentes = [];
                $subcentrosUtilidadExistentes = [];
                $centrosCostoExistentes = [];
                $centrosCostoHomExistentes = [];
                $registrosProcesados = 0;

                // Crear las relaciones existentes en la base de datos
                foreach ($sedesBd as $sedDb) {
                    $sedesExistentes[$sedDb['sed_pk_id']] = $sedDb['sed_nombre_sede'];
                }

                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_pk_id'];
                }

                foreach ($centrosCostoBd as $ccoDb) {
                    $centrosCostoExistentes[$ccoDb['cut_codigo']][$ccoDb['scu_codigo']][$ccoDb['cco_codigo']] = new \stdClass();

                    $centrosCostoExistentes[$ccoDb['cut_codigo']][$ccoDb['scu_codigo']][$ccoDb['cco_codigo']]->cco_pk_id = $ccoDb['cco_pk_id'];
                    $centrosCostoExistentes[$ccoDb['cut_codigo']][$ccoDb['scu_codigo']][$ccoDb['cco_codigo']]->sed_fk_id = $ccoDb['sed_fk_id'];
                    $centrosCostoExistentes[$ccoDb['cut_codigo']][$ccoDb['scu_codigo']][$ccoDb['cco_codigo']]->cco_cod_homologado = $ccoDb['cco_cod_homologado'];
                    $centrosCostoExistentes[$ccoDb['cut_codigo']][$ccoDb['scu_codigo']][$ccoDb['cco_codigo']]->cco_descripcion = $ccoDb['cco_descripcion'];
                    $centrosCostoExistentes[$ccoDb['cut_codigo']][$ccoDb['scu_codigo']][$ccoDb['cco_codigo']]->cco_final = $ccoDb['cco_final'];
                    $centrosCostoExistentes[$ccoDb['cut_codigo']][$ccoDb['scu_codigo']][$ccoDb['cco_codigo']]->cco_unidad_medida = $ccoDb['cco_unidad_medida'];

                    // Codigos homologados
                    $centrosCostoHomExistentes[$ccoDb['cco_cod_homologado']] = $ccoDb['cco_pk_id'];
                }

                // Errores
                $sedesInexistentes = "";
                $centrosUtilidadInexistentes = "";
                $subcentrosUtilidadInexistentes = "";
                $codCentroCostoErroneo = "";
                $codCentroCostoHomRep = "";
                $descripcionesLargas = false;
                $tipoIncorrecto = false;
                $camposVacios = false;

                // Revisar el archivo respecto a las relaciones existentes
                foreach($centrosCosto as $ccoCsv) {
                    $cenUt = strtoupper(utf8_encode(trim($ccoCsv[0])));
                    $subcenUt = strtoupper(utf8_encode(trim($ccoCsv[1])));
                    $sede = strtoupper(utf8_encode(trim($ccoCsv[2])));
                    $cenCos = strtoupper(utf8_encode(trim($ccoCsv[3])));
                    $homologacion = trim(utf8_encode(trim($ccoCsv[4])));
                    $descripcion = utf8_encode(trim($ccoCsv[5]));
                    $tipo = "";
                    $unidadMedida = utf8_encode($ccoCsv[7]);

                    if (strtoupper(trim($ccoCsv[6])) == "F") {
                        $tipo = 1;
                    } else if (strtoupper(trim($ccoCsv[6])) == "NF") {
                        $tipo = 2;
                    } else {
                        $tipo = -1;
                    }

                    // Campos vacios
                    if ($cenUt != "" && $subcenUt != "" && $sede != "" && $cenCos !== "" && $descripcion != "" && $tipo != "" && $unidadMedida != "") {
                        // Tipo de centro de costo correcto
                        if ($tipo != -1) {
                            // Existe la sede
                            if (isset($sedesExistentes[$sede])) {
                                // Existe el centro de costo
                                if (isset($centrosCostoExistentes[$cenUt][$subcenUt][$cenCos])) {
                                    // Actualizar si hay diferencias
                                    if ($centrosCostoExistentes[$cenUt][$subcenUt][$cenCos]->sed_fk_id != $sede ||
                                        $centrosCostoExistentes[$cenUt][$subcenUt][$cenCos]->cco_cod_homologado != $homologacion ||
                                        $centrosCostoExistentes[$cenUt][$subcenUt][$cenCos]->cco_descripcion != $descripcion ||
                                        $centrosCostoExistentes[$cenUt][$subcenUt][$cenCos]->cco_final != $tipo ||
                                        $centrosCostoExistentes[$cenUt][$subcenUt][$cenCos]->cco_unidad_medida != $unidadMedida) {
                                        // Descripciones largas
                                        if (strlen($descripcion) <= 80 && strlen($homologacion) <= 20 && strlen($unidadMedida) <= 80) {
                                            $ccoAux = CentrosCosto::on('costos_principal')
                                                                  ->where("con_fk_id", $con_fk_id)
                                                                  ->where("ins_fk_id", $ins_fk_id)
                                                                  ->where("sed_fk_id", $sede)
                                                                  ->where("cco_ano", $cco_ano)
                                                                  ->where("cut_fk_id", $centrosUtilidadExistentes[$cenUt])
                                                                  ->where("scu_fk_id", $subcentrosUtilidadExistentes[$cenUt][$subcenUt])
                                                                  ->where("cco_codigo", $cenCos);

                                            $codHomOriginal = $ccoAux->pluck('cco_cod_homologado')[0];
                                            $homologacion = $homologacion == "" ? $cenUt.$subcenUt.$cenCos : $homologacion;

                                            // No existe el codigo homologado
                                            if (!isset($centrosCostoHomExistentes[$homologacion]) || $centrosCostoHomExistentes[$homologacion] == $ccoAux->pluck('cco_pk_id')[0]) {
                                                $ccoAux->update(
                                                    [
                                                        "sed_fk_id" => $sede,
                                                        "cco_cod_homologado" => $homologacion,
                                                        "cco_descripcion" => $descripcion,
                                                        "cco_final" => $tipo == "1" ? true : false,
                                                        "cco_unidad_medida" => $unidadMedida
                                                    ]
                                                );

                                                // Codigos homologados
                                                unset($centrosCostoHomExistentes[$codHomOriginal]);
                                                $centrosCostoHomExistentes[$homologacion] = $ccoAux->pluck('cco_pk_id')[0];

                                                $registrosProcesados++;
                                            } else {
                                                $codCentroCostoHomRep .= $homologacion.", ";
                                            }
                                        } else {
                                            $descripcionesLargas = true;
                                        }
                                    } else {
                                        $registrosProcesados++;
                                    }
                                } else { // No existe, es necesario crearlo
                                    // Existe el centro de utilidad
                                    if (isset($centrosUtilidadExistentes[$cenUt])) {
                                        // Existe el subcentro de utilidad
                                        if (isset($subcentrosUtilidadExistentes[$cenUt][$subcenUt])) {
                                            // Codigo del centro de costo correcto
                                            if (strlen($cenCos) == 3 && is_numeric($cenCos)) {
                                                // Descripciones largas
                                                if (strlen($descripcion) <= 80 && strlen($homologacion) <= 20 && strlen($unidadMedida) <= 80) {
                                                    // No existe el codigo homologado
                                                    $homologacion = $homologacion == "" ? $cenUt.$subcenUt.$cenCos : $homologacion;

                                                    if (!isset($centrosCostoHomExistentes[$homologacion])) {
                                                        $centroCosto = CentrosCosto::on('costos_principal');

                                                        $id = $centroCosto->create(
                                                            [
                                                                "con_fk_id" => $con_fk_id,
                                                                "ins_fk_id" => $ins_fk_id,
                                                                "sed_fk_id" => $sede,
                                                                "cco_ano" => $cco_ano,
                                                                "cut_fk_id" => $centrosUtilidadExistentes[$cenUt],
                                                                "scu_fk_id" => $subcentrosUtilidadExistentes[$cenUt][$subcenUt],
                                                                "cco_codigo" => $cenCos,
                                                                "cco_codigo_completo" => $cenUt.$subcenUt.$cenCos,
                                                                "cco_cod_homologado" => $homologacion,
                                                                "cco_descripcion" => $descripcion,
                                                                "cco_final" => $tipo == "1" ? true : false,
                                                                "cco_unidad_medida" => $unidadMedida
                                                            ]
                                                        );

                                                        $registrosProcesados++;

                                                        $centrosCostoExistentes[$cenUt][$subcenUt][$cenCos] = new \stdClass();

                                                        $centrosCostoExistentes[$cenUt][$subcenUt][$cenCos]->cco_pk_id = $id->cco_pk_id;
                                                        $centrosCostoExistentes[$cenUt][$subcenUt][$cenCos]->sed_fk_id = $sede;
                                                        $centrosCostoExistentes[$cenUt][$subcenUt][$cenCos]->cco_cod_homologado = $homologacion == "" ? $cenUt.$subcenUt.$cenCos : $homologacion;
                                                        $centrosCostoExistentes[$cenUt][$subcenUt][$cenCos]->cco_descripcion = $descripcion;
                                                        $centrosCostoExistentes[$cenUt][$subcenUt][$cenCos]->cco_final = $tipo == "1" ? true : false;
                                                        $centrosCostoExistentes[$cenUt][$subcenUt][$cenCos]->cco_unidad_medida = $unidadMedida;

                                                        // Codigos homologados
                                                        $centrosCostoHomExistentes[$homologacion] = $id->cco_pk_id;
                                                    } else {
                                                        $codCentroCostoHomRep .= $homologacion.", ";
                                                    }
                                                } else {
                                                    $descripcionesLargas = true;
                                                }
                                            } else {
                                                $codCentroCostoErroneo .= $cenCos.", ";
                                            }
                                        } else {
                                            $subcentrosUtilidadInexistentes .= $subcenUt.", ";
                                        }
                                    } else {
                                        $centrosUtilidadInexistentes .= $cenUt.", ";
                                    }
                                }
                            } else {
                                $sedesInexistentes .= $sede.", ";
                            }
                        } else {
                            $tipoIncorrecto = true;
                        }
                    } else {
                        $camposVacios = true;
                    }
                }

                // Errores de sedes
                if ($sedesInexistentes !== "") {
                    $sedesInexistentes[strlen($sedesInexistentes) - 1] = " ";
                    $sedesInexistentes[strlen($sedesInexistentes) - 2] = " ";
                    $sedesInexistentes = "No existen las siguientes sedes: ".$sedesInexistentes;

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

                    $resultados->errores = $sedesInexistentes;
                }

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

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

                    $resultados->errores = $centrosUtilidadInexistentes;
                }

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

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

                    $resultados->errores .= $subcentrosUtilidadInexistentes;
                }

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

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

                    $resultados->errores .= $codCentroCostoErroneo;
                }

                // Errores de centros de costo codigos homologados
                if ($codCentroCostoHomRep !== "") {
                    $codCentroCostoHomRep[strlen($codCentroCostoHomRep) - 1] = " ";
                    $codCentroCostoHomRep[strlen($codCentroCostoHomRep) - 2] = " ";
                    $codCentroCostoHomRep = "Los siguientes códigos homologados de centros de costo ya existen: ".$codCentroCostoHomRep;

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

                    $resultados->errores .= $codCentroCostoHomRep;
                }

                // Tipo incorrecto
                if ($tipoIncorrecto) {
                    if ($resultados->errores !== "") {
                        $resultados->errores .= "-  ";
                    }

                    $resultados->errores .= "El campo 'Tipo' solo puede contener dos tipos de valores: 'F' Y 'NF'";
                }

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

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

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

                    $resultados->errores .= "Hay descripciones (80 caracteres), homologaciones (20 caracteres) o unidades de medida (80 caracteres) con una longitud caracteres incorrecta";
                }

                if ($centrosUtilidadInexistentes === "" && $subcentrosUtilidadInexistentes === "" && $codCentroCostoErroneo == "" &&
                    !$descripcionesLargas && !$camposVacios && $sedesInexistentes === "" && $codCentroCostoHomRep == "" && !$tipoIncorrecto) {
                    $resultados->correcto = true;
                } else {
                    $resultados->correcto = false;
                }
                
                $resultados->registros = $registrosProcesados;
            }
        });

        return json_encode($resultados);
    }

    // Revisar que todos los centros y subcentros de utilidad tengan asociados centros de costo
    public function validarEstructuraEmpresa(Request $request) {
        $conteoCentrosUtilidad = CentrosUtilidad::on('costos_principal')
                                                ->where('con_fk_id', $request->input('con_fk_id'))
                                                ->where('ins_fk_id', $request->input('ins_fk_id'))
                                                ->where('cut_ano', $request->input('cco_ano'))
                                                ->count();

        $conteoSubcentrosUtilidad = 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('cco_ano'))
                                                      ->count();

        $conteosCentroCosto = CentrosCosto::on('costos_principal')
                                          ->selectRaw('count(distinct cut_fk_id) as conteo_cut,
                                                       count(distinct scu_fk_id) as conteo_scu,
                                                       count(*) filter (where cco_final = TRUE) as finales,
                                                       count(*) filter (where cco_final = FALSE) as no_finales')
                                          ->where('con_fk_id', $request->input('con_fk_id'))
                                          ->where('ins_fk_id', $request->input('ins_fk_id'))
                                          ->where('cco_ano', $request->input('cco_ano'));

        if (($conteosCentroCosto->value('conteo_cut') == $conteoCentrosUtilidad &&
            $conteosCentroCosto->value('conteo_scu') == $conteoSubcentrosUtilidad) &&
            ($conteoCentrosUtilidad > 0 && $conteoSubcentrosUtilidad > 0)) {
            $this->notificarAvance($request->input('con_fk_id'),
                                $request->input('ins_fk_id'),
                                $request->input('cco_ano'));
        }

        return ($conteosCentroCosto->value('conteo_cut') == $conteoCentrosUtilidad &&
                $conteosCentroCosto->value('conteo_scu') == $conteoSubcentrosUtilidad) &&
                ($conteoCentrosUtilidad > 0 && $conteoSubcentrosUtilidad > 0) &&
                ($conteosCentroCosto->value('finales') > 0 && $conteosCentroCosto->value('no_finales') > 0) ? array("response" => '1') :
                                                                                                              array("response" => '0');
    }

    public function importarEstructura(Request $request) {
        \DB::transaction(function() use($request) {
            $anoActual = $request->input('anoActual');
            $anoImportacion = $request->input('anoImportacion');

            CentrosUtilidad::on('costos_principal')
                           ->where('con_fk_id', $request->input('con_fk_id'))
                           ->where('ins_fk_id', $request->input('ins_fk_id'))
                           ->where('cut_ano', $anoActual)
                           ->delete();

            // Centros de utilidad
            \DB::select("insert into costos_principal.centros_utilidad (con_fk_id, ins_fk_id, cut_ano, cut_codigo, cut_descripcion)
                         select ".$request->input('con_fk_id').",
                                '".$request->input('ins_fk_id')."',
                                ".$anoActual.",
                                cut_codigo,
                                cut_descripcion
                         from costos_principal.centros_utilidad
                         where con_fk_id = ".$request->input('con_fk_id')." and
                               ins_fk_id = '".$request->input('ins_fk_id')."' and
                               cut_ano = ".$anoImportacion);

            $centrosUtilidadDb = CentrosUtilidad::on('costos_principal')
                                                ->where('con_fk_id', $request->input('con_fk_id'))
                                                ->where('ins_fk_id', $request->input('ins_fk_id'))
                                                ->where('cut_ano', $anoActual)
                                                ->get()->toArray();

            $centrosUtilidadExistentes = [];

            foreach($centrosUtilidadDb as $cut) {
                $centrosUtilidadExistentes[$cut['cut_codigo']] = $cut['cut_pk_id'];
            }

            // Subcentros de utilidad
            $subcentrosUtilidad = \DB::select("select cut_codigo, scu_codigo, scu_descripcion
                                               from costos_principal.subcentros_utilidad as scu
                                               join costos_principal.centros_utilidad as cut on (cut_ano = ".$anoImportacion." and scu.cut_fk_id = cut.cut_pk_id)
                                               where scu.con_fk_id = ".$request->input('con_fk_id')." and
                                                     scu.ins_fk_id = '".$request->input('ins_fk_id')."' and
                                                     scu_ano = ".$anoImportacion);

            foreach($subcentrosUtilidad as $scu) {
                SubcentrosUtilidad::on('costos_principal')->create(
                    [
                        "con_fk_id" => $request->input('con_fk_id'),
                        "ins_fk_id" => $request->input('ins_fk_id'),
                        "scu_ano" => $anoActual,
                        "cut_fk_id" => $centrosUtilidadExistentes[$scu->cut_codigo],
                        "scu_codigo" => $scu->scu_codigo,
                        "scu_descripcion" => $scu->scu_descripcion
                    ]
                );
            }

            $subcentrosUtilidadDb = SubcentrosUtilidad::on('costos_principal')
                                                      ->join('centros_utilidad', 'cut_fk_id', '=', 'cut_pk_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', $anoActual)
                                                      ->get()->toArray();

            $subcentrosUtilidadExistentes = [];

            foreach($subcentrosUtilidadDb as $scu) {
                $subcentrosUtilidadExistentes[$scu['cut_codigo']][$scu['scu_codigo']] = $scu['scu_pk_id'];
            }

            // Centros costo
            $centrosCosto = \DB::select("select cut_codigo,
                                                scu_codigo,
                                                cco_codigo,
                                                sed_fk_id,
                                                cco_codigo_completo,
                                                cco_cod_homologado,
                                                cco_descripcion,
                                                cco_final,
                                                cco_unidad_medida
                                        from costos_principal.centros_costo as cco
                                        join costos_principal.centros_utilidad as cut on (cut.cut_ano = ".$anoImportacion." and cco.cut_fk_id = cut.cut_pk_id)
                                        join costos_principal.subcentros_utilidad as scu on (scu.scu_ano = ".$anoImportacion." and cco.scu_fk_id = scu.scu_pk_id)
                                        where cco.con_fk_id = ".$request->input('con_fk_id')." and
                                              cco.ins_fk_id = '".$request->input('ins_fk_id')."' and
                                              cco_ano = ".$anoImportacion);

            foreach($centrosCosto as $cco) {
                CentrosCosto::on('costos_principal')->create(
                    [
                        "con_fk_id" => $request->input('con_fk_id'),
                        "ins_fk_id" => $request->input('ins_fk_id'),
                        "sed_fk_id" => $cco->sed_fk_id,
                        "cco_ano" => $anoActual,
                        "cut_fk_id" => $centrosUtilidadExistentes[$cco->cut_codigo],
                        "scu_fk_id" => $subcentrosUtilidadExistentes[$cco->cut_codigo][$cco->scu_codigo],
                        "cco_codigo" => $cco->cco_codigo,
                        "cco_codigo_completo" => $cco->cco_codigo_completo,
                        "cco_cod_homologado" => $cco->cco_cod_homologado,
                        "cco_descripcion" => $cco->cco_descripcion,
                        "cco_final" => $cco->cco_final,
                        "cco_unidad_medida" => $cco->cco_unidad_medida
                    ]
                );
            }

            $avance = AvanceModulos::on('costos_principal')
                                   ->where('con_fk_id', $request->input('con_fk_id'))
                                   ->where('ins_fk_id', $request->input('ins_fk_id'))
                                   ->where('avm_ano', $anoActual)
                                   ->where('avm_mes', null);

            if ($avance->count() > 0) {
                $avance->update(
                    [
                        "avm_cut" => count($centrosUtilidadDb) > 0 ? true : false,
                        "avm_scu" => count($subcentrosUtilidadDb) > 0 ? true : false
                    ]
                );
            } else {
                AvanceModulos::on('costos_principal')
                ->create(
                    [
                        "con_fk_id" => $request->input('con_fk_id'),
                        "ins_fk_id" => $request->input('ins_fk_id'),
                        "avm_ano" => $anoActual,
                        "avm_mes" => null,
                        "avm_cut" => count($centrosUtilidadDb) > 0 ? true : false,
                        "avm_scu" => count($subcentrosUtilidadDb) > 0 ? true : false
                    ]
                );
            }
        });
    }

    private function notificarAvance($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();

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