<?php

require_once 'odoo_auth.php';
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
class OdooInventario
{
    public static function moveProductBetweenWarehouses($product_id, $source_warehouse_id, $destination_warehouse_id, $picking_type_id, $quantity)
    {
        try {
            $models = OdooAuth::getOdoo();

            // Crear un nuevo stock.picking
            $picking_id = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.picking',
                'create',
                [[
                    'location_id' => $source_warehouse_id,
                    'location_dest_id' => $destination_warehouse_id,
                    'picking_type_id' => $picking_type_id, // Este valor puede variar dependiendo de tu configuración de Odoo
                ]]
            );

            // return $picking_id;

            // Crear un nuevo stock.move
            $response = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.move',
                'create',
                [[
                    'name' => 'Transfer',
                    'product_id' => $product_id,
                    'product_uom_qty' => $quantity,
                    // 'product_uom' => 1, // Este valor puede variar dependiendo de tu configuración de Odoo
                    'picking_id' => $picking_id,
                    'location_id' => $source_warehouse_id,
                    'location_dest_id' => $destination_warehouse_id,
                ]]
            );

            // Confirmar el stock.picking
            // $models->execute_kw(
            //     OdooAuth::$db,
            //     OdooAuth::$uid,
            //     OdooAuth::$password,
            //     'stock.picking',
            //     'action_confirm',
            //     [$picking_id]
            // );

