<?php
/**
 * ajax_actions_vac.php  (shop-floor tablet AJAX endpoints)
 * =====================================================================
 * CHANGES FROM ORIGINAL:
 *
 *   1. recalculateMachineDatesforvac() removed — this file's copy was
 *      already correct (manuf_id-based), but is now the single shared
 *      vac_recalculateMachineDates() in vac_scheduler_lib.php instead of
 *      a standalone copy, so it can't drift from the other files again.
 *
 *   2. get_live_uph_vac: FIX — the ROOT CAUSE of the "Actual UPH
 *      disagreeing with itself" bug. This endpoint had its own,
 *      DIFFERENT "live UPH" calculation from the one
 *      dashboard_vac.php's page-load render used:
 *          $liveUph = round($okUnits / ($windowMinutes / 60), 2);
 *      Since window_minutes is always sent as 60, that denominator is a
 *      hard-coded constant of exactly 1.0 — not real elapsed time. This
 *      poll (which runs every 30 seconds) was overwriting the CORRECT
 *      page-load value (computed by the session-based algorithm now
 *      shared as vac_calculateAndStoreActualUPH()) with a different,
 *      wrong number, over and over. Fixed by calling the exact same
 *      shared function here — there is only one "actual UPH" algorithm
 *      left anywhere in this module, so the two numbers can't disagree
 *      with each other again. Planned UPH also switched to the
 *      route-based vac_calculateBasicUph() (was quantity/total_hours,
 *      same drift problem already fixed in PU).
 *
 *   3. end_breakdown_vac: FIX — previously only inserted a 'completed'
 *      log row. Never cleared is_breakdown_affected, never triggered any
 *      reschedule — the same bug already found and fixed in CNC's and
 *      PU's equivalent endpoints. Now does both.
 *
 *   4. log_breakdown_vac: FIX — `SELECT code FROM keycode WHERE id = ...`
 *      queried a table named `keycode`; every other breakdown-reason
 *      lookup in the CNC and PU modules (and this same file's own
 *      breakdown-reason dropdown elsewhere in the app) queries
 *      `keycode_table`. If `keycode` isn't a real table in your schema,
 *      this silently failed on every call and every VAC breakdown got
 *      logged with reason "Unknown" regardless of what was actually
 *      selected. Changed to `keycode_table` to match the established
 *      convention — please confirm this against your schema before
 *      deploying, since I can't verify table names directly; if `keycode`
 *      turns out to be a real, intentionally different table, revert
 *      this one line.
 *
 *   5. All recalculateMachineDatesforvac() calls now call the shared
 *      vac_fullReschedule() instead.
 *
 *   6. Inventory/BOM functions, log_count_vac, changeover, first-off,
 *      get_current_task_priority_vac (already correctly scoped by
 *      machine_id — VAC has no PU-style composite-id ambiguity) — no
 *      bugs identified, unchanged.
 * =====================================================================
 */

include("../../../include/startup.php");
require_once __DIR__ . '/vac_scheduler_lib.php';

if (isset($_REQUEST['action'])) {
    while (ob_get_level()) ob_end_clean();
    header('Content-Type: application/json');
    header('Cache-Control: no-cache, must-revalidate');
}

