<?php

namespace App\Http\Controllers;

use App\Models\CentrosCosto;
use App\Models\Actividades;
use App\Models\ActividadesCentroCosto;
use App\Models\AvanceModulos;
use Illuminate\Http\Request;

class ActividadesCentroCostoController extends Controller
{
    private $apiKey;

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

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

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

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

            $actividades = json_decode($request->input('actividades'));

            foreach($actividades as $act) {
                $id = $actCentroCosto->create(
                    [
                        "con_fk_id" => $request->input("con_fk_id"),
                        "ins_fk_id" => $request->input("ins_fk_id"),
                        "acc_ano" => $request->input("acc_ano"),
                        "cco_fk_id" => $request->input("cco_fk_id"),
                        "act_fk_id" => $act->act_pk_id,
                        "acc_suma_produccion" => $act->acc_suma_produccion
                    ]
                );
            }

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

    public function actualizarActividadesCentroCosto(Request $request) {
        $actividades = json_decode($request->input('actividades'));

        foreach($actividades as $act) {
            ActividadesCentroCosto::on('costos_principal')
                                  ->where("con_fk_id", $request->input("con_fk_id"))
                                  ->where("ins_fk_id", $request->input("ins_fk_id"))
                                  ->where("acc_ano", $request->input("acc_ano"))
                                  ->where("cco_fk_id", $request->input("cco_fk_id"))
                                  ->where("act_fk_id", $act->act_pk_id)
            ->update(
                [
                    
                    "acc_suma_produccion" => $act->acc_suma_produccion
                ]
            );
        }
    }

    public function borrarActividadCentroCosto(Request $request) {
        ActividadesCentroCosto::on('costos_principal')
                              ->where("acc_pk_id", $request->input("acc_pk_id"))
                              ->delete();
    }

    public function getActividadesCentroCosto(Request $request) {
        return ActividadesCentroCosto::on('costos_principal')
                                     ->join('actividades', 'act_pk_id', '=', 'act_fk_id')
                                     ->where('actividades_centro_costo.con_fk_id', $request->input('con_fk_id'))
                                     ->where('actividades_centro_costo.ins_fk_id', $request->input('ins_fk_id'))
                                     ->where('acc_ano', $request->input('acc_ano'))
                                     ->where('cco_fk_id', $request->input('cco_fk_id'))
                                     ->orderBy('act_codigo')
                                     ->orderBy('act_descripcion')
                                     ->get()->toArray();
    }

    public function getActividadesCentroCostoSinPaquetes(Request $request) {
        return ActividadesCentroCosto::on('costos_principal')
                                     ->join('actividades', 'act_pk_id', '=', 'act_fk_id')
                                     ->where('actividades_centro_costo.con_fk_id', $request->input('con_fk_id'))
                                     ->where('actividades_centro_costo.ins_fk_id', $request->input('ins_fk_id'))
                                     ->where('acc_ano', $request->input('acc_ano'))
                                     ->where('cco_fk_id', $request->input('cco_fk_id'))
                                     ->where('act_paquete', false)
                                     ->orderBy('act_codigo')
                                     ->orderBy('act_descripcion')
                                     ->get()->toArray();
    }

    public function getActividadesCentroCostoCompletas(Request $request) {
        return ActividadesCentroCosto::on('costos_principal')
                                     ->join('actividades', 'act_pk_id', '=', 'act_fk_id')
                                     ->join('centros_costo', 'cco_pk_id', '=', 'cco_fk_id')
                                     ->join('sedes', function($join) use($request) {
                                        $join->on('sed_pk_id', 'sed_fk_id');
                                        $join->on('sedes.con_fk_id', 'actividades.con_fk_id');
                                     })
                                     ->where('actividades_centro_costo.con_fk_id', $request->input('con_fk_id'))
                                     ->where('actividades_centro_costo.ins_fk_id', $request->input('ins_fk_id'))
                                     ->where('acc_ano', $request->input('acc_ano'))
                                     ->orderBy('cco_cod_homologado')
                                     ->orderBy('cco_descripcion')
                                     ->orderBy('act_codigo')
                                     ->orderBy('act_descripcion')
                                     ->get()->toArray();
    }

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

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

            fclose($archivo);

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

