<?php
/**
 * ajax_actions_cnc.php  (shop-floor tablet AJAX endpoints)
 * =====================================================================
 * CHANGES FROM ORIGINAL:
 *
 *   1. All duplicated scheduling functions removed — uses
 *      cnc_scheduler_lib.php.
 *
 *   2. log_breakdown_cnc: the inline "split the task at the breakdown
 *      point" logic (originally duplicated, with slight field
 *      differences, from split_cnc_work_order in the other ajax file)
 *      is now routed through the single cnc_splitCncTask() function.
 *      This means a breakdown-triggered split now correctly propagates
 *      is_dual_table onto the new row and resets original_uph, which
 *      the old inline version never did.
 *
 *   3. end_breakdown_cnc: previously this ONLY inserted a 'completed'
 *      row into cnc_machine_breakdown_log — it never cleared
 *      is_breakdown_affected on the tasks, and never triggered any
 *      reschedule. So stopping a breakdown from the tablet left the
 *      schedule stale until something else happened to trigger a
 *      recompute. Now it clears is_breakdown_affected for the machine
 *      and runs the full reschedule chain, matching what
 *      stop_machine_breakdown does on the admin side.
 *
 *   4. cnc_isMachineInBreakdown() (shared lib) is unchanged in what it
 *      reads (cnc_machine_breakdown_log) — this file already wrote to
 *      that table correctly; it's ajax_actions_for_cnc.php (the admin
 *      side) that has been updated to mirror into it too. See that
 *      file's header comment for the two-system breakdown-visibility
 *      bug this closes.
 *
 *   5. Everything below (count logging / inventory / UPH / clock /
 *      changeover / first-off) had no scheduling bugs identified and
 *      is functionally unchanged — only routed through the shared
 *      library where it touches scheduling, and cleaned up to use
 *      manuf_id consistently (it already did, this file was the one
 *      that got that convention right throughout).
 * =====================================================================
 */
