<?php

namespace App\Http\Controllers;

use App\Models\ContratosEps;
use App\Models\AvanceModulos;
use Illuminate\Http\Request;

class ContratosEpsController extends Controller
{
    private $apiKey;

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

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

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

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

            $id = $contratosEps->create(
                [
                    "con_fk_id" => $request->input("con_fk_id"),
                    "ins_fk_id" => $request->input("ins_fk_id"),
                    "coe_ano" => $request->input("coe_ano"),
                    "coe_nit_eps" => $request->input("coe_nit_eps"),
                    "coe_nombre_eps" => $request->input("coe_nombre_eps"),
                    "reg_fk_id" => $request->input("reg_fk_id"),
                    "coe_numero_contrato" => $request->input("coe_numero_contrato"),
                    "coe_monto_anual" => $request->input("coe_monto_anual"),
                    "coe_monto_mensual" => $request->input("coe_monto_mensual"),
                    "coe_duracion_contrato" => $request->input("coe_duracion_contrato"),
                    "coe_pob_asociada" => $request->input("coe_pob_asociada")
                ]
            );

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

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

    public function actualizarContratoEps(Request $request) {
        ContratosEps::on('costos_principal')
                    ->where("con_fk_id", $request->input("con_fk_id"))
                    ->where("ins_fk_id", $request->input("ins_fk_id"))
                    ->where("coe_ano", $request->input("coe_ano"))
                    ->where("coe_numero_contrato", $request->input("coe_numero_contrato"))
        ->update(
            [
                "coe_nit_eps" => $request->input("coe_nit_eps"),
                "coe_nombre_eps" => $request->input("coe_nombre_eps"),
                "reg_fk_id" => $request->input("reg_fk_id"),
                "coe_monto_anual" => $request->input("coe_monto_anual"),
                "coe_monto_mensual" => $request->input("coe_monto_mensual"),
                "coe_duracion_contrato" => $request->input("coe_duracion_contrato"),
                "coe_pob_asociada" => $request->input("coe_pob_asociada")
            ]
        );
    }

    public function inhabilitarContrato(Request $request) {
        \DB::transaction(function() use($request) {
            $infoContrato = ContratosEps::on('costos_principal')->where("coe_pk_id", $request->input("coe_pk_id"));

            $infoContrato->update(
                [
                    "coe_activo" => false
                ]
            );

            $this->verificarAvance($infoContrato->value('con_fk_id'),
                                   $infoContrato->value('ins_fk_id'),
                                   $infoContrato->value("coe_ano"));
        });
    }

    public function getContratosEps(Request $request) {
        return ContratosEps::on('costos_principal')
                           ->join('regimen', 'reg_pk_id', 'reg_fk_id')
                           ->where('con_fk_id', $request->input('con_fk_id'))
                           ->where('ins_fk_id', $request->input('ins_fk_id'))
                           ->where('coe_ano', $request->input('coe_ano'))
                           ->where('coe_activo', true)
                           ->orderBy('coe_numero_contrato')
                           ->get()->toArray();
    }