            // Validar el stock.picking
            $response2 = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.picking',
                'button_validate',
                array($picking_id)
            );
            
            return $response2;

            // return $picking_id;
        } catch (Exception $e) {
            // Manejo del error
            error_log($e->getMessage());
            return false;
        }
    }

    public static function getFreeStockByAlmacenId($product_id, $warehouse_id)
    {
        try {
            $models = OdooAuth::getOdoo();

            // Obtener las ubicaciones asociadas con el almacén
            $locations = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.warehouse',
                'read',
                array($warehouse_id),
                array('fields' => array('view_location_id'))
            );

            if (empty($locations)) {
                return false;
            }

            // print_r($locations);

            // Obtener las existencias del producto en esas ubicaciones
            $quantities = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'product.product',
                'search_read',
                array(
                    array(
                        array('id', '=', $product_id),
                        array('location_id', 'child_of', $locations[0]['view_location_id'][0])
                    )
                ),
                array('fields' => array('free_qty',))
            );

            // Sumar las cantidades
            // print_r($quantities);

            $total_free_quantity = 0;
            foreach ($quantities as $quantity) {
                $total_free_quantity += $quantity['free_qty'];
            }

            return $total_free_quantity;
        } catch (Exception $e) {
            // Manejo del error
            error_log($e->getMessage());
            return false;
        }
    }

    public static function getStockByAlmacenId($product_id, $warehouse_id)
    {
        try {
            $models = OdooAuth::getOdoo();

            // Obtener las ubicaciones asociadas con el almacén
            $locations = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.warehouse',
                'read',
                array($warehouse_id),
                array('fields' => array('view_location_id'))
            );

            if (empty($locations)) {
                return "No se encontraron ubicaciones para el almacén.";
            }

            // Obtener las existencias del producto en esas ubicaciones
            $quantities = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.quant',
                'search_read',
                array(
                    array(
                        array('product_id', '=', $product_id),
                        array('location_id', 'child_of', $locations[0]['view_location_id'][0])
                    )
                ),
                array('fields' => array('quantity', 'reserved_quantity'))
            );

            // Sumar las cantidades
            $total_quantity = 0;
            foreach ($quantities as $quantity) {
                $total_quantity += ($quantity['quantity'] - $quantity['reserved_quantity']); // <---- This is the GOAT!!!
            }

            return $total_quantity;
        } catch (Exception $e) {
            // Manejo del error
            error_log($e->getMessage());
            return false;
        }
    }

    public static function getStockByProductId($product_id)
    {
        try {

            $models = OdooAuth::getOdoo();

            $product_data = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'product.product',
                'read',
                array($product_id), // ID del producto
                array('fields' => array('free_qty')) // Campo de cantidad disponible
            );

            return $product_data;
        } catch (Exception $e) {
            // Manejo del error
            error_log($e->getMessage());
            return false;
        }
    }

    public static function getAlmacenesPorNombreCompania($nombreCompania)
    {
        try {
            $models = OdooAuth::getOdoo();

            // Buscar el ID de la compañía con el nombre dado
            $company_ids = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'res.company',
                'search',
                array(array(array('name', '=', $nombreCompania)))
            );

            // Si no se encontró la compañía, retornar false
            if (empty($company_ids)) {
                return false;
            }

            // Buscar almacenes que tengan ese ID de compañía
            $warehouse_ids = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.warehouse',
                'search',
                array(array(array('company_id', '=', $company_ids[0])))
            );

            $warehouses = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.warehouse',
                'read',
                array($warehouse_ids),
                array('fields' => array('name', 'company_id', 'partner_id', 'code')) // Agrega aquí los campos que necesites
            );

            return $warehouses;
        } catch (Exception $e) {
            // Manejo del error
            error_log($e->getMessage());
            return false;
        }
    }

    public static function getAlmacenPorNombre($nombre)
    {
        try {
            $models = OdooAuth::getOdoo();
            $warehouse_ids = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.warehouse',
                'search',
                array(array(array('name', '=', $nombre)))
            );

            $warehouses = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.warehouse',
                'read',
                array($warehouse_ids),
                array('fields' => array('name', 'company_id', 'partner_id', 'code')) // Agrega aquí los campos que necesites
            );

            return $warehouses;
        } catch (Exception $e) {
            // Manejo del error
            error_log($e->getMessage());
            return false;
        }
    }

    public static function getAlmacenesId()
    {
        try {
            $models = OdooAuth::getOdoo();
            $warehouse_ids = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.warehouse',
                'search',
                array(array())
            );

            $warehouses = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.warehouse',
                'read',
                array($warehouse_ids),
                array('fields' => array('name', 'company_id', 'partner_id', 'code', 'lot_stock_id')) // Agrega aquí los campos que necesites
            );
            // $warehouses = $models->execute_kw(
            //     OdooAuth::$db,
            //     OdooAuth::$uid,
            //     OdooAuth::$password,
            //     'stock.warehouse',
            //     'read',
            //     array($warehouse_ids)
            // );

            return $warehouses;
        } catch (Exception $e) {
            // Manejo del error
            error_log($e->getMessage());
            return false;
        }
    }

    // public static function getStockDistribution($product_id, $total_quantity_needed, $warehouse_ids)
    // {

    //     $distribution = [];
    //     $quantity_remaining = $total_quantity_needed;

    //     // Iterate over all warehouses
    //     foreach ($warehouse_ids as $key => $warehouse_id) {
    //         // Get the stock quantity in the current warehouse
    //         $quantity = self::getStockByAlmacenId($product_id, $warehouse_id);
    //         // If the warehouse has no stock, skip it
    //         if ($quantity <= 0) {
    //             continue;
    //         }

    //         // If the warehouse has enough stock, take all the remaining quantity from it
    //         if ($quantity >= $quantity_remaining) {
    //             $distribution[] = ['warehouse_id' => $warehouse_id, 'quantity' => $quantity_remaining];
    //             break;
    //         }

    //         // If the warehouse does not have enough stock, take all its stock and continue with the next warehouse
    //         $distribution[] = ['warehouse_id' => $warehouse_id, 'quantity' => $quantity];
    //         $quantity_remaining -= $quantity;
    //     }

    //     // If there is still some quantity remaining, return false
    //     // if ($quantity_remaining > 0) {
    //     //     echo json_encode($quantity_remaining);
    //     //     echo ("---");
    //     //     echo json_encode($quantity);
    //     //     echo ("---");
    //     //     // return false;
    //     // }

    //     return $distribution;
    // }

    public static function getStockDistribution($product_id, $total_quantity_needed, $warehouse_ids)
{
    $distribution = [];
    $quantity_remaining = $total_quantity_needed;
    $selected_warehouse = null;

    // Iterate over all warehouses
    foreach ($warehouse_ids as $key => $warehouse_id) {
        // Get the stock quantity in the current warehouse
        $quantity = self::getStockByAlmacenId($product_id, $warehouse_id);
        // // echo "Warehouse ID: " . $warehouse_id . ", Stock Quantity: " . $quantity . "\n";

        // If the warehouse has no stock, skip it
        if ($quantity <= 0) {
            continue;
        }

        // Check if all products can be taken from this warehouse
        if ($quantity >= $total_quantity_needed) {
            $selected_warehouse = $warehouse_id;
            break;
        }

        // If the warehouse has enough stock, take all the remaining quantity from it
        if ($quantity >= $quantity_remaining) {
            $distribution[] = ['warehouse_id' => $warehouse_id, 'quantity' => $quantity_remaining];
            break;
        }

        // If the warehouse does not have enough stock, take all its stock and continue with the next warehouse
        $distribution[] = ['warehouse_id' => $warehouse_id, 'quantity' => $quantity];
        $quantity_remaining -= $quantity;
    }

    if ($selected_warehouse !== null) {
        return [['warehouse_id' => $selected_warehouse, 'quantity' => $total_quantity_needed]];
    }

    // // echo "Distribution: " . json_encode($distribution) . "\n";

    return $distribution;
}

    public static function getAlmacenInfoById($warehouse_id)
    {
        try {
            $models = OdooAuth::getOdoo();
            $warehouse = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.warehouse',
                'read',
                array($warehouse_id),
                array('fields' => array('name', 'company_id', 'id', 'code'))
            );

            return $warehouse;
        } catch (Exception $e) {
            // Error handling
            error_log($e->getMessage());
            return false;
        }
    }

    public static function getGlobalStock($product_ids, $warehouse_ids = [])
    {
        try {
            $models = OdooAuth::getOdoo();
            $stock = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'product.product',
                'read',
                array($product_ids),
                array('fields' => array('name', 'free_qty'), 'context' => array('warehouse' => $warehouse_ids))
            );

            return $stock;
        } catch (Exception $e) {
            // Error handling
            error_log($e->getMessage());
            return false;
        }
    }

    //En esta función se hace todo el proceso para saber si un almacen tiene todas las cantidades de todos los productos que se requieren
    public static function getWarehouseWithSufficientStock($warehouse_ids, $products)
    {
        try {
            
            $productos_odoo_cantidad = array_map(function ($producto) {
                $aux_producto_cantidad['cantidad'] = $producto['cantidad'];
                $aux_producto_cantidad['id'] = intval($producto['id_producto_odoo']);
                return $aux_producto_cantidad;
            }, $products);

            $foundWarehouse = array();

            foreach($productos_odoo_cantidad as $key => $producto) {
                for($i = 0; $i < count($warehouse_ids); $i++) {
                    $cantidad = $producto['cantidad'];
                    $aux = OdooInventario::getGlobalStock(intval($producto['id']), $warehouse_ids[$i]);

                    if($aux[0]['free_qty'] >= $cantidad){
                        $foundWarehouse[] = array(
                            'warehouse_id' => $warehouse_ids[$i],
                            'quantity' => $aux[0]['free_qty'],
                            'product_id' => $producto['id']
                        );
                    }
                }
            }

            $warehouseProducts = array_reduce($foundWarehouse, function ($match, $item) {
                $warehouseId = $item['warehouse_id'];
                $match[$warehouseId] = isset($match[$warehouseId]) ? array_merge($match[$warehouseId], [$item]) : [$item];
                return $match;
            }, []);

            // echo ('---');
            // echo json_encode($warehouseProducts);
            // echo ('---');

            return array_values($warehouseProducts);

        } catch (Exception $e) {
            // Error handling
            error_log($e->getMessage());
            return false;
        }
    }

    public static function getStockTypes(){
        try {
            $models = OdooAuth::getOdoo();
            $stock_types = $models->execute_kw(
                OdooAuth::$db,
                OdooAuth::$uid,
                OdooAuth::$password,
                'stock.picking.type',
                'search_read',
                array(array()),
                array(
                    'fields' => array('name', 'id', 'warehouse_id')
                )
            );

            return $stock_types;
        } catch (Exception $e) {
            // Error handling
            error_log($e->getMessage());
            return false;
        }
    }

}