/* =====================================================================
 * get_current_task_priority_vac — already correctly scoped by
 * machine_id, unchanged.
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'get_current_task_priority_vac') {
    $workOrderId = intval($_REQUEST['work_order_id']);
    $machineId = intval($_REQUEST['machine_id']);
    $partId = intval($_REQUEST['part_id']);

    $query = "SELECT id, priority FROM vac_machine_table
              WHERE work_order_id = $workOrderId AND machine_id = $machineId AND part_id = $partId LIMIT 1";
    $result = mysqli_query($conn, $query);

    if ($result && mysqli_num_rows($result) > 0) {
        $row = mysqli_fetch_assoc($result);
        echo json_encode(['success' => true, 'task_id' => $row['id'], 'priority' => $row['priority']]);
    } else {
        echo json_encode(['success' => false, 'message' => 'Task not found']);
    }
    exit;
}

/* =====================================================================
 * insert_schedule_break_vac
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'insert_schedule_break_vac') {
    $machineId = intval($_REQUEST['machine_id']);
    $duration = floatval($_REQUEST['duration']);
    $reason = mysqli_real_escape_string($conn, $_REQUEST['reason']);
    $afterTaskId = isset($_REQUEST['after_task_id']) ? intval($_REQUEST['after_task_id']) : 0;
    $afterPriority = isset($_REQUEST['after_priority']) ? intval($_REQUEST['after_priority']) : 0;

    if ($machineId <= 0 || $duration < 0.5 || $duration > 10) {
        echo json_encode(['status' => 'error', 'message' => 'Invalid input values']); exit;
    }

    mysqli_autocommit($conn, false);
    $error = false; $errorMessage = '';
    $breakPriority = $afterPriority + 1;

    if (!mysqli_query($conn, "UPDATE vac_machine_table SET priority = priority + 1 WHERE machine_id = $machineId AND priority >= $breakPriority")) {
        $error = true; $errorMessage = mysqli_error($conn);
    }

    if (!$error) {
        $taskResult = mysqli_query($conn, "SELECT end_date FROM vac_machine_table WHERE id = $afterTaskId");
        if ($taskResult && mysqli_num_rows($taskResult) > 0) {
            $startDate = mysqli_fetch_assoc($taskResult)['end_date'];
            $endDate = date('Y-m-d H:i:s', strtotime($startDate) + ($duration * 3600));
            $remainingHours = $duration;

            $insertQuery = "INSERT INTO vac_machine_table
                           (machine_id, start_date, end_date, total_hours, remaing_hours,
                            is_break, break_reason, priority, work_order_id, part_id, quantity, product_name)
                           VALUES ($machineId, '$startDate', '$endDate', $duration, $remainingHours, 1, '$reason', $breakPriority, 0, 0, 0, 'BREAK: $reason')";
            if (!mysqli_query($conn, $insertQuery)) { $error = true; $errorMessage = mysqli_error($conn); }
        } else {
            $error = true; $errorMessage = "Current task not found";
        }
    }

    if ($error) {
        mysqli_rollback($conn);
        echo json_encode(['status' => 'error', 'message' => $errorMessage]);
    } else {
        mysqli_commit($conn);
        vac_fullReschedule($conn, $machineId);
        echo json_encode(['status' => 'success', 'message' => 'Break scheduled successfully']);
    }
    mysqli_autocommit($conn, true);
    exit;
}

/* =====================================================================
 * log_breakdown_vac
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'log_breakdown_vac') {

    $workOrderId       = intval($_REQUEST['work_order_id']);
    $partId            = intval($_REQUEST['part_id']);
    $machineId         = intval($_SESSION['machine_id']);
    $engineerId        = intval($_SESSION['engineer_id']);
    $vacMachineTableId = intval($_REQUEST['vac_machine_table_id']);
    $breakdownReason   = isset($_REQUEST['breakdown_reason']) ? intval($_REQUEST['breakdown_reason']) : null;
    $breakdownDuration = isset($_REQUEST['breakdown_duration']) ? floatval($_REQUEST['breakdown_duration']) : 1.0;
    $createdOn         = date('Y-m-d H:i:s');

    if (!$workOrderId || !$machineId || !$engineerId) {
        echo json_encode(["success" => false, "message" => "Missing parameters"]); exit;
    }
    if ($breakdownDuration < 0.5 || $breakdownDuration > 24) {
        echo json_encode(["success" => false, "message" => "Invalid breakdown duration. Must be between 0.5 and 24 hours."]); exit;
    }
    if (!$breakdownReason) {
        echo json_encode(["success" => false, "message" => "Breakdown reason is required."]); exit;
    }

    mysqli_autocommit($conn, false);
    $error = false; $errorMessage = ''; $okCount = 0; $remainingQuantity = 0; $newManufId = null;

    $workOrderResult = mysqli_query($conn,
        "SELECT id, work_order_id, part_id, quantity, priority, total_hours, setup_hours, product_name, set_id, end_date
         FROM vac_machine_table WHERE manuf_id = $vacMachineTableId AND machine_id = $machineId LIMIT 1"
    );
    if (!$workOrderResult || mysqli_num_rows($workOrderResult) == 0) {
        mysqli_rollback($conn); mysqli_autocommit($conn, true);
        echo json_encode(["success" => false, "message" => "Work order not found"]); exit;
    }

    $currentWorkOrder = mysqli_fetch_assoc($workOrderResult);
    $currentId       = $currentWorkOrder['id'];
    $currentPriority = intval($currentWorkOrder['priority']);
    $totalQuantity   = intval($currentWorkOrder['quantity']);
    $totalHours      = floatval($currentWorkOrder['total_hours']);
    $setupHours      = floatval($currentWorkOrder['setup_hours']);
    $endDate         = $currentWorkOrder['end_date'];

    $okCountResult = mysqli_query($conn,
        "SELECT SUM(quantity) AS ok_count FROM vac_part_count_log
         WHERE work_order_id = $workOrderId AND vac_machine_table_id = $vacMachineTableId AND part_id = $partId AND type = 'ok'"
    );
    if ($okCountResult && mysqli_num_rows($okCountResult) > 0) {
        $okCount = intval(mysqli_fetch_assoc($okCountResult)['ok_count'] ?? 0);
    }
    $remainingQuantity = $totalQuantity - $okCount;

    // FIX: was `SELECT code FROM keycode` -- every other breakdown-reason
    // lookup in this codebase (CNC, PU, and VAC's own admin-side
    // start_machine_breakdown) queries keycode_table. See file header.
    $reasonText = "Unknown";
    $reasonResult = mysqli_query($conn, "SELECT code FROM keycode_table WHERE id = $breakdownReason LIMIT 1");
    if ($reasonResult && mysqli_num_rows($reasonResult) > 0) {
        $reasonText = mysqli_real_escape_string($conn, mysqli_fetch_assoc($reasonResult)['code']);
    }

    if ($okCount > 0 && $remainingQuantity > 0) {

        $runHoursPerUnit = ($totalHours - $setupHours) / $totalQuantity;
        $completedHours = ($okCount * $runHoursPerUnit) + $setupHours;
        $remainingHours = ($remainingQuantity * $runHoursPerUnit) + $setupHours;
        // NOTE: both halves initially carry $setupHours here, which looks
        // like double-counted setup at a glance -- but total_hours for
        // the REMAINING row is a transient placeholder only. The
        // vac_fullReschedule() call at the end of this handler
        // recomputes total_hours/setup_hours for every row from scratch
        // based on real logic (has production started? does the setting
        // instruction match the previous task?), using total_hours_update
        // (set below to the pure run-hours, no setup baked in) as the
        // base. Verified this self-corrects within the same request.

        $manufId = $vacMachineTableId;
        $manufResult = mysqli_query($conn, "SELECT * FROM manufacture_machine_table WHERE id = $manufId LIMIT 1");

        if ($manufResult && mysqli_num_rows($manufResult) > 0) {
            $originalManuf = mysqli_fetch_assoc($manufResult);
            $manufQuantity = floatval($originalManuf['quantity']);
            $manufTotalHours = floatval($originalManuf['total_hours']);
            $manufHoursPerUnit = $manufQuantity > 0 ? ($manufTotalHours / $manufQuantity) : 0;
            $manufCompletedHours = $okCount * $manufHoursPerUnit;
            $manufRemainingHours = $remainingQuantity * $manufHoursPerUnit;

            if (!mysqli_query($conn, "UPDATE manufacture_machine_table SET quantity = $okCount, total_hours = $manufCompletedHours WHERE id = $manufId")) {
                $error = true; $errorMessage = "Failed to update original manufacture record: " . mysqli_error($conn);
            }

            if (!$error) {
                $manufColumns = []; $manufValues = [];
                foreach ($originalManuf as $col => $val) {
                    if ($col === 'id') continue;
                    $manufColumns[] = "`$col`";
                    if ($col === 'quantity')      $manufValues[] = $remainingQuantity;
                    elseif ($col === 'total_hours') $manufValues[] = $manufRemainingHours;
                    elseif (is_null($val))        $manufValues[] = 'NULL';
                    else $manufValues[] = "'" . mysqli_real_escape_string($conn, $val) . "'";
                }
                $insertManufQuery = "INSERT INTO manufacture_machine_table (" . implode(', ', $manufColumns) . ") VALUES (" . implode(', ', $manufValues) . ")";
                if (!mysqli_query($conn, $insertManufQuery)) {
                    $error = true; $errorMessage = "Failed to create new manufacture record: " . mysqli_error($conn);
                } else {
                    $newManufId = $conn->insert_id;
                }
            }
        }

        if (!$error && !mysqli_query($conn, "UPDATE vac_machine_table SET quantity = $okCount, total_hours = $completedHours, finished = 1 WHERE id = $currentId")) {
            $error = true; $errorMessage = "Failed to update current work order: " . mysqli_error($conn);
        }

        if (!$error && !mysqli_query($conn, "UPDATE vac_machine_table SET priority = priority + 2 WHERE machine_id = $machineId AND priority > $currentPriority")) {
            $error = true; $errorMessage = "Failed to shift priorities: " . mysqli_error($conn);
        }

        if (!$error) {
            $bdStartDate = $endDate;
            $bdEndDate = date('Y-m-d H:i:s', strtotime($bdStartDate) + ($breakdownDuration * 3600));
            if (!mysqli_query($conn, "INSERT INTO vac_machine_table
                    (machine_id, start_date, end_date, total_hours, remaing_hours, is_break, break_reason, priority,
                     work_order_id, part_id, quantity, product_name, setup_hours)
                 VALUES ($machineId, '$bdStartDate', '$bdEndDate', $breakdownDuration, $breakdownDuration, 1,
                         'BREAKDOWN: $reasonText', " . ($currentPriority + 1) . ", 0, 0, 0, 'BREAKDOWN: $reasonText', 0)")) {
                $error = true; $errorMessage = "Failed to insert breakdown task: " . mysqli_error($conn);
            }
        }

        if (!$error) {
            $manufIdForInsert = $newManufId !== null ? intval($newManufId) : 'NULL';
            if (!mysqli_query($conn, "INSERT INTO vac_machine_table
                    (machine_id, manuf_id, work_order_id, part_id, quantity, total_hours, total_hours_update,
                     priority, product_name, set_id, finished, is_break, start_date, end_date, remaing_hours,
                     setup_hours, setting_instruction, cycle, shift_ids)
                 SELECT machine_id, $manufIdForInsert, work_order_id, part_id, $remainingQuantity, $remainingHours,
                        " . ($remainingQuantity * $runHoursPerUnit) . ", " . ($currentPriority + 2) . ", product_name,
                        set_id, 0, 0, NULL, NULL, $remainingHours, $setupHours, setting_instruction, cycle, shift_ids
                 FROM vac_machine_table WHERE id = $currentId")) {
                $error = true; $errorMessage = "Failed to insert remaining work order: " . mysqli_error($conn);
            }
        }

    } else {
        $bdPriority = $currentPriority + 1;
        if (!mysqli_query($conn, "UPDATE vac_machine_table SET priority = priority + 1 WHERE machine_id = $machineId AND priority > $currentPriority")) {
            $error = true; $errorMessage = "Failed to shift priorities: " . mysqli_error($conn);
        }
        if (!$error) {
            $bdStartDate = $endDate;
            $bdEndDate = date('Y-m-d H:i:s', strtotime($bdStartDate) + ($breakdownDuration * 3600));
            if (!mysqli_query($conn, "INSERT INTO vac_machine_table
                    (machine_id, start_date, end_date, total_hours, remaing_hours, is_break, break_reason, priority,
                     work_order_id, part_id, quantity, product_name, setup_hours)
                 VALUES ($machineId, '$bdStartDate', '$bdEndDate', $breakdownDuration, $breakdownDuration, 1,
                         'BREAKDOWN: $reasonText', $bdPriority, 0, 0, 0, 'BREAKDOWN: $reasonText', 0)")) {
                $error = true; $errorMessage = "Failed to insert breakdown task: " . mysqli_error($conn);
            }
        }
    }

    mysqli_query($conn, "INSERT INTO vac_machine_breakdown_log
            (work_order_id, part_id, machine_id, engineer_id, vac_machine_table_id, breakdown_reason,
             breakdown_duration, ok_count_at_breakdown, remaining_quantity, status, created_at)
         VALUES ($workOrderId, $partId, $machineId, $engineerId, $vacMachineTableId, $breakdownReason,
                 $breakdownDuration, $okCount, $remainingQuantity, 'active', '$createdOn')");

    if ($error) {
        mysqli_rollback($conn); mysqli_autocommit($conn, true);
        echo json_encode(["success" => false, "message" => "Breakdown logged but scheduling failed: " . $errorMessage]);
    } else {
        mysqli_commit($conn); mysqli_autocommit($conn, true);
        vac_fullReschedule($conn, $machineId);
        $msg = "Breakdown logged successfully!";
        if ($okCount > 0 && $remainingQuantity > 0) {
            $msg .= " Work order split: $okCount completed, $remainingQuantity remaining.";
            if (!empty($newManufId)) $msg .= " New manufacture record ID: $newManufId.";
        }
        echo json_encode(["success" => true, "message" => $msg]);
    }
    exit;
}

/* =====================================================================
 * log_action_vac
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'log_action_vac') {
    $workOrderId          = intval($_REQUEST['work_order_id']);
    $vac_machine_table_id = intval($_REQUEST['vac_machine_table_id']);
    $partId               = intval($_REQUEST['part_id'] ?? 0);
    $machineId            = intval($_SESSION['machine_id'] ?? 0);
    $engineerId           = intval($_SESSION['engineer_id'] ?? 0);
    $actionType           = $conn->real_escape_string($_REQUEST['action_type']);
    $vacMachineTableId    = intval($_REQUEST['vac_machine_table_id'] ?? 0);
    $createdOn            = date('Y-m-d H:i:s');

    if (!$workOrderId || !$machineId || !$engineerId || !$actionType) {
        echo json_encode(["success" => false, "message" => "Missing parameters"]); exit;
    }

    if ($actionType === 'break') {
        $breakDuration = isset($_REQUEST['break_duration']) ? floatval($_REQUEST['break_duration']) : (20/60);
        $breakReason = isset($_REQUEST['break_reason']) ? mysqli_real_escape_string($conn, $_REQUEST['break_reason']) : 'Scheduled Break';
        if ($breakDuration < (5/60) || $breakDuration > 10) $breakDuration = (20/60);

        mysqli_autocommit($conn, false);
        $error = false; $errorMessage = '';

        $priorityResult = mysqli_query($conn, "SELECT id, priority FROM vac_machine_table WHERE manuf_id = $vac_machine_table_id LIMIT 1");
        if ($priorityResult && mysqli_num_rows($priorityResult) > 0) {
            $priorityRow = mysqli_fetch_assoc($priorityResult);
            $afterTaskId = $priorityRow['id'];
            $afterPriority = $priorityRow['priority'];
            $breakPriority = $afterPriority + 1;

            if (!mysqli_query($conn, "UPDATE vac_machine_table SET priority = priority + 1 WHERE machine_id = $machineId AND priority >= $breakPriority")) {
                $error = true; $errorMessage = mysqli_error($conn);
            }
            if (!$error) {
                $taskResult = mysqli_query($conn, "SELECT end_date FROM vac_machine_table WHERE id = $afterTaskId");
                if ($taskResult && mysqli_num_rows($taskResult) > 0) {
                    $taskRow = mysqli_fetch_assoc($taskResult);
                    $startDate = $taskRow['end_date'];
                    $endDate = date('Y-m-d H:i:s', strtotime($startDate) + ($breakDuration * 3600));
                    if (!mysqli_query($conn, "INSERT INTO vac_machine_table (machine_id, start_date, end_date, total_hours, remaing_hours, is_break, break_reason, priority, work_order_id, part_id, quantity, product_name)
                                             VALUES ($machineId, '$startDate', '$endDate', $breakDuration, $breakDuration, 1, '$breakReason', $breakPriority, 0, 0, 0, 'BREAK: $breakReason')")) {
                        $error = true; $errorMessage = mysqli_error($conn);
                    }
                } else {
                    $error = true; $errorMessage = "Current task not found";
                }
            }
        } else {
            $error = true; $errorMessage = "Task not found for scheduling break";
        }

        mysqli_query($conn, "INSERT INTO vac_machine_activity_log (work_order_id, part_id, machine_id, engineer_id, action_type, vac_machine_table_id, created_at) VALUES ($workOrderId, $partId, $machineId, $engineerId, '$actionType', $vacMachineTableId, '$createdOn')");

        if ($error) {
            mysqli_rollback($conn); mysqli_autocommit($conn, true);
            echo json_encode(["success" => false, "message" => "Break logged but scheduling failed: " . $errorMessage]);
        } else {
            mysqli_commit($conn); mysqli_autocommit($conn, true);
            vac_fullReschedule($conn, $machineId);
            echo json_encode(["success" => true, "message" => "Break scheduled and logged successfully"]);
        }
        exit;
    }

    $result = mysqli_query($conn, "INSERT INTO vac_machine_activity_log (work_order_id, part_id, machine_id, engineer_id, action_type, vac_machine_table_id, created_at) VALUES ($workOrderId, $partId, $machineId, $engineerId, '$actionType', $vacMachineTableId, '$createdOn')");

    if ($result) {
        if ($actionType === 'finish') {
            mysqli_query($conn, "UPDATE vac_machine_table SET finished = 1 WHERE work_order_id = $workOrderId AND part_id = $partId");
        }
        echo json_encode(["success" => true]);
    } else {
        echo json_encode(["success" => false, "message" => mysqli_error($conn)]);
    }
    exit;
}

/* =====================================================================
 * Inventory / BOM helpers — unchanged from original, no scheduling bugs
 * identified in this block.
 * ===================================================================== */

