<?php

namespace App\Controladores;

use App\Modelos\EmpleadoAlmacen;
use App\Modelos\Stock;
use App\Modelos\StockTransferencia;
use App\Modelos\StockTransferenciaDetalle;
use Core\Controller;
use Core\Helpers\Notifica;
use Core\Librerias\Http;
use Core\Librerias\Module;
use Core\Vista;
use App\Modelos\BitacoraStock;

final class StockControlador extends Controller
{
    private $module;
    private $stock_model;
    private $array_errors = [];

    public function __construct()
    {
        parent::__construct();
        $this->module = new Module('productos');
        $this->stock_model = new Stock();
    }

    public function obtenerProductos(int $id_almacen)
    {
        if ('GET' === $_SERVER['REQUEST_METHOD'] && isAjax()) {

            $array_productos = [];
            $id_almacen = filter_var($id_almacen, FILTER_SANITIZE_NUMBER_INT);
            $productos = $this->stock_model->obtenerProductosSegunAlmacen($id_almacen);

            foreach ($productos as $row) {
                $array_productos[] = [
                    'pro_id' => $row['pro_id'],
                    'pro_descripcion' => '(' . $row['pro_codigo'] . ') - ' . $row['pro_descripcion']
                ];
            }

            Http::json_response($array_productos);
        }
    }

    public function guardar()
    {
        if ('POST' === $_SERVER['REQUEST_METHOD'] && isAjax()) {

            $id             = filter_input(INPUT_POST, 'id', FILTER_SANITIZE_NUMBER_INT);
            $ps_proid       = filter_input(INPUT_POST, 'id_producto', FILTER_SANITIZE_NUMBER_INT);
            $ps_almid       = filter_input(INPUT_POST, 'almacen', FILTER_SANITIZE_NUMBER_INT);
            $ps_stockmin    = filter_input(INPUT_POST, 'min', FILTER_SANITIZE_NUMBER_INT) ?? 0;
            $ps_stockmax    = filter_input(INPUT_POST, 'max', FILTER_SANITIZE_NUMBER_INT) ?? 0;
            $ps_cantidad    = filter_input(INPUT_POST, 'cantidad');

            if (empty($ps_almid))
                $this->array_errors[] = 'El campo Almacen es obligatorio.';
            if (empty($ps_stockmax))
                $this->array_errors[] = 'El campo Stock max. es obligatorio.';
            if ($ps_stockmin >= $ps_stockmax) {
                $this->array_errors[] = 'El campo Stock min no puede ser mayor o igual que Stock max.';
            }

            $ps_cantidad = convertir_a_float($ps_cantidad);

            if (empty($this->array_errors)) {

                $data_form = [
                    'ps_cantidad'   => $ps_cantidad,
                    'ps_almid'      => $ps_almid,
                    'ps_disponible' => $ps_cantidad,
                    'ps_proid'      => $ps_proid,
                    'ps_stockmax'   => $ps_stockmax,
                    'ps_stockmin'   => $ps_stockmin
                ];

                $almacen = $this->stock_model->consultar("SELECT * FROM app_almacenes WHERE alm_id = $ps_almid AND alm_garantia=0")->row();

                if (!empty($_POST['id'])) {
                    if ($this->module->has_module_action_permission('productos', 'editar_inventario', $_SESSION['user_data']['emp_id'])) {
                        $datos_antiguos = $this->stock_model->consultar("SELECT * FROM app_productos_stocks WHERE ps_almid = $ps_almid AND ps_proid = $ps_proid")->row();
                        if ($this->stock_model->editar($id, $data_form)) {
                            if ($ps_cantidad > $datos_antiguos['ps_cantidad']) {
                                Notifica::stock($ps_proid, "{$almacen['alm_nombre']}", 'stock', $datos_antiguos['ps_cantidad'], $ps_cantidad - $datos_antiguos['ps_cantidad'], 0, $ps_cantidad);
                            } else {
                                Notifica::stock($ps_proid, "{$almacen['alm_nombre']}", 'stock', $datos_antiguos['ps_cantidad'], 0, $datos_antiguos['ps_cantidad'] - $ps_cantidad, $ps_cantidad);
                            }
                            Notifica::producto(4, $ps_proid, "Ha <strong>modificado</strong> el stock del producto en el almacen <strong>{$almacen['alm_nombre']}</strong> con <strong>cantidad:</strong> $ps_cantidad, <strong>stock min:</strong> $ps_stockmin <strong>stock max:</strong> $ps_stockmax");
                            Http::json_response(true);
                        } else {
                            Http::json_response(false);
                        }
                    } else {
                        $this->array_errors[] = 'Acceso prohibido no posee permisos para modificar stock';
                    }
                } else {
                    if ($this->module->has_module_action_permission('productos', 'cargar_inventario', $_SESSION['user_data']['emp_id'])) {

                        if ($this->stock_model->where([
                            'ps_almid' => $ps_almid,
                            'ps_proid' => $ps_proid
                        ])) {
                            $this->array_errors[] = 'Acción prohibida';
                        }

                        if (empty($this->array_errors)) {
                            if ($this->stock_model->guardar($data_form, true)) {
                                Notifica::stock($ps_proid, "{$almacen['alm_nombre']}", 'stock', '0', $ps_cantidad, 0, $ps_cantidad);
                                Notifica::producto(4, $ps_proid, "Ha <strong>creado</strong> el stock del producto en el almacen <strong>{$almacen['alm_nombre']}</strong> con <strong>cantidad:</strong> $ps_cantidad, <strong>stock min:</strong> $ps_stockmin <strong>stock max:</strong> $ps_stockmax");
                                Http::json_response(true);
                            } else {
                                Http::json_response(false);
                            }
                        }
                    } else {
                        $this->array_errors[] = 'Acceso prohibido no posee permisos para cargar en stock.';
                    }
                }
            }

            Http::json_response(['errors' => $this->array_errors]);
        }
    }

