<?php

class cajaModel {

    // Variables privadas de la clase que se utilizan para armar los arrays de caja

    private string $ventaKey = 'productosVenta';
    private string $pedidoKey = 'productosPedido';
    private string $servicioKey = 'insumosServicio';
    private ?string $error = null;

    public function __construct() {
        
        // Si no estan seteados, se crean los arrays vacios (para luego trabajar con los métodos)

        if (!isset($_SESSION[$this->ventaKey])) {
            $_SESSION[$this->ventaKey] = [];
        }

        if (!isset($_SESSION[$this->pedidoKey])) {
            $_SESSION[$this->pedidoKey] = [];
        }

        if (!isset($_SESSION[$this->servicioKey])) {
            $_SESSION[$this->servicioKey] = [];
        }
    }

    // MÉTODO PARA OBTENER ERRORES Y MANEJARLOS EN CONTROLLER

    public function getError(): ?string {
        return $this->error;
    }

    // <---------------------------------- MANEJO DE CAJA PARA VENTA ---------------------------------->

    // AGREGAR PRODUCTO

    public function agregarProducto(array $producto, int $cantidad): bool {

        if ($cantidad <= 0 || empty($producto['id'])) {
            $this->error = 'Datos inválidos del producto.';
            return false;
        }

        $id = $producto['id'];
        $stockDisponible = $producto['stock'];

        // Si el producto ya se encuentra agregado

        if (isset($_SESSION[$this->ventaKey][$id])) {

            if ($cantidad > $stockDisponible) {
                $this->error = 'La cantidad supera el stock disponible.';
                return false;
            }

            $_SESSION[$this->ventaKey][$id]['cantidad'] = $cantidad;
            return true;
        }

        // Si aún no existe en el array continua la ejecución

        if ($cantidad > $stockDisponible) {
            $this->error = 'La cantidad supera el stock disponible.';
            return false;
        }

        // Cálculos

        $descuentoTotal = $producto['descuento_producto'] + $producto['descuento_categoria'];

        $precioFinal = ((100 - $descuentoTotal) * $producto['precio'] / 100); // PRECIO UNITARIO MENOS EL DESCUENTO

        // Se guardan los datos en el array

        $_SESSION[$this->ventaKey][$id] = [
            'id_producto' => $id,
            'marca' => $producto['marca'],
            'modelo' => $producto['modelo'],
            'precio' => $producto['precio'],
            'descuento_total' => $descuentoTotal,
            'cantidad' => $cantidad,
            'stock' => $producto['stock'],
            'precio_final' => $precioFinal
        ];

        return true;
    }   

    // ELIMINAR PRODUCTO

    public function eliminarProducto(int $id): bool {

        if (!isset($_SESSION[$this->ventaKey][$id])) {
            $this->error = 'El producto no existe en la caja.';
            return false;
        } else{
            unset($_SESSION[$this->ventaKey][$id]);
        }

        return true;
    }

    // EDITAR CANTIDAD DE PRODUCTO

    public function editarCantidad(int $id, int $nuevaCantidad): bool {

        if (!isset($_SESSION[$this->ventaKey][$id])) {
            $this->error = 'Producto inexistente en la caja.';
            return false;
        }

        if ($nuevaCantidad <= 0) {
            $this->error = 'La cantidad debe ser mayor a cero.';
            return false;
        }

        if ($nuevaCantidad > $_SESSION[$this->ventaKey][$id]['stock']) {
            $this->error = 'La cantidad supera el stock disponible.';
            return false;
        }

        $_SESSION[$this->ventaKey][$id]['cantidad'] = $nuevaCantidad;
        return true;
    }

    // LISTAR PRODUCTOS

    public function listarProductos(): array {
        return $_SESSION[$this->ventaKey];
    }

    // CALCULAR SUBTOTAL

    public function calcularSubtotal(): float {

        $total = 0;

        foreach ($_SESSION[$this->ventaKey] as $item) {
            
            $precio = (float) $item['precio'];

            $total += $precio * $item['cantidad'];
        }

        return round($total, 2);
    }