function getEffectiveMaterialId($conn, $workOrderId, $originalPartId, $setId = 0) {
    $workOrderId = intval($workOrderId); $originalPartId = intval($originalPartId); $setId = intval($setId);
    $sql = "SELECT product_id FROM work_order_raw_matrial
            WHERE work_order_id = $workOrderId AND original_product_id = $originalPartId AND set_id = $setId AND is_change = 1 LIMIT 1";
    $result = mysqli_query($conn, $sql);
    if ($result && mysqli_num_rows($result) > 0) {
        $row = mysqli_fetch_assoc($result);
        if (!empty($row['product_id'])) return intval($row['product_id']);
    }
    return $originalPartId;
}

function getBasicQtyOverride($conn, $workOrderId, $productId, $setId = 0) {
    $workOrderId = intval($workOrderId); $productId = intval($productId); $setId = intval($setId);
    if ($productId <= 0) return null;
    $sql = "SELECT basic_qty FROM work_order_raw_matrial WHERE work_order_id = $workOrderId AND product_id = $productId AND set_id = $setId LIMIT 1";
    $result = mysqli_query($conn, $sql);
    if ($result && mysqli_num_rows($result) > 0) {
        $row = mysqli_fetch_assoc($result);
        if ($row['basic_qty'] !== null && $row['basic_qty'] !== '') return floatval($row['basic_qty']);
    }
    return null;
}