    public function transferencia_stock()
    {
        $empleado_almacen_model = new EmpleadoAlmacen();
        return Vista::view('stock/stock_transferencia', [
            'almacenes_origen' => $empleado_almacen_model->obtenerAlmacenes($_SESSION['user_data']['emp_id']),
            'almacenes' => $this->stock_model->obtenerAlmacenes(),
        ]);
    }

    public function guardar_transferencia()
    {
        if ('POST' === $_SERVER['REQUEST_METHOD'] && isAjax()) {

            $ptr_id             = filter_input(INPUT_POST, 'ptr_id', FILTER_SANITIZE_NUMBER_INT);
            $ptr_almorigid      = filter_input(INPUT_POST, 'alm_origen', FILTER_SANITIZE_NUMBER_INT);
            $ptr_almdestid      = filter_input(INPUT_POST, 'alm_destino', FILTER_SANITIZE_NUMBER_INT);
            $ptr_observacion    = filter_input(INPUT_POST, 'observaciones', FILTER_SANITIZE_STRING);
            $producto           = filter_input(INPUT_POST, 'producto', FILTER_SANITIZE_NUMBER_INT);
            $cantidad           = filter_input(INPUT_POST, 'cantidad', FILTER_SANITIZE_NUMBER_INT);

            if (empty($ptr_almorigid))
                $this->array_errors[] = 'El campo Almacen origen es obligatorio.';
            if (empty($ptr_almdestid))
                $this->array_errors[] = 'El campo Almacen destino es obligatorio.';
            if (empty($producto))
                $this->array_errors[] = 'El campo Producto es obligatorio.';
            if (empty($cantidad))
                $this->array_errors[] = 'El campo Cantidad es obligatorio.';

            if (empty($this->array_errors)) {

                if ($ptr_almorigid === $ptr_almdestid) {
                    $this->array_errors[] = 'El almacen de destino no puede ser igual al almacen de origen.';
                } else {

                    $existencia_o = $this->stock_model->where(['ps_almid' => $ptr_almorigid, 'ps_proid' => $producto], true);

                    if ($existencia_o['ps_cantidad'] < $cantidad)
                        $this->array_errors[] = 'La cantidad a transferir es mayor a la cantidad en el stock, solo hay en existencia' . $existencia_o['ps_cantidad'];

                    if (empty($this->array_errors)) {

                        $newStockTransferencia = new StockTransferencia();

                        $data_form = [
                            'ptr_almdestid'   => $ptr_almdestid,
                            'ptr_almorigid'   => $ptr_almorigid,
                            'ptr_observacion' => $ptr_observacion,
                            'ptr_einfoid'     => $_SESSION['user_data']['einfo_id'],
                        ];

                        try {

                            $newStockTransferencia->transactionBegin();

                            if (!empty($ptr_id)) {
                                if (!$newStockTransferencia->existe('ptr_id', $ptr_id)) {
                                    $this->array_errors[] = 'Acción prohibida';
                                } else {
                                    $newStockTransferencia->editar($ptr_id, $data_form);
                                }
                            } else {
                                $ptr_id = $newStockTransferencia->guardar($data_form);
                            }

                            if ($ptr_id && empty($this->array_errors)) {

                                $existe  = $newStockTransferencia->consultar("SELECT ptd_id FROM app_productos_transferencia_detalle WHERE ptd_proid = $producto AND ptd_ptrid = $ptr_id")->row();

                                if ($existe) {
                                    $newStockTransferencia->editar($existe['ptd_id'], [
                                        'ptd_cantidad' => $cantidad
                                    ], 'app_productos_transferencia_detalle', 'ptd_id');
                                } else {
                                    $newStockTransferencia->guardar([
                                        'ptd_proid'     => $producto,
                                        'ptd_cantidad'  => $cantidad,
                                        'ptd_ptrid'     => $ptr_id
                                    ], true, 'app_productos_transferencia_detalle');
                                }
                            }

                            $newStockTransferencia->transactionCommit();
                        } catch (\Throwable $th) {
                            $newStockTransferencia->transactionRollBack();
                            $this->array_errors[] = $th;
                        }

                        if (empty($this->array_errors)) {
                            Http::json_response($ptr_id);
                        }
                    }
                }
            }

            Http::json_response(['errors' => $this->array_errors]);
        }
    }