    public function getContratosEpsSinEAPB(Request $request) {
        return \DB::select("select distinct coe_numero_contrato
                            from costos_principal.contratos_eps
                            where con_fk_id = ".$request->input('con_fk_id')." and
                                  ins_fk_id = '".$request->input('ins_fk_id')."' and
                                  coe_ano = ".$request->input('coe_ano')." and
                                  coe_activo = true
                            order by 1");
    }

    public function getEntidadesContratos(Request $request) {
        return \DB::select("select distinct coe_nit_eps, coe_nombre_eps
                            from costos_principal.contratos_eps
                            where con_fk_id = ".$request->input('con_fk_id')." and
                                  ins_fk_id = '".$request->input('ins_fk_id')."' and
                                  coe_ano = ".$request->input('coe_ano')." and
                                  coe_activo = true
                            order by 2");
    }

    public function getContratoEpsPorNumero(Request $request) {
        return ContratosEps::on('costos_principal')
                          ->join('regimen', 'reg_pk_id', 'reg_fk_id')
                          ->where('con_fk_id', $request->input('con_fk_id'))
                          ->where('ins_fk_id', $request->input('ins_fk_id'))
                          ->where('coe_ano', $request->input('coe_ano'))
                          ->where('coe_numero_contrato', $request->input('coe_numero_contrato'))
                          ->get()->toArray();
    }

    public function getContratoEpsPorNumeroNit(Request $request) {
        return ContratosEps::on('costos_principal')
                          ->join('regimen', 'reg_pk_id', 'reg_fk_id')
                          ->where('con_fk_id', $request->input('con_fk_id'))
                          ->where('ins_fk_id', $request->input('ins_fk_id'))
                          ->where('coe_ano', $request->input('coe_ano'))
                          ->where('coe_numero_contrato', $request->input('coe_numero_contrato'))
                          ->where('coe_nit_eps', $request->input('coe_nit_eps'))
                          ->get()->toArray();
    }

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

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

            fclose($archivo);

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

    private function procesarArchivoContratosEps($contratosEps, $con_fk_id, $ins_fk_id, $coe_ano) {
        $resultados = new \stdClass();
        $resultados->errores = "";

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

                $contratosExistentes = [];
                $registrosProcesados = 0;

                // Crear las relaciones existentes en la base de datos
                foreach ($contratosEpsBd as $coeDb) {
                    $contratosExistentes[$coeDb['coe_numero_contrato']][$coeDb['coe_nit_eps']] = new \stdClass();

                    $contratosExistentes[$coeDb['coe_numero_contrato']][$coeDb['coe_nit_eps']]->coe_nombre_eps = $coeDb['coe_nombre_eps'];
                    $contratosExistentes[$coeDb['coe_numero_contrato']][$coeDb['coe_nit_eps']]->reg_fk_id = $coeDb['reg_fk_id'];
                    $contratosExistentes[$coeDb['coe_numero_contrato']][$coeDb['coe_nit_eps']]->coe_monto_anual = $coeDb['coe_monto_anual'];
                    $contratosExistentes[$coeDb['coe_numero_contrato']][$coeDb['coe_nit_eps']]->coe_monto_mensual = $coeDb['coe_monto_mensual'];
                    $contratosExistentes[$coeDb['coe_numero_contrato']][$coeDb['coe_nit_eps']]->coe_duracion_contrato = $coeDb['coe_duracion_contrato'];
                    $contratosExistentes[$coeDb['coe_numero_contrato']][$coeDb['coe_nit_eps']]->coe_pob_asociada = $coeDb['coe_pob_asociada'];
                    $contratosExistentes[$coeDb['coe_numero_contrato']][$coeDb['coe_nit_eps']]->coe_activo = $coeDb['coe_activo'];
                }

                // Errores
                $descripcionLargas = false;
                $camposVacios = false;
                $valorNumericosIncorrectos = false;
                $actualizacionIncorrecta = "";
                $regimenesIncorrectos = "";

                // Revisar el archivo respecto a las relaciones existentes
                foreach($contratosEps as $coeCsv) {
                    $contrato = utf8_encode($coeCsv[0]);
                    $nit = strtoupper(utf8_encode($coeCsv[1]));
                    $nombre = utf8_encode($coeCsv[2]);
                    $regimen = $coeCsv[3];
                    $montoAnual = $coeCsv[4];
                    $montoMensual = $coeCsv[5];
                    $duracion = $coeCsv[6];
                    $poblacion = $coeCsv[7];

                    // Campos vacios
                    if ($contrato != "" && $nit != "" && $nombre != "" && $regimen != "" && $montoAnual != "" &&
                        $montoMensual != "" && $duracion != "" && $poblacion != "") {
                        // Descripcion largas
                        if (strlen($contrato) <= 30 && strlen($nit) <= 20 && strlen($nombre) <= 150) {
                            // Valores numericos
                            if (is_numeric($montoAnual) && is_numeric($montoMensual) && is_numeric($duracion) && is_numeric($poblacion) &&
                                ($montoAnual >= 1 && $montoMensual >= 1)) {
                                // Regimen
                                if ($regimen == "1" || $regimen == "2" || $regimen == "3" || $regimen == "4" || $regimen == "5" || $regimen == 6 ||
                                    $regimen == "7" || $regimen == "8" || $regimen == "9" || $regimen == "10") {
                                    // Existe la actividad
                                    if (isset($contratosExistentes[$contrato][$nit])) {
                                        // Actualizar y ver que este activo
                                        if ($contratosExistentes[$contrato][$nit]->coe_activo) {
                                            if ($contratosExistentes[$contrato][$nit]->coe_nombre_eps != $nombre ||
                                                $contratosExistentes[$contrato][$nit]->reg_fk_id != $regimen ||
                                                $contratosExistentes[$contrato][$nit]->coe_monto_anual != $montoAnual ||
                                                $contratosExistentes[$contrato][$nit]->coe_monto_mensual != $montoMensual ||
                                                $contratosExistentes[$contrato][$nit]->coe_duracion_contrato != $duracion ||
                                                $contratosExistentes[$contrato][$nit]->coe_pob_asociada != $poblacion) {
                                                ContratosEps::on('costos_principal')
                                                            ->where("con_fk_id", $con_fk_id)
                                                            ->where("ins_fk_id", $ins_fk_id)
                                                            ->where("coe_ano", $coe_ano)
                                                            ->where("coe_numero_contrato", $contrato)
                                                ->update(
                                                    [
                                                        "coe_nit_eps" => $nit,
                                                        "coe_nombre_eps" => $nombre,
                                                        "reg_fk_id" => $regimen,
                                                        "coe_monto_anual" => $montoAnual,
                                                        "coe_monto_mensual" => $montoMensual,
                                                        "coe_duracion_contrato" => $duracion,
                                                        "coe_pob_asociada" => $poblacion
                                                    ]
                                                );
            
                                                $registrosProcesados++;
                                            } else {
                                                $registrosProcesados++;
                                            }
                                        } else {
                                            $actualizacionIncorrecta .= $contrato.", ";
                                        }
                                    } else { // No existe, es necesario crearlo
                                        $contratoEpsNuevo = ContratosEps::on('costos_principal');

                                        $id = $contratoEpsNuevo->create(
                                            [
                                                "con_fk_id" => $con_fk_id,
                                                "ins_fk_id" => $ins_fk_id,
                                                "coe_ano" => $coe_ano,
                                                "coe_nit_eps" => $nit,
                                                "coe_nombre_eps" => $nombre,
                                                "reg_fk_id" => $regimen,
                                                "coe_numero_contrato" => $contrato,
                                                "coe_monto_anual" => $montoAnual,
                                                "coe_monto_mensual" => $montoMensual,
                                                "coe_duracion_contrato" => $duracion,
                                                "coe_pob_asociada" => $poblacion
                                            ]
                                        );

                                        $registrosProcesados++;

                                        $contratosExistentes[$contrato][$nit] = new \stdClass();

                                        $contratosExistentes[$contrato][$nit]->coe_nombre_eps = $nombre;
                                        $contratosExistentes[$contrato][$nit]->reg_fk_id = $regimen;
                                        $contratosExistentes[$contrato][$nit]->coe_monto_anual = $montoAnual;
                                        $contratosExistentes[$contrato][$nit]->coe_monto_mensual = $montoMensual;
                                        $contratosExistentes[$contrato][$nit]->coe_duracion_contrato = $duracion;
                                        $contratosExistentes[$contrato][$nit]->coe_pob_asociada = $poblacion;
                                        $contratosExistentes[$contrato][$nit]->coe_activo = true;
                                    }
                                } else {
                                    $regimenesIncorrectos .= $regimen.", ";
                                }
                            } else {
                                $valorNumericosIncorrectos = true;
                            }
                        } else {
                            $descripcionLargas = true;
                        }
                    } else {
                        $camposVacios = true;
                    }
                }

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

                    $resultados->errores .= "Hay descripciones con más caracteres de los permitidos. El máximo para el nit son 20 caracteres,
                                            150 caracteres para el nombre de la EPS y 30 caracteres para el número del contrato.";
                }

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

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

                // Valores numericos incorrectos
                if ($valorNumericosIncorrectos) {
                    if ($resultados->errores !== "") {
                        $resultados->errores .= "-  ";
                    }

                    $resultados->errores .= "Hay valores numéricos incorrectos (los decimales deben ser separados por un punto).";
                }

                // Actualizacion incorrecta
                if ($actualizacionIncorrecta !== "") {
                    $actualizacionIncorrecta[strlen($actualizacionIncorrecta) - 1] = " ";
                    $actualizacionIncorrecta[strlen($actualizacionIncorrecta) - 2] = " ";
                    $actualizacionIncorrecta = "Los siguientes contratos existen pero están inhabilitados: ".$actualizacionIncorrecta." No puede reusar este número de contrato.";

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

                    $resultados->errores = $actualizacionIncorrecta;
                }

                // Regimenes incorrectos
                if ($regimenesIncorrectos !== "") {
                    $regimenesIncorrectos[strlen($regimenesIncorrectos) - 1] = " ";
                    $regimenesIncorrectos[strlen($regimenesIncorrectos) - 2] = " ";
                    $regimenesIncorrectos = "No existen los siguientes códigos de régimen: ".$regimenesIncorrectos;

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

                    $resultados->errores = $regimenesIncorrectos;
                }

                if (!$descripcionLargas && !$camposVacios && !$valorNumericosIncorrectos && $regimenesIncorrectos == "" &&
                    $actualizacionIncorrecta == "") {
                    $resultados->correcto = true;
                } else {
                    $resultados->correcto = false;
                }

                $resultados->registros = $registrosProcesados;
            }

            $this->verificarAvance($con_fk_id, $ins_fk_id, $coe_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
        $coe = ContratosEps::on('costos_principal')
                           ->where('con_fk_id', $contrato)
                           ->where('ins_fk_id', $institucion)
                           ->where('coe_ano', $ano)
                           ->where('coe_activo', true)
                           ->count();

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