<?php

namespace App\Models\Clientes;

class ClientePreciosModel extends \App\Models\BaseModel
{
    protected $table = "cliente_precios";

    /**
     * Whether primary key uses auto increment.
     *
     * @var bool
     */
    protected $useAutoIncrement = true;

    const SORTABLE = [
        0 => "t1.id",
        1 => "t1.tipo",
        2 => "t1.tipo_maquina",
        3 => "t1.tipo_impresion",
        4 => "t1.tiempo_min",
        5 => "t1.tiempo_max",
        6 => "t1.precio_hora",
        7 => "t1.margen",
    ];

    protected $allowedFields = [
        "cliente_id",
        "plantilla_id",
        "tipo",
        "tipo_maquina",
        "tipo_impresion",
        "tiempo_min",
        "tiempo_max",
        "precio_hora",
        "margen",
        "deleted_at",
        "created_at",
        "updated_at",
        "user_created_id",
        "user_updated_id"
    ];

    protected $returnType = "App\Entities\Clientes\ClientePreciosEntity";

    protected $useTimestamps = true;
    protected $useSoftDeletes = true;
    protected $deletedField = 'deleted_at';

    protected $createdField = "created_at";

    protected $updatedField = "updated_at";

    public static $labelField = "cliente_id";

    protected $validationRules = [
        "cliente_id" => [
            "label" => "ClientePrecios.cliente_id",
            "rules" => "required",
        ],
        "tipo" => [
            "label" => "ClientePrecios.tipo",
            "rules" => "required|in_list[interior,cubierta,sobrecubierta]",
        ],
        "tipo_maquina" => [
            "label" => "ClientePrecios.tipo_maquina",
            "rules" => "required|in_list[toner,inkjet]",
        ],
        "tipo_impresion" => [
            "label" => "ClientePrecios.tipo_impresion",
            "rules" => "required|in_list[negro,color,negrohq,colorhq]",
        ],
        "tiempo_min" => [
            "label" => "ClientePrecios.tiempo_min",
            "rules" => "required|decimal",
        ],
        "tiempo_max" => [
            "label" => "ClientePrecios.tiempo_max",
            "rules" => "required|decimal",
        ],
        "margen" => [
            "label" => "ClientePrecios.margen",
            "rules" => "required|decimal",
        ],



    ];

    protected $validationMessages = [
        "cliente_id" => [
            "required" => "ClientePrecios.validation.required",

        ],
        "tipo" => [
            "required" => "ClientePrecios.validation.required",
        ],
        "tipo_maquina" => [
            "required" => "ClientePrecios.validation.required",
        ],
        "tipo_impresion" => [
            "required" => "ClientePrecios.validation.required",
        ],
        "tiempo_min" => [
            "required" => "ClientePrecios.validation.required",
        ],
        "tiempo_max" => [
            "required" => "ClientePrecios.validation.required",
        ],
        "margen" => [
            "required" => "ClientePrecios.validation.required",
        ],
    ];

    function clean_plantilla_id($cliente_id = 0)
    {
        $this->db
            ->table($this->table . " t1")
            ->where('cliente_id', $cliente_id)
            ->set('plantilla_id', null)
            ->update();
    }

    function set_plantilla_id($cliente_id = 0, $plantilla_id = null)
    {
        $this->db
            ->table($this->table . " t1")
            ->where('cliente_id', $cliente_id)
            ->set('plantilla_id', $plantilla_id)
            ->update();
    }


    function delete_values($cliente_id = 0)
    {
        $session = session();
        $datetime = (new \CodeIgniter\I18n\Time("now"));
        $date_value = $datetime->format('Y-m-d H:i:s');

        $this->db
            ->table($this->table . " t1")
            ->where('cliente_id', $cliente_id)
            ->set('deleted_at', $date_value)
            ->set('user_updated_id', $session->id_user)
            ->update();
    }


