<?php

namespace App\Services;
use App\Services\ProductionService;

use Config\Services;

class LogisticaService
{
    public static function findPedidoOrISBN($search)
    {
        $multienvio = false;

        $modelPedido = model('App\Models\Pedidos\PedidoModel');

        $search = trim($search);
        $searchClean = str_replace('-', '', $search);
        $modelPedido = model('App\Models\Pedidos\PedidoModel');

        $builder = $modelPedido->builder();

        $builder->select([
            'pedidos.id as pedido_id',
            'pedidos_linea.id as linea_id',
            'pedidos_linea.cantidad as cantidad_linea',
            'presupuestos.id as presupuesto_id',
        ]);

        $builder->join('pedidos_linea', 'pedidos_linea.pedido_id = pedidos.id', 'left');
        $builder->join('presupuestos', 'presupuestos.id = pedidos_linea.presupuesto_id', 'left');
        $builder->join('envios_lineas', 'envios_lineas.pedido_id = pedidos_linea.pedido_id', 'left');

        $builder->groupStart()
            ->where('pedidos.id', $search)
            ->whereIn('pedidos.estado', ['finalizado'])
            ->orWhere("REPLACE(presupuestos.isbn, '-', '')", $searchClean)
            ->groupEnd();

        $builder->groupBy('pedidos_linea.id');
        $builder->having('IFNULL(SUM(envios_lineas.unidades_envio), 0) < cantidad_linea', null, false);

        $result = $builder->get()->getResult();

        if (empty($result)) {
            $response = [
                'status' => false,
                'message' => lang('Logistica.errors.notFound'),
            ];
            return $response;
        }

        $PresupuestoDireccionesModel = model('App\Models\Presupuestos\PresupuestoDireccionesModel');
        $numDirecciones = $PresupuestoDireccionesModel->where('presupuesto_id', $result[0]->presupuesto_id)
            ->countAllResults();
        if ($numDirecciones == 0) {
            $response = [
                'status' => false,
                'message' => lang('Logistica.errors.noAddresses'),
            ];
            return $response;
        } else if ($numDirecciones > 1) {
            $multienvio = true;
        }

        $response = [
            'status' => true,
            'data' => $result[0],
        ];


        $response_envio = LogisticaService::generateEnvio($result[0]->pedido_id, $multienvio);
        if ($response_envio['status'] == false) {
            $response = [
                'status' => false,
                'message' => $response_envio['message'],
            ];
            return $response;
        } else {
            $response['data']->id_envio = $response_envio['data']['id_envio'];
            $response['data']->multienvio = $response_envio['data']['multienvio'];
        }

        return $response;
    }


