<?php

namespace App\Http\Controllers;

use App\Models\DistribucionCostosCentros;
use App\Models\DistribucionCostosBases;
use App\Models\InformacionBasesDistribucion2;
use App\Models\AvanceModulos;
use App\Models\CentrosCosto;
use App\Models\BasesDistribucion;
use Illuminate\Http\Request;

class DistribucionCostosController extends Controller
{
    public function crearDistribucionCostos(Request $request) {
        \DB::transaction(function() use($request) {
            $dcCentros = DistribucionCostosCentros::on('costos_principal');
            $dcBases = DistribucionCostosBases::on('costos_principal');

            $centroNoFinal = $request->input('dco_centro_no_final');

            $centrosFinales = json_decode($request->input('centrosFinales'));
            $basesDistribucion = json_decode($request->input('basesDistribucion'));

            $hayPartesIguales = false;

            foreach ($basesDistribucion as $bdi) {
                if ($bdi->bdi_pk_id === 2) {
                    $hayPartesIguales = true;
                    break;
                }
            }

            // Centros de costo
            foreach ($centrosFinales as $cco) {
                $id = $dcCentros->create(
                    [
                        "con_fk_id" => $request->input("con_fk_id"),
                        "ins_fk_id" => $request->input("ins_fk_id"),
                        "dco_ano" => $request->input("dco_ano"),
                        "dco_centro_no_final" => $centroNoFinal,
                        "dco_centro_final" => $cco->cco_pk_id
                    ]
                );

                // Base de distribucion por partes iguales
                if ($hayPartesIguales) {
                    InformacionBasesDistribucion2::on('costos_principal')
                                                    ->where('con_fk_id',  $request->input("con_fk_id"))
                                                    ->where('ins_fk_id',  $request->input("ins_fk_id"))
                                                    ->where('ibd2_ano', $request->input("dco_ano"))
                                                    ->where('ibd2_automatico', true)
                                                    ->where('bdi_fk_id', 2)
                                                    ->where('cco_fk_id', $cco->cco_pk_id)
                                                    ->delete();

                    for($i = 1; $i <= 12; $i++) {
                        InformacionBasesDistribucion2::on('costos_principal')
                        ->create(
                            [
                                "con_fk_id" => $request->input("con_fk_id"),
                                "ins_fk_id" => $request->input("ins_fk_id"),
                                "ibd2_ano" => $request->input("dco_ano"),
                                "ibd2_mes" => $i,
                                "cco_fk_id" => $cco->cco_pk_id,
                                "bdi_fk_id" => $hayPartesIguales ? 2 : 1,
                                "ibd2_valor" => 1 / count($centrosFinales),
                                "ibd2_automatico" => true
                            ]
                        );
                    }
                }
            }

            // Bases de distribucion
            foreach ($basesDistribucion as $bdi) {
                $id = $dcBases->create(
                    [
                        "con_fk_id" => $request->input("con_fk_id"),
                        "ins_fk_id" => $request->input("ins_fk_id"),
                        "dcb_ano" => $request->input("dco_ano"),
                        "cco_fk_id" => $centroNoFinal,
                        "bdi_fk_id" => $bdi->bdi_pk_id,
                        "dcb_ponderacion" => $bdi->dcb_ponderacion
                    ]
                );
            }

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

        return array("response" => 1);
    }

    public function actualizarDistribucionCostos(Request $request) {
        \DB::transaction(function() use($request) {
            $dcCentros = DistribucionCostosCentros::on('costos_principal');
            $dcBases = DistribucionCostosBases::on('costos_principal');

            $centroNoFinal = $request->input('dco_centro_no_final');

            // Borrar la anterior información
            $dcCentros->where('con_fk_id', $request->input('con_fk_id'))
                      ->where('ins_fk_id', $request->input('ins_fk_id'))
                      ->where('dco_ano', $request->input("dco_ano"))
                      ->where('dco_centro_no_final', $centroNoFinal)
                      ->delete();

            $dcBases->where('con_fk_id', $request->input('con_fk_id'))
                    ->where('ins_fk_id', $request->input('ins_fk_id'))
                    ->where('dcb_ano', $request->input("dco_ano"))
                    ->where('cco_fk_id', $centroNoFinal)
                    ->delete();

            // Asignar nueva informacion
            $centrosFinales = json_decode($request->input('centrosFinales'));
            $basesDistribucion = json_decode($request->input('basesDistribucion'));

            $hayPartesIguales = false;

            foreach ($basesDistribucion as $bdi) {
                if ($bdi->bdi_pk_id === 2) {
                    $hayPartesIguales = true;
                    break;
                }
            }

            // Centros de costo
            foreach ($centrosFinales as $cco) {
                $id = $dcCentros->create(
                    [
                        "con_fk_id" => $request->input("con_fk_id"),
                        "ins_fk_id" => $request->input("ins_fk_id"),
                        "dco_ano" => $request->input("dco_ano"),
                        "dco_centro_no_final" => $centroNoFinal,
                        "dco_centro_final" => $cco->cco_pk_id
                    ]
                );

                // Base de distribucion por partes iguales
                if ($hayPartesIguales) {
                    InformacionBasesDistribucion2::on('costos_principal')
                                                    ->where('con_fk_id',  $request->input("con_fk_id"))
                                                    ->where('ins_fk_id',  $request->input("ins_fk_id"))
                                                    ->where('ibd2_ano', $request->input("dco_ano"))
                                                    ->where('ibd2_automatico', true)
                                                    ->where('bdi_fk_id', 2)
                                                    ->where('cco_fk_id', $cco->cco_pk_id)
                                                    ->delete();

                    for($i = 1; $i <= 12; $i++) {
                        InformacionBasesDistribucion2::on('costos_principal')
                        ->create(
                            [
                                "con_fk_id" => $request->input("con_fk_id"),
                                "ins_fk_id" => $request->input("ins_fk_id"),
                                "ibd2_ano" => $request->input("dco_ano"),
                                "ibd2_mes" => $i,
                                "cco_fk_id" => $cco->cco_pk_id,
                                "bdi_fk_id" => $hayPartesIguales ? 2 : 1,
                                "ibd2_valor" => 1 / count($centrosFinales),
                                "ibd2_automatico" => true
                            ]
                        );
                    }
                }
            }

            // Bases de distribucion
            foreach ($basesDistribucion as $bdi) {
                $id = $dcBases->create(
                    [
                        "con_fk_id" => $request->input("con_fk_id"),
                        "ins_fk_id" => $request->input("ins_fk_id"),
                        "dcb_ano" => $request->input("dco_ano"),
                        "cco_fk_id" => $centroNoFinal,
                        "bdi_fk_id" => $bdi->bdi_pk_id,
                        "dcb_ponderacion" => $bdi->dcb_ponderacion
                    ]
                );
            }
        });

        return array("response" => 1);
    }

    public function getDistribucionCostosCentros(Request $request) {
        return DistribucionCostosCentros::on('costos_principal')
                                        ->join('centros_costo', 'dco_centro_final', '=', 'cco_pk_id')
                                        ->where('distribucion_costos_centros.con_fk_id', $request->input('con_fk_id'))
                                        ->where('distribucion_costos_centros.ins_fk_id', $request->input('ins_fk_id'))
                                        ->where('dco_ano', $request->input('dco_ano'))
                                        ->where('dco_centro_no_final', $request->input('dco_centro_no_final'))
                                        ->orderBy('cco_cod_homologado')
                                        ->orderBy('cco_descripcion')
                                        ->get()->toArray();
    }

    public function getDistribucionCostosCentrosCompleto(Request $request) {
        return DistribucionCostosCentros::on('costos_principal')
                                        ->join('centros_costo', 'dco_centro_final', '=', 'cco_pk_id')
                                        ->where('distribucion_costos_centros.con_fk_id', $request->input('con_fk_id'))
                                        ->where('distribucion_costos_centros.ins_fk_id', $request->input('ins_fk_id'))
                                        ->where('dco_ano', $request->input('dco_ano'))
                                        ->orderBy('cco_cod_homologado')
                                        ->orderBy('cco_descripcion')
                                        ->get()->toArray();
    }

    public function getDistribucionCostosBases(Request $request) {
        return DistribucionCostosBases::on('costos_principal')
                                      ->join('bases_distribucion', 'bdi_fk_id', '=', 'bdi_pk_id')
                                      ->where('distribucion_costos_bases.con_fk_id', $request->input('con_fk_id'))
                                      ->where('distribucion_costos_bases.ins_fk_id', $request->input('ins_fk_id'))
                                      ->where('dcb_ano', $request->input('dcb_ano'))
                                      ->where('cco_fk_id', $request->input('cco_fk_id'))
                                      ->orderBy('bdi_descripcion')
                                      ->get()->toArray();
    }

    public function getDistribucionCostosBasesCompleto(Request $request) {
        return DistribucionCostosBases::on('costos_principal')
                                      ->join('bases_distribucion', 'bdi_fk_id', '=', 'bdi_pk_id')
                                      ->where('distribucion_costos_bases.con_fk_id', $request->input('con_fk_id'))
                                      ->where('distribucion_costos_bases.ins_fk_id', $request->input('ins_fk_id'))
                                      ->where('dcb_ano', $request->input('dcb_ano'))
                                      ->orderBy('bdi_descripcion')
                                      ->get()->toArray();
    }

    public function importarInformacionDistribucion(Request $request) {
        \DB::transaction(function() use($request) {
            $contrato = $request->input('con_fk_id');
            $institucion = $request->input('ins_fk_id');
            $anoActual = $request->input('anoActual');
            $anoImportacion = $request->input('anoImportacion');

            // Borrar informacion actual
            DistribucionCostosCentros::on('costos_principal')
                                     ->where('con_fk_id', $contrato)
                                     ->where('ins_fk_id', $institucion)
                                     ->where('dco_ano', $anoActual)
                                     ->delete();

            DistribucionCostosBases::on('costos_principal')
                                   ->where('con_fk_id', $contrato)
                                   ->where('ins_fk_id', $institucion)
                                   ->where('dcb_ano', $anoActual)
                                   ->delete();

            // Parametros establecidos en el ano actual
            $centrosCostoAux = [];
            $centrosCostoBd = CentrosCosto::on('costos_principal')
                                          ->where('con_fk_id', $contrato)
                                          ->where('ins_fk_id', $institucion)
                                          ->where('cco_ano', $anoActual)
                                          ->get()->toArray();

            foreach ($centrosCostoBd as $cco) {
                $centroCostoAux[$cco['cco_cod_homologado']] = $cco['cco_pk_id'];
            }

            $basesDistribucionAux = [];
            $basesDistribucionBd = \DB::select("select *
                                                from costos_principal.bases_distribucion
                                                where (con_fk_id = ".$contrato." or con_fk_id is null) and
                                                    (ins_fk_id = '".$institucion."' or ins_fk_id is null) and
                                                    (bdi_ano = ".$anoActual." or bdi_ano is null) and
                                                    bdi_pk_id != 1 and
                                                    bdi_mano_obra = false");

            foreach ($basesDistribucionBd as $bdi) {
                $basesDistribucionAux[$bdi->bdi_codigo] = $bdi->bdi_pk_id;
            }

            // Bases del año de importacion
            $basesDistribucion = \DB::select("with distribucion as (
                                                select distinct dic.cco_cod_homologado as cco_no_final,
                                                                dic.bdi_codigo,
                                                                dic.dcb_ponderacion
                                                from (
                                                    select cco_cod_homologado, bdi_codigo, dcb_ponderacion
                                                    from costos_principal.distribucion_costos_bases as dcb
                                                    join costos_principal.centros_costo as cco on (dcb.cco_fk_id = cco.cco_pk_id)
                                                    join costos_principal.bases_distribucion as bdi on (dcb.bdi_fk_id = bdi.bdi_pk_id)
                                                    where dcb.con_fk_id = ".$contrato." and
                                                          dcb.ins_fk_id = '".$institucion."' and
                                                          dcb_ano = ".$anoImportacion."
                                                ) as dic
                                                join costos_principal.centros_costo as cco on (dic.cco_cod_homologado = cco.cco_cod_homologado and
                                                                                               cco.con_fk_id = ".$contrato." and cco.ins_fk_id = '".$institucion."' and cco.cco_ano = ".$anoActual.")
                                                join costos_principal.bases_distribucion as bdi on (dic.bdi_codigo = bdi.bdi_codigo and
                                                                                                    ((bdi.con_fk_id = ".$contrato." and bdi.ins_fk_id = '".$institucion."' and bdi.bdi_ano = ".$anoActual.") or
                                                                                                    (bdi.con_fk_id is null and bdi.ins_fk_id is null and bdi.bdi_ano is null)))
                                            )
                                            select *
                                            from distribucion
                                            where cco_no_final in (
                                                /* Centros con suma 100% en bases */
                                                select cco_no_final
                                                from distribucion
                                                group by 1
                                                having sum(dcb_ponderacion) = 100
                                            )
                                            order by 1");

            $centrosFinales = [];
            $listadoCentrosFinales = "";

            foreach ($basesDistribucion as $bdi) {
                if (!isset($centrosFinales[$bdi->cco_no_final])) {
                    $centrosFinales[$bdi->cco_no_final] = 0;
                    $listadoCentrosFinales .= "'".$bdi->cco_no_final."',";
                }
            }

            $centrosFinales = [];

            if (strlen($listadoCentrosFinales) >= 1) {
                $listadoCentrosFinales[strlen($listadoCentrosFinales) - 1] = " ";
            } else {
                $listadoCentrosFinales = "-1";
            }

            // Centros del ano de importacion
            $centrosCosto = \DB::select("with centros_costo_aux as (
                                            select distinct cco_cod_homologado
                                            from costos_principal.centros_costo
                                            where con_fk_id = ".$contrato." and
                                                  ins_fk_id = '".$institucion."' and
                                                  cco_ano = ".$anoActual."
                                        )
                                        select cco_no_final, cco_final
                                        from (
                                            select distinct cco.cco_cod_homologado as cco_no_final,
                                                            cco2.cco_cod_homologado as cco_final
                                            from costos_principal.distribucion_costos_centros as dcc
                                            join costos_principal.centros_costo as cco on (dcc.dco_centro_no_final = cco.cco_pk_id)
                                            join costos_principal.centros_costo as cco2 on (dcc.dco_centro_final = cco2.cco_pk_id)
                                            where dcc.con_fk_id = ".$contrato." and
                                                  dcc.ins_fk_id = '".$institucion."' and
                                                  dco_ano = ".$anoImportacion."
                                        ) as dcc
                                        left join (
                                            select cco_cod_homologado as test_cco_no_final
                                            from centros_costo_aux
                                        ) as cco on (cco.test_cco_no_final = dcc.cco_no_final)
                                        left join (
                                            select cco_cod_homologado as test_cco_final
                                            from centros_costo_aux
                                        ) as cco2 on (cco2.test_cco_final = dcc.cco_final)
                                        where test_cco_no_final is not null and test_cco_final is not null and
                                              cco_no_final in (".$listadoCentrosFinales.")
                                        order by 1");

            // Insertar los datos contruidos
            // Centros costo
            foreach ($centrosCosto as $cco) {
                DistribucionCostosCentros::on('costos_principal')
                ->create(
                    [
                        "con_fk_id" => $contrato,
                        "ins_fk_id" => $institucion,
                        "dco_ano" => $anoActual,
                        "dco_centro_no_final" => $centroCostoAux[$cco->cco_no_final],
                        "dco_centro_final" => $centroCostoAux[$cco->cco_final]
                    ]
                );
            }

            // Bases de distribucion
            foreach ($basesDistribucion as $bdi) {
                DistribucionCostosBases::on('costos_principal')
                ->create(
                    [
                        "con_fk_id" => $contrato,
                        "ins_fk_id" => $institucion,
                        "dcb_ano" => $anoActual,
                        "cco_fk_id" => $centroCostoAux[$bdi->cco_no_final],
                        "bdi_fk_id" => $basesDistribucionAux[$bdi->bdi_codigo],
                        "dcb_ponderacion" => $bdi->dcb_ponderacion
                    ]
                );
            }

            $this->verificarAvance($contrato, $institucion, $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
        $dcc = DistribucionCostosCentros::on('costos_principal')
                                        ->selectRaw('count(distinct dco_centro_no_final) as conteo')
                                        ->where('con_fk_id', $contrato)
                                        ->where('ins_fk_id', $institucion)
                                        ->where('dco_ano', $ano)
                                        ->value('conteo');

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