    function debug_all_clientes_to_defecto()
    {
        $plantilla_id = 5; // por defecto
        // Se borran los valores existentes para todos los clientes en una sola consulta

        $modelCliente = model('App\Models\Clientes\ClienteModel');
        $clientes = $modelCliente->select('id')->where('deleted_at', null)->findAll();

        // Se borra la tabla
        $this->db->table($this->table)->truncate();


        // Preparar los datos para `insertBatch`
        $data = [];
        $date_value = date('Y-m-d H:i:s'); // Asume que $date_value es la fecha actual
        $userId = auth()->user()->id; // ID del usuario actual

        $plantillaModel = model('App\Models\Clientes\ClientePlantillaPreciosLineasModel');
        $values = $plantillaModel->getResource([], $plantilla_id)->get()->getResultObject();

        $batchSize = 1000;
        $data = [];

        foreach ($clientes as $index => $cliente) {
            foreach ($values as $value) {
                $data[] = [
                    'cliente_id' => $cliente->id,
                    'plantilla_id' => $plantilla_id,
                    'tipo' => $value->tipo,
                    'tipo_maquina' => $value->tipo_maquina,
                    'tipo_impresion' => $value->tipo_impresion,
                    'tiempo_min' => $value->tiempo_min,
                    'tiempo_max' => $value->tiempo_max,
                    'precio_hora' => $value->precio_hora,
                    'margen' => $value->margen,
                    'user_updated_id' => $value->user_updated_id,
                    'updated_at' => $value->updated_at,
                    'user_created_id' => $userId,
                    'created_at' => $date_value,
                ];

                if (count($data) === $batchSize) {
                    $this->db->table($this->table)->insertBatch($data);
                    $data = [];
                }
            }
        }

        // Insertar los datos restantes
        if (!empty($data)) {
            $this->db->table($this->table)->insertBatch($data);
        }
    }

    function copy_from_plantilla($cliente_id = 0, $plantilla_id = 0)
    {

        $session = session();
        $datetime = (new \CodeIgniter\I18n\Time("now"));
        $date_value = $datetime->format('Y-m-d H:i:s');

        // Se borran los valores existentes
        $this->delete_values($cliente_id);

        // Se cargan los valores de la plantilla
        $plantillaModel = model('App\Models\Clientes\ClientePlantillaPreciosLineasModel');
        $values = $plantillaModel->getResource([], $plantilla_id)->get()->getResultObject();

        foreach ($values as $value) {
            $this->db
                ->table($this->table . " t1")
                ->set('cliente_id', $cliente_id)
                ->set('plantilla_id', $plantilla_id)
                ->set('tipo', $value->tipo)
                ->set('tipo_maquina', $value->tipo_maquina)
                ->set('tipo_impresion', $value->tipo_impresion)
                ->set('tiempo_min', $value->tiempo_min)
                ->set('tiempo_max', $value->tiempo_max)
                ->set('precio_hora', $value->precio_hora)
                ->set('margen', $value->margen)
                ->set('user_updated_id', $session->id_user)
                ->set('updated_at', $date_value)
                ->set('user_created_id', $session->id_user)
                ->set('created_at', $date_value)
                ->insert();
        }

    }


