<?php

namespace App\Controllers\Produccion;

use App\Controllers\BaseController;
use App\Models\Compras\ProveedorModel;
use App\Models\Configuracion\MaquinaModel;
use App\Models\Configuracion\MaquinaOtTareaModel;
use App\Models\OrdenTrabajo\OrdenTrabajoModel;
use App\Models\OrdenTrabajo\OrdenTrabajoTarea;
use App\Models\OrdenTrabajo\OrdenTrabajoUser;
use App\Models\Presupuestos\PresupuestoModel;
use App\Models\Usuarios\UserModel;
use App\Services\EtiquetasTitulosService;
use App\Services\ImpresoraEtiquetaService;
use App\Services\ProductionService;
use CodeIgniter\Files\File;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\I18n\Time;
use CodeIgniter\Validation\Validation;
use Config\LogoImpresion;
use Exception;
use Hermawan\DataTables\DataTable;
use Psr\Log\LoggerInterface;


class Ordentrabajo extends BaseController
{
    protected $format = 'json';
    protected array $viewData = [];
    protected ProductionService $produccionService;
    protected OrdenTrabajoModel $otModel;
    protected OrdenTrabajoUser $otUserModel;
    protected OrdenTrabajoTarea $otTarea;
    protected ProveedorModel $proveedorModel;
    protected MaquinaModel $maquinaModel;
    protected MaquinaOtTareaModel $maquinaOtTareaModel;
    protected UserModel $userModel;
    protected Validation $validation;
    protected static $viewPath = 'themes/vuexy/form/produccion/';
    protected static $controllerSlug = "orden-trabajo";
    protected $indexRoute = 'viewOrdenTrabajoList';
    protected $indexRoutePlanning = 'ot/viewPlanningRotativa';
    protected $editRoute = 'viewOrdenTrabajoEdit';