    public function obtenerDetalleTransferencia(int $ptr_id)
    {
        if ('GET' === $_SERVER['REQUEST_METHOD'] && isAjax()) {
            $ptr_id = filter_var($ptr_id, FILTER_SANITIZE_NUMBER_INT);
            $transferencia_producto         = new StockTransferencia();
            $transferencia_producto_detalle = new StockTransferenciaDetalle();
            Http::json_response([
                'transferencia_detalle'          => $transferencia_producto->obtenerDetalleTransferencia($ptr_id),
                'transferencia_producto_detalle' => $transferencia_producto_detalle->obtenerProductosTransferencia($ptr_id),
            ]);
        }
    }

    public function procesarTransferencia(int $ptr_id)
    {
        if ('GET' === $_SERVER['REQUEST_METHOD'] && isAjax()) {

            $ptr_id = filter_var($ptr_id, FILTER_SANITIZE_NUMBER_INT);

            $transferencia_producto         = new StockTransferencia();
            $transferencia_producto_detalle = new StockTransferenciaDetalle();
            $bitacora = new BitacoraStock();

            if ($transferencia_producto->existe('ptr_id', $ptr_id)) {

                $almacen    = $transferencia_producto->obtenerProductoTransferencia($ptr_id);
                $productos  = $transferencia_producto_detalle->obtenerProductoTransferenciaDetalle($ptr_id);

                if ($transferencia_producto->editar($ptr_id, [
                    'ptr_estatus' => 1
                ])) {

                    try {

                        $this->stock_model->transactionBegin();

                        foreach ($productos as $row) {

                            $existencia_o = $this->stock_model->where(['ps_almid' => $almacen['ptr_almorigid'], 'ps_proid' => $row['ptd_proid']], true);

                            if ($existencia_o['ps_cantidad'] < $row['ptd_cantidad']) {
                                $this->array_errors[] = 'Lo siento no cuenta con suficiente cantidad en stock para realizar la transferencia';
                            }

                            if (empty($this->array_errors)) {

                                $almacen_o = $this->stock_model->consultar("SELECT * FROM app_almacenes WHERE alm_id = {$almacen['ptr_almorigid']}")->row();

                                $existencia_d = $this->stock_model->where(['ps_almid' => $almacen['ptr_almdestid'], 'ps_proid' => $row['ptd_proid']], true);

                                /*if (!$existencia_d) {
                                    $this->stock_model->consultar("INSERT INTO app_productos_stocks (ps_proid, ps_almid, ps_pterecibir) 
                                    VALUES ({$row['ptd_proid']}, {$almacen['ptr_almdestid']}, {$row['ptd_cantidad']})")->run();
                                }
                                */
                                $this->stock_model->consultar("UPDATE app_productos_stocks SET 
                                ps_cantidad = ps_cantidad - {$row['ptd_cantidad']}, 
                                ps_reservada = ps_reservada + {$row['ptd_cantidad']}
                                WHERE ps_proid = {$row['ptd_proid']} AND ps_almid={$almacen['ptr_almorigid']}")->run();

                                if ($existencia_d) {
                                    $this->stock_model->consultar("UPDATE app_productos_stocks SET 
    ps_pterecibir = ps_pterecibir + {$row['ptd_cantidad']} 
    WHERE ps_proid = {$row['ptd_proid']} AND ps_almid={$almacen['ptr_almdestid']}")->run();
                                } else {
                                    $this->stock_model->consultar("INSERT INTO app_productos_stocks (ps_proid, ps_almid, ps_pterecibir) 
    VALUES ({$row['ptd_proid']}, {$almacen['ptr_almdestid']}, {$row['ptd_cantidad']})")->run();
                                }

                                $bitacora->guardar([
                                    'bsp_proid'     => $row['ptd_proid'],
                                    'bsp_almacen'   => $almacen_o['alm_nombre'],
                                    'bsp_modulo'    => 'Transferencia Stock',
                                    'bsp_empleado'  => $_SESSION['user_data']['einfo_nombres'] . ' ' . $_SESSION['user_data']['einfo_apellidos'],
                                    'bsp_habia'     => $existencia_o['ps_cantidad'] ?? 0,
                                    'bsp_sube'      => 0,
                                    'bsp_baja'      => $row['ptd_cantidad'],
                                    'bsp_total'     => ($existencia_o['ps_cantidad']  ?? 0) - $row['ptd_cantidad'],
                                ], true);
                            }
                        }

                        $this->stock_model->transactionCommit();
                    } catch (\Throwable $th) {
                        $this->stock_model->transactionRollBack();
                        $this->array_errors[] = $th;
                    }
                }
            } else {
                $this->array_errors[] = 'No existe la';
            }

            if (empty($this->array_errors)) {
                Http::json_response(true);
            } else {
                Http::json_response(['errors' => $this->array_errors]);
            }
        }
    }

    public function detalle_transferencia(int $ptr_id)
    {
        $ptr_id = filter_var($ptr_id, FILTER_SANITIZE_NUMBER_INT);

        $transferencia_producto         = new StockTransferencia();
        $transferencia_producto_detalle = new StockTransferenciaDetalle();

        if (empty($ptr_id) || !is_numeric($ptr_id)) {
            Http::notFound();
        } else if (!$transferencia_producto->existe('ptr_id', $ptr_id)) {
            Http::exit_by_forbiden();
        }

        return Vista::view('stock/paginas/stock_detalle_transferencia', [
            'ptr_id' => $ptr_id,
            'transferencia_detalle'          => $transferencia_producto->obtenerDetalleTransferencia($ptr_id),
            'transferencia_producto_detalle' => $transferencia_producto_detalle->obtenerProductosTransferencia($ptr_id),
        ]);
    }

    public function aprobarTransferencia(int $ptr_id)
    {
        if ('GET' === $_SERVER['REQUEST_METHOD'] && isAjax()) {

            $ptr_id = filter_var($ptr_id, FILTER_SANITIZE_NUMBER_INT);

            $empleado_almacen_model = new EmpleadoAlmacen();
            $transferencia_producto         = new StockTransferencia();
            $transferencia_producto_detalle = new StockTransferenciaDetalle();

            $almacen   = $transferencia_producto->obtenerProductoTransferencia($ptr_id);
            $productos = $transferencia_producto_detalle->obtenerProductoTransferenciaDetalle($ptr_id);

            if ($almacen['ptr_estatus'] == 1) {

                try {

                    $this->stock_model->transactionBegin();

                    foreach ($productos as $row) {

                        $almacen_emp = $empleado_almacen_model->existeAlmacen($_SESSION['user_data']['emp_id'], $almacen['ptr_almdestid']);
                        if ($almacen_emp) {
                            $almacen_d = $this->stock_model->consultar("SELECT * FROM app_almacenes WHERE alm_id = {$almacen['ptr_almdestid']}")->row();
                            $existencia_d  = $this->stock_model->consultar("SELECT * FROM app_productos_stocks WHERE ps_proid = {$row['ptd_proid']} AND ps_almid = {$almacen['ptr_almdestid']}")->row();

                            $this->stock_model->consultar("UPDATE app_productos_stocks SET 
                            ps_reservada = ps_reservada - {$row['ptd_cantidad']}
                            WHERE ps_proid = {$row['ptd_proid']} AND ps_almid={$almacen['ptr_almorigid']}")->run();

                            $this->stock_model->consultar("UPDATE app_productos_stocks SET 
                            ps_cantidad = ps_cantidad + {$row['ptd_cantidad']}, 
                            ps_pterecibir = 0 
                            WHERE ps_proid = {$row['ptd_proid']} AND ps_almid={$almacen['ptr_almdestid']}")->run();
                            $bitacora = new BitacoraStock();
                            $bitacora->guardar([
                                'bsp_proid'     => $row['ptd_proid'],
                                'bsp_almacen'   => $almacen_d['alm_nombre'],
                                'bsp_modulo'    => 'Transferencia Stock',
                                'bsp_empleado'  => $_SESSION['user_data']['einfo_nombres'] . ' ' . $_SESSION['user_data']['einfo_apellidos'],
                                'bsp_habia'     => $existencia_d['ps_cantidad'] ?? 0,
                                'bsp_sube'      => $row['ptd_cantidad'],
                                'bsp_baja'      => 0,
                                'bsp_total'     => ($existencia_d['ps_cantidad'] ?? 0) + $row['ptd_cantidad'],
                            ], true, 'app_bitacora_stock_producto');
                        } else {
                            $this->array_errors[] = 'Usted no tiene permiso para hacer cambios en este almacen';
                        }
                    }

                    $this->stock_model->transactionCommit();
                } catch (\Throwable $th) {
                    $this->stock_model->transactionRollBack();
                    $this->array_errors[] = $th;
                }

                if (empty($this->array_errors)) {
                    Http::json_response($transferencia_producto->editar($ptr_id, [
                        'ptr_estatus' => 2
                    ]));
                }
            } else {
                $this->array_errors[] = 'Acción prohibida';
            }

            Http::json_response(['errors' => $this->array_errors]);
        }
    }

    public function negarTransferencia(int $ptr_id)
    {
        if ('GET' === $_SERVER['REQUEST_METHOD'] && isAjax()) {

            $ptr_id = filter_var($ptr_id, FILTER_SANITIZE_NUMBER_INT);

            $transferencia_producto         = new StockTransferencia();
            $transferencia_producto_detalle = new StockTransferenciaDetalle();

            $almacen   = $transferencia_producto->obtenerProductoTransferencia($ptr_id);
            $productos = $transferencia_producto_detalle->obtenerProductoTransferenciaDetalle($ptr_id);

            if ($almacen['ptr_estatus'] == 1) {

                try {

                    $this->stock_model->transactionBegin();

                    foreach ($productos as $row) {

                        $almacen_o = $this->stock_model->consultar("SELECT * FROM app_almacenes WHERE alm_id = {$almacen['ptr_almorigid']}")->row();
                        $existencia_o  = $this->stock_model->consultar("SELECT * FROM app_productos_stocks WHERE ps_proid = {$row['ptd_proid']} AND ps_almid = {$almacen['ptr_almorigid']}")->row();

                        $this->stock_model->consultar("UPDATE app_productos_stocks SET 
                        ps_cantidad = ps_cantidad + {$row['ptd_cantidad']}, 
                        ps_reservada = ps_reservada - {$row['ptd_cantidad']} 
                        WHERE ps_proid = {$row['ptd_proid']} AND ps_almid={$almacen['ptr_almorigid']}")->run();

                        $this->stock_model->consultar("UPDATE app_productos_stocks SET 
                        ps_pterecibir = ps_pterecibir - {$row['ptd_cantidad']} 
                        WHERE ps_proid = {$row['ptd_proid']} AND ps_almid={$almacen['ptr_almdestid']}")->run();

                        $this->stock_model->guardar([
                            'bsp_proid'     => $row['ptd_proid'],
                            'bsp_almacen'   => $almacen_o['alm_nombre'],
                            'bsp_modulo'    => 'Transferencia Stock',
                            'bsp_empleado'  => $_SESSION['user_data']['einfo_nombres'] . ' ' . $_SESSION['user_data']['einfo_apellidos'],
                            'bsp_habia'     => $existencia_o['ps_cantidad'] ?? 0,
                            'bsp_sube'      => $row['ptd_cantidad'],
                            'bsp_baja'      => 0,
                            'bsp_total'     => ($existencia_o['ps_cantidad'] ?? 0) + $row['ptd_cantidad'],
                        ], true, 'app_bitacora_stock_producto');
                    }

                    $this->stock_model->transactionCommit();
                } catch (\Throwable $th) {
                    $this->stock_model->transactionRollBack();
                    $this->array_errors[] = 'Error en transacción';
                }

                if (empty($this->array_errors)) {
                    Http::json_response($transferencia_producto->editar($ptr_id, [
                        'ptr_estatus' => 3
                    ]));
                }
            } else {
                $this->array_errors[] = 'Acción prohibida';
            }

            Http::json_response(['errors' => $this->array_errors]);
        }
    }
}
