<?php

namespace App\Services;

use Config\Services;

class EtiquetasTitulosService
{

    public static function getOtsWithTitulos()
    {

        $db = \Config\Database::connect();

        // 3. Subconsulta principal
        $builder = $db->table('ordenes_trabajo ot')
            ->select("
            ot.id AS id,
            CONCAT('[', ot.id, '] - ', pr.titulo) AS name")
            ->join('pedidos p', 'p.id = ot.pedido_id')
            ->join('pedidos_linea pl', 'p.id = pl.pedido_id')
            ->join('presupuestos pr', 'pr.id = pl.presupuesto_id')
            ->join('orden_trabajo_dates ot_dates', 'ot_dates.orden_trabajo_id = ot.id')
            ->whereIn('p.estado', ['finalizado', 'produccion']);

        return $builder;
    }

    public static function getDireccionesOT($ot_id)
    {

        $db = \Config\Database::connect();

        // 3. Subconsulta principal
        $builder = $db->table('presupuesto_direcciones pd')
            ->select("
            pd.id AS id,
            pd.direccion AS name")
            ->join('presupuestos pr', 'pr.id = pd.presupuesto_id')
            ->join('pedidos_linea pl', 'pr.id = pl.presupuesto_id')
            ->join('pedidos p', 'p.id = pl.pedido_id')
            ->join('ordenes_trabajo ot', 'ot.pedido_id = p.id')
            ->join('orden_trabajo_dates ot_dates', 'ot_dates.orden_trabajo_id = ot.id')
            ->whereIn('p.estado', ['finalizado', 'produccion'])
            ->where('ot.id', $ot_id);

        return $builder;
    }

    public static function addEtiqueta($data)
    {
        $db = \Config\Database::connect();

        $builder = $db->table('presupuesto_direcciones pd');
        $builder->select('pd.att, pd.direccion, pd.cantidad, pr.cliente_id');
        $builder->join('presupuestos pr', 'pr.id = pd.presupuesto_id');
        $builder->join('pedidos_linea pl', 'pr.id = pl.presupuesto_id');
        $builder->join('pedidos p', 'p.id = pl.pedido_id');
        $builder->join('ordenes_trabajo ot', 'ot.pedido_id = p.id');
        $builder->where('ot.id', $data['ot_id']);
        $builder->where('pd.direccion', $data['direccion']);

        $result = $builder->get()->getRow();
        $data['att'] = $result->att;
        $data['direccion'] = $result->direccion;
        $data['cantidad'] = $result->cantidad;
        $data['cliente_id'] = $result->cliente_id;

        $modelEtiquetasTitulos = model('App\Models\Etiquetas\EtiquetasTitulosModel');
        $modelEtiquetasTitulos->insert([
            'direccion' => $data['direccion'],
            'att' => $data['att'],
            'cliente_id' => $data['cliente_id'],
            'user_created_at' => $data['user_id'],
        ]);
        $etiquetaId = $modelEtiquetasTitulos->getInsertID();

        if ($etiquetaId == null) {
            return [
                'status' => false,
                'message' => lang('Logistica.errorInsertarEtiqueta'),
            ];
        }

        $cantidad_restante = intval($data['cantidad']);
        $numero_caja = 1;
        while ($cantidad_restante > 0) {
            $modelEtiquetasTitulosLineas = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel');
            $modelEtiquetasTitulosLineas->insert([
                'etiqueta_titulos_id' => $etiquetaId,
                'ot_id' => $data['ot_id'],
                'unidades' => $cantidad_restante - intval($data['unidades_caja']) < 0 ? $cantidad_restante : intval($data['unidades_caja']),
                'numero_caja' => $numero_caja,
                'user_created_at' => $data['user_id'],
            ]);
            $cantidad_restante -= $data['unidades_caja'];
            $numero_caja++;
        }


        return [
            'status' => true,
            'etiqueta' => $etiquetaId,
        ];
    }

    public static function findOTsWithAddress(int $etiqueta_id)
    {
        $db = \Config\Database::connect();

        // 1. Dirección del envío actual
        $etiqueta = $db->table('etiquetas_titulos')->select('direccion')->where('id', $etiqueta_id)->get()->getRow();
        if (!$etiqueta) {
            return $db->table('(SELECT NULL AS id, NULL AS name, NULL as unidades) AS empty')->where('1 = 0');
        }

        $direccionNormalizada = str_replace(' ', '', strtolower(trim($etiqueta->direccion)));
        $direccionSQL = $db->escape($direccionNormalizada);

        // 2. Obtener presupuestos con esa dirección
        $presupuestosConEsaDireccion = $db->table('presupuesto_direcciones')
            ->select('presupuesto_id')
            ->where("REPLACE(LOWER(TRIM(direccion)), ' ', '') = $direccionSQL", null, false)
            ->get()
            ->getResultArray();

        $presupuestoIds = array_column($presupuestosConEsaDireccion, 'presupuesto_id');
        if (empty($presupuestoIds)) {
            return $db->table('(SELECT NULL AS id, NULL AS name, NULL as unidades) AS empty')->where('1 = 0');
        }

        // 3. Subconsulta principal
        $subBuilder = $db->table('pedidos_linea pl')
            ->select("
            ot.id AS id,
            CONCAT('[', ot.id, '] - ', pr.titulo) AS name,
            pd.cantidad AS description
        ")
            ->join('pedidos p', 'p.id = pl.pedido_id')
            ->join('presupuestos pr', 'pr.id = pl.presupuesto_id')
            ->join('presupuesto_direcciones pd', 'pd.presupuesto_id = pr.id')
            ->join('ordenes_trabajo ot', 'ot.pedido_id = p.id')
            ->join('orden_trabajo_dates ot_dates', 'ot_dates.orden_trabajo_id = ot.id')
            ->whereIn('pr.id', $presupuestoIds)
            ->whereIn('p.estado', ['finalizado', 'produccion'])
            ->groupBy('pl.id');

        // 4. Envolver y filtrar por unidades pendientes
        $builder = $db->table("({$subBuilder->getCompiledSelect(false)}) AS sub");
        $builder->select('id, name, description');

        return $builder;
    }

    public static function addLineasEtiqueta($etiqueta_id, $ot_id, $unidades, $cajas)
    {

        $unidades_caja = intdiv($unidades, $cajas);
        $unidades_caja = $unidades_caja == 0 ? $unidades : $unidades_caja;

        $unidades_restantes = $unidades;

        $modelEtitquetaLinea = model('\App\Models\Etiquetas\EtiquetasTitulosLineasModel');
        $next_caja = $modelEtitquetaLinea
            ->selectMax('numero_caja')
            ->where('etiqueta_titulos_id', $etiqueta_id)
            ->first();
        $next_caja = $next_caja->numero_caja ?? 0;
        $next_caja++;

        $user_id = auth()->user()->id;

        while ($unidades_restantes > 0) {
            $modelEtitquetaLinea->insert([
                'etiqueta_titulos_id' => $etiqueta_id,
                'ot_id' => $ot_id,
                'unidades' => $unidades_restantes - $unidades_caja < 0 ? $unidades_restantes : intval($unidades_caja),
                'numero_caja' => $next_caja,
                'user_created_at' => $user_id,
            ]);
            $unidades_restantes -= $unidades_caja;
            $next_caja++;
        }

        return [
            'status' => true,
            'message' => lang('Logistica.success.successInsertLines'),
        ];

    }

    public static function reordenarCajas($etiqueta_id)
    {
        $model = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel');

        // 1. Obtener todas las líneas ordenadas por numero_caja e id
        $lineas = $model
            ->where('etiqueta_titulos_id', $etiqueta_id)
            ->orderBy('numero_caja ASC')
            ->orderBy('id ASC')
            ->findAll();

        // 2. Agrupar por caja
        $grupos = [];
        foreach ($lineas as $linea) {
            $grupos[$linea->numero_caja][] = $linea;
        }

        // 3. Reasignar números de caja de forma consecutiva
        $nuevoNumeroCaja = 1;
        foreach ($grupos as $grupo) {
            foreach ($grupo as $linea) {
                $model->update($linea->id, ['numero_caja' => $nuevoNumeroCaja]);

            }
            $nuevoNumeroCaja++;
        }

        return [
            'status' => true,
            'message' => lang('Logistica.success.successReordenarCajas'),
        ];
    }

    public static function imprimirEtiquetas($etiqueta_id = null, $ids = [], $printer = null){

        $model = model('App\Models\Etiquetas\EtiquetasTitulosModel');
        $modelLineas = model('App\Models\Etiquetas\EtiquetasTitulosLineasModel');

        if ($etiqueta_id) {
            $etiquetas = $model->where('id', $etiqueta_id)->first();
            $etiquetas_lineas = $modelLineas->whereIn('id', $ids)->orderBy('numero_caja', 'ASC')->findAll();
        } 

        // buscar el maximo numero_cajas en el array de objetos etiquetas_lineas
        $max_num_cajas = 0;
        foreach ($etiquetas_lineas as $linea) {
            if ($linea->numero_caja > $max_num_cajas) {
                $max_num_cajas = $linea->numero_caja;
            }
        }

        // se obtienen los numero_caja diferentes en un array
        $numero_cajas = [];
        foreach ($etiquetas_lineas as $linea) {
            if (!in_array($linea->numero_caja, $numero_cajas)) {
                $numero_cajas[] = $linea->numero_caja;
            }
        }
        
        if (empty($etiquetas)) {
            return [
                'status' => false,
                'message' => lang('Logistica.errors.noEtiqueta'),
            ];
        }
        if (empty($etiquetas_lineas)) {
            return [
                'status' => false,
                'message' => lang('Logistica.errors.noEtiquetaLineas'),
            ];
        }
        
        
        $data = [
            "printer" => $printer->name,
            "header" => [
                "_FORMAT" => "E:MULTI.ZPL",
                "_QUANTITY" => 1,
                "_PRINBTERNAME" => $printer->name,
                "_JOBNAME" => "LBL101"
            ],
            'direccion' => $etiquetas->direccion,
            'grupos' => [],
            'notas' => $etiquetas->comentarios,
            'nombre' => $etiquetas->att,
        ];

        
        $index_etiqueta = 0;
        foreach ($numero_cajas as $caja) {

            array_push($data['grupos'], [
            ]);

            $lineas = array_filter($etiquetas_lineas, function ($linea) use ($caja) {
                return $linea->numero_caja == $caja;
            });

            $lineaCounter = 0;
            foreach($lineas as $linea){

                
                if($lineaCounter >= 5){
                    $lineaCounter = 0;
                    $index_etiqueta++;
                    array_push($data['grupos'], []);
                }

                $modelPresupuestos = model('App\Models\OrdenTrabajo\OrdenTrabajoModel');
                $datos_etiqueta = $modelPresupuestos->select('
                    pr.titulo as titulo, 
                    pr.isbn as isbn, 
                    pr.referencia_cliente as referencia_cliente, 
                    p.id as id_pedido,
                    ordenes_trabajo.total_tirada as total_tirada,')
                ->join('pedidos p', 'p.id = ordenes_trabajo.pedido_id')
                ->join('pedidos_linea pl', 'pl.pedido_id = p.id')
                ->join('presupuestos pr', 'pr.id = pl.presupuesto_id')
                ->where('ordenes_trabajo.id',$linea->ot_id)->first();



                $data['grupos'][$index_etiqueta][] = [
                    'prefix' => $lineaCounter+1,
                    'titulo' => mb_substr($datos_etiqueta->titulo, 0, 40),
                    'cantidad' => $linea->unidades,
                    'tirada' => $datos_etiqueta->total_tirada,
                    'ean' => str_replace('-', '', $datos_etiqueta->isbn),
                    'npedido' => $datos_etiqueta->id_pedido,
                    'refcliente' => $datos_etiqueta->referencia_cliente,
                ];

                $lineaCounter++;
            }
            $index_etiqueta++;
        }

        $servicioImpresora = new ImpresoraEtiquetaService();
        $xml = $servicioImpresora->createEtiquetaTitulos($data);
        if ($xml == null) {
            return [
                'status' => false,
                'message' => lang('Logistica.errors.noEtiquetas'),
            ];
        }
        $sk_environment = getenv('SK_ENVIRONMENT');
        if ($sk_environment == 'production') {

            $status = $servicioImpresora->sendToImpresoraEtiqueta("ETIQUETA", $xml, $printer);
            if ($status) {
                return [
                    'status' => true,
                    'message' => lang('Logistica.success.imprimirEtiquetas'),
                ];
            } else {
                return [
                    'status' => false,
                    'message' => lang('Logistica.errors.noEtiquetas'),
                ];
            }

        } else {
            return [
                'status' => true,
                'message' => lang('Logistica.success.imprimirEtiquetas'),
                'data' => $xml
            ];
        }
    
    
    }
}