    private function procesarArchivoActividadesCentroCosto($actCentroCosto, $con_fk_id, $ins_fk_id, $acc_ano) {
        $resultados = new \stdClass();
        $resultados->errores = "";

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

                $actividadesBd = Actividades::on('costos_principal')
                                            ->where('con_fk_id', $con_fk_id)
                                            ->where('ins_fk_id', $ins_fk_id)
                                            ->where('act_ano', $acc_ano)
                                            ->get()->toArray();

                $actCentroCostoBd = ActividadesCentroCosto::on('costos_principal')
                                                        ->join('actividades', 'act_pk_id', '=', 'act_fk_id')
                                                        ->where('actividades_centro_costo.con_fk_id', $con_fk_id)
                                                        ->where('actividades_centro_costo.ins_fk_id', $ins_fk_id)
                                                        ->where('acc_ano', $acc_ano)
                                                        ->get()->toArray();

                $centrosCostoExistentes = [];
                $actividadesExistentes = [];
                $actCentroCostoExistentes = [];
                $registrosProcesados = 0;

                // Crear las relaciones existentes en la base de datos
                foreach ($centrosCostoBd as $ccoDb) {
                    $centrosCostoExistentes[$ccoDb['cco_cod_homologado']] = $ccoDb['cco_pk_id'];
                }

                foreach ($actividadesBd as $actDb) {
                    $actividadesExistentes[$actDb['act_codigo']] = $actDb['act_pk_id'];
                }

                foreach ($actCentroCostoBd as $accDb) {
                    $actCentroCostoExistentes[$accDb['cco_fk_id']][$accDb['act_codigo']] = $accDb['acc_suma_produccion'];
                }

                // Errores de los centros de utilidad
                $centrosCostoInexistentes = "";
                $actividadesInexistentes = "";
                $camposVacios = false;

                // Revisar el archivo respecto a las relaciones existentes
                foreach($actCentroCosto as $accCsv) {
                    $centroCosto = strtoupper(trim($accCsv[0]));
                    $actividad = strtoupper(trim($accCsv[1]));
                    $sumaProduccion = false;

                    if (strtoupper($accCsv[2]) == "S") {
                        $sumaProduccion = true;
                    }

                    if ($centroCosto != "" && $actividad != "") {
                        // Existe el centro de costo
                        if (isset($centrosCostoExistentes[$centroCosto])) {
                            // Existe la actividad
                            if (isset($actividadesExistentes[$actividad])) {
                                // Existe la relacion actividad - centro de costo
                                if (isset($actCentroCostoExistentes[$centrosCostoExistentes[$centroCosto]][$actividad])) {
                                    // Actualizar si la descripcion es diferente
                                    if ($actCentroCostoExistentes[$centrosCostoExistentes[$centroCosto]][$actividad] != $sumaProduccion) {
                                        ActividadesCentroCosto::on('costos_principal')
                                                            ->where("con_fk_id", $con_fk_id)
                                                            ->where("ins_fk_id", $ins_fk_id)
                                                            ->where("acc_ano", $acc_ano)
                                                            ->where("cco_fk_id", $centrosCostoExistentes[$centroCosto])
                                                            ->where("act_fk_id", $actividadesExistentes[$actividad])
                                        ->update(
                                            [
                                                "acc_suma_produccion" => $sumaProduccion
                                            ]
                                        );

                                        $registrosProcesados++;
                                    } else {
                                        $registrosProcesados++;
                                    }
                                } else {
                                    $actCentroCostoNuevo = ActividadesCentroCosto::on('costos_principal');

                                    $id = $actCentroCostoNuevo->create(
                                        [
                                            "con_fk_id" => $con_fk_id,
                                            "ins_fk_id" => $ins_fk_id,
                                            "acc_ano" => $acc_ano,
                                            "cco_fk_id" => $centrosCostoExistentes[$centroCosto],
                                            "act_fk_id" => $actividadesExistentes[$actividad],
                                            "acc_suma_produccion" => $sumaProduccion
                                        ]
                                    );

                                    $registrosProcesados++;

                                    $actCentroCostoExistentes[$centrosCostoExistentes[$centroCosto]][$actividad] = $sumaProduccion;
                                }
                            } else {
                                $actividadesInexistentes .= $actividad.", ";
                            }
                        } else {
                            $centrosCostoInexistentes .= $centroCosto.", ";
                        }
                    } else {
                        $camposVacios = true;
                    }
                }

                // Errores de centros de costo
                if ($centrosCostoInexistentes !== "") {
                    $centrosCostoInexistentes[strlen($centrosCostoInexistentes) - 1] = " ";
                    $centrosCostoInexistentes[strlen($centrosCostoInexistentes) - 2] = " ";
                    $centrosCostoInexistentes = "No existen los siguientes centros de costo o no son finales: ".$centrosCostoInexistentes;

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

                    $resultados->errores .= $centrosCostoInexistentes;
                }

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

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

                    $resultados->errores .= $actividadesInexistentes;
                }

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

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

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