    function update_from_plantilla($plantilla_id = 0)
    {

        /*$datetime = (new \CodeIgniter\I18n\Time("now"));
        $date_value = $datetime->format('Y-m-d H:i:s');
        
        // Se obtienen todos los id de clientes que usen esa tarifa
        $clientes = $this->db
            ->table($this->table . " t1")
            ->select("t1.cliente_id AS id")
            ->where('t1.plantilla_id', $plantilla_id)
            ->where('t1.is_deleted', 0)
            ->distinct()
            ->get()->getResultObject();
         
        if(count($clientes)<=0){
            return;
        }

        foreach ($clientes as $cliente){
            // Se borran los valores existentes
            $this->delete_values($cliente->id);

            // Se cargan los valores de la plantilla
            $plantillaModel = model('App\Models\Clientes\ClientePlantillaPreciosLineasModel');
            $values = $plantillaModel->getResource([], $plantilla_id)->get()->getResultObject();
            foreach ($values as $value) {
                $this->db
                    ->table($this->table . " t1")
                    ->set('cliente_id', $cliente->id)
                    ->set('plantilla_id', $plantilla_id)
                    ->set('tipo', $value->tipo)
                    ->set('tipo_maquina', $value->tipo_maquina)
                    ->set('tipo_impresion', $value->tipo_impresion)
                    ->set('tiempo_min', $value->tiempo_min)
                    ->set('tiempo_max', $value->tiempo_max)
                    ->set('precio_hora', $value->precio_hora)
                    ->set('margen', $value->margen)
                    ->set('user_updated_id', $value->user_updated_id)
                    ->set('updated_at', $value->updated_at)
                    ->set('user_created_id', auth()->user()->id)
                    ->set('created_at', $date_value)
                    ->insertBatch($values);
            }
        }*/

        // Se borran los valores existentes para todos los clientes en una sola consulta
        $clientes = $this->db
            ->table($this->table . " t1")
            ->select("t1.cliente_id AS id")
            ->where('t1.plantilla_id', $plantilla_id)
            ->where('t1.deleted_at', null)
            ->distinct()
            ->get()->getResultArray();
        // Extraer solo los IDs de los clientes
        $clienteIds = array_map(fn($cliente) => $cliente['id'], $clientes);

        // Borrar los valores existentes para esos clientes en una sola consulta
        if (!empty($clienteIds)) {
            $this->db->table($this->table)->whereIn('cliente_id', $clienteIds)->delete();
        }

        // Preparar los datos para `insertBatch`
        $data = [];
        $date_value = date('Y-m-d H:i:s'); // Asume que $date_value es la fecha actual
        $userId = auth()->user()->id; // ID del usuario actual

        $plantillaModel = model('App\Models\Clientes\ClientePlantillaPreciosLineasModel');
        $values = $plantillaModel->getResource([], $plantilla_id)->get()->getResultObject();

        $batchSize = 1000;
        $data = [];
        
        foreach ($clientes as $cliente) {
            foreach ($values as $value) {
                $data[] = [
                    'cliente_id' => $cliente['id'],
                    'plantilla_id' => $plantilla_id,
                    'tipo' => $value->tipo,
                    'tipo_maquina' => $value->tipo_maquina,
                    'tipo_impresion' => $value->tipo_impresion,
                    'tiempo_min' => $value->tiempo_min,
                    'tiempo_max' => $value->tiempo_max,
                    'precio_hora' => $value->precio_hora,
                    'margen' => $value->margen,
                    'user_updated_id' => $value->user_updated_id,
                    'updated_at' => $value->updated_at,
                    'user_created_id' => $userId,
                    'created_at' => $date_value,
                ];

                if (count($data) === $batchSize) {
                    $this->db->table($this->table)->insertBatch($data);
                    $data = [];
                }
            }
        }

        // Insertar todos los datos de una vez
        if (!empty($data)) {
            $this->db->table($this->table)->insertBatch($data);
        }
    }

    // config es un objeto que incluye
    // - tipo: 'interior', 'cubierta', 'sobrecubierta'
    // - tipo_maquina: 'toner', 'inkjet'
    // - tipo_impresion: 'negro', 'color', 'negrohq', 'colorhq'

    function get_precio_hora($cliente_id, $config, $tiempo)
    {

        // Se cargan los valores de la plantilla
        $values = $this->db
            ->table($this->table . " t1")
            ->select("t1.precio_hora AS precio_hora, t1.margen AS margen")
            ->where('cliente_id', $cliente_id)
            ->where('tipo', $config->tipo)
            ->where('tipo_maquina', $config->tipo_maquina)
            ->where('tipo_impresion', $config->tipo_impresion)
            ->where('tiempo_min <=', $tiempo)
            ->where('tiempo_max >=', $tiempo)
            ->where('deleted_at', null)
            ->get()->getResultObject();

        if (count($values) > 0) {
            return [floatval(($values[0])->precio_hora), floatval(($values[0])->margen)];
        }
        return [null, null];
    }