function reduceBomChildInventory($conn, $mainProductId, $countQty, $workOrderId, $setId = 0) {
    if ($setId > 0) {
        $setResult = mysqli_query($conn, "SELECT part_id FROM set_mangmnt_mapping WHERE set_id = $setId");
        if (!$setResult || mysqli_num_rows($setResult) == 0) return;
        $childTotals = [];
        while ($setRow = mysqli_fetch_assoc($setResult)) {
            $setPartId = intval($setRow['part_id']);
            $bomResult = mysqli_query($conn, "SELECT sub_part_id, quantity_required FROM bom WHERE main_product_id = $setPartId");
            if (!$bomResult) continue;
            while ($bomRow = mysqli_fetch_assoc($bomResult)) {
                $childId = intval($bomRow['sub_part_id']);
                $qtyReq = floatval($bomRow['quantity_required']);
                if (!isset($childTotals[$childId])) $childTotals[$childId] = 0;
                $childTotals[$childId] += $qtyReq * $countQty;
            }
        }
        foreach ($childTotals as $childId => $rawTotal) {
            $effectiveChildId = getEffectiveMaterialId($conn, $workOrderId, $childId, $setId);
            $basicQtyOverride = getBasicQtyOverride($conn, $workOrderId, $effectiveChildId, $setId);
            if ($basicQtyOverride !== null) $rawTotal = $basicQtyOverride * $countQty;
            $ceiledDeduct = ($countQty >= 0) ? ceil($rawTotal) : -ceil(abs($rawTotal));
            updateInventoryStock($conn, $effectiveChildId, -$ceiledDeduct, $workOrderId, $setId);
            reduceWorkOrderRawMaterial($conn, $effectiveChildId, $ceiledDeduct, $workOrderId, $setId);
        }
    } else {
        $mainProductId = intval($mainProductId);
        $bomResult = mysqli_query($conn, "SELECT sub_part_id,quantity_required FROM bom WHERE main_product_id=$mainProductId");
        if (!$bomResult) return;
        while ($bomRow = mysqli_fetch_assoc($bomResult)) {
            $subPartId = intval($bomRow['sub_part_id']);
            $effectiveSubPartId = getEffectiveMaterialId($conn, $workOrderId, $subPartId, $setId);
            $qtyRequired = floatval($bomRow['quantity_required']);
            $basicQtyOverride = getBasicQtyOverride($conn, $workOrderId, $effectiveSubPartId, $setId);
            if ($basicQtyOverride !== null) $qtyRequired = $basicQtyOverride;
            $deductQty = -1 * $qtyRequired * $countQty;
            updateInventoryStock($conn, $effectiveSubPartId, $deductQty, $workOrderId, $setId);
            reduceWorkOrderRawMaterial($conn, $effectiveSubPartId, -$deductQty, $workOrderId, $setId);
        }
    }
}

