<?php
/**
 * sync_sales_from_file.php
 * Lee el archivo C:\opscode\sale.txt generado por la aplicación Delphi
 * y registra automáticamente las ventas nuevas en la base de datos.
 * 
 * Ejecutar cada 2-3 segundos para sincronización en tiempo real.
 */

require_once __DIR__ . '/init.php';

// Configuración
define('SALES_FILE_PATH', 'C:/opscode/sale.txt');
define('SALES_PROCESSED_FILE', __DIR__ . '/data/sales_processed.json');
define('DEBUG_LOG', __DIR__ . '/logs/sync_sales.log');

// Crear directorios si no existen
@mkdir(__DIR__ . '/data', 0755, true);
@mkdir(__DIR__ . '/logs', 0755, true);

$pdo = pdo();

/**
 * Log de debug
 */
function logDebug($msg) {
    $timestamp = date('Y-m-d H:i:s');
    $line = "[{$timestamp}] {$msg}\n";
    @file_put_contents(DEBUG_LOG, $line, FILE_APPEND);
}

/**
 * Obtener IDs de ventas ya procesadas
 */
function getProcessedSales() {
    if (!file_exists(SALES_PROCESSED_FILE)) {
        return [];
    }
    $content = @file_get_contents(SALES_PROCESSED_FILE);
    $data = json_decode($content, true);
    return is_array($data) ? $data : [];
}

/**
 * Guardar ID de venta procesada
 */
function markSaleAsProcessed($saleID, $numVenta) {
    $processed = getProcessedSales();
    $key = $saleID . '_' . $numVenta;
    $processed[$key] = time();
    
    // Mantener solo las últimas 1000 ventas procesadas
    if (count($processed) > 1000) {
        $processed = array_slice($processed, -1000, 1000, true);
    }
    
    @file_put_contents(SALES_PROCESSED_FILE, json_encode($processed));
}

/**
 * Verificar si una venta ya fue procesada
 */
function isSaleProcessed($saleID, $numVenta) {
    $processed = getProcessedSales();
    $key = $saleID . '_' . $numVenta;
    return isset($processed[$key]);
}

/**
 * Parsear el archivo sale.txt
 */
function parseSalesFile() {
    if (!file_exists(SALES_FILE_PATH)) {
        logDebug('ERROR: Archivo ' . SALES_FILE_PATH . ' no encontrado');
        return [];
    }
    
    @clearstatcache(true, SALES_FILE_PATH);
    $content = @file_get_contents(SALES_FILE_PATH);
    
    if ($content === false) {
        logDebug('ERROR: No se pudo leer ' . SALES_FILE_PATH);
        return [];
    }
    
    $lines = explode("\n", $content);
    $sales = [];
    $header = null;
    
    foreach ($lines as $i => $line) {
        $line = trim($line);
        if ($line === '') continue;
        
        $fields = explode("\t", $line);
        
        if ($i === 0 || $header === null) {
            $header = $fields;
            logDebug('Header encontrado: ' . implode(', ', $header));
            continue;
        }
        
        $sale = [];
        foreach ($header as $idx => $colName) {
            $sale[$colName] = isset($fields[$idx]) ? trim($fields[$idx]) : '';
        }
        
        if (empty($sale['ID Venta']) || empty($sale['# de Venta'])) {
            continue;
        }
        
        $sales[] = $sale;
    }
    
    logDebug('Total líneas parseadas: ' . count($sales));
    return $sales;
}

/**
 * Buscar product_id por ID Producto (SKU)
 */