    /**
     * Get resource data.
     *
     * @param string $search
     *
     * @return \CodeIgniter\Database\BaseBuilder
     */
    public function getResource($search = [], $cliente_id = -1)
    {
        $builder = $this->db
            ->table($this->table . " t1")
            ->select(
                "t1.id as id, t1.plantilla_id AS plantilla_id, t1.cliente_id AS cliente_id, 
                t1.tipo AS tipo, t1.tipo_maquina AS tipo_maquina, t1.tipo_impresion AS tipo_impresion,
                t1.tiempo_min AS tiempo_min, t1.tiempo_max AS tiempo_max, t1.precio_hora AS precio_hora, t1.margen AS margen,
                t1.user_updated_id AS user_updated_id, t1.updated_at AS updated_at, CONCAT(t2.first_name, ' ', t2.last_name) AS user_updated"
            );

        $builder->join("users t2", "t1.user_updated_id = t2.id", "left");

        $builder->where('t1.deleted_at', null);
        $builder->where('t1.cliente_id', $cliente_id);

        if (empty($search))
            return $builder;
        else {
            $builder->groupStart();
            foreach ($search as $col_search) {
                if ($col_search[0] > 0 && $col_search[0] < 4)
                    $builder->where(self::SORTABLE[$col_search[0]], $col_search[2]);
                else
                    $builder->like(self::SORTABLE[$col_search[0]], $col_search[2]);
            }
            $builder->groupEnd();
            return $builder;
        }
    }

    public function getPlantilla($cliente_id = -1)
    {
        $builder = $this->db
            ->table($this->table . " t1")
            ->select(
                "t1.plantilla_id AS id, t2.nombre AS nombre"
            );

        $builder->where('t1.deleted_at', null);
        $builder->where('t1.cliente_id', $cliente_id);
        $builder->join("cliente_plantilla_precios t2", "t1.plantilla_id = t2.id", "left");
        $builder->limit(1);

        $values = $builder->get()->getResultArray();
        if (count($values) > 0) {
            return $values[0];
        }

        return [];
    }



    public function checkIntervals($data = [], $id_linea = null, $cliente_id = null)
    {

        helper('general');

        if (floatval($data["tiempo_min"]) >= floatval($data["tiempo_max"])) {
            return lang('ClientePrecios.errors.error_tiempo_range');
        }

        $rows = $this->db
            ->table($this->table)
            ->select("id, tiempo_min, tiempo_max")
            ->where("deleted_at", null)
            ->where("tipo", $data["tipo"])
            ->where("tipo_maquina", $data["tipo_maquina"])
            ->where("tipo_impresion", $data["tipo_impresion"])
            ->where("cliente_id", $cliente_id)
            ->get()->getResultObject();


        foreach ($rows as $row) {
            if (!is_null($id_linea)) {
                if ($row->id == $id_linea) {
                    continue;
                }
            }
            if (
                check_overlap(
                    floatval($data["tiempo_min"]),
                    floatval($data["tiempo_max"]),
                    $row->tiempo_min,
                    $row->tiempo_max
                )
            ) {
                return lang('ClientePrecios.errors.error_tiempo_overlap');
            }
        }

        return "";
    }

    public function get_plantilla_precios($cliente_id = -1)
    {
        $value = $this->db
            ->table($this->table)
            ->select("plantilla_id")
            ->where("deleted_at", null)
            ->where("cliente_id", $cliente_id)
            ->limit(1)->get()->getResultObject();

        if (count($value) > 0) {
            return $value[0]->plantilla_id;
        }
        return null;
    }
}