function updateInventoryStock($conn, $itemId, $qtyChange, $workOrderId, $set_id) {
    $itemId = intval($itemId); $qtyChange = floatval($qtyChange);
    $result = mysqli_query($conn, "SELECT quantity_in_stock FROM inventory WHERE item_id = $itemId");
    if ($result && mysqli_num_rows($result) > 0) {
        if (!mysqli_query($conn, "UPDATE inventory SET quantity_in_stock = quantity_in_stock + ($qtyChange) WHERE item_id = $itemId")) {
            echo json_encode(["success" => false, "message" => "Inventory update failed: " . mysqli_error($conn)]); exit;
        }
    } else {
        if ($qtyChange < 0) { echo json_encode(["success" => false, "message" => "Cannot create inventory with negative stock (Item ID: $itemId)"]); exit; }
        if (!mysqli_query($conn, "INSERT INTO inventory (item_id, quantity_in_stock) VALUES ($itemId, $qtyChange)")) {
            echo json_encode(["success" => false, "message" => "Inventory insert failed: " . mysqli_error($conn)]); exit;
        }
    }
    if ($qtyChange > 0) {
        $existResult = mysqli_query($conn, "SELECT COUNT(*) AS total FROM production_planning WHERE part_id = $itemId AND status IN (1, 2)");
        $existRow = mysqli_fetch_assoc($existResult);
        if ($existRow && intval($existRow['total']) > 0) {
            $remainingQty = $qtyChange;
            $planResult = mysqli_query($conn, "SELECT id, produce_qty FROM production_planning WHERE part_id = $itemId AND status IN (1, 2) AND produce_qty > 0 ORDER BY req_date ASC");
            if ($planResult && mysqli_num_rows($planResult) > 0) {
                while ($planRow = mysqli_fetch_assoc($planResult)) {
                    if ($remainingQty <= 0) break;
                    $planId = intval($planRow['id']);
                    $currentProdQty = floatval($planRow['produce_qty']);
                    if ($remainingQty >= $currentProdQty) {
                        mysqli_query($conn, "UPDATE production_planning SET produce_qty = 0 WHERE id = $planId");
                        $remainingQty -= $currentProdQty;
                    } else {
                        $newProdQty = $currentProdQty - $remainingQty;
                        mysqli_query($conn, "UPDATE production_planning SET produce_qty = $newProdQty WHERE id = $planId");
                        $remainingQty = 0;
                    }
                }
            }
        }
    }
}

function reduceWorkOrderRawMaterial($conn, $itemId, $qtyUsed, $workOrderId, $setId = 0) {
    $itemId = intval($itemId); $qtyUsed = floatval($qtyUsed); $workOrderId = intval($workOrderId); $setId = intval($setId);
    mysqli_query($conn, "UPDATE work_order_raw_matrial SET quantity = quantity - ($qtyUsed) WHERE work_order_id = $workOrderId AND product_id = $itemId AND set_id = $setId");
}

