<?php

namespace App\Controllers\Presupuestos;


use App\Controllers\BaseResourceController;

use App\Models\Collection;

use App\Services\PresupuestoService;

class Presupuestotiradasalternativas extends \App\Controllers\BaseResourceController
{

    protected $modelName = PresupuestoManipuladosModel::class;
    protected $format = 'json';

    protected static $singularObjectName = 'Presupuestos tirada alternativa';
    protected static $singularObjectNameCc = 'PresupuestoTiradaAlternativa';
    protected static $pluralObjectName = 'Presupuesto tiradas alternativas';
    protected static $pluralObjectNameCc = 'PresupuestoTiradasAlternativas';

    protected static $controllerSlug = 'presupuesto-tiradas';

    protected static $viewPath = 'themes/vuexy/form/presupuestos/';


    public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);
    }


    public function edit($requestedId = null)
    {
    }

    public function update($requestedId = null)
    {
    }


    public function datatable()
    {
        if ($this->request->isAJAX()) {
            $reqData = $this->request->getPost();

            $tarifa_manipulado_id = $reqData['tarifa_manipulado_id'] ?? 0;
            $tirada = $reqData['tirada'] ?? 0;
            $POD = $reqData['POD'] ?? 0;
            $tipo = $reqData['tipo'] ?? null;


            $newTokenHash = csrf_hash();
            $csrfTokenName = csrf_token();

            if (is_null($tipo)) {
                $values = $this->model->getPrecioTarifa($tarifa_manipulado_id, $tirada, $POD);
            } else {
                $solapas = $reqData['solapas'] ?? -1;
                $tipo_impresion_id = $reqData['tipo_impresion_id'] ?? 4;
                $values = $this->model->initPresupuesto($tipo_impresion_id, $solapas, $tirada, $POD);
            }

            $data = [
                'values' => $values,
                $csrfTokenName => $newTokenHash
            ];

            return $this->respond($data);
        } else {
            return $this->failUnauthorized('Invalid request', 403);
        }
    }

    // Esta funcion se usa para obtener los datos de la tabla de la vista de presupuestos
    public function datatable_2()
    {

        $reqData = $this->request->getPost();

        $newTokenHash = csrf_hash();
        $csrfTokenName = csrf_token();

        $id = $reqData['id'] ?? 0;

        $json_data = $reqData['json_tiradas'] ?? null;
        $json_data_acabados = $reqData['json_acabados'] ?? null;
        $json_data_encuadernacion = $reqData['json_encuadernaciones'] ?? null;
        $json_data_manipulado = $reqData['json_manipulado'] ?? null;
        $json_data_preimpresion = $reqData['json_preimpresion'] ?? null;
        $json_data_extra = $reqData['json_extra'] ?? null;
        $cliente_id = $reqData['cliente_id'] ?? 0;

        $faja_alto = $reqData['faja_alto'] ?? 0;
        $solapas_faja = $reqData['solapas_faja'] ?? 0;

        $tipo_impresion_id = $reqData['tipo_impresion_id'] ?? 4;

        $tirada = $reqData['tirada'] ?? 0;

        $values = [];

        if ($json_data) {

            $data = json_decode($json_data, true);

            foreach ($data as $linea) {
                // Se obtienen los valores de cada linea para el calculo del precio
                $datosPedido = (object) array(
                    'paginas' => intval($linea['paginas']) ?? 0,
                    'tirada' => intval($reqData['tirada']) ?? 0,
                    'merma' => intval($reqData['merma']) ?? 0,
                    'ancho' => intval($reqData['ancho']) ?? 100000,
                    'alto' => intval($reqData['alto']) ?? 100000,
                    'a_favor_fibra' => $linea['aFavorFibra'] ?? 1,
                    'isCosido' => (new \App\Models\Configuracion\TipoPresupuestoModel())->get_isCosido($tipo_impresion_id), // JJO esto es custom por cada tipo de presupuesto
                );

                if ($linea['row_id'] == 'lp_guardas') {
                    $datosPedido->paginas_impresion = intval($linea['paginas_impresion']) ?? 0;
                    // Para el caso de Fresado y Cosido tapa dura, las guardas son un diptico
                    // y hay que imprimirlas como "cosido" (dos hojas pegadas). En el caso de espiral
                    // o wire-o tapa dura, las guardas se imprimen como hojas sueltas
                    if ($tipo_impresion_id == 1 || $tipo_impresion_id == 3) {
                        $datosPedido->isCosido = true;
                    } else if ($tipo_impresion_id == 5 || $tipo_impresion_id == 7) {
                        $datosPedido->isCosido = false;
                    }
                } else if ($linea['row_id'] == 'lp_sobrecubierta' || $linea['row_id'] == 'lp_cubierta' || $linea['row_id'] == 'lp_faja') {
                    $datosPedido->solapas = $reqData['solapas_cubierta'];
                    if ($linea['row_id'] == 'lp_faja') {
                        $datosPedido->solapas = 1;
                        $datosPedido->alto = $faja_alto;
                    
                    } else if ($linea['row_id'] == 'lp_sobrecubierta') {
                        $datosPedido->solapas = $reqData['solapas_sobrecubierta'];
                    }
                    $datosPedido->solapas_ancho = $reqData['solapas_cubierta_ancho'];
                    if ($linea['row_id'] == 'lp_faja') {
                        $datosPedido->solapas_ancho = $solapas_faja;
                    } else if ($linea['row_id'] == 'lp_sobrecubierta') {
                        $datosPedido->solapas_ancho = $reqData['solapas_sobrecubierta_ancho'];
                    }
                    $datosPedido->lomo = $reqData['lomo'];

                    $type = 'lp_cubierta';
                    if ($linea['row_id'] == 'lp_sobrecubierta') {
                        $type = 'lp_sobrecubierta';
                    } else if ($linea['row_id'] == 'lp_faja') {
                        $type = 'lp_faja';
                    }

                    $datosPedido->anchoExteriores = PresupuestoService::getAnchoTotalExteriores($type, $tipo_impresion_id, $datosPedido);
                    $datosPedido->altoExteriores = PresupuestoService::getAltoTotalExteriores($type, $tipo_impresion_id, $datosPedido);
                }


                $maquina = (new \App\Models\Configuracion\MaquinaModel())->find($linea['maquina_id']);
                $papel = (new \App\Models\Configuracion\PapelImpresionModel())->find($linea['papel_impresion_id']);
                $pg = (new \App\Models\Configuracion\PapelGenericoModel())->find($linea['papel']);

                $papel_generico['id'] = $pg->id;
                $papel_generico['nombre'] = $pg->nombre;

                $maquina->maquina_id = $maquina->id;

                switch ($linea['row_id']) {
                    case 'lp_rot_bn':
                    case 'lp_rot_color':
                        $uso = 'interior';
                        $tipo = strpos($linea['row_id'], "_bn") !== false ? 'negro' : 'color';
                        $paginas_negro = isset($linea['numPagColor']) ? intval($datosPedido->paginas) - intval($linea['numPagColor']) : 0;
                        $paginas_color = $linea['numPagColor'] ?? 0;
                        $paginas = (object) array(
                            'negro' => $paginas_negro,
                            'color' => $paginas_color,
                        );
                        $parametrosRotativa = (object) array(
                            'a_favor_fibra' => $datosPedido->a_favor_fibra,
                            'bnPages' => $paginas->negro,
                            'colorPages' => $paginas->color,
                            'rotativa_gota_negro' => 0,
                            'rotativa_gota_color' => 0,
                        );
                        $parametrosRotativa->rotativa_gota_negro = floatval($linea['gotaNegro'] ?? 0);
                        $parametrosRotativa->rotativa_gota_color = floatval($linea['gotaColor'] ?? 0);
                        $parametrosRotativa->rotativa_negro = floatval($linea['cobNegro'] ?? 0);
                        $parametrosRotativa->rotativa_cyan = floatval($linea['cobCyan'] ?? 0);
                        $parametrosRotativa->rotativa_magenta = floatval($linea['cobMagenta'] ?? 0);
                        $parametrosRotativa->rotativa_amarillo = floatval($linea['cobAmarillo'] ?? 0);
                        break;
                    case 'lp_cubierta':
                        $uso = 'cubierta';
                        break;
                    case 'lp_sobrecubierta':
                        $uso = 'sobrecubierta';
                        break;
                    case 'lp_faja':
                        $uso = 'faja';
                        break;
                    case 'lp_guardas':
                        $uso = 'guardas';
                        break;
                    default:
                        $uso = 'interior';
                        $isHq = strpos($linea['row_id'], "hq") !== false ? true : false;
                        $isColor = strpos($linea['row_id'], "_color") !== false ? true : false;
                        $tipo = $isColor ? ($isHq ? 'colorhq' : 'color') : ($isHq ? 'negrohq' : 'negro');
                        break;
                }

                if ($uso == 'cubierta' || $uso == 'sobrecubierta' || $uso == 'faja' || $uso == 'guardas') {
                    $isColor = true;
                    $isHq = true;
                    $tipo = 'colorhq';
                }

                if (strpos($linea['row_id'], 'lp_rot') !== 0) {
                    // The string does not start with the prefix
                    $opciones_papel = PresupuestoService::get_opciones_papel($uso, $isColor);
                }

                $datosTipolog = $linea['gotaNegro'] ?? null;
                if (!is_null($datosTipolog)) {
                    $datosTipolog = [];
                    $data_temp = (object) array(
                        'negro' => floatval($linea['cobNegro'] ?? 0),
                        'cyan' => floatval($linea['cobCyan'] ?? 0),
                        'magenta' => floatval($linea['cobMagenta'] ?? 0),
                        'amarillo' => floatval($linea['cobAmarillo'] ?? 0),
                        'cg' => floatval($linea['cobCG'] ?? 0),
                        'gota_negro' => floatval($linea['gotaNegro'] ?? 0),
                        'gota_color' => floatval($linea['gotaColor'] ?? 0),
                    );
                    array_push($datosTipolog, $data_temp);
                }

                $datosLinea = array();

                $datosLinea['uso'] = $uso;
                $datosLinea['tipo'] = $tipo;
                $datosLinea['datosPedido'] = $datosPedido;
                $datosLinea['cliente_id'] = $cliente_id;
                $datosLinea['papel'] = $papel;
                if (isset($isColor))
                    $datosLinea['isColor'] = $isColor;
                if (isset($opciones_papel))
                    $datosLinea['opciones_papel'] = $opciones_papel;
                if (isset($parametrosRotativa))
                    $datosLinea['parametrosRotativa'] = $parametrosRotativa;
                if (isset($paginas))
                    $datosLinea['paginas'] = $paginas;
                $datosLinea['maquina'] = $maquina;
                $datosLinea['papel_generico'] = $papel_generico;
                $datosLinea['a_favor_fibra'] = $linea['aFavorFibra'] ?? null;
                $datosLinea['datosTipolog'] = $datosTipolog;
                $datosLinea['gramaje'] = $linea['gramaje'] ?? 0;

                if ($linea['row_id'] != 'lp_rot_bn' && $linea['row_id'] != 'lp_rot_color') {
                    $linea_coste = PresupuestoService::getLineaPresupuestoPlana($datosLinea);
                } else {
                    $linea_coste = PresupuestoService::getLineaPresupuestoRotativa($datosLinea);
                }

                if (empty($linea))
                    continue;

                if ($linea['check_papel_total'] == 0) {
                    $linea_coste['fields']['precio_pedido'] = 0;
                }
                if ($linea['check_impresion_total'] == 0) {
                    $linea_coste['fields']['precio_impresion_horas'] = 0;
                    $linea_coste['fields']['precio_click_pedido'] = 0;
                    if ($linea_coste['fields']['tipo_maquina'] == 'inkjet') {
                        $linea_coste['fields']['precio_tinta'] = 0;
                        if (strpos($linea['row_id'], 'lp_rot') === 0) {
                            $linea_coste['fields']['total_corte'] = 0;
                        }
                    }
                }
                $linea_coste['total_coste'] = $linea_coste['fields']['precio_pedido'] +
                    $linea_coste['fields']['precio_impresion_horas'] +
                    $linea_coste['fields']['precio_click_pedido'];
                if ($linea_coste['fields']['tipo_maquina'] == 'inkjet') {

                    $linea_coste['total_coste'] +=
                        $linea_coste['fields']['precio_tinta'];
                    if (strpos($linea['row_id'], 'lp_rot') === 0) {
                        $linea_coste['total_coste'] +=
                            $linea_coste['fields']['total_corte'];
                    }
                }


                $linea_coste['total_margen'] = $linea_coste['fields']['margen_papel_pedido'] +
                    $linea_coste['fields']['margen_impresion_horas'] +
                    $linea_coste['fields']['margen_click_pedido'];

                unset($linea_coste['fields']);
                array_push($values, $linea_coste);
            }

            // Calculo de los servicios (presimpresion y extra no dependen de nada)
            $servicios = (object) (['coste' => 0.0, 'margen' => 0.0]);

            if ($json_data_acabados) {
                $json_data_acabados = json_decode($json_data_acabados, true);
                if (count($json_data_acabados) > 0) {

                    $acabados = new Presupuestoacabados();
                    $POD = (new \App\Models\Configuracion\ConfigVariableModel())->getVariable('POD')->value;
                    $result = $acabados->getServiciosAcabados($json_data_acabados, $reqData['tirada'], $POD);
                    if (count($result) > 0) {
                        foreach ($result as $servicio) {
                            $servicios->coste += round(floatval($servicio->total), 2);
                            $base = round(floatval($servicio->total / (1 + $servicio->margen / 100.0)), 2);
                            $base = round(floatval($base / $datosPedido->tirada) , 2)* $datosPedido->tirada;
                            $servicios->margen += round(floatval($servicio->total - $base), 2);
                        }
                    }
                }
            }

            if ($json_data_encuadernacion) {
                $json_data_encuadernacion = json_decode($json_data_encuadernacion, true);
                if (count($json_data_encuadernacion) > 0) {

                    $encuadernacion = new Presupuestoencuadernaciones();
                    $POD = (new \App\Models\Configuracion\ConfigVariableModel())->getVariable('POD')->value;
                    $result = $encuadernacion->getServiciosEncuadernacion($json_data_encuadernacion, $reqData['tirada'], $reqData['paginas'], $reqData['ancho'], $reqData['alto'], $POD);
                    if (count($result) > 0) {
                        foreach ($result as $servicio) {
                            $servicios->coste += round(floatval($servicio->total), 2);
                            $base = round(floatval($servicio->total / (1 + $servicio->margen / 100.0)), 2);
                            $base = round(floatval($base / $datosPedido->tirada) , 2)* $datosPedido->tirada;
                            $servicios->margen += round(floatval($servicio->total - $base), 2);
                        }
                    }
                }
            }

            if ($json_data_manipulado) {
                $json_data_manipulado = json_decode($json_data_manipulado, true);
                if (count($json_data_manipulado) > 0) {
                    $manipulados = new Presupuestomanipulados();
                    $POD = (new \App\Models\Configuracion\ConfigVariableModel())->getVariable('POD')->value;
                    $result = $manipulados->getServiciosManipulado($json_data_manipulado, $reqData['tirada'], $POD);
                    if (count($result) > 0) {
                        foreach ($result as $servicio) {
                            $servicios->coste += round(floatval($servicio->total), 2);
                            $base = round(floatval($servicio->total / (1 + $servicio->margen / 100.0)), 2);
                            $base = round(floatval($base / $datosPedido->tirada) , 2)* $datosPedido->tirada;
                            $servicios->margen += round(floatval($servicio->total - $base), 2);
                        }
                    }
                }
            }

            if($json_data_preimpresion){
                $json_data_preimpresion = json_decode($json_data_preimpresion, true);
                if (count($json_data_preimpresion) > 0) {
                    $preimpresion = new Presupuestopreimpresiones();
                    $POD = (new \App\Models\Configuracion\ConfigVariableModel())->getVariable('POD')->value;
                    $result = $preimpresion->getServiciosPreimpresion($json_data_preimpresion);
                    if (count($result) > 0) {
                        foreach ($result as $servicio) {
                            $servicios->coste += round(floatval($servicio->total), 2);
                            $base = round(floatval($servicio->total / (1 + $servicio->margen / 100.0)), 2);
                            $base = round(floatval($base / $datosPedido->tirada) , 2)* $datosPedido->tirada;
                            $servicios->margen += round(floatval($servicio->total - $base), 2);
                        }
                    }
                }
            }

            if($json_data_extra){
                $json_data_extra = json_decode($json_data_extra, true);
                if (count($json_data_extra) > 0) {
                    $extra = new Presupuestoserviciosextra();
                    $json_data_extra = array_map(function($item) {
                        return $item['tarifa_id'];
                    }, $json_data_extra);
                    $result = $extra->getServiciosExtra($json_data_extra);
                    if (count($result) > 0) {
                        foreach ($result as $servicio) {
                            $servicios->coste += round(floatval($servicio->precio), 2);
                            $base = round(floatval($servicio->precio / (1 + floatval($servicio->margen) / 100.0)), 2);
                            $base = round(floatval($base / $datosPedido->tirada) , 2)* $datosPedido->tirada;
                            $servicios->margen += round(floatval($servicio->precio - $base), 2);
                        }
                    }
                }
            }

            $json_envios = $reqData['json_envios'] ?? null;
            $coste_envio = 0.0;
            $margen_envio = 0.0;
            $tirada_base = floatval($reqData['tirada_base']);
            $peso_libro = floatval($reqData['peso_libro']);
            // el primer envio con la tirada base
            $model = model('App\Models\Tarifas\TarifaEnvioModel');
            $envios = $model->getTarifaEnvio(1, 18000, $tirada_base * $peso_libro / 1000.0, "cajas");
            $resultado = $this->calcular_envio($envios, $tirada_base * $peso_libro / 1000.0);
            $coste_envio += $resultado->coste;
            $margen_envio += $resultado->margen;

            if ($json_envios) {
                $json_envios = json_decode($json_envios, true);
                if (count($json_envios) > 0) {
                    //la primera linea es el envio base
                    for ($i = 1; $i < count($json_envios); $i++) {

                        $porcentaje = ($json_envios[$i]['cantidad']) / $tirada_base * 100.0;
                        $cantidad = floor($reqData['tirada'] * $porcentaje / 100.0);
                        $peso_envio = $cantidad * $peso_libro / 1000.0;

                        $paisId = $json_envios[$i]['pais_id'];
                        $cp = $json_envios[$i]['cp'];
                        $tipo_envio = $json_envios[$i]['entregaPieCalle'] == 1 ? 'palets' : 'cajas';

                        $model = model('App\Models\Tarifas\TarifaEnvioModel');
                        $envios = $model->getTarifaEnvio($paisId, $cp, $peso_envio, $tipo_envio);

                        $resultado = $this->calcular_envio($envios, $peso_envio);
                        $coste_envio += $resultado->coste;
                        $margen_envio += $resultado->margen;
                    }
                }
            }


        } else {
            $values = [];
        }

        $newTokenHash = csrf_hash();
        $csrfTokenName = csrf_token();

        $response[$csrfTokenName] = $newTokenHash;
        $response['lineas'] = $values;
        $response['servicios'] = $servicios;
        $response['envios'] = (object) (['coste' => $coste_envio, 'margen' => $margen_envio]);

        return $this->respond($response);

    }

    private function calcular_envio($envio, $peso_envio)
    {
        $coste_envio = 0.0;
        $margen_envio = 0.0;
        if (count(value: $envio) > 0) {
            $envio = $envio[0];
            if ($envio->id != null) {

                if ($peso_envio > $envio->peso_max || floatval($envio->precio_max) == 0) {
                    $coste_envio += number_format(floatval($envio->precio_min) + ($peso_envio - floatval($envio->peso_min)) * floatval($envio->precio_adicional), 2);
                }
                // si no se calcula linealmente
                else {
                    $m = (($envio->precio_max - $envio->precio_min) / ($envio->peso_max - $envio->peso_min));
                    $b = $envio->precio_max - $m * $envio->peso_max;
                    $coste_envio = number_format($m * $peso_envio + $b, 2);

                }

                $margen_envio += $coste_envio * $envio->margen / 100.0;
            }
        }

        return (object) (['coste' => $coste_envio, 'margen' => $margen_envio]);
    }
}