    // CALCULAR PRECIO TOTAL

    public function calcularPrecioTotal(): float {

        $total = 0;

        foreach ($_SESSION[$this->ventaKey] as $item) {
            
            $precio = (float) $item['precio'];

            if (!empty($item['descuento_total'])) {
                $precio -= ($item['descuento_total'] * $precio / 100);
            }

            $total += $precio * $item['cantidad'];
        }

        return round($total, 2);
    }

    // CALCULAR DESCUENTO TOTAL

    public function calcularDescuentoTotal(): float {

        $total = 0;

        foreach ($_SESSION[$this->ventaKey] as $item) {
            
            $precio = (float) $item['precio'];
            $descuento = 0;

            if (!empty($item['descuento_total'])) {
                $descuento += ($item['descuento_total'] * $precio / 100);
            }

            $total += $descuento * $item['cantidad'];
        }

        return round($total, 2);
    }

    // VACIAR CAJA DE PRODUCTOS

    public function vaciarCajaVenta(): bool {
        $_SESSION[$this->ventaKey] = [];
        return true;
    }

    // <---------------------------------- MANEJO DE CAJA PARA PEDIDO ---------------------------------->

    // AGREGAR PRODUCTO PARA PEDIDO

    public function agregarProductoPedido(array $producto, float $costo, int $cantidad): bool {
        
        if ($cantidad <= 0 || $costo <= 0 || empty($producto['id'])) {
            $this->error = 'Datos inválidos del producto.';
            return false;
        }

        $id = $producto['id'];
        $ganancia = (float) ($producto['porcentaje_ganancia'] ?? 0);

        $precio = (100 + $ganancia) * $costo / 100;
        $stockfinal = $producto['stock'] + $cantidad;

        // Si el producto se encuentra en el array

        if (isset($_SESSION[$this->pedidoKey][$id])) {
            $_SESSION[$this->pedidoKey][$id]['costo'] = $costo;
            $_SESSION[$this->pedidoKey][$id]['precio'] = $precio;
            $_SESSION[$this->pedidoKey][$id]['cantidad'] = $cantidad;
            $_SESSION[$this->pedidoKey][$id]['stock_final'] = $stockfinal;
            return true;
        }

        // Caso contrario se guarda en el arreglo

        $_SESSION[$this->pedidoKey][$id] = [
            'id_producto' => $id,
            'marca' => $producto['marca'],
            'modelo' => $producto['modelo'],
            'costo' => $costo,
            'precio' => $precio,
            'cantidad' => $cantidad,
            'stock' => $producto['stock'],
            'stock_final' => $stockfinal,
            'porcentaje_ganancia' => $ganancia
        ];

        return true;
    }

    // CALCULAR TOTAL DE PEDIDO

    public function calcularPrecioTotalPedido(): float {

        $total = 0;

        if (empty($_SESSION[$this->pedidoKey])) {
            return 0;
        }

        foreach ($_SESSION[$this->pedidoKey] as $item) {
            
            $costo = (float) $item['costo'];

            $total += $costo * $item['cantidad'];
        }

        return round($total, 2);
    }

    // LISTAR PRODUCTOS PARA PEDIDO

    public function listarProductosPedido(): array {
        return $_SESSION[$this->pedidoKey] ?? [];
    }

    // ELIMINAR PRODUCTO PARA PEDIDO DE LA CAJA

    public function eliminarProductoPedido($id): bool {

        if (!isset($_SESSION[$this->pedidoKey][$id])) {
            $this->error = 'El producto no existe en el pedido.';
            return false;
        } else {
            unset($_SESSION[$this->pedidoKey][$id]);
        }

        return true;
    }

    // VACIAR CAJA DE PRODUCTOS PARA PEDIDO

    public function vaciarCajaPedido(): bool {
        $_SESSION[$this->pedidoKey] = [];
        return true;
    }

    // EDITAR DATOS DE PRODUCTO PARA PEDIDO