include("../../../include/startup.php");
require_once __DIR__ . '/cnc_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_cnc
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'get_current_task_priority_cnc') {
    $workOrderId = intval($_REQUEST['work_order_id']);
    $tableId     = intval($_REQUEST['table_id']);
    $partId      = intval($_REQUEST['part_id']);

    $result = mysqli_query($conn, "
        SELECT id, priority, machine_id FROM cnc_machine_table
        WHERE work_order_id = $workOrderId AND table_id = $tableId AND part_id = $partId LIMIT 1
    ");
    if ($result && mysqli_num_rows($result) > 0) {
        $row = mysqli_fetch_assoc($result);
        echo json_encode(['success' => true, 'task_id' => $row['id'], 'priority' => $row['priority'], 'machine_id' => $row['machine_id']]);
    } else {
        echo json_encode(['success' => false, 'message' => 'Task not found']);
    }
    exit;
}

/* =====================================================================
 * insert_schedule_break_cnc
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'insert_schedule_break_cnc') {
    $machineId    = intval($_REQUEST['machine_id']);
    $tableId      = intval($_REQUEST['table_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 || $tableId <= 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 cnc_machine_table SET priority = priority + 1
        WHERE machine_id = $machineId AND table_id = $tableId AND priority >= $breakPriority
    ")) {
        $error = true; $errorMessage = mysqli_error($conn);
    }

    if (!$error) {
        $taskResult = mysqli_query($conn, "SELECT end_date FROM cnc_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));

            $insertQuery = "INSERT INTO cnc_machine_table
                (machine_id, table_id, start_date, end_date, original_start_date, original_end_date,
                 total_hours, original_total_hours, remaing_hours, original_remaing_hours,
                 is_break, break_reason, priority, work_order_id, part_id, quantity, product_name)
                VALUES ($machineId, $tableId, '$startDate', '$endDate', '$startDate', '$endDate',
                        $duration, $duration, $duration, $duration, 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);
        cnc_fullRescheduleMachine($conn, $machineId);
        echo json_encode(['status' => 'success', 'message' => 'Break scheduled successfully']);
    }
    mysqli_autocommit($conn, true);
    exit;
}

/* =====================================================================
 * log_action_cnc  (start/pause/finish/break)
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'log_action_cnc') {
    $workOrderId  = intval($_REQUEST['work_order_id']);
    $tableId      = intval($_REQUEST['table_id'] ?? 0);
    $partId       = intval($_REQUEST['part_id'] ?? 0);
    $machineId    = intval($_REQUEST['machine_id'] ?? 0);
    $engineerId   = intval($_SESSION['engineer_id'] ?? 0);
    $actionType   = $conn->real_escape_string($_REQUEST['action_type']);
    $cncMachineTableId = intval($_REQUEST['cnc_machine_table_id'] ?? 0); // this is manuf_id
    $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']) : 1.0;
        $breakReason   = isset($_REQUEST['break_reason']) ? mysqli_real_escape_string($conn, $_REQUEST['break_reason']) : 'Scheduled Break';
        if ($breakDuration < 0.5 || $breakDuration > 10) $breakDuration = 1.0;

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

        $priorityResult = mysqli_query($conn, "
            SELECT id, priority, machine_id FROM cnc_machine_table
            WHERE work_order_id = $workOrderId AND table_id = $tableId
              AND manuf_id = $cncMachineTableId AND part_id = $partId LIMIT 1
        ");

        if ($priorityResult && mysqli_num_rows($priorityResult) > 0) {
            $priorityRow  = mysqli_fetch_assoc($priorityResult);
            $afterTaskId  = $priorityRow['id'];
            $afterPriority = $priorityRow['priority'];
            $machineId    = $priorityRow['machine_id'];
            $breakPriority = $afterPriority + 1;

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

            if (!$error) {
                $taskResult = mysqli_query($conn, "SELECT end_date FROM cnc_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) + ($breakDuration * 3600));

                    $insertBreakQuery = "INSERT INTO cnc_machine_table
                        (machine_id, table_id, start_date, end_date, original_start_date, original_end_date,
                         total_hours, original_total_hours, remaing_hours, original_remaing_hours,
                         is_break, break_reason, priority, work_order_id, part_id, quantity, product_name, finished)
                        VALUES ($machineId, $tableId, '$startDate', '$endDate', '$startDate', '$endDate',
                                $breakDuration, $breakDuration, $breakDuration, $breakDuration, 1, '$breakReason',
                                $breakPriority, 0, 0, 0, 'BREAK: $breakReason', 0)";

                    if (!mysqli_query($conn, $insertBreakQuery)) { $error = true; $errorMessage = mysqli_error($conn); }
                } else {
                    $error = true; $errorMessage = "Current task not found";
                }
            }
        } else {
            $error = true; $errorMessage = "Task not found for scheduling break";
        }

        $logSql = "INSERT INTO cnc_machine_activity_log
            (work_order_id, part_id, machine_id, table_id, cnc_machine_table_id, engineer_id, action_type, created_at)
            VALUES ($workOrderId, $partId, $machineId, $tableId, $cncMachineTableId, $engineerId, '$actionType', '$createdOn')";

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

    // UPH snapshot (keyed by manuf_id, consistent with the rest of this file)
    $uphRes = mysqli_query($conn, "
        SELECT total_hours, setup_hours, quantity, original_uph
        FROM cnc_machine_table WHERE manuf_id = $cncMachineTableId LIMIT 1
    ");
    if ($uphRes && mysqli_num_rows($uphRes) > 0) {
        $uphRow = mysqli_fetch_assoc($uphRes);
        if (floatval($uphRow['original_uph']) <= 0) {
            $productionHours = max(0, floatval($uphRow['total_hours']) - floatval($uphRow['setup_hours']));
            $snapshotUph = ($productionHours > 0) ? round(floatval($uphRow['quantity']) / $productionHours, 2) : 0;
            mysqli_query($conn, "UPDATE cnc_machine_table SET original_uph = '$snapshotUph' WHERE manuf_id = '$cncMachineTableId'");
        }
    }

    if (in_array($actionType, ['scheduler_break_start', 'scheduler_break_stop'])) {
        $sql = "INSERT INTO cnc_machine_activity_log
            (work_order_id, part_id, machine_id, table_id, cnc_machine_table_id, engineer_id, action_type, created_at)
            VALUES ($workOrderId, $partId, $machineId, $tableId, $cncMachineTableId, $engineerId, '$actionType', '$createdOn')";
        echo json_encode(mysqli_query($conn, $sql)
            ? ["success" => true, "message" => "Scheduler break logged successfully"]
            : ["success" => false, "message" => mysqli_error($conn)]);
        exit;
    }

    $sql = "INSERT INTO cnc_machine_activity_log
        (work_order_id, part_id, machine_id, table_id, cnc_machine_table_id, engineer_id, action_type, created_at)
        VALUES ($workOrderId, $partId, $machineId, $tableId, $cncMachineTableId, $engineerId, '$actionType', '$createdOn')";

    if ($actionType === 'finish') {
        mysqli_query($conn, "
            UPDATE cnc_machine_table SET finished = 1, changeover_pending = 1
            WHERE work_order_id = $workOrderId AND part_id = $partId
              AND manuf_id = $cncMachineTableId AND table_id = $tableId
        ");

        // FIX: previously nothing here ever checked whether the finished
        // task was dual-table. If it was, its mirror on the opposite table
        // is now finished too (or it would sit there forever, permanently
        // blocking that table for a job that's actually done) — and since
        // finishing removes the task from future priority walks, the freed
        // table time needs an immediate reschedule rather than waiting for
        // some unrelated action to trigger one.
        $finishedRows = mysqli_query($conn, "
            SELECT id, is_dual_table, machine_id FROM cnc_machine_table
            WHERE work_order_id = $workOrderId AND part_id = $partId
              AND manuf_id = $cncMachineTableId AND table_id = $tableId
        ");
        $finishedMachineId = $machineId;
        while ($fr = mysqli_fetch_assoc($finishedRows)) {
            if (intval($fr['is_dual_table']) === 1) {
                cnc_finishDualTablePartnerRows($conn, intval($fr['id']));
            }
            $finishedMachineId = intval($fr['machine_id']);
        }

        mysqli_query($conn, $sql);
        cnc_fullRescheduleMachine($conn, $finishedMachineId);
        echo json_encode(["success" => true]);
        exit;
    }

    echo json_encode(mysqli_query($conn, $sql) ? ["success" => true] : ["success" => false, "message" => mysqli_error($conn)]);
    exit;
}

/* =====================================================================
 * log_breakdown_cnc — the tablet's "Machine Breakdown" flow
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'log_breakdown_cnc') {

    $machineId       = intval($_REQUEST['machine_id'] ?? 0);
    $engineerId      = intval($_SESSION['engineer_id'] ?? 0);
    $actionType      = $conn->real_escape_string($_REQUEST['action_type']);
    $breakdownReason = isset($_REQUEST['breakdown_reason']) ? intval($_REQUEST['breakdown_reason']) : null;
    $createdOn       = date('Y-m-d H:i:s');

    $rawCncIds = preg_replace('/[^0-9,]/', '', $_REQUEST['cnc_machine_table_id'] ?? ''); // manuf_ids
    $cncIdList = array_filter(array_map('intval', explode(',', $rawCncIds)));

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

    if ($actionType !== 'breakdown') exit;

    $breakdownDuration = isset($_REQUEST['breakdown_duration']) ? floatval($_REQUEST['breakdown_duration']) : 1.0;
    if ($breakdownDuration < 0.5 || $breakdownDuration > 24) {
        echo json_encode(["success" => false, "message" => "Invalid breakdown duration."]);
        exit;
    }

    mysqli_autocommit($conn, false);
    $error = false; $errorMessage = '';
    $tableIdsArray = []; $totalOkCount = 0;
    $newDualTaskIdsNeedingMirror = []; // continuing (remaining-qty) rows that still need a mirror rebuilt

    $tableListResult = mysqli_query($conn, "
        SELECT DISTINCT table_id FROM cnc_machine_table
        WHERE machine_id = $machineId AND manuf_id IN ($inClause) AND is_break = 0 AND finished = 0
    ");
    $tablesToProcess = [];
    while ($tRow = mysqli_fetch_assoc($tableListResult)) {
        $tid = intval($tRow['table_id']);
        $activeTaskResult = mysqli_query($conn, "
            SELECT * FROM cnc_machine_table
            WHERE machine_id = $machineId AND table_id = $tid AND manuf_id IN ($inClause)
              AND is_break = 0 AND finished = 0 ORDER BY priority ASC LIMIT 1
        ");
        if ($activeTaskResult && mysqli_num_rows($activeTaskResult) > 0) {
            $tablesToProcess[] = ['table_id' => $tid, 'task' => mysqli_fetch_assoc($activeTaskResult)];
        }
    }

    if (empty($tablesToProcess)) {
        mysqli_rollback($conn); mysqli_autocommit($conn, true);
        echo json_encode(["success" => false, "message" => "No active tasks found"]);
        exit;
    }

    foreach ($tablesToProcess as $tableEntry) {
        if ($error) break;

        $currentTableId = $tableEntry['table_id'];
        $task = $tableEntry['task'];
        $tableIdsArray[] = $currentTableId;

        $currentId  = intval($task['id']);
        $priority   = intval($task['priority']);
        $currentQty = floatval($task['quantity']);
        $endDate    = $task['end_date'];
        $manufId    = isset($task['manuf_id']) ? intval($task['manuf_id']) : 0;

        $okQuery = mysqli_query($conn, "
            SELECT SUM(quantity) AS ok_count FROM cnc_part_count_log
            WHERE work_order_id = {$task['work_order_id']} AND cnc_machine_table_id = $manufId
              AND part_id = {$task['part_id']} AND type = 'ok'
        ");
        $okCount = floatval(mysqli_fetch_assoc($okQuery)['ok_count'] ?? 0);
        $totalOkCount += $okCount;

        $breakdownStart = $endDate;
        $breakdownEnd   = date('Y-m-d H:i:s', strtotime($breakdownStart) + ($breakdownDuration * 3600));
        $reasonText     = "Unknown";

        if ($okCount > 0 && $okCount < $currentQty) {

            // FIX: this used to be ~60 lines of hand-duplicated split logic
            // (a near-copy of split_cnc_work_order that never propagated
            // is_dual_table onto the new row and never reset original_uph).
            // Now uses the single shared implementation.
            //
            // FIX (override direction): the ORIGINAL row ($currentId) is the
            // one being shrunk down to the already-produced qty (okCount) and
            // marked finished -- it's the "completed" half. The NEW row is
            // the remaining qty and keeps running. The previous version of
            // this call passed ['finished' => 1] as the (only, new-row)
            // override, which would have marked the wrong half -- the
            // portion still meant to resume production -- as finished.
            $splitResult = cnc_splitCncTask(
                $conn, $currentId, $okCount, $currentQty - $okCount,
                ['finished' => 1],  // keepOverrides -> applies to $currentId (the completed portion)
                []                  // splitOverrides -> applies to the new row (the continuing remainder)
            );
            if (!$splitResult) {
                $error = true; $errorMessage = "Failed to split task at breakdown point";
                break;
            }
            if ($splitResult['is_dual_table'] == 1) {
                // The completed half's mirror was already finished inside
                // cnc_splitCncTask() (since keepOverrides finished it). The
                // continuing (new) row still needs a mirror of its own --
                // can't build it yet (needs correct timing from a reschedule
                // pass first), so just remember it for after this loop.
                $newDualTaskIdsNeedingMirror[] = intval($splitResult['new_task_id']);
            }

            // Insert the breakdown-as-break row between the two halves.
            if (!mysqli_query($conn, "
                UPDATE cnc_machine_table SET priority = priority + 1
                WHERE machine_id = $machineId AND table_id = $currentTableId AND priority > $priority
            ")) { $error = true; $errorMessage = mysqli_error($conn); break; }

            if (!mysqli_query($conn, "
                INSERT INTO cnc_machine_table
                (machine_id, table_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, $currentTableId, '$breakdownStart', '$breakdownEnd',
                        $breakdownDuration, $breakdownDuration, 1, 'BREAKDOWN: $reasonText',
                        " . ($priority + 1) . ", 0, 0, 0, 'BREAKDOWN: $reasonText', 0)
            ")) { $error = true; $errorMessage = mysqli_error($conn); break; }

        } else {
            if (!mysqli_query($conn, "
                UPDATE cnc_machine_table SET priority = priority + 1
                WHERE machine_id = $machineId AND table_id = $currentTableId AND priority > $priority
            ")) { $error = true; $errorMessage = mysqli_error($conn); break; }

            if (!mysqli_query($conn, "
                INSERT INTO cnc_machine_table
                (machine_id, table_id, start_date, end_date, total_hours, remaing_hours,
                 is_break, break_reason, priority, setup_hours)
                VALUES ($machineId, $currentTableId, '$breakdownStart', '$breakdownEnd',
                        $breakdownDuration, $breakdownDuration, 1, 'BREAKDOWN: $reasonText',
                        " . ($priority + 1) . ", 0)
            ")) { $error = true; $errorMessage = mysqli_error($conn); break; }
        }
    }

    $cncMachineTableIds = implode(',', $tableIdsArray);
    if (!$error && !mysqli_query($conn, "
        INSERT INTO cnc_machine_breakdown_log
        (machine_id, engineer_id, cnc_machine_table_ids, breakdown_reason, breakdown_duration, ok_count_at_breakdown, status, created_at)
        VALUES ($machineId, $engineerId, '$cncMachineTableIds', $breakdownReason, $breakdownDuration, $totalOkCount, 'active', '$createdOn')
    ")) {
        $error = true; $errorMessage = mysqli_error($conn);
    }

    if ($error) {
        mysqli_rollback($conn);
        echo json_encode(["success" => false, "message" => $errorMessage]);
    } else {
        mysqli_commit($conn);
        cnc_fullRescheduleMachine($conn, $machineId);

        // Any continuing (remaining-qty) rows that are dual-table need a
        // fresh mirror -- their old one belonged to the pre-split job and
        // was finished along with the completed half. Build it now that a
        // reschedule pass has given the new row correct timing to mirror.
        if (!empty($newDualTaskIdsNeedingMirror)) {
            foreach ($newDualTaskIdsNeedingMirror as $ntid) {
                cnc_rebuildDualTableMirror($conn, $ntid);
            }
            cnc_fullRescheduleMachine($conn, $machineId);
        }

        echo json_encode(["success" => true, "message" => "Breakdown logged successfully"]);
    }
    mysqli_autocommit($conn, true);
    exit;
}

/* =====================================================================
 * log_bulk_action_cnc
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'log_bulk_action_cnc') {
    session_start();
    $actionType = mysqli_real_escape_string($conn, $_REQUEST['action_type']);
    $workOrders = json_decode($_REQUEST['work_orders'], true);
    $engineerId = intval($_SESSION['user_id']);
    $createdOn  = date('Y-m-d H:i:s');

    $successCount = 0; $errorCount = 0; $skippedCount = 0;

    if (!is_array($workOrders) || empty($workOrders)) {
        echo json_encode(['success' => false, 'message' => 'No work orders provided.']);
        exit;
    }

    foreach ($workOrders as $order) {
        $workOrderId = intval($order['workOrderId'] ?? 0);
        $partId      = mysqli_real_escape_string($conn, $order['partId'] ?? '');
        $machineId   = intval($order['machineId'] ?? 0);
        $tableId     = intval($order['tableId'] ?? 0);
        $cncMachineTableId = intval($order['cncMachineTableId'] ?? 0); // manuf_id

        if (!$workOrderId || !$machineId || !$engineerId || !$actionType) { $errorCount++; continue; }

        $checkSql = "SELECT action_type FROM cnc_machine_activity_log
            WHERE machine_id = $machineId AND table_id = $tableId AND cnc_machine_table_id = $cncMachineTableId
            ORDER BY created_at DESC LIMIT 1";
        $checkResult = mysqli_query($conn, $checkSql);

        if ($checkResult && mysqli_num_rows($checkResult) > 0) {
            $currentState = mysqli_fetch_assoc($checkResult)['action_type'];
            if (($actionType === 'start' && $currentState === 'start') ||
                ($actionType === 'pause' && $currentState === 'pause')) {
                $skippedCount++;
                continue;
            }
        }

        $sql = "INSERT INTO cnc_machine_activity_log
            (work_order_id, part_id, machine_id, table_id, cnc_machine_table_id, engineer_id, action_type, created_at)
            VALUES ($workOrderId, '$partId', $machineId, $tableId, $cncMachineTableId, $engineerId, '$actionType', '$createdOn')";

        if (mysqli_query($conn, $sql)) {
            if ($actionType === 'finish') {
                mysqli_query($conn, "UPDATE cnc_machine_table SET finished = 1 WHERE work_order_id = $workOrderId AND part_id = '$partId'");
            }
            $successCount++;
        } else {
            $errorCount++;
        }
    }

    $message = "Processed: $successCount changed";
    if ($skippedCount > 0) $message .= ", $skippedCount already in desired state";
    if ($errorCount > 0)   $message .= ", $errorCount failed";

    echo json_encode(['success' => true, 'message' => $message, 'changed' => $successCount, 'skipped' => $skippedCount, 'errors' => $errorCount]);
    exit;

} 
 else if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'end_breakdown_cnc') {

    $machineId  = intval($_REQUEST['machine_id']);
    $engineerId = intval($_SESSION['engineer_id'] ?? 0);
    $createdOn  = date('Y-m-d H:i:s');

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

    $res = mysqli_query($conn, "SELECT * FROM cnc_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);
    $cncMachineTableIds = mysqli_real_escape_string($conn, $row['cnc_machine_table_ids']);

    // FIX: use ACTUAL elapsed time (now - when the breakdown started),
    // not the operator-entered ESTIMATE stored on the active row. That
    // estimate is what the placeholder BREAKDOWN block(s) were scheduled
    // with — if the real outage ran longer or shorter, the reschedule
    // below needs the true duration or everything downstream stays wrong.
    $startTs     = strtotime($row['created_at']);
    $nowTs       = strtotime($createdOn);
    $actualHours = round(max($nowTs - $startTs, 60) / 3600, 4); // floor 1 min, avoid 0/negative

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

    if (!mysqli_query($conn, "
        INSERT INTO cnc_machine_breakdown_log
        (machine_id, engineer_id, cnc_machine_table_ids, breakdown_reason, breakdown_duration, ok_count_at_breakdown, status, created_at)
        VALUES ($machineId, $engineerId, '$cncMachineTableIds', {$row['breakdown_reason']},
                $actualHours, {$row['ok_count_at_breakdown']}, 'completed', '$createdOn')
    ")) {
        $error = true; $errorMessage = mysqli_error($conn);
    }

    // FIX: correct the placeholder 'BREAKDOWN: ...' block(s) in
    // cnc_machine_table to reflect the ACTUAL elapsed time before the
    // reschedule below runs off of them — otherwise cnc_fullRescheduleMachine()
    // would still build the rest of the schedule on the original guess.
    if (!$error) {
        $blocksRes = mysqli_query($conn, "
            SELECT id, start_date FROM cnc_machine_table
            WHERE machine_id = $machineId AND is_break = 1
              AND break_reason LIKE 'BREAKDOWN%' AND finished = 0
        ");
        while ($block = mysqli_fetch_assoc($blocksRes)) {
            $blockId = intval($block['id']);
            $newEnd  = date('Y-m-d H:i:s', strtotime($block['start_date']) + $actualHours * 3600);
            if (!mysqli_query($conn, "
                UPDATE cnc_machine_table
                SET total_hours = $actualHours, remaing_hours = $actualHours, end_date = '$newEnd'
                WHERE id = $blockId
            ")) { $error = true; $errorMessage = mysqli_error($conn); break; }
        }
    }

    if ($error) {
        mysqli_rollback($conn);
        mysqli_autocommit($conn, true);
        echo json_encode(["success" => false, "message" => $errorMessage]);
    } else {
        mysqli_commit($conn);
        mysqli_autocommit($conn, true);
        mysqli_query($conn, "UPDATE cnc_machine_table SET is_breakdown_affected = 0 WHERE machine_id = $machineId AND is_breakdown_affected = 1");
        cnc_fullRescheduleMachine($conn, $machineId);
        echo json_encode(["success" => true, "message" => "Breakdown closed successfully", "actual_duration_hours" => $actualHours]);
    }
    exit;
}



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

    $machineId  = intval($_REQUEST['machine_id']);
    $engineerId = intval($_SESSION['engineer_id'] ?? 0);
    $createdOn  = date('Y-m-d H:i:s');

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

    $res = mysqli_query($conn, "SELECT * FROM cnc_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);
    $cncMachineTableIds = mysqli_real_escape_string($conn, $row['cnc_machine_table_ids']);

    if (mysqli_query($conn, "
        INSERT INTO cnc_machine_breakdown_log
        (machine_id, engineer_id, cnc_machine_table_ids, breakdown_reason, breakdown_duration, ok_count_at_breakdown, status, created_at)
        VALUES ($machineId, $engineerId, '$cncMachineTableIds', {$row['breakdown_reason']},
                {$row['breakdown_duration']}, {$row['ok_count_at_breakdown']}, '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.
        mysqli_query($conn, "UPDATE cnc_machine_table SET is_breakdown_affected = 0 WHERE machine_id = $machineId AND is_breakdown_affected = 1");
        cnc_fullRescheduleMachine($conn, $machineId);

        echo json_encode(["success" => true, "message" => "Breakdown closed successfully"]);
    } else {
        echo json_encode(["success" => false, "message" => mysqli_error($conn)]);
    }
    exit;
}
*/
/* =====================================================================
 * log_count_cnc  (OK / NOK / Quarantine counting + inventory)
 * No scheduling bugs identified in this block — behaviour preserved
 * exactly, including its already-correct use of manuf_id.
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'log_count_cnc') {

    $tableId     = intval($_REQUEST['table_id']);
    $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;
    $cncMachineTableId = intval($_REQUEST['cnc_machine_table_id'] ?? 0);
    $createdOn   = date('Y-m-d H:i:s');
    $set_id      = intval($_REQUEST['setId'] ?? 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);
                }
            }
            reduceBomChildInventory($conn, $partId, $quantity, $workOrderId, $set_id);

            if ($quantity > 0) {
                $insertSql = "INSERT INTO cnc_part_count_log
                    (work_order_id, machine_id, table_id, part_id, partIds, engineer_id, setId, type, quantity, final_quantity, cnc_machine_table_id, created_at)
                    VALUES ($workOrderId, $machineId, $tableId, $partId, $partId, $engineerId, $set_id, '$type', $quantity, $quantity, $cncMachineTableId, '$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, final_quantity FROM cnc_part_count_log
                    WHERE work_order_id = $workOrderId AND machine_id = $machineId AND engineer_id = $engineerId
                      AND part_id = $partId AND cnc_machine_table_id = $cncMachineTableId 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 cnc_part_count_log WHERE id = {$row['id']}")) { echo json_encode(["success" => false, "message" => mysqli_error($conn)]); exit; }
                } else {
                    $newFinalQty = $row['final_quantity'] + $quantity;
                    if (!mysqli_query($conn, "UPDATE cnc_part_count_log SET quantity = $newQuantity, final_quantity = $newFinalQty WHERE id = {$row['id']}")) { echo json_encode(["success" => false, "message" => mysqli_error($conn)]); exit; }
                }
            }
            echo json_encode(["success" => true]);
            exit;
        }

        if ($quantity > 0) {
            $insertSql = "INSERT INTO cnc_part_count_log
                (work_order_id, machine_id, table_id, part_id, partIds, engineer_id, type, quantity, final_quantity, cnc_machine_table_id, created_at)
                VALUES ($workOrderId, $machineId, $tableId, $partId, $partId, $engineerId, '$type', $quantity, $quantity, $cncMachineTableId, '$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)]);
        } else if ($quantity < 0) {
            $checkResult = $conn->query("SELECT id, quantity, final_quantity FROM cnc_part_count_log
                WHERE work_order_id = $workOrderId AND machine_id = $machineId AND engineer_id = $engineerId
                  AND part_id = $partId AND cnc_machine_table_id = $cncMachineTableId 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);
                if ($newQuantity == 0) {
                    $ok = mysqli_query($conn, "DELETE FROM cnc_part_count_log WHERE id = {$row['id']}");
                } else {
                    $newFinalQty = $row['final_quantity'] + $quantity;
                    $ok = mysqli_query($conn, "UPDATE cnc_part_count_log SET quantity = $newQuantity, final_quantity = $newFinalQty 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;
    }

    // NOK / QUARANTINE — unchanged from original (preserved verbatim below).
    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 cnc_part_count_log
            (work_order_id, machine_id, table_id, part_id, engineer_id, type, setId, partIds, reason_id, quantity, final_quantity, cnc_machine_table_id, created_at)
            VALUES ($workOrderId, $machineId, $tableId, $partId, $engineerId, '$type', '$set_id', '$nok_q_scrap_part_ids_part_ids', $reasonId, $quantity, $quantity, $cncMachineTableId, '$createdOn')";

        if (!mysqli_query($conn, $insertMain)) {
            mysqli_rollback($conn); mysqli_autocommit($conn, true);
            echo json_encode(["success" => false, "message" => mysqli_error($conn)]); exit;
        }
        $cncPartCountLogId = 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;
            $sql = "INSERT INTO cnc_selected_ok_parts (part_id, quantity, cnc_machine_table_id, cnc_part_count_log_id, created_at)
                    VALUES ($singlePartId, 1, $cncMachineTableId, $cncPartCountLogId, '$createdOn')";
            if (!mysqli_query($conn, $sql)) { $success = false; break; }
        }

        if ($success) {
            foreach ($unselectedParts as $singlePartId) {
                if ($singlePartId <= 0) continue;
                $sql = "INSERT INTO cnc_unselected_ok_parts (part_id, quantity, cnc_machine_table_id, cnc_part_count_log_id, created_at)
                        VALUES ($singlePartId, 1, $cncMachineTableId, $cncPartCountLogId, '$createdOn')";
                if (!mysqli_query($conn, $sql)) { $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" => "Failed to record NOK/Quarantine details"]);
        }
        exit;

    } else if ($quantity < 0) {
        mysqli_autocommit($conn, false);
        $success = true;

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

        if ($checkResult->num_rows > 0) {
            $row = $checkResult->fetch_assoc();
            $existingId = $row['id'];
            $newQuantity = $row['quantity'] + $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 cnc_unselected_ok_parts WHERE cnc_part_count_log_id = $existingId");
                $unselectedReversals = [];
                while ($uRow = mysqli_fetch_assoc($allUnselectedRes)) {
                    $invPartId = intval($uRow['part_id']);
                    $unselectedReversals[$invPartId] = ($unselectedReversals[$invPartId] ?? 0) + floatval($uRow['quantity']);
                }
                foreach ($unselectedReversals as $invPartId => $totalQty) {
                    updateInventoryStock($conn, $invPartId, -$totalQty, $workOrderId, $set_id);
                }
                if (!mysqli_query($conn, "DELETE FROM cnc_selected_ok_parts WHERE cnc_part_count_log_id = $existingId")) $success = false;
                if ($success && !mysqli_query($conn, "DELETE FROM cnc_unselected_ok_parts WHERE cnc_part_count_log_id = $existingId")) $success = false;
                if ($success && !mysqli_query($conn, "DELETE FROM cnc_part_count_log WHERE id = $existingId")) $success = false;
            } else {
                $lastUnselectedRes = mysqli_query($conn, "SELECT id, part_id, quantity FROM cnc_unselected_ok_parts WHERE cnc_part_count_log_id = $existingId ORDER BY id DESC LIMIT 1");
                if ($lastUnselectedRes && mysqli_num_rows($lastUnselectedRes) > 0) {
                    $lastRow = mysqli_fetch_assoc($lastUnselectedRes);
                    updateInventoryStock($conn, intval($lastRow['part_id']), -floatval($lastRow['quantity']), $workOrderId, $set_id);
                }
                if (!mysqli_query($conn, "DELETE FROM cnc_selected_ok_parts WHERE cnc_part_count_log_id = $existingId ORDER BY id DESC LIMIT 1")) $success = false;
                if ($success) mysqli_query($conn, "DELETE FROM cnc_unselected_ok_parts WHERE cnc_part_count_log_id = $existingId ORDER BY id DESC LIMIT 1");
                if ($success && !mysqli_query($conn, "UPDATE cnc_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;
}

/* =====================================================================
 * schedule_break_all_tables_cnc / stop_all_breaks_cnc / check_break_status_cnc
 * changeover / first-off / UPH / clock / logout endpoints
 * — unchanged from original, no scheduling bugs identified.
 * ===================================================================== */
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'schedule_break_all_tables_cnc') {
    $tables = json_decode($_POST['tables'], true);
    $durationMinutes = floatval($_POST['duration']);
    $durationHours   = $durationMinutes / 60;
    $reason = mysqli_real_escape_string($conn, $_POST['reason']);
    $engId  = intval($_SESSION['engineer_id'] ?? 0);

    if (empty($tables) || $durationMinutes < 1 || $durationMinutes > 600) {
        echo json_encode(['success' => false, 'message' => 'Invalid parameters']); exit;
    }

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

    foreach ($tables as $table) {
        $tableId     = intval($table['table_id']);
        $workOrderId = intval($table['work_order_id']);
        $partId      = intval($table['part_id']);
        $machineId   = intval($table['machine_id']);
        $cncId       = intval($table['cnc_machine_table_id']);

        $priorityResult = mysqli_query($conn, "
            SELECT id, priority FROM cnc_machine_table
            WHERE work_order_id = $workOrderId AND table_id = $tableId AND part_id = $partId AND manuf_id = $cncId LIMIT 1
        ");
        if ($priorityResult && mysqli_num_rows($priorityResult) > 0) {
            $priorityRow = mysqli_fetch_assoc($priorityResult);
            $afterTaskId = $priorityRow['id'];
            $breakPriority = $priorityRow['priority'] + 1;

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

            $taskResult = mysqli_query($conn, "SELECT end_date FROM cnc_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) + ($durationMinutes * 60));

                if (!mysqli_query($conn, "
                    INSERT INTO cnc_machine_table
                    (machine_id, table_id, start_date, end_date, original_start_date, original_end_date,
                     total_hours, original_total_hours, remaing_hours, original_remaing_hours,
                     is_break, break_reason, priority, work_order_id, part_id, quantity, product_name, finished)
                    VALUES ($machineId, $tableId, '$startDate', '$endDate', '$startDate', '$endDate',
                            $durationHours, $durationHours, $durationHours, $durationHours, 1, '$reason',
                            $breakPriority, 0, 0, 0, 'BREAK: $reason', 0)
                ")) { $error = true; $errorMessage = mysqli_error($conn); break; }

                $now = date('Y-m-d H:i:s');
                $lastStatusRow = mysqli_fetch_assoc(mysqli_query($conn, "
                    SELECT action_type FROM cnc_machine_activity_log
                    WHERE machine_id = $machineId AND table_id = $tableId AND cnc_machine_table_id = $cncId
                    ORDER BY created_at DESC LIMIT 1
                "));
                if (isset($lastStatusRow['action_type']) && $lastStatusRow['action_type'] === 'start') {
                    mysqli_query($conn, "
                        INSERT INTO cnc_machine_activity_log
                        (work_order_id, part_id, machine_id, table_id, cnc_machine_table_id, engineer_id, action_type, created_at)
                        VALUES ($workOrderId, $partId, $machineId, $tableId, $cncId, $engId, 'pause', '$now')
                    ");
                }
            } else {
                $error = true; $errorMessage = "Task not found for table $tableId"; break;
            }
        } else {
            $error = true; $errorMessage = "Task not found for table $tableId"; break;
        }
    }

    if ($error) {
        mysqli_rollback($conn);
        echo json_encode(['success' => false, 'message' => $errorMessage]);
    } else {
        mysqli_commit($conn);
        if ($machineId) cnc_fullRescheduleMachine($conn, $machineId);
        echo json_encode(['success' => true, 'message' => 'Break scheduled for all tables']);
    }
    mysqli_autocommit($conn, true);
    exit;
}

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'stop_all_breaks_cnc') {
    echo json_encode(mysqli_query($conn, "UPDATE cnc_machine_table SET finished = 1 WHERE is_break = 1 AND finished = 0")
        ? ['success' => true, 'message' => 'All breaks stopped']
        : ['success' => false, 'message' => mysqli_error($conn)]);
    exit;
}

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'check_break_status_cnc') {
    $result = mysqli_query($conn, "SELECT COUNT(*) as break_count FROM cnc_machine_table WHERE is_break = 1 AND finished = 0");
    $row = mysqli_fetch_assoc($result);
    echo json_encode(['success' => true, 'is_break_active' => ($row['break_count'] > 0)]);
    exit;
}

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'start_changeover_cnc') {
    $machineId  = intval($_REQUEST['machine_id']);
    $cncTableId = intval($_REQUEST['cnc_machine_table_id']); // manuf_id
    $clockNo    = mysqli_real_escape_string($conn, $_REQUEST['clock_no'] ?? '');

    if (!$clockNo || !$cncTableId) { echo json_encode(["success" => false, "message" => "Missing parameters"]); 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']);

    $sql = "INSERT INTO cnc_machine_changeover (machine_id, employee_id, work_order_table_id, start_time, status)
            VALUES ($machineId, $employeeId, $cncTableId, NOW(), 'running')";
    echo json_encode(mysqli_query($conn, $sql) ? ["success" => true] : ["success" => false, "message" => mysqli_error($conn)]);
    exit;
}

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'end_changeover_cnc') {
    $machineId = intval($_REQUEST['machine_id']);
    $endTime   = date('Y-m-d H:i:s');

    $result = mysqli_query($conn, "
        SELECT id, start_time, work_order_table_id FROM cnc_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 cnc_machine_changeover SET end_time = '$endTime', duration_seconds = $duration, status = 'completed'
            WHERE id = {$row['id']}
        ");

        if (!empty($row['work_order_table_id'])) {
            mysqli_query($conn, "UPDATE cnc_machine_table SET changeover_pending = 0 WHERE manuf_id = {$row['work_order_table_id']}");
        }
        echo json_encode(["success" => true]);
    } else {
        echo json_encode(["success" => false, "message" => "No active changeover found"]);
    }
    exit;
}

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'first_off_signoff_cnc') {
    $workOrderId       = intval($_REQUEST['work_order_id']);
    $partId            = intval($_REQUEST['part_id']);
    $machineId         = intval($_REQUEST['machine_id']);
    $cncMachineTableId = intval($_REQUEST['cnc_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']);

    $insert = "INSERT INTO cnc_first_off_signoff
        (work_order_id, part_id, cnc_machine_table_id, machine_id, qc_employee_id, qc_comment, signed_at)
        VALUES ($workOrderId, $partId, $cncMachineTableId, $machineId, $qcEmployeeId, '$qcComment', '$signedAt')";
    echo json_encode(mysqli_query($conn, $insert) ? ["success" => true] : ["success" => false, "message" => mysqli_error($conn)]);
    exit;
}

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']);
                $childTotals[$childId] = ($childTotals[$childId] ?? 0) + floatval($bomRow['quantity_required']);
            }
        }
        foreach ($childTotals as $childId => $sumQty) {
            $rawDeduct = $sumQty * $countQty;
            $ceiledDeduct = ($countQty >= 0) ? ceil($rawDeduct) : -ceil(abs($rawDeduct));
            updateInventoryStock($conn, $childId, -$ceiledDeduct, $workOrderId, $setId);
        }
    } else {
        $mainProductId = intval($mainProductId);
        $bomResult = mysqli_query($conn, "SELECT sub_part_id, quantity_required FROM bom WHERE main_product_id = $mainProductId");
        while ($bomRow = mysqli_fetch_assoc($bomResult)) {
            $deductQty = -1 * floatval($bomRow['quantity_required']) * $countQty;
            updateInventoryStock($conn, intval($bomRow['sub_part_id']), $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")) {
            error_log("Inventory update failed: " . mysqli_error($conn) . " for item_id: $itemId");
            return false;
        }
    } else {
        if ($qtyChange < 0) { error_log("Cannot create inventory with negative stock (Item ID: $itemId)"); return false; }
        if (!mysqli_query($conn, "INSERT INTO inventory (item_id, quantity_in_stock) VALUES ($itemId, $qtyChange)")) {
            error_log("Inventory insert failed: " . mysqli_error($conn) . " for item_id: $itemId");
            return false;
        }
    }

    if ($qtyChange > 0) {
        $existRow = mysqli_fetch_assoc(mysqli_query($conn, "SELECT COUNT(*) AS total FROM production_planning WHERE part_id = $itemId AND status IN (1,2)"));
        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;
                    }
                }
            }
        }
    }
    return true;
}

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'check_active_changeover_cnc') {
    $machineId = intval($_REQUEST['machine_id']);
    $tableId   = isset($_REQUEST['table_id']) && $_REQUEST['table_id'] !== 'null' ? intval($_REQUEST['table_id']) : null;

    $sql = "SELECT c.*, t.table_id FROM cnc_machine_changeover c
            JOIN cnc_machine_table t ON t.manuf_id = c.work_order_table_id
            WHERE c.machine_id = $machineId AND c.status = 'running'";
    if ($tableId) $sql .= " AND t.table_id = $tableId";
    $sql .= " ORDER BY c.id DESC";

    $result = mysqli_query($conn, $sql);
    if ($result && mysqli_num_rows($result) > 0) {
        $changeovers = [];
        while ($row = mysqli_fetch_assoc($result)) {
            $changeovers[] = ['id' => $row['id'], 'table_id' => $row['table_id'], 'start_time' => $row['start_time'], 'employee_id' => $row['employee_id']];
        }
        echo json_encode($tableId
            ? ['success' => true, 'has_active_changeover' => true, 'changeover_data' => $changeovers[0]]
            : ['success' => true, 'has_active_changeover' => true, 'changeover_data' => $changeovers]);
    } else {
        echo json_encode(['success' => true, 'has_active_changeover' => false]);
    }
    exit;
}