    public static function findLineaEnvioPorEnvio(int $envio_id)
    {
        $db = \Config\Database::connect();
        $subCliente = $db->table('envios')
            ->select('cliente_id')
            ->where('id', $envio_id)
            ->getCompiledSelect();

        $builder = $db->table('envios e_main');

        $builder->select("
        CONCAT('[', p.id, '] - ', pr.titulo) AS name,
        pl.id AS id,
        pl.cantidad,
        (
            SELECT IFNULL(SUM(el.unidades_envio), 0)
            FROM envios_lineas el
            JOIN envios e ON e.id = el.envio_id
            WHERE el.pedido_id = p.id
            AND e.direccion = e_main.direccion
            AND pr.cliente_id = ($subCliente)
        ) AS unidades_enviadas,
        (
            pl.cantidad - (
                SELECT IFNULL(SUM(el2.unidades_envio), 0)
                FROM envios_lineas el2
                JOIN envios e2 ON e2.id = el2.envio_id
                WHERE el2.pedido_id = p.id
                AND e2.direccion = e_main.direccion
                AND pr.cliente_id = ($subCliente)
            )
        ) AS unidades_pendientes
    ");

        $builder->join('pedidos_linea pl', '1=1'); // para incluir líneas sin envío aún
        $builder->join('pedidos p', 'p.id = pl.pedido_id');
        $builder->join('presupuestos pr', 'pr.id = pl.presupuesto_id');
        $builder->where('e_main.id', $envio_id);
        $builder->where('p.estado', 'finalizado');
        $builder->where("pr.cliente_id = ($subCliente)", null, false);

        $builder->having('unidades_pendientes >', 0);
        $builder->orderBy('name', 'ASC');

        return $builder;
    }


    public static function addLineaEnvio($envio_id = null, $pedido_id = null, $direccion = null)
    {
        $modelPedido = model('App\Models\Pedidos\PedidoModel');

        $builder = $modelPedido->builder();

        $builder->select("
            pedidos.id as pedido_id,
            pedidos_linea.id as linea_id,
            pedidos_linea.cantidad as total_unidades,
            (
                SELECT IFNULL(SUM(el.unidades_envio), 0)
                FROM envios_lineas el
                JOIN envios e ON e.id = el.envio_id
                WHERE el.pedido_id = pedidos.id
                AND e.finalizado = 1
                AND TRIM(e.direccion) = '" . addslashes(trim($direccion)) . "'
            ) as unidades_enviadas,
            pedidos_linea.cantidad - IFNULL(SUM(envios_lineas.unidades_envio), 0) as unidades_envio,
            presupuestos.id as presupuesto_id
        ");

        $builder->join('pedidos_linea', 'pedidos_linea.pedido_id = pedidos.id', 'left');
        $builder->join('presupuestos', 'presupuestos.id = pedidos_linea.presupuesto_id', 'left');
        $builder->join('envios_lineas', 'envios_lineas.pedido_id = pedidos_linea.pedido_id', 'left');

        $builder->groupBy('pedidos_linea.id');
        $builder->having('IFNULL(SUM(envios_lineas.unidades_envio), 0) < pedidos_linea.cantidad', null, false);
        $builder->where('pedidos.estado', 'finalizado');
        $builder->where('pedidos.id', $pedido_id);

        $result = $builder->get()->getResultObject();

        if (empty($result)) {
            return [
                'status' => false,
                'message' => lang('Logistica.errors.notFound'),
            ];
        } else {
            $EnvioLineasModel = model('App\Models\Logistica\EnvioLineaModel');
            $EnvioLineasModel->save([
                'envio_id' => $envio_id,
                'pedido_id' => $result[0]->pedido_id,
                'unidades_envio' => $result[0]->unidades_envio,
                'unidades_total' => $result[0]->total_unidades,
                'cajas' => null,
                'unidades_cajas' => 1,
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
                'created_by' => auth()->user()->id,
                'updated_by' => auth()->user()->id,
                'presupuesto_id' => $result[0]->presupuesto_id,
            ]);
        }

        return [
            'status' => true,
            'data' => [
                'unidades_envio' => $result[0]->unidades_envio,
                'unidades_enviadas' => $result[0]->unidades_enviadas,
                'total_unidades' => $result[0]->total_unidades,
            ]
        ];
    }



    private static function generateEnvio($pedido_id, $multienvio = false)
    {

        $presupuestoDireccionesModel = model('App\Models\Presupuestos\PresupuestoDireccionesModel');

        if (!$multienvio) {
            // solo hay una dirección, se obtiene de los albaranes

            $datosEnvio = $presupuestoDireccionesModel
                ->select('
                    presupuestos.id as presupuesto_id,
                    presupuesto_direcciones.att,
                    presupuesto_direcciones.direccion,
                    presupuesto_direcciones.provincia as ciudad,
                    presupuesto_direcciones.cp,
                    presupuesto_direcciones.telefono,
                    presupuesto_direcciones.email,
                    presupuesto_direcciones.pais_id,
                    presupuesto_direcciones.cantidad - IFNULL(SUM(envios_lineas.unidades_envio), 0) as cantidad,
                    presupuesto_direcciones.cantidad as cantidad_total,
                    presupuestos.cliente_id as cliente_id
                ')
                ->join('pedidos_linea', 'pedidos_linea.presupuesto_id = presupuesto_direcciones.presupuesto_id')
                ->join('pedidos', 'pedidos.id = pedidos_linea.pedido_id')
                ->join('presupuestos', 'pedidos_linea.presupuesto_id = presupuestos.id')
                ->join('envios_lineas', 'envios_lineas.pedido_id = pedidos.id', 'left')
                ->join('envios', 'envios.id = envios_lineas.envio_id', 'left')
                ->where('pedidos.id', $pedido_id)
                ->groupBy('presupuesto_direcciones.id') // Necesario por el uso de SUM
                ->first();


            // se genera un nuevo envio con estos datos
            $EnvioModel = model('App\Models\Logistica\EnvioModel');
            $EnvioModel->set('cliente_id', $datosEnvio->cliente_id);
            $EnvioModel->set('att', $datosEnvio->att);
            $EnvioModel->set('direccion', $datosEnvio->direccion);
            $EnvioModel->set('ciudad', $datosEnvio->ciudad);
            $EnvioModel->set('cp', $datosEnvio->cp);
            $EnvioModel->set('telefono', $datosEnvio->telefono);
            $EnvioModel->set('email', $datosEnvio->email);
            $EnvioModel->set('pais_id', $datosEnvio->pais_id);
            $EnvioModel->set('cantidad', $datosEnvio->cantidad);
            $EnvioModel->set('cajas', 1);
            $EnvioModel->set('multienvio', $multienvio ? 1 : 0);
            $EnvioModel->set('created_at', date('Y-m-d H:i:s'));
            $EnvioModel->set('updated_at', date('Y-m-d H:i:s'));
            $EnvioModel->insert();
            $idEnvio = $EnvioModel->insertID();

            // se genera la linea de envio
            $EnvioLineasModel = model('App\Models\Logistica\EnvioLineaModel');
            $EnvioLineasModel->save([
                'envio_id' => $idEnvio,
                'pedido_id' => $pedido_id,
                'unidades_envio' => $datosEnvio->cantidad,
                'unidades_total' => $datosEnvio->cantidad_total,
                'cajas' => 1,
                'unidades_cajas' => 1,
                'created_at' => date('Y-m-d H:i:s'),
                'updated_at' => date('Y-m-d H:i:s'),
                'created_by' => auth()->user()->id,
                'updated_by' => auth()->user()->id,
                'presupuesto_id' => (int) $datosEnvio->presupuesto_id
            ]);



            return [
                'status' => true,
                'data' => [
                    'id_envio' => $idEnvio,
                    'multienvio' => false,
                ],
            ];

        }

        if (empty($datosEnvio)) {
            return [
                'status' => false,
                'message' => lang('Logistica.errors.noAddresses'),
            ];
        }
    }


    public static function finalizarEnvio($envio_id, $finalizar_ot = false)
    {
        // hay que comprobar que para todas las lineas de envio de este envio
        // se ha enviado toda la cantidad teniendo en cuenta otros envios
        $EnvioModel = model('App\Models\Logistica\EnvioModel');
        $EnvioLineasModel = model('App\Models\Logistica\EnvioLineaModel');

        $ots = [];

        $envio = $EnvioModel->find($envio_id);
        if (empty($envio)) {
            return [
                'status' => false,
                'message' => lang('Logistica.errors.noEnvio'),
            ];
        }
        $lineasEnvio = $EnvioLineasModel->where('envio_id', $envio_id)
            ->findAll();
        if (empty($lineasEnvio)) {
            return [
                'status' => false,
                'message' => lang('Logistica.errors.noEnvioLineas'),
            ];
        }

        foreach ($lineasEnvio as $linea) {

            $pedido = model('App\Models\Pedidos\PedidoModel')->find($linea->pedido_id);
            if (empty($pedido)) {
                return [
                    'status' => false,
                    'message' => lang('Logistica.errors.notFound'),
                ];
            }
            $cantidad_enviada = $EnvioLineasModel->select('SUM(envios_lineas.unidades_envio) as unidades_enviadas')
                ->where('envios_lineas.pedido_id', $linea->pedido_id)
                ->where('envios_lineas.envio_id !=', $envio_id)
                ->where('envios.finalizado', 1)
                ->join('envios', 'envios.id = envios_lineas.envio_id')
                ->get()->getResult();

            if (
                count($cantidad_enviada) == 0 ||
                empty($cantidad_enviada[0]->unidades_enviadas) ||
                $cantidad_enviada[0]->unidades_enviadas == null
            ) {
                $cantidad_enviada = 0;
            } else {
                $cantidad_enviada = $cantidad_enviada[0]->unidades_enviadas;
            }

            if ($cantidad_enviada + $linea->unidades_envio == $linea->unidades_total) {
                $otModel = model('App\Models\OrdenTrabajo\OrdenTrabajoModel');
                $ot = $otModel->where('pedido_id', $linea->pedido_id)
                    ->first();
                $ps = (new ProductionService())->init($ot->id);
                $ps->updateOrdenTrabajoDate([
                    "name" => "envio_at",
                    "envio_at" => date('Y-m-d H:i:s')
                ]);
                if ($finalizar_ot) {
                    $ps->updateOrdenTrabajo(
                        [
                            "estado" => 'F'
                        ]
                    );
                    array_push($ots, $ot->id);
                }
            }
        }

        $EnvioModel->update($envio_id, ['finalizado' => 1]);

        $data_return = [
            'status' => true,
            'message' => lang('Logistica.success.finalizado'),
        ];

        if ($finalizar_ot) {
            $data_return['ots'] = $ots;
        }
        return $data_return;
    }
}