    public function editarDatosProductoPedido(int $id, $nuevoCosto, $nuevaCantidad): bool {

        if ($nuevoCosto <= 0 || $nuevaCantidad <= 0) {
            $this->error = 'Costo o cantidad inválidos.';
            return false;
        }

        if (!isset($_SESSION[$this->pedidoKey][$id])) {
            return false;
        } else {

            $_SESSION[$this->pedidoKey][$id]['costo'] = $nuevoCosto;
            $_SESSION[$this->pedidoKey][$id]['cantidad'] = $nuevaCantidad;

            // Actualización de otro datos

            $precio = (100 + $_SESSION[$this->pedidoKey][$id]['porcentaje_ganancia']) * $nuevoCosto / 100;

            $stockfinal = $_SESSION[$this->pedidoKey][$id]['stock'] + $nuevaCantidad;

            $_SESSION[$this->pedidoKey][$id]['precio'] = $precio;
            $_SESSION[$this->pedidoKey][$id]['stock_final'] = $stockfinal;
        }

        return true;
    }

    // <---------------------------------- MANEJO DE CAJA PARA SERVICIO ---------------------------------->

    // LISTAR INSUMOS SERVICIO

    public function listarInsumos(): array {
        return $_SESSION[$this->servicioKey];
    }

    // CALCULAR EL TOTAL DEL SERVICIO

    public function calcularPrecioTotalServicio(): float {

        $total = 0;

        if (empty($_SESSION[$this->servicioKey])) {
            return 0;
        }

        foreach ($_SESSION[$this->servicioKey] as $item) {
            
            $precio = (float) $item['precio'];

            $total += $precio * $item['cantidad'];
        }

        return round($total, 2);
    }

    // AGREGAR INSUMO A LA CAJA

    public function agregarInsumo(array $insumo, int $cantidad): bool {

        if ($cantidad <= 0 || empty($insumo['id'])) {
            $this->error = 'Datos inválidos del insumo.';
            return false;
        }

        $id = $insumo['id'];
        $stockDisponible = $insumo['stock'];

        // Si el insumo ya existe en el array

        if (isset($_SESSION[$this->servicioKey][$id])) {

            if ($cantidad > $stockDisponible) {
                $this->error = 'La cantidad supera el stock disponible.';
                return false;
            }

            $_SESSION[$this->servicioKey][$id]['cantidad'] = $cantidad;
            return true;
        }

        // Si no se encuentra en el array, lo inserta

        if ($cantidad > $stockDisponible) {
            $this->error = 'La cantidad supera el stock disponible.';
            return false;
        }

        $_SESSION[$this->servicioKey][$id] = [
            'id_producto' => $id,
            'marca' => $insumo['marca'],
            'modelo' => $insumo['modelo'],
            'precio' => $insumo['precio'],
            'cantidad' => $cantidad,
            'stock' => $insumo['stock'],
        ];

        return true;
    }

    // VACIAR CAJA DE INSUMOS PARA SERVICIO

    public function vaciarCajaServicio(): bool {
        $_SESSION[$this->servicioKey] = [];
        return true;
    }

    // ELIMINAR INSUMO PARA SERVICIO DE LA CAJA

    public function eliminarInsumoServicio($id): bool {

        if (!isset($_SESSION[$this->servicioKey][$id])) {
            $this->error = 'El insumo no existe en el pedido.';
            return false;
        } else {
            unset($_SESSION[$this->servicioKey][$id]);
        }

        return true;
    }

    // EDITAR CANTIDAD DE INSUMO

    public function editarCantidadInsumo(int $id, int $nuevaCantidad): bool {

        if (!isset($_SESSION[$this->servicioKey][$id])) {
            $this->error = 'Insumo inexistente en la caja.';
            return false;
        }

        if ($nuevaCantidad <= 0) {
            $this->error = 'La cantidad debe ser mayor a cero.';
            return false;
        }

        if ($nuevaCantidad > $_SESSION[$this->servicioKey][$id]['stock']) {
            $this->error = 'La cantidad supera el stock disponible.';
            return false;
        }

        $_SESSION[$this->servicioKey][$id]['cantidad'] = $nuevaCantidad;
        return true;
    }
}