/* =====================================================================
 * log_count_vac — unchanged from original, no scheduling bugs.
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'log_count_vac') {

    $workOrderId = intval($_REQUEST['work_order_id']);
    $machineId = intval($_SESSION['machine_id'] ?? 0);
    $engineerId = intval($_SESSION['engineer_id'] ?? 0);
    $type = $conn->real_escape_string($_REQUEST['type']);
    $quantity = intval($_REQUEST['quantity'] ?? 1);
    $nok_q_scrap_part_ids_part_ids = isset($_REQUEST['nok_q_scrap_part_ids_part_ids']) ? $conn->real_escape_string($_REQUEST['nok_q_scrap_part_ids_part_ids']) : '';
    $reasonId = isset($_REQUEST['reason_id']) ? intval($_REQUEST['reason_id']) : null;
    $partId = isset($_REQUEST['part_id']) ? intval($_REQUEST['part_id']) : 0;
    $vacMachineTableId = intval($_REQUEST['vac_machine_table_id'] ?? 0);
    $createdOn = date('Y-m-d H:i:s');
    $set_id = intval($_REQUEST['set_id'] ?? 0);

    if (!$workOrderId || !$machineId || !$engineerId || !$type) {
        echo json_encode(["success" => false, "message" => "Missing parameters"]); exit;
    }

    if ($type === 'ok') {
        if ($set_id > 0) {
            $mapResult = $conn->query("SELECT part_id, ratio FROM set_mangmnt_mapping WHERE set_id = $set_id");
            if ($mapResult->num_rows > 0) {
                while ($map = $mapResult->fetch_assoc()) {
                    updateInventoryStock($conn, intval($map['part_id']), floatval($map['ratio']) * $quantity, $workOrderId, $set_id);
                }
            }
            if ($quantity > 0) {
                $insertSql = "INSERT INTO vac_part_count_log (work_order_id, machine_id, part_id, partIds, engineer_id, setId, type, quantity, vac_machine_table_id, created_at)
                              VALUES ($workOrderId, $machineId, $partId, $partId, $engineerId, $set_id, '$type', $quantity, $vacMachineTableId, '$createdOn')";
                if (!mysqli_query($conn, $insertSql)) { echo json_encode(["success" => false, "message" => mysqli_error($conn)]); exit; }
            } elseif ($quantity < 0) {
                $checkResult = $conn->query("SELECT id, quantity FROM vac_part_count_log
                                             WHERE work_order_id = $workOrderId AND machine_id = $machineId AND engineer_id = $engineerId
                                             AND part_id = $partId AND vac_machine_table_id = $vacMachineTableId AND type = '$type'
                                             ORDER BY id DESC LIMIT 1");
                if ($checkResult->num_rows == 0) { echo json_encode(["success" => false, "message" => "Cannot decrement non-existent set record"]); exit; }
                $row = $checkResult->fetch_assoc();
                $newQuantity = $row['quantity'] + $quantity;
                if ($newQuantity < 0) { echo json_encode(["success" => false, "message" => "Count cannot be negative for set ID: $set_id"]); exit; }
                if ($newQuantity == 0) {
                    if (!mysqli_query($conn, "DELETE FROM vac_part_count_log WHERE id = {$row['id']}")) { echo json_encode(["success" => false, "message" => mysqli_error($conn)]); exit; }
                } else {
                    if (!mysqli_query($conn, "UPDATE vac_part_count_log SET quantity = $newQuantity WHERE id = {$row['id']}")) { echo json_encode(["success" => false, "message" => mysqli_error($conn)]); exit; }
                }
            }
            reduceBomChildInventory($conn, $partId, $quantity, $workOrderId, $set_id);
            echo json_encode(["success" => true]);
            exit;
        }
        if ($quantity > 0) {
            $insertSql = "INSERT INTO vac_part_count_log (work_order_id, machine_id, part_id, partIds, engineer_id, type, quantity, vac_machine_table_id, created_at)
                          VALUES ($workOrderId, $machineId, $partId, $partId, $engineerId, '$type', $quantity, $vacMachineTableId, '$createdOn')";
            updateInventoryStock($conn, $partId, $quantity, $workOrderId, $set_id);
            reduceBomChildInventory($conn, $partId, $quantity, $workOrderId, $set_id);
            echo json_encode(mysqli_query($conn, $insertSql) ? ["success" => true] : ["success" => false, "message" => mysqli_error($conn)]);
        } elseif ($quantity < 0) {
            $checkResult = $conn->query("SELECT id, quantity FROM vac_part_count_log
                                         WHERE work_order_id = $workOrderId AND machine_id = $machineId AND engineer_id = $engineerId
                                         AND part_id = $partId AND vac_machine_table_id = $vacMachineTableId AND type = '$type'
                                         ORDER BY id DESC LIMIT 1");
            if ($checkResult->num_rows > 0) {
                $row = $checkResult->fetch_assoc();
                $newQuantity = $row['quantity'] + $quantity;
                if ($newQuantity < 0) { echo json_encode(["success" => false, "message" => "Count cannot be negative"]); exit; }
                updateInventoryStock($conn, $partId, $quantity, $workOrderId, $set_id);
                reduceBomChildInventory($conn, $partId, $quantity, $workOrderId, $set_id);
                $ok = ($newQuantity == 0)
                    ? mysqli_query($conn, "DELETE FROM vac_part_count_log WHERE id = {$row['id']}")
                    : mysqli_query($conn, "UPDATE vac_part_count_log SET quantity = $newQuantity WHERE id = {$row['id']}");
                echo json_encode($ok ? ["success" => true] : ["success" => false, "message" => mysqli_error($conn)]);
            } else {
                echo json_encode(["success" => false, "message" => "Cannot decrement non-existent record"]); exit;
            }
        }
    } else {
        if ($quantity > 0) {
            if (empty($nok_q_scrap_part_ids_part_ids)) { echo json_encode(["success" => false, "message" => "No parts selected"]); exit; }
            if (empty($reasonId)) { echo json_encode(["success" => false, "message" => "No reason selected"]); exit; }

            mysqli_autocommit($conn, false);
            $success = true;

            $insertMain = "INSERT INTO vac_part_count_log (work_order_id, machine_id, part_id, engineer_id, type, setId, partIds, reason_id, quantity, vac_machine_table_id, created_at)
                           VALUES ($workOrderId, $machineId, $partId, $engineerId, '$type', '$set_id', '$nok_q_scrap_part_ids_part_ids', $reasonId, $quantity, $vacMachineTableId, '$createdOn')";
            if (!mysqli_query($conn, $insertMain)) {
                mysqli_rollback($conn); mysqli_autocommit($conn, true);
                echo json_encode(["success" => false, "message" => mysqli_error($conn)]); exit;
            }
            $vacPartCountLogId = mysqli_insert_id($conn);

            $selectedParts = array_map('intval', array_filter(explode(',', $nok_q_scrap_part_ids_part_ids), 'strlen'));
            $unselectedParts = array_map('intval', array_filter(explode(',', $_REQUEST['nok_q_ok_part_ids'] ?? ''), 'strlen'));

            foreach ($selectedParts as $singlePartId) {
                if ($singlePartId <= 0) continue;
                if (!mysqli_query($conn, "INSERT INTO vac_selected_ok_parts (part_id, quantity, vac_machine_table_id, vac_part_count_log_id, created_at)
                                          VALUES ($singlePartId, 1, $vacMachineTableId, $vacPartCountLogId, '$createdOn')")) {
                    $success = false; break;
                }
            }
            if ($success) {
                foreach ($unselectedParts as $singlePartId) {
                    if ($singlePartId <= 0) continue;
                    if (!mysqli_query($conn, "INSERT INTO vac_unselected_ok_parts (part_id, quantity, vac_machine_table_id, vac_part_count_log_id, created_at)
                                              VALUES ($singlePartId, 1, $vacMachineTableId, $vacPartCountLogId, '$createdOn')")) {
                        $success = false; break;
                    }
                    updateInventoryStock($conn, $singlePartId, 1, $workOrderId, $set_id);
                }
            }
            if ($success) {
                reduceBomChildInventory($conn, $partId, $quantity, $workOrderId, $set_id);
                mysqli_commit($conn); mysqli_autocommit($conn, true);
                echo json_encode(["success" => true]);
            } else {
                mysqli_rollback($conn); mysqli_autocommit($conn, true);
                echo json_encode(["success" => false, "message" => mysqli_error($conn)]);
            }
            exit;
        } else if ($quantity < 0) {
            mysqli_autocommit($conn, false);
            $success = true;

            $checkResult = $conn->query("SELECT id, quantity FROM vac_part_count_log
                             WHERE work_order_id = $workOrderId AND machine_id = $machineId AND engineer_id = $engineerId AND part_id = $partId
                             AND vac_machine_table_id = $vacMachineTableId AND type = '$type' ORDER BY id DESC LIMIT 1");

            if ($checkResult->num_rows > 0) {
                $row = $checkResult->fetch_assoc();
                $existingId = $row['id']; $currentQuantity = $row['quantity']; $newQuantity = $currentQuantity + $quantity;

                if ($newQuantity < 0) { mysqli_autocommit($conn, true); echo json_encode(["success" => false, "message" => "Count cannot be negative"]); exit; }

                if ($newQuantity == 0) {
                    $allUnselectedRes = mysqli_query($conn, "SELECT part_id, quantity FROM vac_unselected_ok_parts WHERE vac_part_count_log_id = $existingId");
                    $unselectedReversals = [];
                    while ($uRow = mysqli_fetch_assoc($allUnselectedRes)) {
                        $invPartId = intval($uRow['part_id']);
                        if (!isset($unselectedReversals[$invPartId])) $unselectedReversals[$invPartId] = 0;
                        $unselectedReversals[$invPartId] += floatval($uRow['quantity']);
                    }
                    foreach ($unselectedReversals as $invPartId => $totalQty) updateInventoryStock($conn, $invPartId, -$totalQty, $workOrderId, $set_id);
                    if (!mysqli_query($conn, "DELETE FROM vac_selected_ok_parts WHERE vac_part_count_log_id = $existingId")) $success = false;
                    if ($success && !mysqli_query($conn, "DELETE FROM vac_unselected_ok_parts WHERE vac_part_count_log_id = $existingId")) $success = false;
                    if ($success && !mysqli_query($conn, "DELETE FROM vac_part_count_log WHERE id = $existingId")) $success = false;
                } else {
                    $lastUnselectedRes = mysqli_query($conn, "SELECT id, part_id, quantity FROM vac_unselected_ok_parts WHERE vac_part_count_log_id = $existingId ORDER BY id DESC LIMIT 1");
                    if ($lastUnselectedRes && mysqli_num_rows($lastUnselectedRes) > 0) {
                        $lastUnselectedRow = mysqli_fetch_assoc($lastUnselectedRes);
                        updateInventoryStock($conn, intval($lastUnselectedRow['part_id']), -floatval($lastUnselectedRow['quantity']), $workOrderId, $set_id);
                    }
                    if (!mysqli_query($conn, "DELETE FROM vac_selected_ok_parts WHERE vac_part_count_log_id = $existingId ORDER BY id DESC LIMIT 1")) $success = false;
                    if ($success) mysqli_query($conn, "DELETE FROM vac_unselected_ok_parts WHERE vac_part_count_log_id = $existingId ORDER BY id DESC LIMIT 1");
                    if ($success && !mysqli_query($conn, "UPDATE vac_part_count_log SET quantity = $newQuantity WHERE id = $existingId")) $success = false;
                }

                if ($success) {
                    reduceBomChildInventory($conn, $partId, $quantity, $workOrderId, $set_id);
                    mysqli_commit($conn); mysqli_autocommit($conn, true);
                    echo json_encode(["success" => true]);
                } else {
                    mysqli_rollback($conn); mysqli_autocommit($conn, true);
                    echo json_encode(["success" => false, "message" => mysqli_error($conn)]);
                }
            } else {
                mysqli_autocommit($conn, true);
                echo json_encode(["success" => false, "message" => "No recent $type entry found to decrement"]);
            }
            exit;
        }
    }
    exit;
}

/* =====================================================================
 * start_changeover / end_changeover / first_off_signoff — unchanged.
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'start_changeover') {
    $machineId = intval($_REQUEST['machine_id']);
    $clockNo = mysqli_real_escape_string($conn, $_REQUEST['clock_no'] ?? '');
    $workOrderTableId = intval($_REQUEST['work_order_table_id'] ?? 0);
    $startTime = date('Y-m-d H:i:s');

    if (empty($clockNo)) { echo json_encode(["success" => false, "message" => "Clock number required"]); exit; }
    $userRes = mysqli_query($conn, "SELECT id FROM admin WHERE clock_no = '$clockNo' LIMIT 1");
    if (!$userRes || mysqli_num_rows($userRes) == 0) { echo json_encode(["success" => false, "message" => "Invalid Clock Number"]); exit; }
    $employeeId = intval(mysqli_fetch_assoc($userRes)['id']);
    if ($workOrderTableId <= 0) { echo json_encode(["success" => false, "message" => "No work order selected"]); exit; }

    if (mysqli_query($conn, "INSERT INTO vac_machine_changeover (machine_id, employee_id, work_order_table_id, start_time, status) VALUES ($machineId, $employeeId, $workOrderTableId, '$startTime', 'running')")) {
        echo json_encode(["success" => true]);
    } else {
        echo json_encode(["success" => false, "message" => mysqli_error($conn)]);
    }
    exit;
}

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'end_changeover') {
    $machineId = intval($_REQUEST['machine_id']);
    $endTime = date('Y-m-d H:i:s');
    $result = mysqli_query($conn, "SELECT id, start_time FROM vac_machine_changeover WHERE machine_id = $machineId AND status = 'running' ORDER BY id DESC LIMIT 1");
    if ($result && mysqli_num_rows($result) > 0) {
        $row = mysqli_fetch_assoc($result);
        $duration = time() - strtotime($row['start_time']);
        mysqli_query($conn, "UPDATE vac_machine_changeover SET end_time = '$endTime', duration_seconds = $duration, status = 'completed' WHERE id = {$row['id']}");
        echo json_encode(["success" => true]);
    } else {
        echo json_encode(["success" => false]);
    }
    exit;
}

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'first_off_signoff') {
    $workOrderId = intval($_REQUEST['work_order_id']);
    $partId = intval($_REQUEST['part_id']);
    $machineId = intval($_REQUEST['machine_id']);
    $vacMachineTableId = intval($_REQUEST['vac_machine_table_id']);
    $signedAt = date('Y-m-d H:i:s');
    $qcComment = mysqli_real_escape_string($conn, $_REQUEST['qc_comment'] ?? '');
    $qcClockNo = mysqli_real_escape_string($conn, $_REQUEST['qc_clock_no'] ?? '');

    if (empty($qcClockNo)) { echo json_encode(["success" => false, "message" => "Clock number required"]); exit; }
    $userRes = mysqli_query($conn, "SELECT id FROM admin WHERE clock_no = '$qcClockNo' LIMIT 1");
    if (!$userRes || mysqli_num_rows($userRes) == 0) { echo json_encode(["success" => false, "message" => "Invalid Clock Number"]); exit; }
    $qcEmployeeId = intval(mysqli_fetch_assoc($userRes)['id']);

    if (mysqli_query($conn, "INSERT INTO vac_first_off_signoff (work_order_id, part_id, vac_machine_table_id, machine_id, qc_employee_id, qc_comment, signed_at)
                              VALUES ($workOrderId, $partId, $vacMachineTableId, $machineId, $qcEmployeeId, '$qcComment', '$signedAt')")) {
        echo json_encode(["success" => true]);
    } else {
        echo json_encode(["success" => false, "message" => mysqli_error($conn)]);
    }
    exit;
}

/* =====================================================================
 * end_breakdown_vac
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'end_breakdown_vac') {
    $machineId = intval($_SESSION['machine_id'] ?? 0);
    $engineerId = intval($_SESSION['engineer_id'] ?? 0);
    $createdOn = date('Y-m-d H:i:s');

    if (!$machineId || !$engineerId) { echo json_encode(["success" => false, "message" => "Missing parameters"]); exit; }

    $res = mysqli_query($conn, "SELECT * FROM vac_machine_breakdown_log WHERE machine_id = $machineId AND status = 'active' ORDER BY id DESC LIMIT 1");
    if (!$res || mysqli_num_rows($res) == 0) { echo json_encode(["success" => false, "message" => "No active breakdown found"]); exit; }
    $row = mysqli_fetch_assoc($res);

    if (mysqli_query($conn, "INSERT INTO vac_machine_breakdown_log (work_order_id, part_id, machine_id, engineer_id, vac_machine_table_id, breakdown_reason, breakdown_duration, ok_count_at_breakdown, remaining_quantity, status, created_at)
        VALUES ({$row['work_order_id']}, {$row['part_id']}, $machineId, $engineerId, {$row['vac_machine_table_id']}, {$row['breakdown_reason']}, {$row['breakdown_duration']}, {$row['ok_count_at_breakdown']}, {$row['remaining_quantity']}, 'completed', '$createdOn')")) {

        // FIX: previously this endpoint stopped here -- is_breakdown_affected
        // was never cleared and no reschedule ever ran, so the schedule
        // stayed stale after a tablet-side "Breakdown Over" click. Same fix
        // already applied to CNC's and PU's equivalent endpoints.
        mysqli_query($conn, "UPDATE vac_machine_table SET is_breakdown_affected = 0 WHERE machine_id = $machineId AND is_breakdown_affected = 1");
        vac_fullReschedule($conn, $machineId);

        echo json_encode(["success" => true, "message" => "Breakdown closed successfully"]);
    } else {
        echo json_encode(["success" => false, "message" => mysqli_error($conn)]);
    }
    exit;
}
/*
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'get_live_uph_vac') {

    $workOrderId       = intval($_REQUEST['work_order_id']   ?? 0);
    $partId            = intval($_REQUEST['part_id']         ?? 0);
    $vacMachineTableId = intval($_REQUEST['vac_machine_table_id'] ?? 0);
    $machineId         = intval($_SESSION['machine_id']      ?? 0);
    $windowMinutes     = intval($_REQUEST['window_minutes']  ?? UPH_WINDOW_MINUTES);
    $windowMinutes     = max(5, min(480, $windowMinutes));

    if (!$workOrderId || !$partId || !$vacMachineTableId || !$machineId) {
        echo json_encode(['success' => false, 'message' => 'Missing parameters']); exit;
    }

    $windowStart = date('Y-m-d H:i:s', strtotime("-{$windowMinutes} minutes"));

    $countRes = mysqli_query($conn, "SELECT COALESCE(SUM(quantity), 0) AS ok_units FROM vac_part_count_log
                                     WHERE work_order_id = $workOrderId AND vac_machine_table_id = $vacMachineTableId
                                     AND part_id = $partId AND type = 'ok' AND created_at >= '$windowStart'");
    $okUnits = (int) mysqli_fetch_assoc($countRes)['ok_units'];

    $liveUph = round($okUnits / ($windowMinutes / 60), 2);

    $plannedRes = mysqli_query($conn, "SELECT quantity, total_hours FROM vac_machine_table 
                                       WHERE manuf_id = $vacMachineTableId AND machine_id = $machineId LIMIT 1");
    $plannedRow = mysqli_fetch_assoc($plannedRes);
    $plannedUph = ($plannedRow && $plannedRow['total_hours'] > 0) ? round($plannedRow['quantity'] / $plannedRow['total_hours'], 2) : 0;

    echo json_encode([
        'success'        => true,
        'live_uph'       => $liveUph,
        'planned_uph'    => $plannedUph,
        'ok_units'       => $okUnits,
        'window_minutes' => $windowMinutes,
        'is_green'       => ($plannedUph > 0 && $liveUph >= $plannedUph),
    ]);
    exit;
}*/
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'get_live_uph_vac') {

    $workOrderId       = intval($_REQUEST['work_order_id'] ?? 0);
    $partId            = intval($_REQUEST['part_id'] ?? 0);
    $vacMachineTableId = intval($_REQUEST['vac_machine_table_id'] ?? 0);
    $machineId         = intval($_SESSION['machine_id'] ?? 0);

    if (!$workOrderId || !$partId || !$vacMachineTableId || !$machineId) {
        echo json_encode([
            'success' => false,
            'message' => 'Missing parameters'
        ]);
        exit;
    }

    /*----------------------------------------------------------
      Find when production actually started
    ----------------------------------------------------------*/
    $startRes = mysqli_query($conn, "
        SELECT MIN(created_at) AS job_start
        FROM vac_part_count_log
        WHERE work_order_id = $workOrderId
          AND vac_machine_table_id = $vacMachineTableId
          AND part_id = $partId
          AND type = 'ok'
    ");

    $jobStart = null;

    if ($startRes && mysqli_num_rows($startRes) > 0) {
        $jobStart = mysqli_fetch_assoc($startRes)['job_start'];
    }

    $liveUph = 0;
    $okUnits = 0;
    $elapsedMinutes = 0;
    $mode = "no_production";

    if ($jobStart) {

        $elapsedMinutes = (time() - strtotime($jobStart)) / 60;

        /*=========================================================
          FIRST HOUR
          Projected UPH
        =========================================================*/
        if ($elapsedMinutes < 60) {

            $countRes = mysqli_query($conn, "
                SELECT COALESCE(SUM(quantity),0) AS ok_units
                FROM vac_part_count_log
                WHERE work_order_id = $workOrderId
                  AND vac_machine_table_id = $vacMachineTableId
                  AND part_id = $partId
                  AND type='ok'
            ");

            $okUnits = intval(mysqli_fetch_assoc($countRes)['ok_units']);

            if ($elapsedMinutes > 0) {
                $liveUph = round(($okUnits * 60) / $elapsedMinutes);
            }

            $mode = "projected";
        }

        /*=========================================================
          AFTER FIRST HOUR
          Rolling 60-minute UPH
        =========================================================*/
        else {

            $windowStart = date('Y-m-d H:i:s', strtotime('-60 minutes'));

            $windowRes = mysqli_query($conn, "
                SELECT COALESCE(SUM(quantity),0) AS ok_units
                FROM vac_part_count_log
                WHERE work_order_id = $workOrderId
                  AND vac_machine_table_id = $vacMachineTableId
                  AND part_id = $partId
                  AND type='ok'
                  AND created_at >= '$windowStart'
            ");

            $okUnits = intval(mysqli_fetch_assoc($windowRes)['ok_units']);

            // Parts produced during the last 60 minutes
            $liveUph = $okUnits;

            $mode = "rolling";
        }
    }

    /*----------------------------------------------------------
      Planned / Target UPH
    ----------------------------------------------------------*/
    $plannedRes = mysqli_query($conn, "
        SELECT part_id, set_id
        FROM vac_machine_table
        WHERE manuf_id = $vacMachineTableId
          AND machine_id = $machineId
        LIMIT 1
    ");

    $plannedUph = 0;

    if ($plannedRes && mysqli_num_rows($plannedRes) > 0) {

        $plannedRow = mysqli_fetch_assoc($plannedRes);

        $plannedUph = vac_calculateBasicUph(
            $conn,
            $plannedRow['part_id'],
            intval($plannedRow['set_id'])
        );
    }

    echo json_encode([
        'success'          => true,
        'live_uph'         => intval($liveUph),
        'planned_uph'      => round($plannedUph),
        'ok_units'         => $okUnits,
        'elapsed_minutes'  => round($elapsedMinutes, 1),
        'mode'             => $mode,          // projected / rolling / no_production
        'is_green'         => ($plannedUph > 0 && $liveUph >= $plannedUph)
    ]);

    exit;
}

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'logout_vac') {
    unset($_SESSION['engineer_id']);
    unset($_SESSION['machine_id']);
    echo json_encode(['success' => true]);
    exit;
}
?>