define('CNC_UPH_WINDOW_MINUTES', 60);

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'get_live_uph_cnc') {
    $workOrderId       = intval($_REQUEST['work_order_id'] ?? 0);
    $partId            = intval($_REQUEST['part_id'] ?? 0);
    $cncMachineTableId = intval($_REQUEST['cnc_machine_table_id'] ?? 0);
    $tableId           = intval($_REQUEST['table_id'] ?? 0);
    $machineId         = intval($_SESSION['machine_id'] ?? 0);
    $windowMinutes     = max(5, min(480, intval($_REQUEST['window_minutes'] ?? CNC_UPH_WINDOW_MINUTES)));

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

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

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

    // Use the requested window itself as the time base (no activity-log lookup)
    $productiveHours = $windowMinutes / 60;
    $liveUph = ($productiveHours > 0) ? round($okUnits / $productiveHours, 2) : 0;

    $plannedRow = mysqli_fetch_assoc(mysqli_query($conn, "
        SELECT original_uph, quantity, total_hours, setup_hours FROM cnc_machine_table WHERE manuf_id = $cncMachineTableId LIMIT 1
    "));
    $plannedUph = 0;
    if ($plannedRow) {
        if (floatval($plannedRow['original_uph']) > 0) {
            $plannedUph = floatval($plannedRow['original_uph']);
        } else {
            $prodHours = max(0, floatval($plannedRow['total_hours']) - floatval($plannedRow['setup_hours']));
            $plannedUph = ($prodHours > 0) ? round(floatval($plannedRow['quantity']) / $prodHours, 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), 'table_id' => $tableId,
    ]);
    exit;
}

function getProductionDate($datetime = null) {
    $ts = $datetime ? strtotime($datetime) : time();
    return ((int) date('H', $ts) < 6) ? date('Y-m-d', strtotime('-1 day', $ts)) : date('Y-m-d', $ts);
}

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'update_clock_cnc') {
    $machineId = intval($_REQUEST['machine_id'] ?? 0);
    $productionSeconds = max(0, min(intval($_REQUEST['production_seconds'] ?? 0), 86400));
    $isRunning = intval($_REQUEST['is_running'] ?? 0) ? 1 : 0;
    $lastStartRaw = $_REQUEST['last_start_time'] ?? '';
    $lastStartTime = ($lastStartRaw !== '') ? date('Y-m-d H:i:s', strtotime($lastStartRaw)) : null;

    if (!$machineId) { echo json_encode(['success' => false, 'message' => 'Missing machine_id']); exit; }

    $prodDate = getProductionDate();
    $lastStartSql = ($lastStartTime !== null) ? "'" . mysqli_real_escape_string($conn, $lastStartTime) . "'" : "NULL";

    $upsertSql = "INSERT INTO cnc_machine_clock_daily (machine_id, production_date, production_seconds, last_start_time, is_running)
                  VALUES ($machineId, '$prodDate', $productionSeconds, $lastStartSql, $isRunning)
                  ON DUPLICATE KEY UPDATE production_seconds = VALUES(production_seconds), last_start_time = VALUES(last_start_time), is_running = VALUES(is_running)";

    echo json_encode(mysqli_query($conn, $upsertSql) ? ['success' => true, 'production_date' => $prodDate] : ['success' => false, 'message' => mysqli_error($conn)]);
    exit;
}

if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'get_clock_cnc') {
    $machineId = intval($_REQUEST['machine_id'] ?? 0);
    if (!$machineId) { echo json_encode(['success' => false, 'message' => 'Missing machine_id']); exit; }

    $prodDate = getProductionDate();
    $res = mysqli_query($conn, "SELECT * FROM cnc_machine_clock_daily WHERE machine_id = $machineId AND production_date = '$prodDate' LIMIT 1");

    if ($res && mysqli_num_rows($res) > 0) {
        $row = mysqli_fetch_assoc($res);
        $seconds = (int) $row['production_seconds'];
        if ($row['is_running'] && $row['last_start_time']) {
            $seconds += max(0, time() - strtotime($row['last_start_time']));
        }
        echo json_encode(['success' => true, 'production_seconds' => $seconds, 'is_running' => (bool) $row['is_running'],
            'last_start_time' => $row['last_start_time'], 'production_date' => $prodDate, 'updated_at' => $row['updated_at']]);
    } else {
        echo json_encode(['success' => true, 'production_seconds' => 0, 'is_running' => false,
            'last_start_time' => null, 'production_date' => $prodDate, 'updated_at' => null]);
    }
    exit;
}

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