    public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger)
    {
        $this->otModel = model(OrdenTrabajoModel::class);
        $this->userModel = model(UserModel::class);
        $this->produccionService = new ProductionService();
        $this->otTarea = model(OrdenTrabajoTarea::class);
        $this->maquinaModel = model(MaquinaModel::class);
        $this->maquinaOtTareaModel = model(MaquinaOtTareaModel::class);
        $this->proveedorModel = model(ProveedorModel::class);
        $this->validation = service("validation");
        helper("time");
        parent::initController($request, $response, $logger);
    }

    public function index()
    {
        // Breadcrumbs
        $this->viewData['breadcrumb'] = [
            ['title' => lang("Produccion.ot"), 'route' => "javascript:void(0);", 'active' => false],
            ['title' => lang("Produccion.ots"), 'route' => site_url('produccion/ordentrabajo'), 'active' => true]
        ];
        return view(static::$viewPath . $this->indexRoute, $this->viewData);
    }
    public function index_planning_rotativa()
    {
        // Breadcrumbs
        $this->viewData['breadcrumb'] = [
            ['title' => lang("Produccion.ots"), 'route' => "javascript:void(0);", 'active' => false],
            ['title' => lang("Produccion.ots"), 'route' => site_url('produccion/ordentrabajo/planning/rotativa'), 'active' => true]
        ];
        return view(static::$viewPath . $this->indexRoutePlanning, $this->viewData);
    }


    public function find_tarea($orden_trabajo_tarea_id)
    {
        $t = $this->otTarea->find($orden_trabajo_tarea_id);
        return $this->response->setJSON($t);
    }
    public function get_orden_trabajo_summary($orden_trabajo_id)
    {
        try {
            //code...
            $summary = $this->produccionService->init($orden_trabajo_id)->getSummary();
            return $this->response->setJSON($summary);
        } catch (\Throwable $th) {
            return $this->response->setStatusCode(500)->setJSON(["message" => $th->getMessage(), "error" => $th]);
        }
    }
    public function add() {}

    /**========================================================================
     *                           UPDATES
     *========================================================================**/
    public function update_orden_trabajo()
    {
        $bodyData = $this->request->getPost();
        // return $this->response->setJSON(["message" => lang("App.global_alert_save_success"),  "data" => $bodyData]);
        $validated = $this->validation->run($bodyData, "orden_trabajo");
        if ($validated) {
            $r = $this->produccionService->init($bodyData["orden_trabajo_id"])->updateOrdenTrabajo($bodyData);
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r, "data" => $bodyData]);
        } else {
            return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
        }
    }
    public function update_orden_trabajo_tarea()
    {
        $bodyData = $this->request->getPost();
        $validated = $this->validation->run($bodyData, "orden_trabajo_tarea");
        if ($validated) {
            $r = $this->produccionService->updateOrdenTrabajoTarea($bodyData["orden_trabajo_tarea_id"], $bodyData);
            $tareaEntity = $this->otTarea->find($bodyData["orden_trabajo_tarea_id"]);
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r, "data" => $tareaEntity]);
        } else {
            return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
        }
    }
    public function update_orden_trabajo_pliegos()
    {
        $bodyData = $this->request->getPost();
        // return $this->response->setJSON(["message" => lang("App.global_alert_save_success"),  "data" => $bodyData]);
        $validated = $this->validation->run($bodyData, "orden_trabajo");
        if ($validated) {
            $r = $this->produccionService->init($bodyData["orden_trabajo_id"])->updateOrdenTrabajoTareaPliegos($bodyData);
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r, "data" => $bodyData]);
        } else {
            return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
        }
    }
    public function update_orden_trabajo_date()
    {
        $bodyData = $this->request->getPost();
        // return $this->response->setJSON(["message" => lang("App.global_alert_save_success"),  "data" => $bodyData]);
        $validated = $this->validation->run($bodyData, "orden_trabajo_date");
        if ($validated) {
            $r = $this->produccionService->init($bodyData["orden_trabajo_id"])->updateOrdenTrabajoDate($bodyData);
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r["status"], "user" => $r["user"], "data" => $bodyData]);
        } else {
            return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
        }
    }
    public function update_presupuesto_tarea_proveedor()
    {
        $bodyData = $this->request->getPost();
        $validated = $this->validation->run($bodyData, "proveedor_tarea");
        if ($validated) {
            $validatedData = $this->validation->getValidated();
            $r = $this->produccionService->updateProveedorLinea($validatedData['orden_trabajo_tarea_id'], $validatedData['proveedor_id']);
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r]);
        } else {
            return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
        }
    }
    public function reset_orden_trabajo_date()
    {
        $bodyData = $this->request->getPost();
        // return $this->response->setJSON(["message" => lang("App.global_alert_save_success"),  "data" => $bodyData]);
        $validated = $this->validation->run($bodyData, "orden_trabajo_date");
        if ($validated) {
            $validatedData = $bodyData;
            $r = $this->produccionService->emptyOrdenTrabajoDate($validatedData['orden_trabajo_id'], $validatedData['name']);
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r, "user" => auth()->user(), "data" => $bodyData]);
        } else {
            return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
        }
    }
    public function update_orden_trabajo_pedido_date()
    {
        try {
            $bodyData = $this->request->getPost();
            $r = $this->produccionService->init($bodyData["orden_trabajo_id"])->updateOrdenTrabajoPedidoDate($bodyData);
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r["status"], "user" => $r["user"], "data" => $bodyData]);
        } catch (\Throwable $th) {
            return $this->response->setJSON(["errors" => $th->getMessage(), "status" => false])->setStatusCode(500);
        }
    }
    public function reset_orden_trabajo_pedido_date()
    {
        $bodyData = $this->request->getPost();
        $validated = $this->validation->run($bodyData, "orden_trabajo_date");
        if ($validated) {
            $validatedData = $bodyData;
            $r = $this->produccionService->init($bodyData['orden_trabajo_id'])->emptyOrdenTrabajoPedidoDate($validatedData['name']);
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r, "user" => auth()->user(), "data" => $bodyData]);
        } else {
            return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
        }
    }
    public function update_orden_trabajo_pedido()
    {
        try {
            $bodyData = $this->request->getPost();
            $r = $this->produccionService->init($bodyData["orden_trabajo_id"])->updateOrdenTrabajoPedido($bodyData);
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r, "data" => $bodyData]);
        } catch (\Throwable $th) {
            return $this->response->setJSON(["errors" => $th->getMessage(), "status" => false])->setStatusCode(500);
        }
    }
    public function edit($orden_trabajo_id)
    {
        // Breadcrumbs
        $this->viewData['breadcrumb'] = [
            ['title' => lang("Produccion.ot"), 'route' => site_url('produccion/ordentrabajo'), 'active' => false],
            ['title' => $this->otModel->find($orden_trabajo_id)->pedido()->presupuesto()->titulo, 'route' => site_url('produccion/ordentrabajo/edit/' . $orden_trabajo_id), 'active' => true]
        ];
        $this->viewData["modelId"] = $orden_trabajo_id;
        $this->produccionService->init($orden_trabajo_id);
        $this->produccionService->reInsertOrdenTrabajoDates();
        $this->produccionService->reInsertOrdenTrabajoUsers();
        $this->viewData["presupuesto"] = $this->produccionService->getPresupuesto();
        $this->viewData["cliente"] = $this->produccionService->getCliente();
        $this->viewData["ot"] = $this->produccionService->getOrdenTrabajo();
        $this->viewData["is_finalizada"] = $this->produccionService->getOrdenTrabajo()->estado == "F";
        $this->viewData["user_dates"] = $this->produccionService->userDates();
        $this->viewData["pedido_user_dates"] = $this->produccionService->pedidoUserDates();
        $this->viewData["colors"] = $this->produccionService->getPdfColors();
        $this->viewData["tiempo_estimado"] = $this->produccionService->getTiempoProcesamientoHHMMSS();
        $this->viewData["flags"] = $this->produccionService->getFlags();
        $this->viewData["tareaCosido"] = $this->produccionService->getTareaCosido();


        return view(static::$viewPath . $this->editRoute, $this->viewData);
    }

    public function datatable()
    {
        $logo = config(LogoImpresion::class);

        $q = $this->otModel->getDatatableQuery()->where("ordenes_trabajo.estado", "F");
        // return $this->response->setJSON($q->get()->getResultArray());
        return DataTable::of($q)
            ->add("logo", fn($q) => ["logo" => site_url($logo->get_logo_path($q->presupuesto_linea_tipo)), "imposicion" => $q->imposicion_name, "color" =>  $this->produccionService->init($q->id)->getOtColorStatus()])
            ->edit(
                "fecha_encuadernado_at",
                fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : ""
            )
            ->add("action", fn($q) => $q->id)
            ->toJson(true);
    }
    public function datatable_pendientes()
    {
        $logo = config(LogoImpresion::class);

        $q = $this->otModel->getDatatableQuery()->whereIn("ordenes_trabajo.estado", ["I", "PM"])->where('ordenes_trabajo.preimpresion_revisada', true);
        // return $this->response->setJSON($q->get()->getResultArray());
        return DataTable::of($q)
            ->add("logo", fn($q) => ["logo" => site_url($logo->get_logo_path($q->presupuesto_linea_tipo)), "imposicion" => $q->imposicion_name, "color" =>  $this->produccionService->init($q->id)->getOtColorStatus()])
            ->edit(
                "fecha_encuadernado_at",
                fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : ""
            )
            ->add("action", fn($q) => $q->id)
            ->toJson(true);
    }
    public function datatable_ferro_pendiente()
    {
        $logo = config(LogoImpresion::class);

        $q = $this->otModel->getDatatableQuery()->where('presupuestos.ferro', 1)->where("ferro_ok_at", null);
        // return $this->response->setJSON($q->get()->getResultArray());
        return DataTable::of($q)
            ->add("logo", fn($q) => ["logo" => site_url($logo->get_logo_path($q->presupuesto_linea_tipo)), "imposicion" => $q->imposicion_name, "color" =>  $this->produccionService->init($q->id)->getOtColorStatus()])
            ->edit(
                "fecha_encuadernado_at",
                fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : ""
            )
            ->add("action", fn($q) => $q->id)
            ->toJson(true);
    }
    public function datatable_ferro_ok()
    {
        $logo = config(LogoImpresion::class);

        $q = $this->otModel->getDatatableQuery()->where('presupuestos.ferro', 1)->where("ferro_ok_at is NOT NULL", NULL, FALSE);
        // return $this->response->setJSON($q->get()->getResultArray());
        return DataTable::of($q)
            ->add("logo", fn($q) => ["logo" => site_url($logo->get_logo_path($q->presupuesto_linea_tipo)), "imposicion" => $q->imposicion_name, "color" =>  $this->produccionService->init($q->id)->getOtColorStatus()])
            ->edit(
                "fecha_encuadernado_at",
                fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : ""
            )
            ->add("action", fn($q) => $q->id)
            ->toJson(true);
    }
    public function datatable_news()
    {
        $logo = config(LogoImpresion::class);

        $q = $this->otModel->getDatatableQuery()->where('ordenes_trabajo.preimpresion_revisada', false);
        return DataTable::of($q)
            ->add("logo", fn($q) => ["logo" => site_url($logo->get_logo_path($q->presupuesto_linea_tipo)), "imposicion" => $q->imposicion_name, "color" =>  $this->produccionService->init($q->id)->getOtColorStatus()])
            ->edit(
                "fecha_encuadernado_at",
                fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : ""
            )
            ->add("action", fn($q) => $q->id)
            ->toJson(true);
    }
    public function datatable_prod()
    {
        $logo = config(LogoImpresion::class);

        $q = $this->otModel->getDatatableQuery()->where('ordenes_trabajo.preimpresion_revisada', true)->where('pedidos.estado', 'produccion');
        return DataTable::of($q)
            ->add("logo", fn($q) => ["logo" => site_url($logo->get_logo_path($q->presupuesto_linea_tipo)), "imposicion" => $q->imposicion_name, "color" =>  $this->produccionService->init($q->id)->getOtColorStatus()])
            ->edit(
                "fecha_encuadernado_at",
                fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : ""
            )
            ->add("action", fn($q) => $q->id)
            ->toJson(true);
    }
    public function datatable_waiting()
    {
        $logo = config(LogoImpresion::class);

        $q = $this->otModel->getDatatableQuery()->where('ordenes_trabajo.is_pedido_espera', 1);
        return DataTable::of($q)
            ->add("logo", fn($q) => ["logo" => site_url($logo->get_logo_path($q->presupuesto_linea_tipo)), "imposicion" => $q->imposicion_name, "color" =>  $this->produccionService->init($q->id)->getOtColorStatus()])
            ->edit(
                "fecha_encuadernado_at",
                fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : ""
            )
            ->add("action", fn($q) => $q->id)
            ->toJson(true);
    }
    public function datatable_revision_com()
    {
        $logo = config(LogoImpresion::class);

        $q = $this->otModel->getDatatableQuery()->where('presupuestos.ferro', 1)->where("ferro_ok_at is NOT NULL", NULL, FALSE);
        return DataTable::of($q)
            ->add("logo", fn($q) => ["logo" => site_url($logo->get_logo_path($q->presupuesto_linea_tipo)), "imposicion" => $q->imposicion_name, "color" =>  $this->produccionService->init($q->id)->getOtColorStatus()])
            ->edit(
                "fecha_encuadernado_at",
                fn($q) => $q->fecha_encuadernado_at ? Time::createFromFormat("Y-m-d H:i:s", $q->fecha_encuadernado_at)->format("d/m/Y") : ""
            )
            ->add("action", fn($q) => $q->id)
            ->toJson(true);
    }
    public function papel_gramaje_datatable()
    {

        $q = $this->produccionService->papelGramajeDatatableQuery();
        return DataTable::of($q)
            ->edit("tiempoReal", fn($q) => $q->tiempoReal)
            ->add("action", fn($q) => ["title" => lang('Produccion.datatable.filter_by_paper'), 'data' => $q])
            ->toJson(true);
    }
    public function papel_pliego_datatable()
    {

        $q = $this->produccionService->papelPliegoDatatableQuery();
        return DataTable::of($q)
            ->edit("tiempoReal", fn($q) => $q->tiempoReal)
            ->add("action", fn($q) => ["title" => lang('Produccion.datatable.filter_by_paper'), 'data' => $q])
            ->toJson(true);
    }
    public function reset_tareas(int $orden_trabajo_id)
    {
        $r = $this->produccionService->init($orden_trabajo_id)->resetAllTareas();
        return $this->response->setJSON(["message" => "Tareas reseteadas", "status" => $r]);
    }
    public function delete_tarea(int $orden_trabajo_tarea_id)
    {
        $r = $this->otTarea->delete($orden_trabajo_tarea_id);
        return $this->response->setJSON(["message" => "Tarea eliminada", "states" => $r]);
    }
    public function tareas_datatable(int $orden_trabajo_id)
    {
        $q = $this->produccionService->init($orden_trabajo_id)->taskDatatableQuery($orden_trabajo_id);
        // return $this->response->setJSON($q->get()->getResultArray());
        return DataTable::of($q)
            ->add("action", fn($q) => $q)
            ->edit("orden", fn($q) => ["id" => $q->id, "orden" => $q->orden])
            ->add("tarea_estado", fn($q) => $this->produccionService->getTitleTareaEstado($q->id))
            ->edit("tiempo_estimado", fn($q) => float_seconds_to_hhmmss_string($q->tiempo_estimado))
            ->edit("tiempo_real", fn($q) => float_seconds_to_hhmmss_string($q->tiempo_real))
            ->add("proveedor", fn($q) => $this->produccionService->getProveedorTarea($q->id))
            ->edit("maquina_tarea", fn($q) => ["id" => $q->id, "maquina_id" => $q->maquina_tarea, "maquina_name" => $q->maquina_nombre])
            ->add("imposicion", fn($q) => ["id" => $q->id, "imposicion_id" => $q->imposicion_id, "name" => $q->imposicion_name, "is_presupuesto_linea" => $q->presupuesto_linea_id ? true : false])
            ->toJson(true);
    }
    public function get_pdf($orden_trabajo_id)
    {
        return $this->produccionService->init($orden_trabajo_id)->getPdf();
    }
    public function get_ferro_pdf($orden_trabajo_id)
    {
        return $this->produccionService->init($orden_trabajo_id)->getFerroPdf();
    }
    public function get_prototipo_pdf($orden_trabajo_id)
    {
        return $this->produccionService->init($orden_trabajo_id)->getPrototipoPdf();
    }
    public function upload_orden_trabajo_portada()
    {
        try {
            $file = $this->request->getFile("portada_file");
            $bodyData = $this->request->getPost();
            $id = $bodyData["orden_trabajo_id"];
            $r = null;
            $fullpath = null;
            if ($file->isValid() && !$file->hasMoved()) {
                $fullpath = $file->store('ordenes_trabajo_portadas');
                $otEntity = $this->otModel->find($id);
                if ($otEntity->portada_path) {
                    if (file_exists($otEntity->full_path)) {
                        unlink($otEntity->full_path);
                    }
                }
                $r = $this->otModel->update($id, ["portada_path" => $fullpath]);
            }
            return $this->response->setJSON(["message" => "Portada subida", "data" => $r]);
        } catch (\Throwable $th) {
            if ($fullpath) {
                delete_files($fullpath);
            }
            return $this->response->setJSON(["message" => "Portada error", "error" => $th->getMessage()])->setStatusCode(500);
        }
    }
    public function delete_orden_trabajo_portada($orden_trabajo_id)
    {
        try {
            helper('filesystem');
            $otEntity = $this->otModel->find($orden_trabajo_id);
            $pathActualFile = $otEntity->portada_path;
            $fullPath = WRITEPATH . 'uploads/' . $pathActualFile;
            if (file_exists($fullPath)) {
                delete_files($fullPath);
            }
            $r = $this->otModel->update($otEntity->id, ["portada_path" => null]);
            return $this->response->setJSON(["message" => "Portada eliminada", "data" => $r]);
        } catch (\Throwable $th) {
            return $this->response->setStatusCode(500)->setJSON(["message" => "Portada error", "error" => $th->getMessage()]);
        }
    }
    public function get_portada_img($orden_trabajo_id)
    {
        try {
            $ot = $this->otModel->find($orden_trabajo_id);
            if ($ot->portada_path) {
                $filePath = $ot->full_path;
                if (file_exists($filePath)) {

                    $mimeType = mime_content_type($filePath);
                    return $this->response
                        ->setHeader('Content-Type', $mimeType)
                        ->setHeader('Content-Length', filesize($filePath))
                        ->setBody(file_get_contents($filePath));
                } else {
                    throw new Exception('File' . $ot->portada_path . ' does not exist');
                }
            } else {
                return $this->response->setJSON(["message" => "Portada error", "error" => "No hay portada"])->setStatusCode(400);
            }
        } catch (\Throwable $th) {
            return $this->response->setJSON(["message" => "Portada error", "error" => $th->getMessage()])->setStatusCode(500);
        }
    }
    public function planning_rotativa_datatable()
    {
        $query = $this->produccionService->planningRotativaQueryDatatable();
        return DataTable::of($query)
            ->edit("fecha_entrega_real_at", fn($q) => $q->fecha_entrega_real_at ? Time::createFromFormat("Y-m-d", $q->fecha_entrega_real_at)->format("d/m/Y") : "")
            ->add("metros_check", fn($q) => $q->otId)
            ->add("corte", fn($q) => ["otId" => $q->otId, "tipo_corte" => $this->produccionService->ordenTrabajoTareaCorte($q->otId)])
            ->add("action", fn($q) => ["data" => $q])
            ->toJson(true);
    }
    public function planning_plana_datatable()
    {
        $query = $this->produccionService->planningPlanaQueryDatatable();
        $padreId = $this->request->getGet('padre_id');
        if ($padreId) {
            $query->where('lg_maquinas.padre_id', $padreId);
        }
        return DataTable::of($query)
            ->edit("tiempo_real_sum", fn($q) => $q->tiempo_real_sum)
            ->edit("fecha_entrega_real_at", fn($q) => $q->fecha_entrega_real_at ? Time::createFromFormat("Y-m-d", $q->fecha_entrega_real_at)->format("d/m/Y") : "")
            ->add("pliegos_check", fn($q) => $q->otId)
            ->add("action", fn($q) => ["data" => $q])
            ->toJson(true);
    }
    public function select_maquina_planning_rot()
    {
        $q = $this->request->getGet('q');
        $result = $this->produccionService->querySelectMaquinaPlanningRotativa($q);
        return $this->response->setJSON($result);
    }
    public function select_papel_planning_rot()
    {
        $q = $this->request->getGet('q');
        $result = $this->produccionService->querySelectPapelPlanningRot($q);
        return $this->response->setJSON($result);
    }
    public function select_maquina_planning_plana()
    {
        $q = $this->request->getGet('q');
        $result = $this->produccionService->querySelectMaquinaPlanningPlana($q);
        return $this->response->setJSON($result);
    }
    public function select_maquina_padre_planning_plana()
    {
        $q = $this->request->getGet('q');
        $result = $this->produccionService->querySelectMaquinaPadrePlanningPlana($q);
        return $this->response->setJSON($result);
    }
    public function select_papel_planning_plana()
    {
        $q = $this->request->getGet('q');
        $result = $this->produccionService->querySelectPapelPlanningPlana($q);
        return $this->response->setJSON($result);
    }
    public function tarea_toggle_corte($orden_trabajo_id)
    {
        $status = $this->produccionService->tareaUpdateMaquinaCorte($orden_trabajo_id);
        return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $status]);
    }
    public function get_files()
    {
        $bodyData = $this->request->getPost();
        $files = $this->produccionService->init($bodyData["orden_trabajo_id"])->getOtFiles();
        $response = [];
        foreach ($files as $key => $file) {
            $file_ci4 = new File($file->file_path);
            $response[] = [
                "name" => $file->name,
                "size" => $file_ci4->getSize(),
                "hash" => $file->hash()
            ];
        }
        return json_encode($response);
    }
    public function upload_files()
    {
        try {
            //code...
            $otFiles = [];
            $bodyData = $this->request->getPost();
            $files = $this->request->getFileMultiple('file');
            $ps = $this->produccionService->init($bodyData["orden_trabajo_id"]);
            $existingFiles = json_decode($bodyData["oldFiles"]);
            $ps->deleteOtFiles($existingFiles);
            if ($files) {
                $response = $ps->storeOtFiles($files);
            } else {
                $response = null;
            }
            return $this->response->setJSON([
                "message" => lang("App.global_alert_save_success"),
                "data" => $response,
                "status" => true
            ]);
        } catch (\Throwable $th) {
            return $this->response->setJSON(
                [
                    "message" => lang("App.global_alert_save_error"),
                    "data" => $th,
                    "error" => $th->getMessage(),
                    "status" => false
                ]
            );
        }
    }
    public function get_orden_trabajo_color_status(int $orden_trabajo_id)
    {
        $color = $this->produccionService->init($orden_trabajo_id)->getOtColorStatus();
        return $this->response->setJSON(["color" => $color]);
    }
    public function imprimir_codigo_safekat(int $orden_trabajo_id)
    {
        helper('file');
        $barcode = $this->produccionService->init($orden_trabajo_id)->getFileBarCode();
        return $this->response
            ->setHeader('Content-Type', 'image/png')
            ->setHeader('Content-Disposition', "attachment; filename=CodigoBarrasOT_{$orden_trabajo_id}.png")
            ->setBody($barcode);
    }

    public function maquinista_maquinas_view()
    {
        // Breadcrumbs
        $this->viewData['breadcrumb'] = [
            ['title' => lang("Produccion.maquinista.maquinas"), 'route' => route_to("viewProduccionMaquinistaMaquinas"), 'active' => true],
        ];
        $data = [
            "impresion" => $this->maquinaModel->queryViewMaquinistaMaquinas('impresion')->get()->getResultArray(),
            "manipulado" => $this->maquinaModel->queryViewMaquinistaMaquinas('manipulado')->get()->getResultArray(),
            "acabado" => $this->maquinaModel->queryViewMaquinistaMaquinas('acabado')->get()->getResultArray(),
        ];
        $this->viewData["maquinas"] = $data;
        return view(static::$viewPath . '/maquinista/viewMaquinistaMaquinaList', $this->viewData);
    }
    public function maquinista_maquina_tareas_list(int $maquina_id)
    {
        $maquina = $this->maquinaModel->find($maquina_id);
        $this->viewData['breadcrumb'] = [
            ['title' => lang("Produccion.maquinista.maquinas"), 'route' => route_to("viewProduccionMaquinistaMaquinas"), 'active' => false],
            ['title' => $maquina->nombre, 'route' => route_to("viewProduccionMaquinistaMaquina", $maquina_id), 'active' => true],
        ];
        $this->viewData["maquinaEntity"] = $maquina;
        $tareasRunning = $this->maquinaOtTareaModel->queryDatatableJoinOrdenTrabajo($maquina->id)->countAllResults();
        if ($tareasRunning) {
            return view(static::$viewPath . '/maquinista/viewProduccionMaquinistaOtTareasView', $this->viewData);
        } else {
            return view(static::$viewPath . '/maquinista/viewMaquinistaMaquinaTareas', $this->viewData);
        }
    }
    public function maquinista_maquina_tareas_fichaje_automatico(int $maquina_id)
    {
        $maquina = $this->maquinaModel->find($maquina_id);
        $this->viewData["maquinaEntity"] = $maquina;
        return view(static::$viewPath . '/maquinista/viewMaquinistaFichajeAutomatico', $this->viewData);
    }
    public function maquinista_maquina_tareas_scan(int $maquina_id)
    {
        $maquina = $this->maquinaModel->find($maquina_id);
        $this->viewData["maquinaEntity"] = $maquina;
        return view(static::$viewPath . '/maquinista/viewMaquinistaTareaScan', $this->viewData);
    }

    public function maquinista_maquina_tarea_view(int $orden_trabajo_tarea_id)
    {
        $modelImpresoras = model('App\Models\Configuracion\ImpresoraEtiquetaModel');
        $impresoras = $modelImpresoras->select('id, name')
            ->where('deleted_at', null)
            ->where('tipo', 1)
            ->orderBy('name', 'asc')
            ->findAll();
        $impresoras = array_map(fn($impresora) => $impresora->toArray(), $impresoras);
        $otTareaEntity = $this->otTarea->find($orden_trabajo_tarea_id);
        $this->viewData['ot_tarea'] = $otTareaEntity;
        $this->viewData['ot'] = $otTareaEntity->orden_trabajo();
        $this->viewData['presupuesto'] = $this->viewData['ot']->presupuesto();
        
        $this->viewData['impresoras'] = $impresoras;
        $this->viewData['breadcrumb'] = [
            ['title' => lang("Produccion.maquinista.maquinas"), 'route' => route_to("viewProduccionMaquinistaMaquinas"), 'active' => false],
            ['title' => $otTareaEntity->maquina_actual()->nombre, 'route' => route_to("viewProduccionMaquinaTareasList", $otTareaEntity?->maquina_actual()?->id), 'active' => true],
            ['title' => $otTareaEntity->nombre, 'route' => route_to("viewProduccionMaquinistaTareaView", $otTareaEntity->id), 'active' => true]

        ];
        return view(static::$viewPath . '/maquinista/viewMaquinistaMaquinaTarea', $this->viewData);
    }
    public function maquinista_maquina_ot_tareas_view(int $maquina_id)
    {
        $maquinaEntity = $this->maquinaModel->find($maquina_id);
        $this->viewData['maquinaEntity'] = $maquinaEntity;
        $tareasRunning = $this->maquinaOtTareaModel->queryDatatableJoinOrdenTrabajo($maquina_id)->countAllResults();
        if ($tareasRunning) {
            return view(static::$viewPath . '/maquinista/viewProduccionMaquinistaOtTareasView', $this->viewData);
        } else {
            return view(static::$viewPath . '/maquinista/viewMaquinistaMaquinaTareas', $this->viewData);
        }
    }
    public function maquinista_colas_view()
    {
        return view(static::$viewPath . '/maquinista/viewMaquinistaPlanningList', $this->viewData);
    }
    public function maquinista_maquina_tareas_datatable(string $content, int $maquina_id)
    {
        $pm = $this->produccionService->getMaquinaImpresionTareasList($maquina_id);
        if ($content == 'today') {
            $pm->like('pedidos.fecha_impresion', Time::now()->format('Y-m-d'));
        }
        return DataTable::of($pm)
            ->edit('fecha_impresion', fn($q) => $q->fecha_impresion ? Time::createFromFormat('Y-m-d H:i:s', $q->fecha_impresion)->format('d/m/Y') : '')
            ->add("tareaEstado", fn($q) => $this->produccionService->getTitleTareaEstado($q->ot_tarea_id))
            ->add('action', fn($q) => $this->produccionService->buttonActionDatatableTareaList($q->ot_tarea_id))
            ->toJson(true);
    }
    public function maquinista_maquina_tareas_aplazada_datatable(int $maquina_id)
    {
        $pm = $this->produccionService->getMaquinaImpresionTareasList($maquina_id)->where("tarea_progress.estado", 'D');
        return DataTable::of($pm)
            ->edit('fecha_impresion', fn($q) => $q->fecha_impresion ? Time::createFromFormat('Y-m-d H:i:s', $q->fecha_impresion)->format('d/m/Y') : '')
            ->add("tareaEstado", fn($q) => $this->produccionService->getTitleTareaEstado($q->ot_tarea_id))
            ->add('action', fn($q) => $this->produccionService->buttonActionDatatableTareaList($q->ot_tarea_id))
            ->toJson(true);
    }


    public function store_orden_trabajo_progress_date()
    {
        try {
            $bodyData = $this->request->getPost();
            $validated = $this->validation->run($bodyData, "orden_trabajo_tarea_progress_date");
            if ($validated) {
                $validatedData = $this->validation->getValidated();
                $r = $this->produccionService->storeOrdenTrabajoTareaProgressDate($validatedData);
                $otTareaEntity = $this->otTarea->find($validatedData['ot_tarea_id']);
                $data = [
                    "tiempo_trabajado" => float_seconds_to_hhmm_string($otTareaEntity->tiempo_real),
                    "tarea" => $otTareaEntity,
                    "estado" => $validatedData['estado'],
                ];
                return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $r, "data" => $data]);
            } else {
                return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
            }
        } catch (\Throwable $th) {
            return $this->response->setJSON(["status" => false, "error" => $th->getMessage()])->setStatusCode(500);
        }
    }
    public function delete_orden_trabajo_progress_date(int $orden_trabajo_tarea_id)
    {
        $status = $this->produccionService->deleteOrdenTrabajoTareaProgressDates($orden_trabajo_tarea_id);
        return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $status]);
    }
    public function get_orden_trabajo_progress_date(int $orden_trabajo_tarea_id)
    {
        $otTareaEntity = $this->otTarea->find($orden_trabajo_tarea_id);
        $data = [
            "tiempo_trabajado" => float_seconds_to_hhmm_string($otTareaEntity->tiempo_trabajado()),
            "progress_dates" => $otTareaEntity->progress_dates(),
        ];
        return $this->response->setJSON($data);
    }
    public function  update_pod_pedido_dates($orden_trabajo_id)
    {

        $this->produccionService->init($orden_trabajo_id);
        if ($this->produccionService->isPOD) {
            $status = $this->produccionService->updatePodDates();
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => $status, "data" => $this->produccionService->getPedido()]);
        } else {
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => false, "data" => $this->produccionService->getPedido()]);
        }
    }
    public function get_orden_trabajo_tareas_dates($orden_trabajo_id)
    {
        $data = $this->produccionService->init($orden_trabajo_id)->getOrdenTrabajoTareaDates();
        return $this->response->setJSON(["data" => $data]);
    }
    public function get_tareas_ot_maquina(int $orden_trabajo_id, int $maquina_id)
    {
        $tareasWithMaquina = $this->produccionService->init($orden_trabajo_id)->getTareasWithMaquina($maquina_id, ['P', 'I', 'S', 'D']);
        if ($tareasWithMaquina) {
            $data = [
                'tareas' => $tareasWithMaquina,
                'ot' => $this->produccionService->getOrdenTrabajo(),
                'presupuesto' => $this->produccionService->getPresupuesto()
            ];
            return $this->response->setJSON(["message" => lang("App.global_alert_fetch_success"), "data" => $data]);
        } else {
            $tareasWithMaquina = $this->produccionService->init($orden_trabajo_id)->getTareasWithMaquina($maquina_id, ['F']);
            if ($tareasWithMaquina) {
                return $this->response->setJSON(["message" => lang("Produccion.errors.tareas_finalizadas"), "data" => $tareasWithMaquina])->setStatusCode(400);
            } else {
                return $this->response->setJSON(["message" => lang("Produccion.errors.maquina_not_in_ot"), "data" => null])->setStatusCode(400);
            }
        }
    }

    public function update_orden_trabajo_fa_tareas()
    {
        $responseData = [
            "tiempo_total_estimado" => 0,
            "tiempo_total_real" => 0,
            "clicks_total" => 0,
            "tirada_total" => 0,
            "estado" => "P",
        ];
        $bodyData = $this->request->getPost();
        $validated = $this->validation->run($bodyData, "orden_trabajo_fichaje_auto");
        if ($validated) {
            $validatedData = $this->validation->getValidated();
            $this->produccionService->init($validatedData['orden_trabajo_id']);
            foreach ($validatedData['tareas'] as $key => $tareaId) {
                $this->produccionService->storeOrdenTrabajoTareaProgressDate(
                    [
                        'estado' => $validatedData['estado'],
                        'ot_tarea_id' => $tareaId
                    ]
                );
                $tareaEntity = $this->otTarea->find($tareaId);
                $tiempo_trabajado = $tareaEntity->tiempo_trabajado();
                $responseData['tiempo_total_estimado']+=$tareaEntity->tiempo_estimado;
                $responseData['tiempo_total_real']+=$tiempo_trabajado;
                $responseData["estado"] = $validatedData["estado"];
                $tareaEntity->tiempo_real = $tiempo_trabajado / count($validatedData['tareas']);
                $tareaEntity->click_init = $validatedData['click_init'] / count($validatedData['tareas']);
                $tareaEntity->click_end = $validatedData['click_end'] / count($validatedData['tareas']);

                $this->otTarea->save($tareaEntity);
            }
            $responseData['tiempo_total_estimado'] = float_seconds_to_hhmmss_string($responseData['tiempo_total_estimado']);
            $responseData['tiempo_total_real'] = float_seconds_to_hhmmss_string($responseData['tiempo_total_real']);
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => true, "data" => $responseData]);
        } else {
            return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
        }
    }
    public function delete_orden_trabajo_fa_tareas()
    {
        $bodyData = $this->request->getPost();
        $validated = $this->validation->run($bodyData, "orden_trabajo_fichaje_auto");
        if ($validated) {
            $validatedData = $this->validation->getValidated();
            $this->produccionService->init($validatedData['orden_trabajo_id']);
            foreach ($validatedData['tareas'] as $key => $tareaId) {
                $this->produccionService->deleteOrdenTrabajoTareaProgressDates($tareaId);
            }
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => true, "data" => $validatedData]);
        } else {
            return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
        }
    }
    public function store_maquina_ordenes_trabajo()
    {
        $bodyData = $this->request->getPost();
        $validated = $this->validation->run($bodyData, "maquina_ordenes_trabajo");
        if ($validated) {
            $validatedData = $this->validation->getValidated();

            foreach ($validatedData['ordenes_trabajo'] as $key => $orden_trabajo_id) {
                $maquinaOtTarea = $this->maquinaOtTareaModel->where('orden_trabajo_id', $orden_trabajo_id)->where('maquina_id', $validatedData['maquina_id'])->where('deleted_at',null)->countAllResults();
                if ($maquinaOtTarea) {
                    continue;
                }
                $this->maquinaOtTareaModel->insert(['maquina_id' => $validatedData['maquina_id'], 'orden_trabajo_id' => $orden_trabajo_id]);
            }
            return $this->response->setJSON(["message" => lang("App.global_alert_save_success"), "status" => true, "data" => $validatedData]);
        } else {
            return $this->response->setJSON(["errors" => $this->validation->getErrors()])->setStatusCode(400);
        }
    }
    public function update_maquina_ordenes_trabajo_estado()
    {
        $bodyData = $this->request->getPost();
        $maquina_id = $bodyData['maquina_id'];
        $estado = $bodyData['estado'];
        $maquina_ots = $this->maquinaOtTareaModel->where('maquina_id', $maquina_id)->findAll();
        $totalTareas = [];

        foreach ($maquina_ots as $key => $maquina_ot) {
            $tareas = $this->produccionService->init($maquina_ot->orden_trabajo_id)
                ->getTareasWithMaquina($maquina_id, ['P', 'I', 'S', 'D']);
            foreach ($tareas as $key => $tarea) {
                $this->produccionService->storeOrdenTrabajoTareaProgressDate(
                    [
                        'estado' => $estado,
                        'ot_tarea_id' => $tarea->id
                    ]
                );
                $tarea->click_init = $bodyData['click_init'];
                $tarea->click_end = $bodyData['click_end'];
                $totalTareas[] = $tarea;

            }
            
        }
        foreach ($totalTareas as $key => $tarea) {
                $tiempo_trabajado = $tarea->tiempo_trabajado();
                $tarea->tiempo_real = $tiempo_trabajado / count($totalTareas);
                $tarea->click_init = $tarea->click_init / count($totalTareas);
                $tarea->click_end = $tarea->click_end / count($totalTareas);

                $this->otTarea->save($tarea);
        }
        if ($estado == "F") {
            $this->maquinaOtTareaModel->where('maquina_id', $maquina_id)->delete();
        }

        return $this->response->setJSON(["message" => lang("Produccion.responses.update_maquina_ordenes_trabajo_estado")]);
    }
    public function delete_maquina_orden_trabajo_tarea($maquina_orden_trabajo_tarea_id)
    {
        
        $status = $this->maquinaOtTareaModel->delete($maquina_orden_trabajo_tarea_id);
        return $this->response->setJSON(["message" => lang("App.user_alert_delete"), "status" => $status]);
    }
    public function delete_maquina_orden_trabajo_all($maquina_id)
    {
        $maquina_ots = $this->maquinaOtTareaModel->where('maquina_id', $maquina_id)->findAll();
        foreach ($maquina_ots as $key => $maquina_ot) {
            $tareas = $this->produccionService->init($maquina_ot->orden_trabajo_id)
                ->getTareasWithMaquina($maquina_id, ['P', 'I', 'S', 'D']);
            foreach ($tareas as $key => $tarea) {
                $this->produccionService->deleteOrdenTrabajoTareaProgressDates($tarea->id);
            }
        }
        $status = $this->maquinaOtTareaModel->where('maquina_id',$maquina_id)->delete();
        return $this->response->setJSON(["message" => lang("App.user_alert_delete"), "status" => $status]);
    }

    public function datatable_maquina_ordenes_trabajo($maquina_id)
    {
        $query = $this->maquinaOtTareaModel->queryDatatableJoinOrdenTrabajo($maquina_id);
        return DataTable::of($query)
            ->add('action', fn($q) => $q->otId)
            ->add('titulo', fn($q) => $this->otModel->find($q->otId)->presupuesto()->titulo)
            ->add('barcode', fn($q) => $this->otModel->find($q->otId)->getBarCode())
            ->toJson(true);
    }
    public function get_maquina_ots($maquina_id)
    {
        $responseData = [
            "tiempo_total_estimado" => 0,
            "tiempo_total_real" => 0,
            "clicks_total" => 0,
            "tirada_total" => 0,
            "estado" => "P",
        ];
        $maquina_ots = $this->maquinaOtTareaModel->where('maquina_id', $maquina_id)->findAll();
        foreach ($maquina_ots as $key => $maquina_ot) {
            $tareas = $this->produccionService->init($maquina_ot->orden_trabajo_id)
                ->getTareasWithMaquina($maquina_id, ['P', 'I', 'S', 'D']);
            foreach ($tareas as $key => $tarea) {
                $responseData['tiempo_total_estimado']+= $tarea->tiempo_estimado;
                $responseData['tiempo_total_real']+= $tarea->tiempo_real;
                $responseData["estado"] = $tarea->lastState()->estado;
                if($tarea->presupuesto_linea_id){
                    $responseData["clicks_total"] += $tarea->presupuesto_linea()->rotativa_clicks_total;
                    $responseData["tirada_total"] += $tarea->orden_trabajo()->presupuesto()->tirada;

                }
            }
        }
        $responseData['tiempo_total_estimado'] = float_seconds_to_hhmmss_string($responseData['tiempo_total_estimado']);
        $responseData['tiempo_total_real'] = float_seconds_to_hhmmss_string($responseData['tiempo_total_real']);
        return $this->response->setJSON($responseData);

    }

    public function printPackagingLabels(){

        $ot_id = $this->request->getPost('ot_id') ?? null;
        $unidades_caja = $this->request->getPost('unidades_caja') ?? null;
        $impresora_id = $this->request->getPost('impresora_id') ?? null;

        if ($ot_id == null || $impresora_id == null) {
            return [
                'status' => false,
                'message' => lang('Logistica.errors.errorMissingData')
            ];
        }

        $modelImpresora = model('App\Models\Configuracion\ImpresoraEtiquetaModel');
        $impresora = $modelImpresora->select('id, name, ip, port, user, pass')
            ->where('deleted_at', null)
            ->where('id', $impresora_id)
            ->orderBy('name', 'asc')
            ->first();
        if ($impresora == null) {
            return $this->response->setJSON([
                'status' => false,
                'message' => 'Impresora no válida'
            ]);
        }

        $printerService = new ImpresoraEtiquetaService();
        $result = $printerService->generateEtiquetasEmbalaje($ot_id, $unidades_caja, $impresora);

        return $this->response->setJSON($result);
    }
}