function findProductByID2($pdo, $id2) {
    // Buscar por SKU primero
    $stmt = $pdo->prepare("SELECT id FROM products WHERE sku = ? LIMIT 1");
    $stmt->execute([$id2]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if ($row) {
        logDebug("  Producto encontrado por SKU: {$id2} -> ID {$row['id']}");
        return (int)$row['id'];
    }
    
    // Buscar por ID directo como fallback
    $stmt = $pdo->prepare("SELECT id FROM products WHERE id = ? LIMIT 1");
    $stmt->execute([(int)$id2]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if ($row) {
        logDebug("  Producto encontrado por ID: {$id2} -> ID {$row['id']}");
        return (int)$row['id'];
    }
    
    logDebug("  ERROR: Producto NO encontrado (ID2={$id2})");
    return null;
}

/**
 * Buscar hose_id por surtidor y manguera
 */
function findHoseId($pdo, $pumpNumber, $hoseNumber) {
    // Buscar manguera por pump_id y número
    $stmt = $pdo->prepare("SELECT id FROM hoses WHERE pump_id = ? AND (name = ? OR id = ?) LIMIT 1");
    $stmt->execute([$pumpNumber, $hoseNumber, $hoseNumber]);
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    if ($row) {
        logDebug("  Manguera encontrada: Surtidor {$pumpNumber}, Manguera {$hoseNumber} -> ID {$row['id']}");
        return (int)$row['id'];
    }
    
    logDebug("  ADVERTENCIA: Manguera NO encontrada (Surtidor={$pumpNumber}, Manguera={$hoseNumber})");
    return null;
}

/**
 * Convertir formato de número: "1.234,5" -> 1234.5
 */
function parseNumber($str) {
    $str = trim($str);
    $str = str_replace(['$', 'Gal', ' '], '', $str);
    $str = str_replace('.', '', $str);
    $str = str_replace(',', '.', $str);
    return floatval($str);
}

/**
 * Registrar venta en la base de datos
 */
function registerSale($pdo, $sale) {
    $saleID = trim($sale['ID Venta']);
    $numVenta = trim($sale['# de Venta']);
    $fechaFin = trim($sale['Fecha de Fin']);
    $horaFin = trim($sale['Hora de Fin']);
    $surtidor = (int)trim($sale['Surtidor']);
    $manguera = (int)trim($sale['Manguera']);
    $productID2 = trim($sale['ID Producto']);
    $combustible = trim($sale['Combustible']);
    $volumen = parseNumber($sale['Volumen']);
    $ppu = parseNumber($sale['PPU']);
    $monto = parseNumber($sale['Monto']);
    $tipoPago = trim($sale['Tipo de Pago']);
    
    logDebug("========================================");
    logDebug("Procesando venta:");
    logDebug("  ID Venta: {$saleID}");
    logDebug("  # Venta: {$numVenta}");
    logDebug("  Surtidor: {$surtidor}");
    logDebug("  Producto: {$combustible} (ID2: {$productID2})");
    logDebug("  Volumen: {$volumen} Gal");
    logDebug("  Monto: \${$monto}");
    
    // Verificar si ya fue procesada
    if (isSaleProcessed($saleID, $numVenta)) {
        logDebug("  -> YA PROCESADA, omitiendo");
        return false;
    }
    
    // Buscar producto
    $productId = findProductByID2($pdo, $productID2);
    if (!$productId) {
        logDebug("  -> ERROR: Producto no encontrado, omitiendo");
        return false;
    }
    
    // Buscar manguera
    $hoseId = findHoseId($pdo, $surtidor, $manguera);
    
    // Construir fecha/hora
    $createdAt = null;
    if ($fechaFin && $horaFin) {
        $parts = explode('/', $fechaFin);
        if (count($parts) === 3) {
            $day = str_pad($parts[0], 2, '0', STR_PAD_LEFT);
            $month = str_pad($parts[1], 2, '0', STR_PAD_LEFT);
            $year = $parts[2];
            $createdAt = "{$year}-{$month}-{$day} {$horaFin}";
        }
    }
    
    if (!$createdAt) {
        $createdAt = date('Y-m-d H:i:s');
        logDebug("  -> ADVERTENCIA: Fecha inválida, usando fecha actual");
    }
    
    logDebug("  Fecha procesada: {$createdAt}");
    
    // Determinar método de pago
    $paymentMethod = 'cash';
    if (stripos($tipoPago, 'EFECTIVO') !== false) {
        $paymentMethod = 'cash';
    } elseif (stripos($tipoPago, 'TARJETA') !== false || stripos($tipoPago, 'CARD') !== false) {
        $paymentMethod = 'card';
    }
    
    try {
        $pdo->beginTransaction();
        
        // Generar código de venta único
        $saleCode = 'W' . $saleID . '_' . $numVenta;
        
        // Verificar duplicados en BD
        $stmt = $pdo->prepare("SELECT id FROM sales WHERE sale_code = ? LIMIT 1");
        $stmt->execute([$saleCode]);
        if ($stmt->fetch()) {
            $pdo->rollBack();
            logDebug("  -> YA EXISTE en BD (sale_code={$saleCode}), omitiendo");
            markSaleAsProcessed($saleID, $numVenta);
            return false;
        }
        
        // Insertar venta
        $userId = 1; // Usuario por defecto (sistema)
        $stmt = $pdo->prepare("
            INSERT INTO sales (sale_code, user_id, total, payment_method, created_at) 
            VALUES (?, ?, ?, ?, ?)
        ");
        $stmt->execute([$saleCode, $userId, $monto, $paymentMethod, $createdAt]);
        $newSaleId = $pdo->lastInsertId();
        
        logDebug("  Venta insertada en BD: ID={$newSaleId}");
        
        // Insertar item de venta
        $stmt = $pdo->prepare("
            INSERT INTO sale_items (sale_id, product_id, hose_id, qty, unit_price, total) 
            VALUES (?, ?, ?, ?, ?, ?)
        ");
        $stmt->execute([
            $newSaleId,
            $productId,
            $hoseId,
            $volumen,
            $ppu,
            $monto
        ]);
        
        logDebug("  Item insertado: product_id={$productId}, hose_id={$hoseId}");
        
        // Actualizar inventario de tanques
        $stmt = $pdo->prepare("
            UPDATE tanques 
            SET vendido = vendido + ?, 
                disponible = disponible - ?, 
                updated_at = NOW() 
            WHERE producto_id = ?
        ");
        $affected = $stmt->execute([$volumen, $volumen, $productId]);
        
        logDebug("  Tanques actualizados: {$affected} filas afectadas");
        
        $pdo->commit();
        
        logDebug("  -> ✓ REGISTRADA EXITOSAMENTE");
        
        markSaleAsProcessed($saleID, $numVenta);
        
        return true;
        
    } catch (Exception $e) {
        $pdo->rollBack();
        logDebug("  -> ERROR al registrar: " . $e->getMessage());
        return false;
    }
}

/**
 * Proceso principal
 */
function syncSales() {
    $pdo = pdo();
    
    logDebug("========================================");
    logDebug("SINCRONIZACIÓN INICIADA");
    logDebug("========================================");
    
    $sales = parseSalesFile();
    
    if (empty($sales)) {
        logDebug("No se encontraron ventas en el archivo");
        logDebug("========================================\n");
        return ['ok' => 1, 'registered' => 0, 'skipped' => 0, 'message' => 'No hay ventas nuevas'];
    }
    
    logDebug("Total de ventas en archivo: " . count($sales));
    
    $registered = 0;
    $skipped = 0;
    
    // Procesar SOLO las últimas 20 ventas (las más recientes)
    $sales = array_slice($sales, -20);
    
    logDebug("Procesando últimas " . count($sales) . " ventas");
    
    foreach ($sales as $sale) {
        $result = registerSale($pdo, $sale);
        if ($result) {
            $registered++;
        } else {
            $skipped++;
        }
    }
    
    logDebug("----------------------------------------");
    logDebug("RESUMEN:");
    logDebug("  Registradas: {$registered}");
    logDebug("  Omitidas: {$skipped}");
    logDebug("========================================\n");
    
    return [
        'ok' => 1,
        'registered' => $registered,
        'skipped' => $skipped,
        'message' => "Ventas sincronizadas: {$registered} nuevas, {$skipped} omitidas"
    ];
}

// Si se ejecuta directamente
if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME'])) {
    try {
        $result = syncSales();
        header('Content-Type: application/json');
        echo json_encode($result);
    } catch (Exception $e) {
        logDebug("ERROR CRÍTICO: " . $e->getMessage());
        header('Content-Type: application/json');
        echo json_encode(['ok' => 0, 'error' => $e->getMessage()]);
    }
}