<?php

namespace App\Http\Controllers;

use App\Models\ManoObraCentroCosto;
use App\Models\CentrosCosto;
use App\Models\ManoObra;
use App\Models\TipoRecurso;
use App\Models\CaracterRecurso;
use Illuminate\Http\Request;

class ManoObraCentroCostoController extends Controller
{
    private $apiKey;

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

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

    public function getManoObraCentroCosto(Request $request) {
        return ManoObraCentroCosto::on('costos_principal')
                                  ->where('con_fk_id', $request->input("con_fk_id"))
                                  ->where('ins_fk_id', $request->input("ins_fk_id"))
                                  ->where('mcc_ano', $request->input("mcc_ano"))
                                  ->get()->toArray();

    }

    public function getManoObraCentroCostoEspecifico(Request $request) {
        return ManoObraCentroCosto::on('costos_principal')
                                  ->where('mcc_pk_id', $request->input('mcc_pk_id'))
                                  ->get()->toArray();

    }

    public function crearManoObraCentroCosto(Request $request) {
        $manoObraCc = ManoObraCentroCosto::on('costos_principal');

        $id = $manoObraCc->create(
            [
                "con_fk_id" => $request->input("con_fk_id"),
                "ins_fk_id" => $request->input("ins_fk_id"),
                "mcc_ano" => $request->input("mcc_ano"),
                "cco_fk_id" => $request->input("cco_fk_id"),
                "mob_fk_id" => $request->input("mob_fk_id"),
                "tre_fk_id" => $request->input("tre_fk_id"),
                "cre_fk_id" => $request->input("cre_fk_id")
            ]
        );

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

    public function actualizarManoObraCentroCosto(Request $request) {
        ManoObraCentroCosto::on('costos_principal')->where("mcc_pk_id", $request->input("mcc_pk_id"))
        ->update(
            [
                "tre_fk_id" => $request->input("tre_fk_id"),
                "cre_fk_id" => $request->input("cre_fk_id")
            ]
        );
    }

    public function borrarManoObraCentroCosto(Request $request) {
        ManoObraCentroCosto::on('costos_principal')
                           ->where("mcc_pk_id", $request->input("mcc_pk_id"))
                           ->delete();
    }

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

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

            fclose($archivo);

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

    private function procesarArchivoManoObraCentroCosto($manoObraCentroCosto, $con_fk_id, $ins_fk_id, $mcc_ano) {
        $resultados = new \stdClass();
        $resultados->errores = "";

        \DB::transaction(function() use(&$resultados, $manoObraCentroCosto, $con_fk_id, $ins_fk_id, $mcc_ano) {
            if (count($manoObraCentroCosto) === 0) {
                $resultados->correcto = false;
                $resultados->errores = 'El archivo está vacío. ';
                return json_encode($resultados);
            } else if (count($manoObraCentroCosto[0]) !== 4) {
                $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', $mcc_ano)
                                              ->get()->toArray();

                $manoObraBd = ManoObra::on('costos_principal')
                                      ->where('con_fk_id', $con_fk_id)
                                      ->where('ins_fk_id', $ins_fk_id)
                                      ->where('mob_ano', $mcc_ano)
                                      ->get()->toArray();

                $tiposRecursoBd = TipoRecurso::on('costos_principal')->get()->toArray();
                $caracteresRecursoBd = CaracterRecurso::on('costos_principal')->get()->toArray();

                $manoObraCentroCostBd = ManoObraCentroCosto::on('costos_principal')
                                                           ->join('centros_costo', 'cco_pk_id', 'cco_fk_id')
                                                           ->join('mano_obra', 'mob_pk_id', 'mob_fk_id')
                                                           ->where('mano_obra_centro_costo.con_fk_id', $con_fk_id)
                                                           ->where('mano_obra_centro_costo.ins_fk_id', $ins_fk_id)
                                                           ->where('mcc_ano', $mcc_ano)
                                                           ->get()->toArray();

                $centrosCostoExistentes = [];
                $manoObraExistente = [];
                $tiposRecursoExistentes = [];
                $caracteresRecursoExistentes = [];
                $manoObraCentroCostoExistente = [];

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

                foreach ($manoObraBd as $mobDb) {
                    $manoObraExistente[$mobDb['mob_codigo']] = $mobDb['mob_pk_id'];
                }

                foreach ($tiposRecursoBd as $treDb) {
                    $tiposRecursoExistentes[$treDb['tre_pk_id']] = $treDb['tre_descripcion'];
                }

                foreach ($caracteresRecursoBd as $creDb) {
                    $caracteresRecursoExistentes[$creDb['cre_pk_id']] = $creDb['cre_descripcion'];
                }

                foreach ($manoObraCentroCostBd as $mccDb) {
                    $manoObraCentroCostoExistente[$mccDb['cco_cod_homologado']][$mccDb['mob_codigo']] = new \stdClass();

                    $manoObraCentroCostoExistente[$mccDb['cco_cod_homologado']][$mccDb['mob_codigo']]->tre_fk_id = $mccDb['tre_fk_id'];
                    $manoObraCentroCostoExistente[$mccDb['cco_cod_homologado']][$mccDb['mob_codigo']]->cre_fk_id = $mccDb['cre_fk_id'];
                }

                // Variables de control
                $registrosProcesados = 0;
                $centrosCostoInexistentes = "";
                $manoObraInexistente = "";
                $tiposRecursoInexistentes = "";
                $caracteresRecursoInexistentes = "";
                $camposVacios = false;

                // Revisar el archivo respecto a las relaciones existentes
                foreach($manoObraCentroCosto as $mccCsv) {
                    $centroCosto = strtoupper(utf8_encode(trim($mccCsv[0])));
                    $manoObra = strtoupper(utf8_encode(trim($mccCsv[1])));
                    $tipoRecurso = utf8_encode(trim($mccCsv[2]));
                    $caracterRecurso = utf8_encode(trim($mccCsv[3]));

                    // Campos vacios
                    if ($centroCosto != "" && $manoObra != "" && $tipoRecurso != "" && $caracterRecurso != "") {
                        // Existe el centro de costo
                        if (isset($centrosCostoExistentes[$centroCosto])) {
                            // Existe el cargo
                            if (isset($manoObraExistente[$manoObra])) {
                                // Existe el tipo de recurso
                                if (isset($tiposRecursoExistentes[$tipoRecurso])) {
                                    // Existe el caractr de recurso
                                    if (isset($caracteresRecursoExistentes[$caracterRecurso])) {
                                        if (isset($manoObraCentroCostoExistente[$centroCosto][$manoObra])) {
                                            // Actualizar si hay diferencias
                                            if ($manoObraCentroCostoExistente[$centroCosto][$manoObra]->tre_fk_id != $tipoRecurso ||
                                                $manoObraCentroCostoExistente[$centroCosto][$manoObra]->cre_fk_id != $caracterRecurso) {
                                                ManoObraCentroCosto::on('costos_principal')
                                                                   ->where("con_fk_id", $con_fk_id)
                                                                   ->where("ins_fk_id", $ins_fk_id)
                                                                   ->where("mcc_ano", $mcc_ano)
                                                                   ->where("cco_fk_id", $centrosCostoExistentes[$centroCosto])
                                                                   ->where("mob_fk_id", $manoObraExistente[$manoObra])
                                                ->update(
                                                    [
                                                        "tre_fk_id" => $tipoRecurso,
                                                        "cre_fk_id" => $caracterRecurso
                                                    ]
                                                );

                                                $registrosProcesados++;
                                            } else {
                                                $registrosProcesados++;
                                            }
                                        } else { // Crear la mano de obra por centro de costo
                                            $manoObraCentroCostoNuevo = ManoObraCentroCosto::on('costos_principal');

                                            $id = $manoObraCentroCostoNuevo->create(
                                                [
                                                    "con_fk_id" => $con_fk_id,
                                                    "ins_fk_id" => $ins_fk_id,
                                                    "mcc_ano" => $mcc_ano,
                                                    "cco_fk_id" => $centrosCostoExistentes[$centroCosto],
                                                    "mob_fk_id" => $manoObraExistente[$manoObra],
                                                    "tre_fk_id" => $tipoRecurso,
                                                    "cre_fk_id" => $caracterRecurso
                                                ]
                                            );

                                            $registrosProcesados++;

                                            $manoObraCentroCostoExistente[$centroCosto][$manoObra] = new \stdClass();

                                            $manoObraCentroCostoExistente[$centroCosto][$manoObra]->tre_fk_id = $tipoRecurso;
                                            $manoObraCentroCostoExistente[$centroCosto][$manoObra]->cre_fk_id = $caracterRecurso;
                                        }
                                    } else {
                                        $caracteresRecursoInexistentes .= $caracterRecurso.", ";    
                                    }
                                } else {
                                    $tiposRecursoInexistentes .= $tipoRecurso.", ";
                                }
                            } else {
                                $manoObraInexistente .= $manoObra.", "; 
                            }
                        } else {
                            $centrosCostoInexistentes .= $centroCosto.", ";
                        }
                    } else {
                        $camposVacios = true;
                    }
                }

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

                    $resultados->errores = $centrosCostoInexistentes;
                }

                // Errores de mano de obra
                if ($manoObraInexistente !== "") {
                    $manoObraInexistente[strlen($manoObraInexistente) - 1] = " ";
                    $manoObraInexistente[strlen($manoObraInexistente) - 2] = " ";
                    $manoObraInexistente = "No existen la siguiente mano de obra: ".$manoObraInexistente;

                    $resultados->errores = $manoObraInexistente;
                }

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

                    $resultados->errores = $tiposRecursoInexistentes;
                }

                // Errores de caracteres de recurso
                if ($caracteresRecursoInexistentes !== "") {
                    $caracteresRecursoInexistentes[strlen($caracteresRecursoInexistentes) - 1] = " ";
                    $caracteresRecursoInexistentes[strlen($caracteresRecursoInexistentes) - 2] = " ";
                    $caracteresRecursoInexistentes = "No existen los siguientes tipos de recurso: ".$caracteresRecursoInexistentes;

                    $resultados->errores = $caracteresRecursoInexistentes;
                }

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

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

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

                $resultados->registros = $registrosProcesados;
            }
        });

        return json_encode($resultados);
    }
}