                $resultados->registros = $registrosProcesados;
            }

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

        return json_encode($resultados);
    }

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

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

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


            // Actividades y centros de costo
            \DB::select("insert into costos_principal.actividades (con_fk_id, ins_fk_id, act_ano, act_codigo, act_descripcion)
                        select ".$request->input('con_fk_id').",
                               '".$request->input('ins_fk_id')."',
                               ".$anoActual.",
                               act_codigo,
                               act_descripcion
                        from costos_principal.actividades
                        where con_fk_id = ".$request->input('con_fk_id')." and
                              ins_fk_id = '".$request->input('ins_fk_id')."' and
                              act_ano = ".$anoImportacion);

            $actividadesBd = Actividades::on('costos_principal')
                                        ->where('con_fk_id', $request->input('con_fk_id'))
                                        ->where('ins_fk_id', $request->input('ins_fk_id'))
                                        ->where('act_ano', $anoActual)
                                        ->get()->toArray();

            $actividadesExistentes = [];

            foreach ($actividadesBd as $act) {
                $actividadesExistentes[$act['act_codigo']] = $act['act_pk_id'];
            }

            $centrosCostoBd = 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', $anoActual)
                                          ->get()->toArray();

            $centrosCostoExistentes = [];


            foreach ($centrosCostoBd as $cco) {
                $centrosCostoExistentes[$cco['cco_codigo_completo']] = $cco['cco_pk_id'];
            }

            // Actividades por centro de costo
            $actividadesCentroCosto = \DB::select("select cco_codigo_completo,
                                                          act_codigo,
                                                          acc_suma_produccion
                                                   from costos_principal.actividades_centro_costo as acc
                                                   join costos_principal.centros_costo as cco on (acc.cco_fk_id = cco.cco_pk_id)
                                                   join costos_principal.actividades as act on (acc.act_fk_id = act.act_pk_id)
                                                   where acc.con_fk_id = ".$request->input('con_fk_id')." and
                                                         acc.ins_fk_id = '".$request->input('ins_fk_id')."' and
                                                         acc_ano = ".$anoImportacion);

            foreach ($actividadesCentroCosto as $acc) {
                // Si el centro de costo existe, se hace la importacion
                if (isset($centrosCostoExistentes[$acc->cco_codigo_completo])) {
                    ActividadesCentroCosto::on('costos_principal')->create(
                        [
                            "con_fk_id" => $request->input('con_fk_id'),
                            "ins_fk_id" => $request->input('ins_fk_id'),
                            "acc_ano" => $anoActual,
                            "cco_fk_id" => $centrosCostoExistentes[$acc->cco_codigo_completo],
                            "act_fk_id" => $actividadesExistentes[$acc->act_codigo],
                            "acc_suma_produccion" => $acc->acc_suma_produccion
                        ]
                    );
                }
            }

            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)
            ->update(
                [
                    "avm_actividades" => count($actividadesExistentes) > 0 ? true : false
                ]
            );

            $this->verificarAvance($request->input('con_fk_id'),
                                   $request->input('ins_fk_id'),
                                   $anoActual);
        });
    }

    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
        $act = ActividadesCentroCosto::on('costos_principal')
                                     ->selectRaw('count(distinct cco_fk_id) as cco')
                                     ->where('con_fk_id', $contrato)
                                     ->where('ins_fk_id', $institucion)
                                     ->where('acc_ano', $ano)
                                     ->value('cco');

        $act2 = CentrosCosto::on('costos_principal')
                            ->where('con_fk_id', $contrato)
                            ->where('ins_fk_id', $institucion)
                            ->where('cco_ano', $ano)
                            ->where('cco_final', true)
                            ->count();

        if ($conteo > 0) {
            if ($act > 0 && $act == $act2) {
                AvanceModulos::on('costos_principal')
                                ->where('con_fk_id', $contrato)
                                ->where('ins_fk_id', $institucion)
                                ->where('avm_ano', $ano)
                                ->where('avm_mes', null)
                ->update(
                    [
                        "avm_rel_actividades" => 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_rel_actividades" => false
                    ]
                ); 
            }
        } else {
            if ($act > 0 && $act == $act2) {
                AvanceModulos::on('costos_principal')
                ->create(
                    [
                        "con_fk_id" => $contrato,
                        "ins_fk_id" => $institucion,
                        "avm_ano" => $ano,
                        "avm_mes" => null,
                        "avm_rel_actividades" => true
                    ]
                );
            } else {
                AvanceModulos::on('costos_principal')
                ->create(
                    [
                        "con_fk_id" => $contrato,
                        "ins_fk_id" => $institucion,
                        "avm_ano" => $ano,
                        "avm_mes" => null,
                        "avm_rel_actividades" => false
                    ]
                );
            }
        }          
    }
}
