<?php
// SECURITY FIX: display_errors was left on (a leftover from early
// debugging) — any uncaught error here would print full file paths and
// stack traces straight to the browser. Errors are now logged instead,
// never shown, matching how db.php and generate_certificate.php already
// handle this.
ini_set('display_errors', 0);
ini_set('log_errors', 1);
error_reporting(E_ALL);

require_once 'includes/auth.php';
require_login();

require_once 'db.php';

$me = current_user();

// Coordinator's role is read-only client relations — the active work
// register isn't relevant to them, send them to their real landing page.
if ($me['role'] === 'coordinator') {
    header('Location: expiry_dashboard.php');
    exit;
}

// Capture Filter Parameters
$client   = $_GET['client'] ?? '';
$category = $_GET['category'] ?? '';
$status   = $_GET['status'] ?? '';
?>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8">
    
    <meta name="csrf-token" content="<?= htmlspecialchars(csrf_token()); ?>">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mehok Inspection Dashboard</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
    <style>
        body { background-color: #f4f6f9; font-family: 'Segoe UI', Arial, sans-serif; }
        .table-header { background-color: #2c3e50; color: #fff; }
        .badge-pass { background-color: #198754; }
        .badge-fail { background-color: #dc3545; }
        .badge-pending { background-color: #ffc107; color: #000; }

        /* Row highlight: marks whichever record was just added/edited so the
           user can immediately spot it after the modal closes. Fades out on
           its own after a few seconds rather than staying forever. */
        @keyframes rowHighlightFade {
            0%   { background-color: #fff3cd; }
            100% { background-color: transparent; }
        }
        tr.just-saved {
            animation: rowHighlightFade 3s ease-out forwards;
        }

        #toastContainer {
            position: fixed;
            top: 16px;
            right: 16px;
            z-index: 2000;
        }
    </style>
</head>
<body class="bg-light">

<div id="toastContainer"></div>

<div class="container-fluid py-4 px-4">

    <!-- Header Banner -->
    <div class="d-flex justify-content-between align-items-center mb-4 pb-2 border-bottom">
        <div>
            <h2 class="fw-bold text-primary m-0">ZORO INSPECTION REGISTER</h2>
            <p class="text-muted small m-0">Liftek Technical Inspection & NDT Register</p>
        </div>
        <button class="btn btn-outline-primary d-lg-none" type="button" data-bs-toggle="offcanvas" data-bs-target="#mobileNavMenu" aria-controls="mobileNavMenu" aria-label="Open menu">
                <i class="fa-solid fa-bars"></i>
            </button>
            <div class="d-none d-lg-flex align-items-center">
            <a href="master_items.php" class="btn btn-secondary fw-bold me-2"><i class="fa-solid fa-database me-1"></i> Master Bank</a>
            <a href="manage_checklists.php" class="btn btn-dark fw-bold me-2"><i class="fa-solid fa-list-check me-1"></i> Manage Checklists</a>
            <a href="reports.php" class="btn btn-success fw-bold me-2"><i class="fa-solid fa-file-shield me-1"></i> Reports</a>
            <a href="expiry_dashboard.php" class="btn btn-warning fw-bold me-2"><i class="fa-solid fa-clock-rotate-left me-1"></i> Expiry</a>
            <?php if ($me['role'] === 'admin'): ?>
                <a href="certificate_settings.php" class="btn btn-outline-dark fw-bold me-2"><i class="fa-solid fa-stamp me-1"></i> Branding</a>
                <a href="trash.php" class="btn btn-outline-danger fw-bold me-2"><i class="fa-solid fa-trash me-1"></i> Trash</a>
            <?php endif; ?>
            <button type="button" class="btn btn-outline-primary fw-bold me-2" onclick="openClientsModal()"><i class="fa-solid fa-address-book me-1"></i> Clients</button>
            <button type="button" class="btn btn-primary fw-bold me-3" onclick="openAddJobModal()"><i class="fa-solid fa-plus me-1"></i> Add New Inspection</button>

            <div class="dropdown">
                <button class="btn btn-light border fw-bold dropdown-toggle" type="button" data-bs-toggle="dropdown">
                    <i class="fa-solid fa-user-circle me-1"></i> <?= htmlspecialchars($me['name']); ?>
                    <span class="badge bg-secondary ms-1 text-capitalize"><?= htmlspecialchars($me['role']); ?></span>
                </button>
                <ul class="dropdown-menu dropdown-menu-end">
                    <li><a class="dropdown-item" href="account.php"><i class="fa-solid fa-signature me-2"></i> My Account &amp; Signature</a></li>
                    <?php if ($me['role'] === 'admin'): ?>
                        <li><a class="dropdown-item" href="manage_users.php"><i class="fa-solid fa-users-gear me-2"></i> Manage Users</a></li>
                        <li><a class="dropdown-item" href="activity_log.php"><i class="fa-solid fa-clock-rotate-left me-2"></i> Activity Log</a></li>
                    <?php endif; ?>
                    <li><hr class="dropdown-divider"></li>
                    <li><a class="dropdown-item text-danger" href="logout.php"><i class="fa-solid fa-right-from-bracket me-2"></i> Log Out</a></li>
                </ul>
            </div>
        </div>
    </div>

    <!-- Mobile Navigation Sidebar -->
    <div class="offcanvas offcanvas-end" tabindex="-1" id="mobileNavMenu" aria-labelledby="mobileNavMenuLabel">
        <div class="offcanvas-header border-bottom">
            <h5 class="offcanvas-title" id="mobileNavMenuLabel">
                <i class="fa-solid fa-user-circle me-1"></i> <?= htmlspecialchars($me['name']); ?>
                <span class="badge bg-secondary ms-1 text-capitalize"><?= htmlspecialchars($me['role']); ?></span>
            </h5>
            <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
        </div>
        <div class="offcanvas-body d-flex flex-column gap-2">
            <a href="master_items.php" class="btn btn-secondary fw-bold text-start"><i class="fa-solid fa-database me-1"></i> Master Bank</a>
            <a href="manage_checklists.php" class="btn btn-dark fw-bold text-start"><i class="fa-solid fa-list-check me-1"></i> Manage Checklists</a>
            <a href="reports.php" class="btn btn-success fw-bold text-start"><i class="fa-solid fa-file-shield me-1"></i> Reports</a>
            <a href="expiry_dashboard.php" class="btn btn-warning fw-bold text-start"><i class="fa-solid fa-clock-rotate-left me-1"></i> Expiry</a>
            <?php if ($me['role'] === 'admin'): ?>
                <a href="certificate_settings.php" class="btn btn-outline-dark fw-bold text-start"><i class="fa-solid fa-stamp me-1"></i> Branding</a>
                <a href="trash.php" class="btn btn-outline-danger fw-bold text-start"><i class="fa-solid fa-trash me-1"></i> Trash</a>
            <?php endif; ?>
            <button type="button" class="btn btn-outline-primary fw-bold text-start" data-bs-dismiss="offcanvas" onclick="openClientsModal()"><i class="fa-solid fa-address-book me-1"></i> Clients</button>
            <button type="button" class="btn btn-primary fw-bold text-start" data-bs-dismiss="offcanvas" onclick="openAddJobModal()"><i class="fa-solid fa-plus me-1"></i> Add New Inspection</button>
            <hr>
            <a href="account.php" class="btn btn-light border text-start"><i class="fa-solid fa-signature me-2"></i> My Account &amp; Signature</a>
            <?php if ($me['role'] === 'admin'): ?>
                <a href="manage_users.php" class="btn btn-light border text-start"><i class="fa-solid fa-users-gear me-2"></i> Manage Users</a>
                <a href="activity_log.php" class="btn btn-light border text-start"><i class="fa-solid fa-clock-rotate-left me-2"></i> Activity Log</a>
            <?php endif; ?>
            <a href="logout.php" class="btn btn-outline-danger text-start"><i class="fa-solid fa-right-from-bracket me-2"></i> Log Out</a>
        </div>
    </div>

    <!-- Filter Toolbar -->
    <div class="card shadow-sm mb-4 border-0">
        <div class="card-body bg-white rounded p-3">
            <form method="GET" action="index.php" class="row g-2 align-items-center" id="filterForm">

                <div class="col-md-3">
                    <div class="input-group">
                        <span class="input-group-text bg-light"><i class="fa-solid fa-magnifying-glass"></i></span>
                        <input type="text" name="client" class="form-control" placeholder="Search Job No, Client, or Serial No..." value="<?= htmlspecialchars($client); ?>">
                    </div>
                </div>

                <div class="col-md-2">
                    <select name="category" class="form-select">
                        <option value="">All Categories</option>
                        <option value="NDT" <?= $category === 'NDT' ? 'selected' : ''; ?>>NDT</option>
                        <option value="LLG" <?= $category === 'LLG' ? 'selected' : ''; ?>>LLG</option>
                        <option value="Appliance" <?= $category === 'Appliance' ? 'selected' : ''; ?>>Appliance</option>
                        <option value="Misc" <?= $category === 'Misc' ? 'selected' : ''; ?>>Misc</option>
                        <option value="Training" <?= $category === 'Training' ? 'selected' : ''; ?>>Training</option>
                    </select>
                </div>

                <div class="col-md-2">
                    <select name="status" class="form-select">
                        <option value="">All Statuses</option>
                        <option value="Pass" <?= $status === 'Pass' ? 'selected' : ''; ?>>Pass</option>
                        <option value="Fail" <?= $status === 'Fail' ? 'selected' : ''; ?>>Fail</option>
                    </select>
                </div>

                <div class="col-md-2">
                    <button type="submit" class="btn btn-primary w-100 fw-bold">
                        <i class="fa-solid fa-filter me-1"></i> Filter
                    </button>
                </div>

                <div class="col-md-1">
                    <a href="index.php" class="btn btn-outline-secondary w-100">Reset</a>
                </div>

                <?php if ($me['role'] === 'admin'): ?>
                <div class="col-md-2">
                    <a href="index.php?<?= http_build_query(array_merge($_GET, ['pending' => isset($_GET['pending']) ? '' : '1'])); ?>"
                       class="btn w-100 fw-bold <?= isset($_GET['pending']) ? 'btn-warning' : 'btn-outline-warning'; ?>"
                       title="Show only jobs with a complete checklist that are ready to approve">
                        <i class="fa-solid fa-hourglass-half me-1"></i> Pending Approval
                    </a>
                </div>
                <?php endif; ?>

                <div class="col-md-2 text-end">
                    <?php
                        $exportQuery = http_build_query([
                            'client' => $client,
                            'category' => $category,
                            'status' => $status
                        ]);
                    ?>
                    <a href="export_excel.php?<?= $exportQuery; ?>" class="btn btn-success w-100 fw-bold">
                        <i class="fa-solid fa-file-excel me-1"></i> Excel
                    </a>
                </div>

            </form>
        </div>
    </div>

    <!-- Main Jobs Table -->
    <div class="card shadow-sm border-0">
        <div class="card-body p-0">
            <div class="table-responsive">
                <table class="table table-hover align-middle m-0">
                    <thead class="table-header">
                        <tr>
                            <th class="ps-3">Job No</th>
                            <th>Issue Date</th>
                            <th>Client Name</th>
                            <th>Category</th>
                            <th>Item Name</th>
                            <th>Serial No</th>
                            <th>Inspector</th>
                            <th>Status</th>
                            <th class="text-center">Actions</th>
                        </tr>
                    </thead>
                    <tbody id="jobsTableBody">
                        <?php include 'includes/table_rows.php'; ?>
                    </tbody>
                </table>
            </div>
        </div>
    </div>

</div>

<!-- Global Inspection Modal Window (used for Add AND View/Edit) -->
<div class="modal fade" id="inspectionModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-xl modal-dialog-scrollable">
    <div class="modal-content" id="modalContentBody">
       <!-- Content dynamically loaded via AJAX -->
    </div>
  </div>
</div>

<!-- Certificate Preview Modal — the job-detail popup's "Certificate" button
     opens here instead of a new browser tab/page. Same pattern as
     reports.php's modal; kept as its own separate modal (not reused with
     #inspectionModal) since it shows an iframe rather than an AJAX-fetched
     form fragment, and a user may want both underlying views available. -->
<div class="modal fade" id="certificateModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-xl modal-dialog-scrollable">
    <div class="modal-content" style="height: 92vh;">
      <div class="modal-header py-2">
        <h6 class="modal-title fw-bold m-0" id="certificateModalLabel">Certificate</h6>
        <div class="ms-auto me-2 btn-group btn-group-sm">
          <button type="button" class="btn btn-outline-primary" id="certModalViewBtn" onclick="setCertificateModalView('html')">
            <i class="fa-solid fa-eye me-1"></i> View
          </button>
          <button type="button" class="btn btn-outline-success" id="certModalPdfBtn" onclick="setCertificateModalView('pdf')">
            <i class="fa-solid fa-file-pdf me-1"></i> PDF
          </button>
        </div>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body p-0">
        <!-- BUG FIX (client report 2026-08-20): see the identical fix (with
             full explanation) on reports.php's certificate modal — Chrome
             blocks an iframe-triggered download without explicit opt-in,
             falling back to opening a new tab instead. -->
        <iframe id="certificateModalFrame" src="about:blank" allow="downloads" style="width:100%; height:100%; border:0;"></iframe>
      </div>
    </div>
  </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>

<script>
var currentQueryString = window.location.search; // preserves active filters across table refreshes

function showToast(message, isError) {
    var container = document.getElementById('toastContainer');
    var toast = document.createElement('div');
    toast.className = 'alert ' + (isError ? 'alert-danger' : 'alert-success') + ' shadow-sm mb-2';
    toast.style.minWidth = '280px';
    toast.innerHTML = '<i class="fa-solid ' + (isError ? 'fa-triangle-exclamation' : 'fa-circle-check') + ' me-2"></i>' + message;
    container.appendChild(toast);
    setTimeout(function () { toast.remove(); }, 4000);
}

// ---------------------------------------------------------------------------
// CRITICAL FIX: <script> tags inserted via element.innerHTML never execute
// — this is standard browser behavior (a security/spec restriction), not a
// bug in this app. It silently broke EVERY inline script inside every
// AJAX-loaded fragment (master item auto-fill, Training field toggling,
// client search, photo upload/delete, inline client editing) because they
// were all being injected via plain `modalBody.innerHTML = html`. The fix:
// after injecting HTML, replace each inert <script> node with a freshly
// created one — browsers only execute scripts created via
// createElement/appendChild, never ones parsed from an innerHTML string.
// EVERY place that injects fetched HTML must use this helper instead of
// touching .innerHTML directly.
// ---------------------------------------------------------------------------
function injectHtmlWithScripts(container, html) {
    container.innerHTML = html;
    var oldScripts = container.querySelectorAll('script');
    oldScripts.forEach(function (oldScript) {
        var newScript = document.createElement('script');
        Array.prototype.forEach.call(oldScript.attributes, function (attr) {
            newScript.setAttribute(attr.name, attr.value);
        });
        newScript.textContent = oldScript.textContent;
        oldScript.parentNode.replaceChild(newScript, oldScript);
    });
}

// Refreshes ONLY the table rows via AJAX — no page navigation, no reload.
// Optionally highlights the row for jobId (the record just added/edited).
function refreshTable(jobIdToHighlight) {
    fetch('includes/table_rows.php' + currentQueryString)
        .then(function (r) { return r.text(); })
        .then(function (html) {
            var tbody = document.getElementById('jobsTableBody');
            tbody.innerHTML = html; // plain rows, no <script> tags here — fine as-is
            if (jobIdToHighlight) {
                var row = tbody.querySelector('tr[data-job-id="' + jobIdToHighlight + '"]');
                if (row) {
                    row.classList.add('just-saved');
                    row.scrollIntoView({ behavior: 'smooth', block: 'center' });
                }
            }
            bindDeleteButtons();
        });
}

// "Move to Trash" (soft delete, see delete_job.php / trash.php) — the
// button only ever appears for admins on NOT-YET-APPROVED jobs (see
// includes/table_rows.php), matching the pattern already used for
// reports.php's unlock button. Re-bound every time the table's HTML is
// replaced (initial load AND every refreshTable()), since the buttons are
// fresh DOM nodes each time and previous listeners don't carry over.
function bindDeleteButtons() {
    document.querySelectorAll('.js-delete-job').forEach(function (btn) {
        btn.addEventListener('click', function () {
            if (!confirm('Move this job to the Trash? It can be restored later from the Trash page.')) return;
            var jobId = btn.getAttribute('data-job-id');
            var formData = new FormData();
            formData.append('job_id', jobId);
            formData.append('csrf_token', document.querySelector('meta[name="csrf-token"]').content);

            fetch('delete_job.php', { method: 'POST', body: formData })
                .then(function (r) {
                    if (r.status === 401) { window.location.href = 'login.php'; return Promise.reject(new Error('Session expired.')); }
                    return r.json();
                })
                .then(function (data) {
                    showToast(data.message, data.status !== 'success');
                    if (data.status === 'success') {
                        var row = document.querySelector('tr[data-job-id="' + jobId + '"]');
                        if (row) row.remove();
                    }
                })
                .catch(function (err) { showToast(err.message, true); });
        });
    });
}
bindDeleteButtons();

// If the session expired mid-use, any AJAX fragment request gets a 401
// from includes/auth.php's require_login(). Injecting that into the modal
// would look broken (plain text "Not authenticated" inside a form-shaped
// box) — redirect the whole tab to login.php instead, same as a normal
// page would. Every fetch() call below runs its response through this.
function handleAuthRedirect(response) {
    if (response.status === 401) {
        window.location.href = 'login.php';
        return null; // signal callers to stop processing
    }
    return response;
}

function openInspectionModal(jobId, category) {
    var modalEl = document.getElementById('inspectionModal');
    var modalBody = document.getElementById('modalContentBody');

    modalBody.innerHTML = '<div class="text-center p-5"><div class="spinner-border text-primary" role="status"></div><p class="mt-2 text-muted">Loading Inspection Form...</p></div>';

    var myModal = bootstrap.Modal.getOrCreateInstance(modalEl);
    myModal.show();

    // BUG FIX: only Appliance/Misc jobs (which have real tbl_appliance_inspections
    // data — brand, model, load-chart, etc.) belong in view_appliance_job.php.
    // Every other category (LLG, Training, and anything else) must go to the
    // general view_job.php, which branches internally by category. The
    // previous version only special-cased LLG explicitly, so Training (and
    // any future category) silently fell through to the Appliance view —
    // showing Brand/Model/Serial fields that make no sense for a training
    // record. Appliance/Misc is now the explicit special case instead.
    var targetUrl = 'view_job.php';
    var upperCategory = category ? category.toUpperCase() : '';
    if (upperCategory === 'APPLIANCE' || upperCategory === 'MIS') { // FIX (docx item 3): tbl_master_items/tbl_jobs actually store the MIS category as 'Mis' (-> 'MIS' uppercased), never 'MISC' — this typo meant MIS jobs always fell through to the generic view_job.php (no item description, no way to hide test parameters) instead of view_appliance_job.php as intended.
        targetUrl = 'view_appliance_job.php';
    }

    fetch(targetUrl + '?id=' + jobId)
        .then(handleAuthRedirect)
        .then(function (response) {
            if (!response) return null;
            if (!response.ok) throw new Error('HTTP error ' + response.status);
            return response.text();
        })
        .then(function (html) {
            if (html === null) return;
            injectHtmlWithScripts(modalBody, html);
        })
        .catch(function (err) {
            console.error('Error loading form:', err);
            modalBody.innerHTML = '<div class="alert alert-danger m-3">Failed to load inspection details: ' + err.message + '</div>';
        });
}

// Opens a certificate (HTML view by default) inside the shared modal above
// instead of a new tab. &embed=1 tells generate_certificate.php to hide its
// own "Back" link (the modal's close button already covers that) and
// &from=index makes it link back here in the rare case the certificate is
// later opened directly (not embedded) with this same origin remembered.
var certModalJobId = null;
function openCertificateModal(jobId, mode) {
    certModalJobId = jobId;
    bootstrap.Modal.getOrCreateInstance(document.getElementById('certificateModal')).show();
    setCertificateModalView(mode === 'pdf' ? 'pdf' : 'html');
}
function setCertificateModalView(mode) {
    if (!certModalJobId) return;
    var frame = document.getElementById('certificateModalFrame');
    var viewBtn = document.getElementById('certModalViewBtn');
    var pdfBtn = document.getElementById('certModalPdfBtn');
    if (mode === 'pdf') {
        // Streamed with Content-Disposition: attachment — triggers a
        // download rather than replacing the iframe's content, so the
        // modal simply stays open on whatever it was already showing.
        frame.src = 'generate_certificate_pdf.php?id=' + encodeURIComponent(certModalJobId) + '&embed=1';
        pdfBtn.classList.replace('btn-outline-success', 'btn-success');
        viewBtn.classList.replace('btn-primary', 'btn-outline-primary');
    } else {
        frame.src = 'generate_certificate.php?id=' + encodeURIComponent(certModalJobId) + '&embed=1&from=index';
        viewBtn.classList.replace('btn-outline-primary', 'btn-primary');
        pdfBtn.classList.replace('btn-success', 'btn-outline-success');
    }
}

// prefillData (task 22, "Save & Duplicate"): optional plain object of
// draft-field values (see add_job.php's draftFieldNames) to repopulate the
// freshly-fetched blank form with — used when duplicating a just-saved job.
// Stashed on window.__pendingAddJobPrefill BEFORE the fetch below so it's
// already in place the instant add_job.php's own script re-executes (via
// injectHtmlWithScripts), which is what actually consumes and clears it.
// This avoids a setTimeout/polling loop to wait for the new DOM to exist.
function openAddJobModal(prefillData) {
    var modalEl = document.getElementById('inspectionModal');
    var modalBody = document.getElementById('modalContentBody');

    modalBody.innerHTML = '<div class="text-center p-5"><div class="spinner-border text-primary" role="status"></div><p class="mt-2 text-muted">Loading New Job Form...</p></div>';

    var myModal = bootstrap.Modal.getOrCreateInstance(modalEl);
    myModal.show();

    window.__pendingAddJobPrefill = prefillData || null;

    fetch('add_job.php')
        .then(handleAuthRedirect)
        .then(function (response) { return response ? response.text() : null; })
        .then(function (html) { if (html !== null) injectHtmlWithScripts(modalBody, html); })
        .catch(function (err) {
            modalBody.innerHTML = '<div class="alert alert-danger m-3">Failed to load form: ' + err.message + '</div>';
        });
}

// This was referenced by the "Clients" button but never actually defined —
// a genuine missing-code bug, not just the script-execution issue above.
function openClientsModal() {
    var modalEl = document.getElementById('inspectionModal');
    var modalBody = document.getElementById('modalContentBody');

    modalBody.innerHTML = '<div class="text-center p-5"><div class="spinner-border text-primary" role="status"></div><p class="mt-2 text-muted">Loading Clients...</p></div>';

    var myModal = bootstrap.Modal.getOrCreateInstance(modalEl);
    myModal.show();

    fetch('clients.php')
        .then(handleAuthRedirect)
        .then(function (response) { return response ? response.text() : null; })
        .then(function (html) { if (html !== null) injectHtmlWithScripts(modalBody, html); })
        .catch(function (err) {
            modalBody.innerHTML = '<div class="alert alert-danger m-3">Failed to load clients: ' + err.message + '</div>';
        });
}

// ---------------------------------------------------------------------------
// UNIFIED AJAX SAVE HANDLER — covers all three forms that can live inside
// the modal: the "Add New Job" form, the merged LLG/general "update_job"
// form, and the Appliance/Misc form. Every one of them now returns JSON
// {status, message, job_id} instead of redirecting, so none of them ever
// navigate the browser away from index.php.
// ---------------------------------------------------------------------------
document.addEventListener('submit', function (event) {
    var form = event.target;
    if (!form.classList || !form.classList.contains('ajax-job-form')) return;

    event.preventDefault();

    var formData = new FormData(form);
    var submitBtn = form.querySelector('[type="submit"], .js-submit-btn');
    if (submitBtn) submitBtn.disabled = true;

    fetch(form.getAttribute('action'), {
        method: 'POST',
        body: formData
    })
    .then(function (response) {
        if (response.status === 401) {
            window.location.href = 'login.php';
            return Promise.reject(new Error('Session expired.'));
        }
        return response.text().then(function (text) {
            try { return JSON.parse(text); }
            catch (e) { throw new Error('Server response error: ' + text.substring(0, 200)); }
        });
    })
    .then(function (data) {
        if (data.status === 'success') {
            bootstrap.Modal.getOrCreateInstance(document.getElementById('inspectionModal')).hide();
            showToast(data.message || 'Saved successfully.', false);
            refreshTable(data.job_id);
        } else {
            showToast(data.message || 'Save failed.', true);
            if (submitBtn) submitBtn.disabled = false;
        }
    })
    .catch(function (err) {
        showToast(err.message, true);
        if (submitBtn) submitBtn.disabled = false;
        console.error(err);
    });
});

// Same AJAX pattern for the Appliance form's "Save Changes" button, which
// is a plain button (not type=submit) for historical reasons — kept
// working exactly as before, just now also refreshes+highlights+toasts
// consistently with everything else instead of only showing an inline alert.
document.addEventListener('click', function (event) {
    if (event.target && event.target.id === 'saveApplianceBtn') {
        var form = document.getElementById('applianceInspectionForm');
        if (!form) return;

        var formData = new FormData(form);
        event.target.disabled = true;

        fetch('save_appliance_job.php', {
            method: 'POST',
            body: formData
        })
        .then(function (response) {
            if (response.status === 401) {
                window.location.href = 'login.php';
                return Promise.reject(new Error('Session expired.'));
            }
            return response.text().then(function (text) {
                try { return JSON.parse(text); }
                catch (e) { throw new Error('Server response error: ' + text.substring(0, 200)); }
            });
        })
        .then(function (data) {
            if (data.status === 'success') {
                bootstrap.Modal.getOrCreateInstance(document.getElementById('inspectionModal')).hide();
                showToast(data.message || 'Saved successfully.', false);
                refreshTable(formData.get('job_id'));
            } else {
                showToast(data.message || 'Save failed.', true);
            }
        })
        .catch(function (err) {
            showToast(err.message, true);
            console.error(err);
        })
        .finally(function () {
            event.target.disabled = false;
        });
    }
});
</script>
</body>
</html>
