<?php
/**
 * API: Búsqueda Inteligente de Productos (OPTIMIZADA)
 * Sistema Sufarma - Versión con JOINs en lugar de subconsultas
 */

// 1. Configuración de cabeceras y manejo de errores
ini_set('display_errors', 0); 
error_reporting(E_ALL); 
header('Content-Type: application/json; charset=utf-8');

// OPTIMIZACIÓN: Permitir caché en el cliente por 1 minuto para búsquedas idénticas
header("Cache-Control: public, max-age=60, s-maxage=60");

require_once '../../db_connection.php';

$response = [
    'success' => false,
    'productos' => [],
    'total' => 0
];

try {
    // 2. Recibir y limpiar parámetros
    $query = isset($_GET['query']) ? trim($_GET['query']) : '';
    $page = isset($_GET['page']) ? (int)$_GET['page'] : 1;
    if ($page < 1) $page = 1;
    $perPage = 10;
    $offset = ($page - 1) * $perPage;

    // 3. Obtener sucursal activa y su nombre para mapeo con lugarcompra
    $config = require '../../config/sucursal_activa.php';
    $sucursal_id = $config['sucursal_id'];
    
    // Obtener el nombre de la sucursal activa
    $stmtSuc = $pdo->prepare("SELECT nombre FROM sucursales WHERE id = :id");
    $stmtSuc->bindValue(':id', $sucursal_id, PDO::PARAM_INT);
    $stmtSuc->execute();
    $sucursalRow = $stmtSuc->fetch(PDO::FETCH_ASSOC);
    $sucursal_nombre = $sucursalRow ? $sucursalRow['nombre'] : '';
    
    // Determinar lugar de compra
    if ($sucursal_id == 1 || strtoupper($sucursal_nombre) == 'BODEGACENTRAL') {
        $lugar_compra_nombre = 'GENERAL';
    } else {
        $lugar_compra_nombre = strtoupper($sucursal_nombre);
    }

    // Pre-obtener el ID del lugar de compra (evita JOIN complejo)
    $stmtLugar = $pdo->prepare("SELECT id FROM lugarcompra WHERE UPPER(nombre) = :nombre LIMIT 1");
    $stmtLugar->bindValue(':nombre', $lugar_compra_nombre, PDO::PARAM_STR);
    $stmtLugar->execute();
    $lugarRow = $stmtLugar->fetch(PDO::FETCH_ASSOC);
    $lugar_compra_id = $lugarRow ? (int)$lugarRow['id'] : 0;

    // 4. Construcción de condiciones de búsqueda
    $whereConditions = ["p.estado = 1"];
    $params = [];

    if (!empty($query)) {
        $queryLimpio = $query;
        
        // Dividir en palabras
        $palabras = array_values(array_unique(array_filter(explode(' ', $query), function($v) { 
            return trim($v) !== ''; 
        })));

        // OPTIMIZACIÓN: Usar condiciones individuales en lugar de CONCAT_WS
        $searchConditions = [];
        
        // Búsqueda exacta (prioridad 1) - Usar placeholders únicos
        $searchConditions[] = "(p.NombreComercial = :query_exact1 OR p.NombreGenerico = :query_exact2)";
        $params[':query_exact1'] = $queryLimpio;
        $params[':query_exact2'] = $queryLimpio;
        
        // Búsqueda parcial en campos indexados - placeholders únicos
        $searchConditions[] = "(
            p.CodigoInterno LIKE :query_like1 
            OR p.CodigoBarra LIKE :query_like2 
            OR p.NombreComercial LIKE :query_like3 
            OR p.NombreGenerico LIKE :query_like4
            OR p.laboratorio LIKE :query_like5
        )";
        $params[':query_like1'] = "%{$queryLimpio}%";
        $params[':query_like2'] = "%{$queryLimpio}%";
        $params[':query_like3'] = "%{$queryLimpio}%";
        $params[':query_like4'] = "%{$queryLimpio}%";
        $params[':query_like5'] = "%{$queryLimpio}%";
        
        // Búsqueda por palabras individuales (solo si hay más de una palabra)
        if (count($palabras) > 1) {
            $wordConditions = [];
            $i = 0;
            foreach ($palabras as $palabra) {
                $wordConditions[] = "(
                    p.CodigoInterno LIKE :word{$i}a
                    OR p.CodigoBarra LIKE :word{$i}b
                    OR p.NombreComercial LIKE :word{$i}c
                    OR p.NombreGenerico LIKE :word{$i}d
                    OR p.laboratorio LIKE :word{$i}e
                )";
                $params[":word{$i}a"] = "%{$palabra}%";
                $params[":word{$i}b"] = "%{$palabra}%";
                $params[":word{$i}c"] = "%{$palabra}%";
                $params[":word{$i}d"] = "%{$palabra}%";
                $params[":word{$i}e"] = "%{$palabra}%";
                $i++;
            }
            
            if (!empty($wordConditions)) {
                $searchConditions[] = "(" . implode(" AND ", $wordConditions) . ")";
            }
        }
        
        $whereConditions[] = "(" . implode(" OR ", $searchConditions) . ")";
    }

    $whereClause = implode(" AND ", $whereConditions);

    // 5. Consulta de conteo (simplificada)
    $countSql = "SELECT COUNT(*) as total FROM productos p WHERE {$whereClause}";
    $countStmt = $pdo->prepare($countSql);
    foreach ($params as $key => $val) {
        $countStmt->bindValue($key, $val, PDO::PARAM_STR);
    }
    $countStmt->execute();
    $total = $countStmt->fetch()['total'];

    // 6. OPTIMIZACIÓN PRINCIPAL: JOIN en lugar de subconsulta correlacionada
    $relevanciaExpr = !empty($query) 
        ? "CASE
            WHEN p.NombreComercial = :order_exact1 OR p.NombreGenerico = :order_exact2 THEN 1
            WHEN p.NombreComercial LIKE :order_frase1 OR p.NombreGenerico LIKE :order_frase2 THEN 2
            ELSE 3
           END"
        : "3";
    
    $orderBy = !empty($query) ? "relevancia ASC, p.NombreComercial ASC" : "p.NombreComercial ASC";

    // Consulta principal: usa inventario_sucursal (nuevo)
    $sqlData = "
    SELECT 
        pf.id,
        COALESCE(pf.CodigoInterno, '') as codigo,
        COALESCE(pf.CodigoBarra, '') as codigo_barra,
        COALESCE(pf.NombreComercial, 'Sin Nombre') as nombre,
        COALESCE(pf.laboratorio, 'Genérico') as laboratorio,
        COALESCE(pcp.costo_promedio_unidad_base, 0) as costo_unitario_base,
        COALESCE(pf.imagen_producto, '') as imagen,
        COALESCE(pf.exento_iva, 0) as exento_iva,
        COALESCE(pf.receta_controlada, 0) as receta_controlada,
        COALESCE(inv.stock_total, 0) as stock,
        pf.relevancia
    FROM (
        SELECT p.id, p.CodigoInterno, p.CodigoBarra, p.NombreComercial, p.laboratorio, 
               p.exento_iva, p.receta_controlada, p.imagen_producto,
               {$relevanciaExpr} as relevancia
        FROM productos p
        WHERE {$whereClause}
        ORDER BY {$orderBy}
        LIMIT :limit OFFSET :offset
    ) as pf
    LEFT JOIN productos_costo_promedio pcp ON pf.id = pcp.producto_id
    LEFT JOIN inventario_sucursal inv ON pf.id = inv.producto_id AND inv.sucursal_id = :sucursal_id_inv
    ORDER BY pf.relevancia ASC, pf.NombreComercial ASC";

    $stmt = $pdo->prepare($sqlData);
    
    // Vincular parámetro de sucursal para inventario
    $stmt->bindValue(':sucursal_id_inv', $sucursal_id, PDO::PARAM_INT);
    
    // Vincular parámetros de ordenamiento (placeholders únicos)
    if (!empty($query)) {
        $stmt->bindValue(':order_exact1', $query, PDO::PARAM_STR);
        $stmt->bindValue(':order_exact2', $query, PDO::PARAM_STR);
        $stmt->bindValue(':order_frase1', "%{$query}%", PDO::PARAM_STR);
        $stmt->bindValue(':order_frase2', "%{$query}%", PDO::PARAM_STR);
    }
    
    // Vincular parámetros de búsqueda
    foreach ($params as $key => $val) {
        $stmt->bindValue($key, $val, PDO::PARAM_STR);
    }
    
    // Vincular LIMIT y OFFSET
    $stmt->bindValue(':limit', $perPage, PDO::PARAM_INT);
    $stmt->bindValue(':offset', $offset, PDO::PARAM_INT);

    $stmt->execute();
    $productos = $stmt->fetchAll();

    // Fetch active presentations for the returned products
    $presentations = [];
    $productIds = array_column($productos, 'id');
    if (!empty($productIds)) {
        $inClause = implode(',', array_fill(0, count($productIds), '?'));
        $sqlPres = "
            SELECT pp.producto_id, pp.presentacion_id, pp.factor_conversion, pp.precio_venta, pp.es_facturable, pp.es_unidad_base, pp.orden, pr.nombre as nombre_presentacion
            FROM producto_presentaciones pp
            JOIN presentaciones pr ON pp.presentacion_id = pr.id
            WHERE pp.producto_id IN ($inClause) AND pp.activo = 1
            ORDER BY pp.producto_id, pp.es_unidad_base DESC, pp.orden ASC, pp.presentacion_id ASC
        ";
        $stmtPres = $pdo->prepare($sqlPres);
        $stmtPres->execute($productIds);
        while ($presRow = $stmtPres->fetch(PDO::FETCH_ASSOC)) {
            $presentations[$presRow['producto_id']][] = $presRow;
        }
    }

    // 7. Formatear la salida
    $productosFormateados = [];
    foreach ($productos as $row) {
        $costo_base = (float)$row['costo_unitario_base'];
        $productId = (int)$row['id'];
        
        $prodPres = isset($presentations[$productId]) ? $presentations[$productId] : [];
        
        $base = null;
        $others = [];
        
        foreach ($prodPres as $p) {
            if ((int)$p['es_unidad_base'] === 1 && $base === null) {
                $base = $p;
            } else {
                $others[] = $p;
            }
        }
        
        // Fallback if no base presentation is marked as es_unidad_base
        if ($base === null && !empty($prodPres)) {
            $base = array_shift($prodPres);
            $others = $prodPres;
        }
        
        // Defaults
        $precio_unidad = 0.0;
        $precio_blister = 0.0;
        $precio_caja = 0.0;
        
        $nombre_unidad = 'Unidad';
        $nombre_blister = 'Blíster';
        $nombre_caja = 'Caja';
        
        $factor_blister = 1;
        $factor_caja = 1;
        
        $facturable_unidad = 1;
        $facturable_blister = 1;
        $facturable_caja = 1;
        
        if ($base !== null) {
            $precio_unidad = (float)$base['precio_venta'];
            $nombre_unidad = $base['nombre_presentacion'];
            $facturable_unidad = (int)$base['es_facturable'];
        }
        
        if (isset($others[0])) {
            $precio_blister = (float)$others[0]['precio_venta'];
            $nombre_blister = $others[0]['nombre_presentacion'];
            $factor_blister = (int)$others[0]['factor_conversion'];
            $facturable_blister = (int)$others[0]['es_facturable'];
        }
        
        if (isset($others[1])) {
            $precio_caja = (float)$others[1]['precio_venta'];
            $nombre_caja = $others[1]['nombre_presentacion'];
            $factor_caja = (int)$others[1]['factor_conversion'];
            $facturable_caja = (int)$others[1]['es_facturable'];
        }
        
        $productosFormateados[] = [
            'id' => $productId,
            'codigo' => $row['codigo'],
            'codigo_barra' => $row['codigo_barra'],
            'nombre' => $row['nombre'],
            'laboratorio' => $row['laboratorio'],
            'stock' => (int)$row['stock'],
            'imagen' => $row['imagen'],
            'exento_iva' => (int)$row['exento_iva'],
            'receta_controlada' => (int)$row['receta_controlada'],
            'precios' => [
                'unidad' => $precio_unidad,
                'blister' => $precio_blister,
                'misto' => 0.0,
                'caja' => $precio_caja
            ],
            'nombres' => [
                'unidad' => $nombre_unidad,
                'blister' => $nombre_blister,
                'caja' => $nombre_caja
            ],
            'costos' => [
                'unidad' => $costo_base,
                'blister' => $costo_base * $factor_blister,
                'misto' => $costo_base,
                'caja' => $costo_base * $factor_caja
            ],
            'es_facturable' => [
                'unidad' => $facturable_unidad,
                'blister' => $facturable_blister,
                'caja' => $facturable_caja
            ],
            'factor_blister' => $factor_blister,
            'factor_caja' => $factor_caja
        ];
    }

    $response['success'] = true;
    $response['productos'] = $productosFormateados;
    $response['total'] = (int)$total;
    $response['page'] = $page;

} catch (Exception $e) {
    $response['success'] = false;
    $response['error'] = 'Error del servidor: ' . $e->getMessage();
}

// Salida JSON final
echo json_encode($response, JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR);
?>