public/app.js Back to Presentation
// ==========================================================================
// B2B Quotation and Takeoff Program - Frontend Controller (Auth, BLOB & Embedded PDFs)
// ==========================================================================

const API_BASE = '/api';

// Globally intercept fetch to bypass localtunnel reminder page
const originalFetch = window.fetch;
window.fetch = async function (url, options = {}) {
    if (!options.headers) {
        options.headers = {};
    }
    if (options.headers instanceof Headers) {
        options.headers.set('bypass-tunnel-reminder', 'true');
    } else {
        options.headers['bypass-tunnel-reminder'] = 'true';
    }
    return originalFetch(url, options);
};

// Timezone-aware SQLite datetime parser (Thailand Timezone ICT +07:00 alignment)
function parseDbDate(dateStr) {
    if (!dateStr) return null;
    if (dateStr instanceof Date) return dateStr;
    if (typeof dateStr === 'number') return new Date(dateStr);
    
    const str = String(dateStr).trim();
    
    // Check if it's date-only YYYY-MM-DD
    if (/^\d{4}-\d{2}-\d{2}$/.test(str)) {
        const parts = str.split('-');
        return new Date(parseInt(parts[0], 10), parseInt(parts[1], 10) - 1, parseInt(parts[2], 10));
    }
    
    // If it already has Z or offset, parse directly
    if (str.includes('Z') || str.includes('+') || (str.includes('-') && str.includes('T') && str.length > 20)) {
        return new Date(str);
    }
    
    // For SQLite datetime like "YYYY-MM-DD HH:MM:SS" (stored in UTC), parse manually as UTC
    const match = str.match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2}):(\d{2})(\.\d+)?$/);
    if (match) {
        return new Date(Date.UTC(
            parseInt(match[1], 10),
            parseInt(match[2], 10) - 1,
            parseInt(match[3], 10),
            parseInt(match[4], 10),
            parseInt(match[5], 10),
            parseInt(match[6], 10)
        ));
    }
    
    // For datetime-local inputs like "YYYY-MM-DDTHH:MM", parse as local time
    const matchShort = str.match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})$/);
    if (matchShort) {
        return new Date(
            parseInt(matchShort[1], 10),
            parseInt(matchShort[2], 10) - 1,
            parseInt(matchShort[3], 10),
            parseInt(matchShort[4], 10),
            parseInt(matchShort[5], 10)
        );
    }

    return new Date(str);
}

// Helper to escape special regex characters for message highlighting
function escapeRegExp(string) {
    return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

// Test environment bypass for browser automation confirm dialogs
if (window.location.search.includes('test=true')) {
    window.confirm = () => true;
    window.prompt = (msg) => window.TEST_PROMPT_VAL || 'Drawings';

    // Expose test helper for project documents upload simulation
    window.TEST_UPLOAD_DOC = async (fileName) => {
        const dummyBlob = new Blob(['dummy content'], { type: 'application/octet-stream' });
        const dummyFile = new File([dummyBlob], fileName, { type: 'application/octet-stream' });
        await handleDocsUpload([dummyFile]);
    };
}

// Global Application State
let state = {
    workspaceMode: 'estimate',
    currentUser: null, // { id, username, role }
    currentLanguage: localStorage.getItem('lang') || 'th', // Active language state
    projects: [],
    activeProjectId: null,
    activeProject: null,
    activeProjectSummary: null,
    categories: [],
    groups: [],
    systems: [],
    suppliers: [], // List of all suppliers
    contractors: [], // List of all contractors
    rfqList: [], // List of contractor RFQs for the active project
    selectedSectionId: null, // target section when adding catalog items
    isSelectingForTemplate: false,
    editingCatalogProduct: null, // product object being edited in detail form
    currentDocFolderPath: '/', // Current path inside Project Document Vault
    currentFatReportItems: [], // Loaded items for the active FAT report
    activeProjectDocs: { folders: [], files: [] }, // Folders & files list in active project
    collapsedSections: new Set(), // Tracks IDs of collapsed sections
    imageFileToUpload: null, // selected image file
    pdfFileToUpload: null, // selected PDF specification sheet
    quoteFileToUpload: null, // selected supplier quotation file

    // Pagination states
    explorerCurrentPage: 1,
    explorerPageSize: 999999,
    explorerProducts: [],
    managerCurrentPage: 1,
    managerPageSize: 999999,
    managerProducts: [],
    activityLogPage: 1,
    activityLogLimit: 50,
    activityLogTotal: 0,
    availableReports: [],
    chatConversations: [],
    activeChatConversationId: null,
    chatThreadPollInterval: null,
    chatUnreadPollInterval: null,
    chatUserDirectory: []
};

// Helper function to prepare headers for API requests
function getHeaders() {
    const headers = {
        'Content-Type': 'application/json'
    };
    const token = localStorage.getItem('authToken');
    if (token) {
        headers['Authorization'] = `Bearer ${token}`;
    }
    return headers;
}

// Helper to get auth header object (for FormData requests that can't use getHeaders)
function getAuthHeader() {
    const token = localStorage.getItem('authToken');
    if (token) {
        return { 'Authorization': `Bearer ${token}` };
    }
    return {};
}

// Helper to handle fetch requests with auth headers
async function authFetch(url, options = {}) {
    options.credentials = 'include';
    if (!options.headers) {
        options.headers = {};
    }

    // Add JWT Bearer token
    const token = localStorage.getItem('authToken');
    if (token) {
        options.headers['Authorization'] = `Bearer ${token}`;
    }

    // Default Content-Type to JSON if body exists and is not FormData
    if (options.body && !(options.body instanceof FormData) && !options.headers['Content-Type']) {
        options.headers['Content-Type'] = 'application/json';
    }

    const res = await fetch(url, options);
    if (res.status === 401) {
        // Token expired or invalid - force re-login
        localStorage.removeItem('authToken');
        localStorage.removeItem('currentUser');
        state.currentUser = null;
        checkSession();
        showToast('Session expired. Please log in again.', 'error');
        throw new Error('Unauthorized');
    }
    if (res.status === 403) {
        const errData = await res.json();
        showToast(errData.error || t('toast_error_permission'), 'error');
        throw new Error('Forbidden');
    }
    return res;
}

// Plain <img>/<a> tags can't send an Authorization header, so append the JWT
// as a query param for authenticated media-streaming URLs (server accepts both).
function withAuthToken(url) {
    const token = localStorage.getItem('authToken');
    if (!token) return url;
    const separator = url.includes('?') ? '&' : '?';
    return `${url}${separator}token=${encodeURIComponent(token)}`;
}

// Helper to track modified project IDs during session
function markProjectModified(projectId) {
    if (!projectId || !state.currentUser) return;
    const userId = state.currentUser.id;
    const key = `modifiedProjects_${userId}`;
    let modified = [];
    try {
        modified = JSON.parse(localStorage.getItem(key)) || [];
    } catch (e) {
        modified = [];
    }
    if (!modified.includes(projectId)) {
        modified.push(projectId);
        localStorage.setItem(key, JSON.stringify(modified));
    }
}

// ==========================================================================
// Initialization & Event Listeners
// ==========================================================================
document.addEventListener('DOMContentLoaded', () => {
    // Restore sidebar collapse preference
    const sidebarCollapsed = localStorage.getItem('sidebarCollapsed') === 'true';
    if (sidebarCollapsed) {
        document.body.classList.add('sidebar-collapsed');
    }

    // Restore header menu collapse preference
    const headerMenuHidden = localStorage.getItem('headerMenuHidden') === 'true';
    const menuGrid = document.querySelector('.header-menu-grid');
    const toggleBtn = document.getElementById('btn-toggle-header-menu');
    if (headerMenuHidden && menuGrid && toggleBtn) {
        menuGrid.classList.add('menu-hidden');
        toggleBtn.setAttribute('data-i18n', 'btn_show_menu');
        const icon = toggleBtn.querySelector('i');
        if (icon) icon.className = 'fa-solid fa-eye';
    }

    initLanguage();

    const fatSelect = document.getElementById('fat-select-type');
    if (fatSelect) {
        const options = Array.from(fatSelect.options);
        const placeholder = options.shift();
        options.sort((a, b) => a.text.trim().localeCompare(b.text.trim()));
        fatSelect.innerHTML = '';
        if (placeholder) fatSelect.appendChild(placeholder);
        options.forEach(opt => fatSelect.appendChild(opt));
    }

    checkSession();
    setupEventListeners();
    setupIdleTracker();
    initPdfAnnotationEvents();

    // Bind header menu toggle button click
    if (toggleBtn && menuGrid) {
        toggleBtn.addEventListener('click', () => {
            const isHidden = menuGrid.classList.toggle('menu-hidden');
            localStorage.setItem('headerMenuHidden', isHidden);
            if (isHidden) {
                toggleBtn.setAttribute('data-i18n', 'btn_show_menu');
                const icon = toggleBtn.querySelector('i');
                if (icon) icon.className = 'fa-solid fa-eye';
            } else {
                toggleBtn.setAttribute('data-i18n', 'btn_hide_menu');
                const icon = toggleBtn.querySelector('i');
                if (icon) icon.className = 'fa-solid fa-eye-slash';
            }
            applyLanguage();
        });
    }
});

// Localization Initialization & Logic
function initLanguage() {
    state.currentLanguage = localStorage.getItem('lang') || 'th';

    // Setup event listeners for the language switcher buttons
    document.querySelectorAll('.btn-lang').forEach(btn => {
        btn.addEventListener('click', (e) => {
            const selectedLang = e.currentTarget.dataset.lang;
            changeLanguage(selectedLang);
        });
    });

    applyLanguage();
}

function changeLanguage(lang) {
    state.currentLanguage = lang;
    localStorage.setItem('lang', lang);
    applyLanguage();

    // Re-render user profile details
    updateHeaderUserDisplay();

    // Re-render dynamic components
    fetchProjects();
    if (state.activeProjectId) {
        fetchActiveProjectDetails().then(() => {
            renderWorkspace();
        });
    } else {
        renderWorkspace();
    }
}

function applyLanguage() {
    const lang = state.currentLanguage || 'th';

    // Switch HTML tag lang
    document.documentElement.lang = lang;

    // Update visual toggle buttons active classes
    document.querySelectorAll('.btn-lang').forEach(btn => {
        if (btn.dataset.lang === lang) {
            btn.classList.add('active');
        } else {
            btn.classList.remove('active');
        }
    });

    // Translate static elements marked with data-i18n
    document.querySelectorAll('[data-i18n]').forEach(el => {
        const key = el.getAttribute('data-i18n');
        const translation = t(key);
        if (translation !== key) {
            // If the element contains an icon element, keep the icon
            const icon = el.querySelector('i');
            if (icon) {
                el.innerHTML = icon.outerHTML + ' ' + translation;
            } else {
                el.textContent = translation;
            }
        }
    });

    // Translate form inputs placeholders
    document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
        const key = el.getAttribute('data-i18n-placeholder');
        const translation = t(key);
        if (translation !== key) {
            el.placeholder = translation;
        }
    });

    // Translate tooltip and titles
    document.querySelectorAll('[data-i18n-title]').forEach(el => {
        const key = el.getAttribute('data-i18n-title');
        const translation = t(key);
        if (translation !== key) {
            el.title = translation;
        }
    });
}

function checkSession() {
    const savedUser = localStorage.getItem('currentUser');
    const loginContainer = document.getElementById('login-container');

    if (savedUser) {
        state.currentUser = JSON.parse(savedUser);
        loginContainer.style.display = 'none';

        // Show user details in Header
        updateHeaderUserDisplay();

        initApp();
        // startAnnouncementPolling(); // Disabled in favor of announcements.js
        if (typeof window.checkAnnouncements === 'function') {
            window.checkAnnouncements();
        }
    } else {
        state.currentUser = null;
        loginContainer.style.display = 'flex';
        document.body.classList.remove('hide-cost-columns');
        if (state.chatUnreadPollInterval) {
            clearInterval(state.chatUnreadPollInterval);
            state.chatUnreadPollInterval = null;
        }
        if (state.announcementPollInterval) {
            clearInterval(state.announcementPollInterval);
            state.announcementPollInterval = null;
        }
        stopChatThreadPolling();
        
        if (typeof window.checkAnnouncements === 'function') {
            window.checkAnnouncements();
        }
    }
}

function updateHeaderUserDisplay() {
    if (state.currentUser) {
        const nameVal = state.currentUser.username;
        const roleVal = translateRole(state.currentUser.role);
        
        const elName = document.getElementById('logged-in-user-name');
        if (elName) elName.textContent = nameVal;
        
        const elRole = document.getElementById('logged-in-user-role');
        if (elRole) elRole.textContent = roleVal;
        
        const elNameDropdown = document.getElementById('logged-in-user-name-dropdown');
        if (elNameDropdown) elNameDropdown.textContent = nameVal;
        
        const elRoleDropdown = document.getElementById('logged-in-user-role-dropdown');
        if (elRoleDropdown) elRoleDropdown.textContent = roleVal;

        // Toggle cost columns visibility class
        const allowedRoles = ['superadmin', 'admin', 'excusive', 'procurment', 'procurement_manager', 'account_manager'];
        if (allowedRoles.includes(state.currentUser.role)) {
            document.body.classList.remove('hide-cost-columns');
        } else {
            document.body.classList.add('hide-cost-columns');
        }
    }
}

function translateRole(role) {
    const map = {
        'admin': t('role_admin'),
        'supervisor': t('role_supervisor'),
        'estimate': t('role_estimate'),
        'user': t('role_user'),
        'sale': t('role_sale'),
        'design': t('role_design'),
        'production': t('role_production'),
        'qc': t('role_qc'),
        'qa': t('role_qa'),
        'stock': t('role_stock'),
        'procurment': t('role_procurment'),
        'support': t('role_support'),
        'excusive': t('role_excusive'),
        'draft': t('role_draft'),
        'sale_manager': t('role_sale_manager'),
        'design_manager_mech': t('role_design_manager_mech'),
        'design_manager_elec': t('role_design_manager_elec'),
        'consultant_mech': t('role_consultant_mech'),
        'consultant_elec': t('role_consultant_elec'),
        'factory_manager': t('role_factory_manager'),
        'account_manager': t('role_account_manager'),
        'procurement_manager': t('role_procurement_manager'),
        'contractor': t('role_contractor')
    };
    return map[role] || role;
}

function isReadOnlyRole(role) {
    return !['admin', 'superadmin', 'supervisor', 'estimate'].includes(role);
}

async function checkPendingAnnouncements() {
    if (state.currentUser && state.currentUser.role === 'contractor') {
        return;
    }
    // If the modal is already active, don't query/overwrite
    const modal = document.getElementById('modal-announcement');
    if (modal && modal.classList.contains('active')) {
        return;
    }
    try {
        const res = await authFetch(`${API_BASE}/announcements/pending`);
        const announcements = await res.json();
        if (announcements.length > 0) {
            state.pendingAnnouncementsQueue = announcements;
            showNextPendingAnnouncement();
        }
    } catch (err) {
        console.error('Failed to check pending announcements:', err);
    }
}

function startAnnouncementPolling() {
    if (state.currentUser && state.currentUser.role === 'contractor') {
        if (state.announcementPollInterval) {
            clearInterval(state.announcementPollInterval);
            state.announcementPollInterval = null;
        }
        return;
    }
    if (state.announcementPollInterval) clearInterval(state.announcementPollInterval);
    checkPendingAnnouncements();
    state.announcementPollInterval = setInterval(checkPendingAnnouncements, 15000);
}

function showNextPendingAnnouncement() {
    const modal = document.getElementById('modal-announcement');
    if (!state.pendingAnnouncementsQueue || state.pendingAnnouncementsQueue.length === 0) {
        modal.classList.remove('active');
        return;
    }
    const announcement = state.pendingAnnouncementsQueue[0];
    document.getElementById('announcement-id').value = announcement.id;
    document.getElementById('announcement-title').textContent = announcement.title;
    document.getElementById('announcement-body').textContent = announcement.body;
    modal.classList.add('active');
}

async function handleAcknowledgeAnnouncement() {
    const id = document.getElementById('announcement-id').value;
    const btn = document.getElementById('btn-acknowledge-announcement');
    btn.disabled = true;
    try {
        await authFetch(`${API_BASE}/announcements/${id}/ack`, { method: 'POST' });
    } catch (err) {
        console.error('Failed to acknowledge announcement:', err);
    } finally {
        btn.disabled = false;
    }
    state.pendingAnnouncementsQueue.shift();
    showNextPendingAnnouncement();
}

async function initApp() {
    await fetchProjects();
    await fetchCategories();
    await fetchGroups();
    await fetchSystems();
    await populateSystemDropdowns();
    applyRoleBasedUI();
    checkReportsButtonVisibility();
    startChatUnreadPolling();

    // Start background projects polling for contractor to monitor new RFQs
    if (state.currentUser && state.currentUser.role === 'contractor') {
        if (state.contractorProjectsPollInterval) clearInterval(state.contractorProjectsPollInterval);
        state.contractorProjectsPollInterval = setInterval(fetchProjects, 30000);
    }

    // Auto-select first project if available
    if (state.projects.length > 0) {
        selectProject(state.projects[0].id);
    } else {
        renderWorkspace();
    }
}

function applyRoleBasedUI() {
    const role = state.currentUser ? state.currentUser.role : 'user';

    // Reset all access masking classes on body
    document.body.classList.remove('role-user');
    document.body.classList.remove('role-confidential');
    document.body.classList.remove('role-contractor');

    if (role === 'superadmin' || role === 'excusive' || role === 'admin' || role === 'supervisor' || role === 'estimate') {
        // Executive level or full estimators / administrators - sees all prices (costs and selling prices)
    } else if (role === 'sale' || role === 'sale_manager') {
        // Confidential level - sees selling prices, hides costs
        document.body.classList.add('role-confidential');
    } else {
        // ระดับทั่วไป (General) and ระดับต่ำ (Low / contractor) - hides all pricing
        document.body.classList.add('role-user');
        if (role === 'contractor') {
            document.body.classList.add('role-contractor');
        }
    }

    // Toggle Admin Panel button
    const adminPanelBtn = document.getElementById('btn-open-admin-panel');
    if (adminPanelBtn) {
        adminPanelBtn.style.display = (role === 'admin' || role === 'superadmin' || role === 'supervisor' || role === 'estimate') ? 'inline-flex' : 'none';
    }

    // Toggle Announcements button
    const announcementsBtn = document.getElementById('btn-open-announcements');
    if (announcementsBtn) {
        announcementsBtn.style.display = (role === 'admin' || role === 'superadmin' || role === 'excusive') ? 'inline-flex' : 'none';
    }

    // Toggle Super Admin System Panel button
    const systemPanelBtn = document.getElementById('btn-open-system-panel');
    if (systemPanelBtn) {
        systemPanelBtn.style.display = role === 'superadmin' ? 'inline-flex' : 'none';
    }

    // Toggle Procurement Panel button
    const procurementPanelBtn = document.getElementById('btn-open-procurement-panel');
    if (procurementPanelBtn) {
        procurementPanelBtn.style.display = ['procurment', 'admin', 'superadmin', 'excusive', 'ee_manager', 'me_manager'].includes(role) ? 'inline-flex' : 'none';
    }

    // Toggle Stock Panel button
    const stockPanelBtn = document.getElementById('btn-open-stock-panel');
    if (stockPanelBtn) {
        stockPanelBtn.style.display = ['stock', 'admin', 'superadmin'].includes(role) ? 'inline-flex' : 'none';
    }

    // Toggle BOM & PR button in project toolbar
    const openProjectBomsBtn = document.getElementById('btn-open-project-boms');
    if (openProjectBomsBtn) {
        openProjectBomsBtn.style.display = (role !== 'contractor') ? 'inline-flex' : 'none';
    }

    // Only Admin or Super Admin can manage catalog, suppliers, and templates database
    const openCatalogBtn = document.getElementById('btn-open-catalog-manager');
    const openSupplierBtn = document.getElementById('btn-open-supplier-manager');
    const openTemplateBtn = document.getElementById('btn-open-template-manager');
    const addCatalogBtn = document.getElementById('btn-add-catalog-product');

    const isCatalogWriter = (role === 'admin' || role === 'superadmin' || role === 'supervisor' || role === 'estimate');
    if (openCatalogBtn) openCatalogBtn.style.display = isCatalogWriter ? 'inline-flex' : 'none';
    if (openSupplierBtn) openSupplierBtn.style.display = isCatalogWriter ? 'inline-flex' : 'none';
    if (openTemplateBtn) openTemplateBtn.style.display = isCatalogWriter ? 'inline-flex' : 'none';
    if (addCatalogBtn) addCatalogBtn.style.display = isCatalogWriter ? 'inline-flex' : 'none';

    // User Role (Viewer only) - disable all create/edit buttons on workspace
    const projectActions = document.querySelector('.project-info-actions');
    const addSectionBtn = document.getElementById('btn-add-section');
    const createProjectBtn = document.getElementById('btn-create-project');

    if (isReadOnlyRole(role)) {
        if (projectActions) {
            projectActions.style.display = 'flex';
            document.getElementById('btn-approve-project').style.display = 'none';
            document.getElementById('btn-edit-proposal-letter').style.display = 'none';
            document.getElementById('btn-edit-project-active').style.display = 'none';
            document.getElementById('btn-clone-project-active').style.display = 'none';
            document.getElementById('btn-delete-project-active').style.display = 'none';
            document.getElementById('btn-print-bom-trigger').style.display = 'none';
        }
        if (addSectionBtn) addSectionBtn.style.display = 'none';
        if (createProjectBtn) createProjectBtn.style.display = 'none';
    } else {
        if (projectActions) {
            projectActions.style.display = 'flex';
            document.getElementById('btn-approve-project').style.display = 'inline-flex';
            document.getElementById('btn-edit-proposal-letter').style.display = 'inline-flex';
            document.getElementById('btn-edit-project-active').style.display = 'inline-flex';
            document.getElementById('btn-clone-project-active').style.display = 'inline-flex';
            document.getElementById('btn-print-bom-trigger').style.display = 'inline-flex';

            // Supervisors can only delete projects they created
            const deleteBtn = document.getElementById('btn-delete-project-active');
            if (role === 'supervisor' || role === 'estimate') {
                if (state.activeProjectSummary && state.activeProjectSummary.created_by === state.currentUser.id) {
                    deleteBtn.style.display = 'inline-flex';
                } else {
                    deleteBtn.style.display = 'none';
                }
            } else {
                deleteBtn.style.display = 'inline-flex';
            }
        }
        if (addSectionBtn) addSectionBtn.style.display = 'inline-flex';
        if (createProjectBtn) createProjectBtn.style.display = 'inline-flex';
    }

    // If active project is soft-deleted, override and hide editing/managing actions
    if (state.activeProjectSummary && state.activeProjectSummary.is_deleted === 1) {
        const projectActions = document.querySelector('.project-info-actions');
        const addSectionBtn = document.getElementById('btn-add-section');
        if (projectActions) {
            document.getElementById('btn-approve-project').style.display = 'none';
            document.getElementById('btn-edit-proposal-letter').style.display = 'none';
            document.getElementById('btn-edit-project-active').style.display = 'none';
            document.getElementById('btn-clone-project-active').style.display = 'none';
            document.getElementById('btn-delete-project-active').style.display = 'none';
            document.getElementById('btn-print-bom-trigger').style.display = 'none';
        }
        if (addSectionBtn) addSectionBtn.style.display = 'none';
    }

    // Contractor role adjustments
    const isContractor = role === 'contractor';
    const rfqDirectBtn = document.getElementById('btn-open-project-rfq-direct');
    const contractorDropdown = document.getElementById('btn-contractor-dropdown-trigger')?.parentElement;
    const exportDropdown = document.getElementById('btn-export-dropdown-trigger')?.parentElement;
    const summaryCards = document.querySelector('.summary-cards-grid');

    // Toggle app-header layout for contractor to align actions left
    const appHeader = document.querySelector('.app-header');
    if (appHeader) {
        if (isContractor) {
            appHeader.style.justifyContent = 'flex-start';
            appHeader.style.gap = '32px';
        } else {
            appHeader.style.justifyContent = 'space-between';
            appHeader.style.gap = '';
        }
    }

    if (isContractor) {
        if (rfqDirectBtn) rfqDirectBtn.style.display = 'none';
        if (contractorDropdown) contractorDropdown.style.display = 'none';
        if (exportDropdown) {
            exportDropdown.style.display = 'none';
        }
        
        // Show contractor-specific buttons
        const extraBtn = document.getElementById('btn-open-extra-work');
        const deductBtn = document.getElementById('btn-open-deduct-work');
        const billingBtn = document.getElementById('btn-open-billing');
        const complaintsBtn = document.getElementById('btn-open-complaints');
        const rfqWrapper = document.getElementById('contractor-rfq-dropdown-wrapper');
        const projectChatBtn = document.getElementById('btn-open-project-chat');
        if (extraBtn) extraBtn.style.display = 'inline-flex';
        if (deductBtn) deductBtn.style.display = 'inline-flex';
        if (billingBtn) billingBtn.style.display = 'inline-flex';
        if (complaintsBtn) complaintsBtn.style.display = 'inline-flex';
        if (rfqWrapper) rfqWrapper.style.display = 'inline-block';
        if (projectChatBtn) projectChatBtn.style.display = 'inline-flex';
        
        // Hide other toolbar buttons
        document.getElementById('btn-open-project-docs').style.display = 'none';
        document.getElementById('btn-open-project-progress').style.display = 'none';
        document.getElementById('btn-open-project-fat').style.display = 'inline-flex';
        document.getElementById('btn-open-project-test-script').style.display = 'none';
        document.getElementById('btn-open-revisions').style.display = 'none';
        document.getElementById('btn-open-attachments').style.display = 'none';

        // Hide RFQ creation trigger for contractor
        const createRfqBtn = document.getElementById('btn-create-rfq-trigger');
        if (createRfqBtn) createRfqBtn.style.display = 'none';
        
        // Hide chat button for contractor
        const chatBtn = document.getElementById('btn-open-chat');
        if (chatBtn) chatBtn.style.display = 'none';
        
        // Align FAT and RFQ buttons to the left next to project details
        const metaHeader = document.querySelector('.project-meta-header');
        if (metaHeader) {
            metaHeader.style.justifyContent = 'flex-start';
            metaHeader.style.gap = '24px';
        }
        
        if (summaryCards) summaryCards.style.display = 'none';

        // Populate dynamic RFQ dropdown items
        const rfqContainer = document.getElementById('contractor-rfq-dropdown-menu');
        const rfqGlobalBadge = document.getElementById('contractor-rfq-global-badge');
        if (state.activeProjectId && rfqContainer) {
            authFetch(`${API_BASE}/projects/${state.activeProjectId}/contractor-rfqs`)
                .then(res => {
                    if (res.ok) return res.json();
                    return [];
                })
                .then(rfqs => {
                    rfqContainer.innerHTML = '';
                    let hasAnyNew = false;
                    
                    if (rfqs.length === 0) {
                        rfqContainer.innerHTML = `
                            <div style="padding: 10px 16px; font-size: 0.85rem; color: var(--text-muted); text-align: center;">
                                ${state.currentLanguage === 'en' ? 'No RFQs' : 'ไม่มีใบขอราคา'}
                            </div>
                        `;
                    } else {
                        rfqs.forEach(rfq => {
                            const isNew = rfq.status === 'sent';
                            if (isNew) hasAnyNew = true;
                            
                            const item = document.createElement('button');
                            item.className = 'dropdown-item';
                            item.innerHTML = `
                                <i class="fa-solid fa-file-invoice-dollar text-success"></i>
                                <span>${state.currentLanguage === 'en' ? 'Quotation Request' : 'ขอใบราคา'} ${escapeHtml(rfq.rfq_number)}</span>
                                ${isNew ? '<span class="badge bg-danger" style="background-color:#ef4444; color:white; font-size:0.65rem; font-weight:700; padding:1px 4px; border-radius:10px; margin-left:6px; animation: pulse 2s infinite;">New</span>' : ''}
                            `;
                            item.addEventListener('click', async () => {
                                rfqContainer.classList.remove('active');
                                state.selectedRfqId = rfq.id;
                                await fetchActiveProjectDetails();
                                renderWorkspace();
                                openRfqDetailModal(rfq.id);
                            });
                            rfqContainer.appendChild(item);
                        });
                    }
                    
                    if (rfqGlobalBadge) {
                        rfqGlobalBadge.style.display = hasAnyNew ? 'inline-block' : 'none';
                    }
                })
                .catch(err => console.error('Failed to fetch contractor RFQs:', err));
        }
    } else {
        if (rfqDirectBtn) rfqDirectBtn.style.display = 'none';
        if (contractorDropdown) contractorDropdown.style.display = 'inline-block';
        if (exportDropdown) {
            exportDropdown.style.display = 'inline-block';
            const bomTrigger = document.getElementById('btn-print-bom-trigger');
            const freeIssueTrigger = document.getElementById('btn-print-free-issue-trigger');
            if (bomTrigger) bomTrigger.style.display = 'block';
            if (freeIssueTrigger) freeIssueTrigger.style.display = 'block';
        }
        
        // Hide contractor-specific buttons for others
        const extraBtn = document.getElementById('btn-open-extra-work');
        const deductBtn = document.getElementById('btn-open-deduct-work');
        const billingBtn = document.getElementById('btn-open-billing');
        const complaintsBtn = document.getElementById('btn-open-complaints');
        const rfqWrapper = document.getElementById('contractor-rfq-dropdown-wrapper');
        const projectChatBtn = document.getElementById('btn-open-project-chat');
        if (extraBtn) extraBtn.style.display = 'none';
        if (deductBtn) deductBtn.style.display = 'none';
        if (billingBtn) billingBtn.style.display = 'none';
        if (complaintsBtn) complaintsBtn.style.display = 'none';
        if (projectChatBtn) projectChatBtn.style.display = 'none';
        if (rfqWrapper) {
            rfqWrapper.style.display = 'none';
            const rfqContainer = document.getElementById('contractor-rfq-dropdown-menu');
            if (rfqContainer) rfqContainer.innerHTML = '';
        }
        
        // Restore defaults for non-contractor roles
        document.getElementById('btn-open-project-docs').style.display = 'inline-flex';
        document.getElementById('btn-open-project-progress').style.display = 'inline-flex';
        document.getElementById('btn-open-project-fat').style.display = 'inline-flex';
        document.getElementById('btn-open-project-test-script').style.display = 'inline-flex';
        document.getElementById('btn-open-revisions').style.display = 'inline-flex';
        document.getElementById('btn-open-attachments').style.display = 'inline-flex';
        
        const chatBtn = document.getElementById('btn-open-chat');
        if (chatBtn) chatBtn.style.display = 'inline-flex';
        
        // Show RFQ creation trigger for others
        const createRfqBtn = document.getElementById('btn-create-rfq-trigger');
        if (createRfqBtn) createRfqBtn.style.display = 'inline-flex';
        
        const alarmBadge = document.getElementById('rfq-alarm-badge');
        if (alarmBadge) alarmBadge.style.display = 'none';
        
        // Restore default layout
        const metaHeader = document.querySelector('.project-meta-header');
        if (metaHeader) {
            metaHeader.style.justifyContent = 'space-between';
            metaHeader.style.gap = '';
        }
        
        if (summaryCards) summaryCards.style.display = '';
    }
}

function setupContractorFeatures() {
    // Helper to get active project ID
    const getActiveId = () => state.activeProjectId;

    // 1. Extra Works Handlers
    const openExtraBtn = document.getElementById('btn-open-extra-work');
    const modalExtra = document.getElementById('modal-extra-works');
    const formExtra = document.getElementById('form-create-extra-work');
    const btnCreateExtra = document.getElementById('btn-create-extra-work-trigger');
    const btnCancelExtra = document.getElementById('btn-cancel-extra-work');
    const extraTbody = document.getElementById('extra-works-tbody');

    const btnOrderExtra = document.getElementById('btn-order-extra-work-trigger');
    const formOrderExtra = document.getElementById('form-order-extra-work');
    const btnCancelOrderExtra = document.getElementById('btn-cancel-order-extra-work');
    const orderExtraContractorSelect = document.getElementById('order-extra-work-contractor');

    async function populateContractorSelect(selectEl, pId) {
        if (!selectEl) return;
        try {
            const res = await authFetch(`${API_BASE}/projects/${pId}/contractor-rfqs`);
            if (!res.ok) return;
            const rfqs = await res.json();
            const seen = new Map();
            rfqs.forEach(r => {
                if (!seen.has(r.contractor_id)) seen.set(r.contractor_id, r.contractor_name);
            });
            selectEl.innerHTML = Array.from(seen.entries()).map(([id, name]) =>
                `<option value="${id}">${escapeHtml(name)}</option>`
            ).join('');
            if (seen.size === 0) {
                selectEl.innerHTML = `<option value="">ไม่มีผู้รับเหมาสำหรับโครงการนี้</option>`;
            }
        } catch (err) {
            console.error(err);
        }
    }

    const openExtraHandler = () => {
        const pId = getActiveId();
        if (!pId) {
            alert('Please select a project first');
            return;
        }
        modalExtra.classList.add('active');
        if (formExtra) formExtra.style.display = 'none';
        if (formOrderExtra) formOrderExtra.style.display = 'none';

        const isContractor = state.currentUser && state.currentUser.role === 'contractor';
        const isCreator = state.activeProjectSummary && state.activeProjectSummary.created_by === state.currentUser?.id;
        const isAdmin = state.currentUser?.role === 'admin' || state.currentUser?.role === 'superadmin';
        if (btnCreateExtra) {
            btnCreateExtra.style.display = isContractor ? 'inline-flex' : 'none';
        }
        if (btnOrderExtra) {
            btnOrderExtra.style.display = (isCreator || isAdmin) ? 'inline-flex' : 'none';
        }
        if (isCreator || isAdmin) {
            populateContractorSelect(orderExtraContractorSelect, pId);
        }

        loadExtraWorks();
    };

    if (openExtraBtn && modalExtra) {
        openExtraBtn.addEventListener('click', openExtraHandler);
    }

    const adminOpenExtraBtn = document.getElementById('btn-admin-open-extra-work');
    if (adminOpenExtraBtn && modalExtra) {
        adminOpenExtraBtn.addEventListener('click', () => {
            document.getElementById('contractor-dropdown-menu')?.classList.remove('active');
            openExtraHandler();
        });
    }

    if (btnCreateExtra && formExtra) {
        btnCreateExtra.addEventListener('click', () => {
            formExtra.style.display = formExtra.style.display === 'none' ? 'block' : 'none';
        });
    }

    if (btnCancelExtra && formExtra) {
        btnCancelExtra.addEventListener('click', () => {
            formExtra.style.display = 'none';
            formExtra.reset();
        });
    }

    if (formExtra) {
        formExtra.addEventListener('submit', async (e) => {
            e.preventDefault();
            const pId = getActiveId();
            if (!pId) return;

            const work_name = document.getElementById('extra-work-name').value;
            const quantity = document.getElementById('extra-work-qty').value;
            const estimated_cost = document.getElementById('extra-work-cost').value;

            try {
                const res = await authFetch(`${API_BASE}/projects/${pId}/extra-works`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ work_name, quantity, estimated_cost })
                });
                if (res.ok) {
                    showToast(state.currentLanguage === 'en' ? 'Extra work request submitted successfully' : 'ส่งคำขอเพิ่มงานเรียบร้อยแล้ว');
                    formExtra.reset();
                    formExtra.style.display = 'none';
                    loadExtraWorks();
                } else {
                    const err = await res.json();
                    alert(err.error || 'Failed to submit extra work request');
                }
            } catch (err) {
                console.error(err);
                alert('Connection error');
            }
        });
    }

    if (btnOrderExtra && formOrderExtra) {
        btnOrderExtra.addEventListener('click', () => {
            formOrderExtra.style.display = formOrderExtra.style.display === 'none' ? 'block' : 'none';
        });
    }

    if (btnCancelOrderExtra && formOrderExtra) {
        btnCancelOrderExtra.addEventListener('click', () => {
            formOrderExtra.style.display = 'none';
            formOrderExtra.reset();
        });
    }

    const orderExtraQty = document.getElementById('order-extra-work-qty');
    const orderExtraMaterialRate = document.getElementById('order-extra-work-material-rate');
    const orderExtraLabourRate = document.getElementById('order-extra-work-labour-rate');
    const orderExtraTotal = document.getElementById('order-extra-work-total');

    function recomputeOrderExtraTotal() {
        if (!orderExtraTotal) return;
        const qty = parseFloat(orderExtraQty?.value) || 0;
        const matRate = parseFloat(orderExtraMaterialRate?.value) || 0;
        const labRate = parseFloat(orderExtraLabourRate?.value) || 0;
        const total = qty * (matRate + labRate);
        orderExtraTotal.textContent = `฿${total.toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2})}`;
    }
    [orderExtraQty, orderExtraMaterialRate, orderExtraLabourRate].forEach(el => {
        if (el) el.addEventListener('input', recomputeOrderExtraTotal);
    });

    if (formOrderExtra) {
        formOrderExtra.addEventListener('submit', async (e) => {
            e.preventDefault();
            const pId = getActiveId();
            if (!pId) return;

            const contractor_id = orderExtraContractorSelect?.value;
            const work_name = document.getElementById('order-extra-work-name').value;
            const section_name = document.getElementById('order-extra-work-section').value;
            const brand = document.getElementById('order-extra-work-brand').value;
            const quantity = orderExtraQty.value;
            const unit = document.getElementById('order-extra-work-unit').value;
            const material_rate = orderExtraMaterialRate.value;
            const labour_rate = orderExtraLabourRate.value;

            if (!contractor_id) {
                alert(state.currentLanguage === 'en' ? 'Please select a contractor' : 'กรุณาเลือกผู้รับเหมา');
                return;
            }

            try {
                const res = await authFetch(`${API_BASE}/projects/${pId}/extra-works`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ contractor_id, work_name, section_name, brand, quantity, unit, material_rate, labour_rate })
                });
                if (res.ok) {
                    showToast(state.currentLanguage === 'en' ? 'Extra work order saved successfully' : 'บันทึกงานสั่งเพิ่มเรียบร้อยแล้ว');
                    formOrderExtra.reset();
                    formOrderExtra.style.display = 'none';
                    recomputeOrderExtraTotal();
                    loadExtraWorks();
                } else {
                    const err = await res.json();
                    alert(err.error || 'Failed to order extra work');
                }
            } catch (err) {
                console.error(err);
                alert('Connection error');
            }
        });
    }

    async function loadExtraWorks() {
        const pId = getActiveId();
        if (!pId || !extraTbody) return;
        try {
            const res = await authFetch(`${API_BASE}/projects/${pId}/extra-works`);
            if (res.ok) {
                const data = await res.json();
                extraTbody.innerHTML = data.map(item => {
                    const detailParts = [item.section_name, item.brand].filter(Boolean).map(escapeHtml);
                    const detailLine = detailParts.length ? `<br><small style="color:var(--text-secondary);">${detailParts.join(' / ')}</small>` : '';
                    const statusText = item.status === 'approved' ? (state.currentLanguage === 'en' ? 'Approved' : 'อนุมัติแล้ว') :
                                       item.status === 'rejected' ? (state.currentLanguage === 'en' ? 'Rejected' : 'ปฏิเสธแล้ว') :
                                       (state.currentLanguage === 'en' ? 'Pending' : 'รอดำเนินการ');
                    return `
                    <tr>
                        <td>${parseDbDate(item.created_at).toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH')}</td>
                        <td>${escapeHtml(item.contractor_name || '')}</td>
                        <td><strong>${escapeHtml(item.work_name)}</strong>${detailLine}</td>
                        <td>${parseFloat(item.quantity).toLocaleString()}${item.unit ? ' ' + escapeHtml(item.unit) : ''}</td>
                        <td>฿${parseFloat(item.estimated_cost).toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2})}</td>
                        <td><span class="badge badge-${item.status === 'approved' ? 'success' : item.status === 'rejected' ? 'danger' : 'warning'}">${statusText}</span></td>
                    </tr>
                `;
                }).join('');
                if (data.length === 0) {
                    extraTbody.innerHTML = `<tr><td colspan="6" style="text-align:center;">${state.currentLanguage === 'en' ? 'No extra work records found' : 'ไม่มีข้อมูลรายการงานเพิ่ม'}</td></tr>`;
                }
            }
        } catch (err) {
            console.error(err);
        }
    }

    // 2. Deduct Works Handlers
    const openDeductBtn = document.getElementById('btn-open-deduct-work');
    const modalDeduct = document.getElementById('modal-deduct-works');
    const formDeduct = document.getElementById('form-create-deduct-work');
    const btnCreateDeduct = document.getElementById('btn-create-deduct-work-trigger');
    const btnCancelDeduct = document.getElementById('btn-cancel-deduct-work');
    const deductTbody = document.getElementById('deduct-works-tbody');

    const btnRecordDeduct = document.getElementById('btn-record-deduct-work-trigger');
    const formRecordDeduct = document.getElementById('form-record-deduct-work');
    const btnCancelRecordDeduct = document.getElementById('btn-cancel-record-deduct-work');
    const recordDeductContractorSelect = document.getElementById('record-deduct-work-contractor');
    const recordDeductItemSelect = document.getElementById('record-deduct-work-item');
    const recordDeductQuotedQty = document.getElementById('record-deduct-work-quoted-qty');
    const recordDeductActualQty = document.getElementById('record-deduct-work-actual-qty');
    const recordDeductRate = document.getElementById('record-deduct-work-rate');
    const recordDeductVariance = document.getElementById('record-deduct-work-variance');

    const openDeductHandler = () => {
        const pId = getActiveId();
        if (!pId) {
            alert('Please select a project first');
            return;
        }
        modalDeduct.classList.add('active');
        if (formDeduct) formDeduct.style.display = 'none';
        if (formRecordDeduct) formRecordDeduct.style.display = 'none';

        const isContractor = state.currentUser && state.currentUser.role === 'contractor';
        const isCreator = state.activeProjectSummary && state.activeProjectSummary.created_by === state.currentUser?.id;
        const isAdmin = state.currentUser?.role === 'admin' || state.currentUser?.role === 'superadmin';
        if (btnCreateDeduct) {
            btnCreateDeduct.style.display = isContractor ? 'inline-flex' : 'none';
        }
        if (btnRecordDeduct) {
            btnRecordDeduct.style.display = (isCreator || isAdmin) ? 'inline-flex' : 'none';
        }
        if (isCreator || isAdmin) {
            populateContractorSelect(recordDeductContractorSelect, pId).then(() => {
                if (recordDeductContractorSelect?.value) loadDeductContractItems();
            });
        }

        loadDeductWorks();
    };

    if (openDeductBtn && modalDeduct) {
        openDeductBtn.addEventListener('click', openDeductHandler);
    }

    const adminOpenDeductBtn = document.getElementById('btn-admin-open-deduct-work');
    if (adminOpenDeductBtn && modalDeduct) {
        adminOpenDeductBtn.addEventListener('click', () => {
            document.getElementById('contractor-dropdown-menu')?.classList.remove('active');
            openDeductHandler();
        });
    }

    if (btnCreateDeduct && formDeduct) {
        btnCreateDeduct.addEventListener('click', () => {
            formDeduct.style.display = formDeduct.style.display === 'none' ? 'block' : 'none';
        });
    }

    if (btnCancelDeduct && formDeduct) {
        btnCancelDeduct.addEventListener('click', () => {
            formDeduct.style.display = 'none';
            formDeduct.reset();
        });
    }

    if (formDeduct) {
        formDeduct.addEventListener('submit', async (e) => {
            e.preventDefault();
            const pId = getActiveId();
            if (!pId) return;

            const item_name = document.getElementById('deduct-work-name').value;
            const quantity = document.getElementById('deduct-work-qty').value;
            const deduct_amount = document.getElementById('deduct-work-amount').value;

            try {
                const res = await authFetch(`${API_BASE}/projects/${pId}/deduct-works`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ item_name, quantity, deduct_amount })
                });
                if (res.ok) {
                    showToast(state.currentLanguage === 'en' ? 'Deducted work request submitted successfully' : 'เสนอลดงานเรียบร้อยแล้ว');
                    formDeduct.reset();
                    formDeduct.style.display = 'none';
                    loadDeductWorks();
                } else {
                    const err = await res.json();
                    alert(err.error || 'Failed to submit deduct work request');
                }
            } catch (err) {
                console.error(err);
                alert('Connection error');
            }
        });
    }

    if (btnRecordDeduct && formRecordDeduct) {
        btnRecordDeduct.addEventListener('click', () => {
            formRecordDeduct.style.display = formRecordDeduct.style.display === 'none' ? 'block' : 'none';
        });
    }

    if (btnCancelRecordDeduct && formRecordDeduct) {
        btnCancelRecordDeduct.addEventListener('click', () => {
            formRecordDeduct.style.display = 'none';
            formRecordDeduct.reset();
            resetDeductItemSelect();
        });
    }

    function resetDeductItemSelect() {
        if (recordDeductItemSelect) {
            recordDeductItemSelect.innerHTML = `<option value="">-- เลือกผู้รับเหมาก่อน --</option>`;
            recordDeductItemSelect.disabled = true;
        }
        if (recordDeductQuotedQty) recordDeductQuotedQty.value = '-';
        if (recordDeductRate) recordDeductRate.value = '-';
        if (recordDeductVariance) recordDeductVariance.textContent = '-';
    }

    async function loadDeductContractItems() {
        const pId = getActiveId();
        const contractorId = recordDeductContractorSelect?.value;
        if (!pId || !contractorId || !recordDeductItemSelect) return;
        recordDeductItemSelect.innerHTML = `<option value="">กำลังโหลด...</option>`;
        recordDeductItemSelect.disabled = true;
        try {
            const res = await authFetch(`${API_BASE}/projects/${pId}/contract-quotation?contractor_id=${contractorId}`);
            if (res.ok) {
                const data = await res.json();
                if (!data.items || data.items.length === 0) {
                    recordDeductItemSelect.innerHTML = `<option value="">ไม่พบใบเสนอราคาที่อนุมัติของผู้รับเหมานี้</option>`;
                    return;
                }
                recordDeductItemSelect.innerHTML = data.items.map(it => {
                    const rate = (parseFloat(it.material_rate) || 0) + (parseFloat(it.labour_rate) || 0);
                    const label = [it.section_name, it.description].filter(Boolean).join(' - ');
                    return `<option value="${it.id}" data-qty="${it.qty}" data-unit="${escapeHtml(it.unit || '')}" data-rate="${rate}">${escapeHtml(label)}</option>`;
                }).join('');
                recordDeductItemSelect.disabled = false;
                recordDeductItemSelect.dispatchEvent(new Event('change'));
            }
        } catch (err) {
            console.error(err);
        }
    }

    if (recordDeductContractorSelect) {
        recordDeductContractorSelect.addEventListener('change', () => {
            resetDeductItemSelect();
            loadDeductContractItems();
        });
    }

    function updateDeductVariancePreview() {
        if (!recordDeductVariance) return;
        const selectedOption = recordDeductItemSelect?.options[recordDeductItemSelect.selectedIndex];
        const quotedQty = parseFloat(selectedOption?.dataset.qty) || 0;
        const rate = parseFloat(selectedOption?.dataset.rate) || 0;
        const actualQty = parseFloat(recordDeductActualQty?.value) || 0;
        const varianceQty = quotedQty - actualQty;
        const amount = varianceQty * rate;
        const label = amount >= 0 ? 'ลด' : 'เพิ่ม';
        const color = amount >= 0 ? 'var(--success-color, #16a34a)' : 'var(--danger-color, #dc2626)';
        recordDeductVariance.innerHTML = `<span style="color:${color};">฿${Math.abs(amount).toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2})} (${label})</span>`;
    }

    if (recordDeductItemSelect) {
        recordDeductItemSelect.addEventListener('change', () => {
            const selectedOption = recordDeductItemSelect.options[recordDeductItemSelect.selectedIndex];
            const qty = selectedOption?.dataset.qty;
            const unit = selectedOption?.dataset.unit;
            const rate = selectedOption?.dataset.rate;
            if (recordDeductQuotedQty) recordDeductQuotedQty.value = qty !== undefined ? `${parseFloat(qty).toLocaleString()} ${unit || ''}`.trim() : '-';
            if (recordDeductRate) recordDeductRate.value = rate !== undefined ? `฿${parseFloat(rate).toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2})}` : '-';
            updateDeductVariancePreview();
        });
    }

    if (recordDeductActualQty) {
        recordDeductActualQty.addEventListener('input', updateDeductVariancePreview);
    }

    if (formRecordDeduct) {
        formRecordDeduct.addEventListener('submit', async (e) => {
            e.preventDefault();
            const pId = getActiveId();
            if (!pId) return;

            const contractor_id = recordDeductContractorSelect?.value;
            const rfq_item_id = recordDeductItemSelect?.value;
            const actual_qty = recordDeductActualQty?.value;

            if (!contractor_id || !rfq_item_id) {
                alert(state.currentLanguage === 'en' ? 'Please select a contractor and an item from the quotation' : 'กรุณาเลือกผู้รับเหมาและรายการในใบเสนอราคา');
                return;
            }

            try {
                const res = await authFetch(`${API_BASE}/projects/${pId}/deduct-works`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ contractor_id, rfq_item_id, actual_qty })
                });
                if (res.ok) {
                    showToast(state.currentLanguage === 'en' ? 'Deduct/extra work recorded successfully' : 'บันทึกงานลด/เพิ่มเรียบร้อยแล้ว');
                    formRecordDeduct.reset();
                    formRecordDeduct.style.display = 'none';
                    resetDeductItemSelect();
                    loadDeductWorks();
                } else {
                    const err = await res.json();
                    alert(err.error || 'Failed to record deduct work');
                }
            } catch (err) {
                console.error(err);
                alert('Connection error');
            }
        });
    }

    async function loadDeductWorks() {
        const pId = getActiveId();
        if (!pId || !deductTbody) return;
        try {
            const res = await authFetch(`${API_BASE}/projects/${pId}/deduct-works`);
            if (res.ok) {
                const data = await res.json();
                deductTbody.innerHTML = data.map(item => {
                    const amount = parseFloat(item.deduct_amount) || 0;
                    const isAdd = amount < 0;
                    const amountLabel = `฿${Math.abs(amount).toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2})}${isAdd ? (state.currentLanguage === 'en' ? ' (Add)' : ' (เพิ่ม)') : ''}`;
                    const quotedText = state.currentLanguage === 'en' ? 'Quoted: ' : 'ตามสัญญา: ';
                    const actualText = state.currentLanguage === 'en' ? ' / Actual: ' : ' / ติดตั้งจริง: ';
                    const detailLine = item.quoted_qty ? `<br><small style="color:var(--text-secondary);">${quotedText}${parseFloat(item.quoted_qty).toLocaleString()}${actualText}${parseFloat(item.actual_qty).toLocaleString()}</small>` : '';
                    const statusText = item.status === 'approved' ? (state.currentLanguage === 'en' ? 'Approved' : 'อนุมัติแล้ว') :
                                       item.status === 'rejected' ? (state.currentLanguage === 'en' ? 'Rejected' : 'ปฏิเสธแล้ว') :
                                       (state.currentLanguage === 'en' ? 'Pending' : 'รอดำเนินการ');
                    return `
                    <tr>
                        <td>${parseDbDate(item.created_at).toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH')}</td>
                        <td>${escapeHtml(item.contractor_name || '')}</td>
                        <td><strong>${escapeHtml(item.item_name)}</strong>${detailLine}</td>
                        <td>${parseFloat(item.quantity).toLocaleString()}</td>
                        <td style="${isAdd ? 'color:var(--danger-color, #dc2626);' : ''}">${amountLabel}</td>
                        <td><span class="badge badge-${item.status === 'approved' ? 'success' : item.status === 'rejected' ? 'danger' : 'warning'}">${statusText}</span></td>
                    </tr>
                `;
                }).join('');
                if (data.length === 0) {
                    deductTbody.innerHTML = `<tr><td colspan="6" style="text-align:center;">${state.currentLanguage === 'en' ? 'No deducted work records found' : 'ไม่มีข้อมูลรายการงานลด'}</td></tr>`;
                }
            }
        } catch (err) {
            console.error(err);
        }
    }

    // 2b. Project Chat Handlers
    const btnOpenProjectChat = document.getElementById('btn-open-project-chat');
    if (btnOpenProjectChat) {
        btnOpenProjectChat.addEventListener('click', async () => {
            const pId = getActiveId();
            if (!pId) {
                alert('Please select a project first');
                return;
            }
            try {
                const res = await authFetch(`${API_BASE}/projects/${pId}/chat/open`, { method: 'POST' });
                if (res.ok) {
                    const data = await res.json();
                    await openChatModal();
                    await openConversationThread(data.conversation_id, data.name);
                } else {
                    const err = await res.json();
                    alert(err.error || 'Failed to open chat');
                }
            } catch (err) {
                console.error(err);
                alert('Connection error');
            }
        });
    }

    const btnAdminOpenProjectChat = document.getElementById('btn-admin-open-project-chat');
    const modalProjectChatPicker = document.getElementById('modal-project-chat-picker');
    const projectChatPickerContractor = document.getElementById('project-chat-picker-contractor');
    const btnProjectChatPickerOpen = document.getElementById('btn-project-chat-picker-open');

    if (btnAdminOpenProjectChat && modalProjectChatPicker) {
        btnAdminOpenProjectChat.addEventListener('click', () => {
            document.getElementById('contractor-dropdown-menu')?.classList.remove('active');
            const pId = getActiveId();
            if (!pId) {
                alert('Please select a project first');
                return;
            }
            modalProjectChatPicker.classList.add('active');
            populateContractorSelect(projectChatPickerContractor, pId);
        });
    }

    if (btnProjectChatPickerOpen) {
        btnProjectChatPickerOpen.addEventListener('click', async () => {
            const pId = getActiveId();
            const contractor_id = projectChatPickerContractor?.value;
            if (!pId || !contractor_id) {
                alert('กรุณาเลือกผู้รับเหมา');
                return;
            }
            try {
                const res = await authFetch(`${API_BASE}/projects/${pId}/chat/open`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ contractor_id })
                });
                if (res.ok) {
                    const data = await res.json();
                    modalProjectChatPicker.classList.remove('active');
                    await openChatModal();
                    await openConversationThread(data.conversation_id, data.name);
                } else {
                    const err = await res.json();
                    alert(err.error || 'Failed to open chat');
                }
            } catch (err) {
                console.error(err);
                alert('Connection error');
            }
        });
    }

    // 3. Billing Invoices Handlers
    const openBillingBtn = document.getElementById('btn-open-billing');
    const modalBilling = document.getElementById('modal-billing');
    const formInvoice = document.getElementById('form-create-invoice');
    const btnCreateInvoice = document.getElementById('btn-create-invoice-trigger');
    const btnCancelInvoice = document.getElementById('btn-cancel-invoice');
    const invoicesTbody = document.getElementById('invoices-tbody');

    if (openBillingBtn && modalBilling) {
        openBillingBtn.addEventListener('click', () => {
            const pId = getActiveId();
            if (!pId) {
                alert('Please select a project first');
                return;
            }
            modalBilling.classList.add('active');
            if (formInvoice) formInvoice.style.display = 'none';
            loadInvoices();
        });
    }

    if (btnCreateInvoice && formInvoice) {
        btnCreateInvoice.addEventListener('click', () => {
            formInvoice.style.display = formInvoice.style.display === 'none' ? 'block' : 'none';
        });
    }

    if (btnCancelInvoice && formInvoice) {
        btnCancelInvoice.addEventListener('click', () => {
            formInvoice.style.display = 'none';
            formInvoice.reset();
        });
    }

    if (formInvoice) {
        formInvoice.addEventListener('submit', async (e) => {
            e.preventDefault();
            const pId = getActiveId();
            if (!pId) return;

            const invoice_no = document.getElementById('invoice-no').value;
            const description = document.getElementById('invoice-desc').value;
            const amount = document.getElementById('invoice-amount').value;

            try {
                const res = await authFetch(`${API_BASE}/projects/${pId}/invoices`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ invoice_no, description, amount })
                });
                if (res.ok) {
                    showToast(state.currentLanguage === 'en' ? 'Invoice submitted successfully' : 'ส่งเอกสารวางบิลเรียบร้อยแล้ว');
                    formInvoice.reset();
                    formInvoice.style.display = 'none';
                    loadInvoices();
                } else {
                    const err = await res.json();
                    alert(err.error || 'Failed to submit invoice');
                }
            } catch (err) {
                console.error(err);
                alert('Connection error');
            }
        });
    }

    async function loadInvoices() {
        const pId = getActiveId();
        if (!pId || !invoicesTbody) return;
        try {
            const res = await authFetch(`${API_BASE}/projects/${pId}/invoices`);
            if (res.ok) {
                const data = await res.json();
                invoicesTbody.innerHTML = data.map(item => {
                    const statusText = item.status === 'paid' ? (state.currentLanguage === 'en' ? 'Paid' : 'ชำระแล้ว') :
                                       item.status === 'overdue' ? (state.currentLanguage === 'en' ? 'Overdue' : 'เกินกำหนด') :
                                       (state.currentLanguage === 'en' ? 'Pending' : 'รอชำระ');
                    return `
                    <tr>
                        <td>${parseDbDate(item.created_at).toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH')}</td>
                        <td>${escapeHtml(item.contractor_name || '')}</td>
                        <td><code>${escapeHtml(item.invoice_no)}</code></td>
                        <td>${escapeHtml(item.description)}</td>
                        <td>฿${parseFloat(item.amount).toLocaleString(undefined, {minimumFractionDigits:2, maximumFractionDigits:2})}</td>
                        <td><span class="badge badge-${item.status === 'paid' ? 'success' : item.status === 'overdue' ? 'danger' : 'warning'}">${statusText}</span></td>
                    </tr>
                `;
                }).join('');
                if (data.length === 0) {
                    invoicesTbody.innerHTML = `<tr><td colspan="6" style="text-align:center;">${state.currentLanguage === 'en' ? 'No billing records found' : 'ไม่มีข้อมูลเอกสารวางบิล'}</td></tr>`;
                }
            }
        } catch (err) {
            console.error(err);
        }
    }

    // 4. Complaints Handlers
    const openComplaintsBtn = document.getElementById('btn-open-complaints');
    const modalComplaints = document.getElementById('modal-complaints');
    const formComplaint = document.getElementById('form-create-complaint');
    const btnCreateComplaint = document.getElementById('btn-create-complaint-trigger');
    const btnCancelComplaint = document.getElementById('btn-cancel-complaint');
    const complaintsTbody = document.getElementById('complaints-tbody');

    if (openComplaintsBtn && modalComplaints) {
        openComplaintsBtn.addEventListener('click', () => {
            const pId = getActiveId();
            if (!pId) {
                alert('Please select a project first');
                return;
            }
            modalComplaints.classList.add('active');
            if (formComplaint) formComplaint.style.display = 'none';
            loadComplaints();
        });
    }

    if (btnCreateComplaint && formComplaint) {
        btnCreateComplaint.addEventListener('click', () => {
            formComplaint.style.display = formComplaint.style.display === 'none' ? 'block' : 'none';
        });
    }

    if (btnCancelComplaint && formComplaint) {
        btnCancelComplaint.addEventListener('click', () => {
            formComplaint.style.display = 'none';
            formComplaint.reset();
        });
    }

    if (formComplaint) {
        formComplaint.addEventListener('submit', async (e) => {
            e.preventDefault();
            const pId = getActiveId();
            if (!pId) return;

            const title = document.getElementById('complaint-title').value;
            const detail = document.getElementById('complaint-detail').value;

            try {
                const res = await authFetch(`${API_BASE}/projects/${pId}/complaints`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ title, detail })
                });
                if (res.ok) {
                    showToast(state.currentLanguage === 'en' ? 'Complaint submitted successfully' : 'ส่งเรื่องร้องเรียนเรียบร้อยแล้ว');
                    formComplaint.reset();
                    formComplaint.style.display = 'none';
                    loadComplaints();
                } else {
                    const err = await res.json();
                    alert(err.error || 'Failed to submit complaint');
                }
            } catch (err) {
                console.error(err);
                alert('Connection error');
            }
        });
    }

    async function loadComplaints() {
        const pId = getActiveId();
        if (!pId || !complaintsTbody) return;
        try {
            const res = await authFetch(`${API_BASE}/projects/${pId}/complaints`);
            if (res.ok) {
                const data = await res.json();
                complaintsTbody.innerHTML = data.map(item => {
                    const statusText = item.status === 'resolved' ? (state.currentLanguage === 'en' ? 'Resolved' : 'แก้ไขแล้ว') :
                                       item.status === 'in_progress' ? (state.currentLanguage === 'en' ? 'In Progress' : 'กำลังดำเนินการ') :
                                       (state.currentLanguage === 'en' ? 'Pending' : 'รอดำเนินการ');
                    return `
                    <tr>
                        <td>${parseDbDate(item.created_at).toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH')}</td>
                        <td>${escapeHtml(item.contractor_name || '')}</td>
                        <td><strong>${escapeHtml(item.title)}</strong></td>
                        <td>${escapeHtml(item.detail)}</td>
                        <td><span class="badge badge-${item.status === 'resolved' ? 'success' : item.status === 'in_progress' ? 'info' : 'warning'}">${statusText}</span></td>
                    </tr>
                `;
                }).join('');
                if (data.length === 0) {
                    complaintsTbody.innerHTML = `<tr><td colspan="5" style="text-align:center;">${state.currentLanguage === 'en' ? 'No complaints found' : 'ไม่มีข้อมูลเรื่องร้องเรียน'}</td></tr>`;
                }
            }
        } catch (err) {
            console.error(err);
        }
    }
}
function setupEventListeners() {
    setupContractorFeatures();

    // Global event delegation for PDF spec sheets
    document.addEventListener('click', (e) => {
        const pdfLink = e.target.closest('.pdf-spec-link');
        if (pdfLink) {
            e.preventDefault();
            e.stopPropagation();
            const productId = pdfLink.getAttribute('data-product-id');
            const description = pdfLink.getAttribute('data-description');
            if (productId) {
                openPdfViewer(productId, description);
            }
        }
    });

    // Workspace tabs handler
    document.querySelectorAll('.workspace-mode-tabs .btn-mode-tab').forEach(btn => {
        btn.addEventListener('click', (e) => {
            const mode = e.currentTarget.id.replace('btn-mode-', '');
            state.workspaceMode = mode;
            renderWorkspace();
        });
    });
    // Main Menu Dropdown Toggle
    const mainMenuBtn = document.getElementById('btn-main-menu-trigger');
    const mainMenuDropdown = document.getElementById('main-menu-dropdown');
    if (mainMenuBtn && mainMenuDropdown) {
        mainMenuBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            mainMenuDropdown.classList.toggle('active');
            // Close other dropdowns if open
            document.getElementById('project-selector-dropdown')?.classList.remove('active');
            document.getElementById('export-dropdown-menu')?.classList.remove('active');
            document.getElementById('contractor-rfq-dropdown-menu')?.classList.remove('active');
            document.getElementById('announcement-bell-dropdown')?.classList.remove('active');
        });
    }

    // Auto-close main menu dropdown when clicking any menu-dropdown-item except message bell
    document.querySelectorAll('.menu-dropdown-item').forEach(item => {
        item.addEventListener('click', (e) => {
            if (item.id !== 'btn-open-announcements-bell') {
                mainMenuDropdown?.classList.remove('active');
            }
        });
    });

    // Close main menu dropdown when clicking outside
    document.addEventListener('click', (e) => {
        if (mainMenuDropdown && !mainMenuDropdown.contains(e.target) && e.target !== mainMenuBtn && !mainMenuBtn.contains(e.target)) {
            mainMenuDropdown.classList.remove('active');
        }
    });

    // Project Selector Dropdown Toggle
    const projSelectorBtn = document.getElementById('btn-project-selector');
    const projSelectorDropdown = document.getElementById('project-selector-dropdown');
    if (projSelectorBtn && projSelectorDropdown) {
        projSelectorBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            projSelectorDropdown.classList.toggle('active');
            // Close other dropdowns if open
            document.getElementById('export-dropdown-menu')?.classList.remove('active');
            document.getElementById('contractor-rfq-dropdown-menu')?.classList.remove('active');
        });
    }

    // Export/Print Dropdown Toggle
    const exportBtn = document.getElementById('btn-export-dropdown-trigger');
    const exportMenu = document.getElementById('export-dropdown-menu');
    if (exportBtn && exportMenu) {
        exportBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            exportMenu.classList.toggle('active');
            // Close other dropdowns if open
            document.getElementById('project-selector-dropdown')?.classList.remove('active');
            document.getElementById('contractor-rfq-dropdown-menu')?.classList.remove('active');
        });
    }

    // Contractor RFQ Dropdown Toggle
    const contractorRfqBtn = document.getElementById('btn-contractor-rfq-dropdown');
    const contractorRfqMenu = document.getElementById('contractor-rfq-dropdown-menu');
    if (contractorRfqBtn && contractorRfqMenu) {
        contractorRfqBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            contractorRfqMenu.classList.toggle('active');
            // Close other dropdowns if open
            document.getElementById('project-selector-dropdown')?.classList.remove('active');
            document.getElementById('export-dropdown-menu')?.classList.remove('active');
        });
    }

    // Close dropdowns on outside click
    document.addEventListener('click', (e) => {
        if (projSelectorDropdown && !projSelectorDropdown.contains(e.target) && e.target !== projSelectorBtn) {
            projSelectorDropdown.classList.remove('active');
        }
        if (exportMenu && !exportMenu.contains(e.target) && e.target !== exportBtn) {
            exportMenu.classList.remove('active');
        }
        if (contractorRfqMenu && !contractorRfqMenu.contains(e.target) && e.target !== contractorRfqBtn && !contractorRfqBtn.contains(e.target)) {
            contractorRfqMenu.classList.remove('active');
        }
    });

    // Project Dropdown Search Input
    const dropdownSearch = document.getElementById('project-dropdown-search');
    if (dropdownSearch) {
        dropdownSearch.addEventListener('input', () => {
            renderSidebar();
        });
        dropdownSearch.addEventListener('click', (e) => {
            e.stopPropagation();
        });
    }

    // Show Deleted Projects Checkbox
    const chkShowDeleted = document.getElementById('chk-show-deleted-projects');
    if (chkShowDeleted) {
        chkShowDeleted.addEventListener('change', () => {
            fetchProjects();
        });
        chkShowDeleted.addEventListener('click', (e) => {
            e.stopPropagation();
        });
    }

    // Login Form Submit
    document.getElementById('form-login').addEventListener('submit', handleLogin);

    // Logout Button
    document.getElementById('btn-logout').addEventListener('click', handleLogout);

    // Project creation button (dropdown header & empty state)
    const createProjectHeader = document.getElementById('btn-create-project-header');
    if (createProjectHeader) {
        createProjectHeader.addEventListener('click', () => {
            if (projSelectorDropdown) projSelectorDropdown.classList.remove('active');
            openProjectModal();
        });
    }
    document.getElementById('btn-create-project-empty').addEventListener('click', () => openProjectModal());
    document.getElementById('btn-close-project-modal').addEventListener('click', closeProjectModal);
    document.getElementById('btn-cancel-project-modal').addEventListener('click', closeProjectModal);
    document.getElementById('form-project').addEventListener('submit', handleProjectSubmit);



    // Active project actions
    document.getElementById('btn-edit-project-active').addEventListener('click', () => {
        if (state.activeProjectSummary) openProjectModal(state.activeProjectSummary);
    });

    // Project status direct dropdown listener
    const statusSelect = document.getElementById('active-project-status-select');
    if (statusSelect) {
        statusSelect.addEventListener('change', async (e) => {
            if (!state.activeProjectId) return;
            const newStatus = e.target.value;
            try {
                const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/status`, {
                    method: 'PUT',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ status: newStatus })
                });
                if (!res.ok) {
                    throw new Error('Failed to update project status');
                }
                showToast(state.currentLanguage === 'en' ? 'Project status updated successfully' : 'อัปเดตสถานะโครงการเรียบร้อยแล้ว');
                await fetchActiveProjectDetails();
                renderWorkspace();
                await fetchProjects();
            } catch (err) {
                showToast(err.message, 'error');
                if (state.activeProjectSummary) {
                    statusSelect.value = state.activeProjectSummary.status;
                }
            }
        });
    }

    document.getElementById('btn-clone-project-active').addEventListener('click', handleCloneProject);
    document.getElementById('btn-delete-project-active').addEventListener('click', handleDeleteProject);
    document.getElementById('btn-restore-project').addEventListener('click', handleRestoreProject);

    // Refresh project details
    document.getElementById('btn-refresh-project-details').addEventListener('click', async () => {
        const btn = document.getElementById('btn-refresh-project-details');
        const icon = btn.querySelector('i');
        if (icon) icon.classList.add('fa-spin');
        
        try {
            await fetchProjects();
            if (state.activeProjectId) {
                await selectProject(state.activeProjectId);
            }
            showToast(state.currentLanguage === 'en' ? 'Data refreshed' : 'รีเฟรชข้อมูลสำเร็จ');
        } catch (e) {
            console.error(e);
            showToast(state.currentLanguage === 'en' ? 'Failed to refresh data' : 'ไม่สามารถรีเฟรชข้อมูลได้', 'error');
        } finally {
            if (icon) icon.classList.remove('fa-spin');
        }
    });

    // Revision History Actions
    document.getElementById('btn-open-revisions').addEventListener('click', openRevisionsModal);
    document.getElementById('btn-close-revisions-modal').addEventListener('click', closeRevisionsModal);
    document.getElementById('btn-close-revisions-footer').addEventListener('click', closeRevisionsModal);
    document.getElementById('btn-compare-revisions').addEventListener('click', compareRevisions);

    // Subsection creation
    document.getElementById('btn-add-section').addEventListener('click', openSubsectionModal);
    document.getElementById('btn-close-subsection-modal').addEventListener('click', closeSubsectionModal);
    document.getElementById('btn-cancel-subsection-modal').addEventListener('click', closeSubsectionModal);
    document.getElementById('form-subsection').addEventListener('submit', handleSubsectionSubmit);
    document.getElementById('subsection-name').addEventListener('change', (e) => {
        const customNameGroup = document.getElementById('subsection-custom-name-group');
        const customInput = document.getElementById('subsection-custom-name');
        if (e.target.value === '__custom__') {
            customNameGroup.style.display = 'block';
            customInput.required = true;
            customInput.focus();
        } else {
            customNameGroup.style.display = 'none';
            customInput.required = false;
        }
    });
    // Template Manager
    document.getElementById('btn-open-template-manager').addEventListener('click', openTemplateManagerModal);
    document.getElementById('btn-close-template-manager').addEventListener('click', closeTemplateManagerModal);
    document.getElementById('btn-cancel-template-manager').addEventListener('click', closeTemplateManagerModal);
    document.getElementById('template-select-system').addEventListener('change', (e) => {
        loadTemplateItemsForSelectedSystem();
    });
    document.getElementById('btn-template-select-catalog').addEventListener('click', openExplorerModalForTemplate);
    document.getElementById('btn-save-system-template').addEventListener('click', saveSystemTemplate);
    document.getElementById('btn-template-clone').addEventListener('click', async () => {
        const select = document.getElementById('template-select-system');
        const systemName = select.value;
        if (systemName === '__custom__') {
            showToast(state.currentLanguage === 'en' ? 'Please select a system template to clone' : 'กรุณาเลือกระบบงานที่ต้องการโคลน', 'error');
            return;
        }

        const templateObj = allSystemTemplates.find(t => t.system_name === systemName);
        const items = templateObj ? templateObj.items : [];

        const defaultNewName = systemName + ' - Copy';
        const newNamePrompt = state.currentLanguage === 'en' ? 'Enter a name for the cloned system template:' : 'กรุณาระบุชื่อระบบงานใหม่ที่ต้องการโคลน:';
        const newName = prompt(newNamePrompt, defaultNewName);
        if (newName === null) return; // Cancelled
        const trimmedNewName = newName.trim();
        if (!trimmedNewName) {
            showToast(state.currentLanguage === 'en' ? 'System name cannot be empty' : 'ชื่อระบบงานต้องไม่ว่างเปล่า', 'error');
            return;
        }

        try {
            const res = await authFetch(`${API_BASE}/system-templates/${encodeURIComponent(trimmedNewName)}`, {
                method: 'PUT',
                body: JSON.stringify({ items })
            });

            if (res.ok) {
                showToast(state.currentLanguage === 'en' ? 'Template cloned successfully' : 'โคลนเทมเพลตระบบงานสำเร็จแล้ว');
                await populateSystemDropdowns();
                select.value = trimmedNewName;
                loadTemplateItemsForSelectedSystem();
            } else {
                const err = await res.json();
                showToast(err.error || (state.currentLanguage === 'en' ? 'Failed to clone template' : 'ไม่สามารถโคลนเทมเพลตได้'), 'error');
            }
        } catch (err) {
            console.error(err);
            showToast(state.currentLanguage === 'en' ? 'Failed to clone template' : 'ไม่สามารถโคลนเทมเพลตได้', 'error');
        }
    });
    // Catalog Explorer
    document.getElementById('btn-close-explorer-modal').addEventListener('click', closeExplorerModal);
    document.getElementById('btn-close-explorer-footer').addEventListener('click', closeExplorerModal);
    document.getElementById('explorer-search').addEventListener('input', debounce(filterExplorerProducts, 300));
    document.getElementById('explorer-category-select').addEventListener('change', filterExplorerProducts);
    document.getElementById('explorer-group-select').addEventListener('change', filterExplorerProducts);
    document.getElementById('explorer-system-select').addEventListener('change', filterExplorerProducts);

    // Catalog Manager Database Modal
    document.getElementById('btn-open-catalog-manager').addEventListener('click', openCatalogManagerModal);
    document.getElementById('btn-close-catalog-modal').addEventListener('click', closeCatalogManagerModal);
    document.getElementById('btn-cancel-catalog-footer').addEventListener('click', closeCatalogManagerModal);
    document.getElementById('btn-save-catalog-footer').addEventListener('click', () => {
        showToast('บันทึกข้อมูลแคตตาล็อกสินค้าลงฐานข้อมูลเรียบร้อยแล้ว');
        closeCatalogManagerModal();
    });
    document.getElementById('catalog-manager-search').addEventListener('input', debounce(filterManagerProducts, 300));
    document.getElementById('catalog-manager-category').addEventListener('change', filterManagerProducts);
    document.getElementById('catalog-manager-group').addEventListener('change', filterManagerProducts);
    document.getElementById('catalog-manager-system').addEventListener('change', filterManagerProducts);
    document.getElementById('btn-add-catalog-product').addEventListener('click', () => openProductDetailModal());

    // Catalog Product Add/Edit Form Detail
    document.getElementById('btn-close-product-detail-modal').addEventListener('click', closeProductDetailModal);
    document.getElementById('btn-close-product-detail-footer').addEventListener('click', closeProductDetailModal);
    document.getElementById('form-product-detail').addEventListener('submit', handleProductDetailSubmit);

    // Tab active state switcher for product catalog detail modal
    document.querySelectorAll('.product-detail-tabs .tab-item').forEach(tab => {
        tab.addEventListener('click', (e) => {
            e.preventDefault();
            const target = tab.getAttribute('href');
            switchProductDetailTab(target);
        });
    });

    // Auto-switch to correct tab if a hidden input fails validation
    const prodDetailForm = document.getElementById('form-product-detail');
    if (prodDetailForm) {
        prodDetailForm.addEventListener('invalid', (e) => {
            const invalidField = e.target;
            const parentCard = invalidField.closest('.form-card');
            if (parentCard) {
                switchProductDetailTab('#' + parentCard.id);
            }
        }, true);
    }


    // Image file selection trigger
    const imageInput = document.getElementById('product-image-file');
    document.getElementById('btn-trigger-file-input').addEventListener('click', () => imageInput.click());
    imageInput.addEventListener('change', handleImageSelection);

    // Mobile camera capture trigger (opens native camera app on mobile devices)
    const imageCameraInput = document.getElementById('product-image-camera');
    document.getElementById('btn-trigger-camera-input').addEventListener('click', () => imageCameraInput.click());
    imageCameraInput.addEventListener('change', handleImageSelection);

    // PDF file selection trigger
    const pdfInput = document.getElementById('product-pdf-file');
    document.getElementById('btn-trigger-pdf-input').addEventListener('click', () => pdfInput.click());
    pdfInput.addEventListener('change', handlePdfSelection);

    // Report printing triggers
    document.getElementById('btn-print-quotation-trigger')?.addEventListener('click', () => triggerPrintReport('quotation'));
    document.getElementById('btn-print-bom-trigger')?.addEventListener('click', () => triggerPrintReport('bom'));
    document.getElementById('btn-print-free-issue-trigger')?.addEventListener('click', () => triggerPrintReport('free-issue'));

    // Procurement report bindings
    document.getElementById('btn-rep-proc-quote')?.addEventListener('click', () => triggerPrintReport('quotation'));
    document.getElementById('btn-rep-proc-bom')?.addEventListener('click', () => triggerPrintReport('bom'));

    // Wire up all new report items to show a simulated print preview or trigger actual modals
    const reportItemIds = [
        'btn-rep-est-scope', 'btn-rep-est-catalog', 'btn-rep-est-rfq-contractor', 
        'btn-rep-est-rfq-material', 'btn-rep-est-revisions', 'btn-rep-proc-profit', 
        'btn-rep-prod-req-mat', 'btn-rep-prod-missing-mat', 'btn-rep-prod-progress', 
        'btn-rep-prod-plan', 'btn-rep-prod-issues', 'btn-rep-proj-issues', 
        'btn-rep-proj-service', 'btn-rep-proj-extra', 'btn-rep-proj-deduct', 
        'btn-rep-proj-app-docs', 'btn-rep-proj-app-extra', 'btn-rep-proj-del-docs', 
        'btn-rep-proj-del-asbuilt', 'btn-rep-sale-quote', 'btn-rep-sale-delivery', 
        'btn-rep-sale-ack', 'btn-rep-sale-pnl', 'btn-rep-sale-issues', 
        'btn-rep-sale-comments', 'btn-rep-sale-contact', 'btn-rep-excl-daily-est', 
        'btn-rep-excl-daily-sale', 'btn-rep-excl-daily-design', 'btn-rep-excl-daily-prod', 
        'btn-rep-excl-daily-qc', 'btn-rep-excl-daily-proc', 'btn-rep-excl-daily-stock', 
        'btn-rep-excl-progress', 'btn-rep-excl-issues', 'btn-rep-excl-complaints'
    ];

    reportItemIds.forEach(id => {
        const btn = document.getElementById(id);
        if (btn) {
            btn.addEventListener('click', (e) => {
                e.stopPropagation();
                
                // If it is a progress report trigger, let's open progress report
                if (id === 'btn-rep-excl-progress') {
                    triggerPrintProgressReport();
                    return;
                }
                // If extra work report, we can open the extra works modal
                if (id === 'btn-rep-proj-extra') {
                    document.getElementById('btn-open-extra-work')?.click();
                    return;
                }
                // If deduct work report, we can open deduct works modal
                if (id === 'btn-rep-proj-deduct') {
                    document.getElementById('btn-open-deduct-work')?.click();
                    return;
                }
                
                const repTitle = btn.textContent.trim().replace(/^[a-z0-9.]+\s*/i, '');
                showToast(
                    state.currentLanguage === 'en' 
                        ? `Generating ${repTitle}...` 
                        : `กำลังสร้าง ${repTitle}...`, 
                    'info'
                );
                
                // Show printable simulation window or simulated PDF
                setTimeout(() => {
                    const printWindow = window.open('', '_blank');
                    if (printWindow) {
                        printWindow.document.write(`
                            <html>
                            <head>
                                <title>${repTitle}</title>
                                <link href="https://fonts.googleapis.com/css2?family=Sarabun:wght@300;400;600;700&display=swap" rel="stylesheet">
                                <style>
                                    body { font-family: 'Sarabun', sans-serif; padding: 40px; color: #1e293b; background: #f8fafc; }
                                    .report-card { background: white; padding: 40px; border-radius: 8px; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1); max-width: 800px; margin: 0 auto; border-top: 5px solid #0f172a; }
                                    h1 { font-size: 1.8rem; font-weight: 700; margin-bottom: 20px; border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; }
                                    .meta-row { display: flex; justify-content: space-between; margin-bottom: 30px; font-size: 0.9rem; color: #64748b; }
                                    .content-block { line-height: 1.6; margin-bottom: 30px; }
                                    .stamp { font-size: 0.8rem; color: #94a3b8; text-align: center; margin-top: 50px; border-top: 1px dashed #cbd5e1; padding-top: 20px; }
                                </style>
                            </head>
                            <body>
                                <div class="report-card">
                                    <h1>${repTitle}</h1>
                                    <div class="meta-row">
                                        <div><strong>โครงการ / Project ID:</strong> ${state.activeProjectId || '-'}</div>
                                        <div><strong>วันที่ / Date:</strong> ${new Date().toLocaleDateString('th-TH')}</div>
                                    </div>
                                    <div class="content-block">
                                        <p>ระบบกำลังดึงข้อมูลสำหรับรายงาน <strong>"${repTitle}"</strong>...</p>
                                        <p>รายงานนี้ประกอบด้วยสถิติ, ข้อมูลสรุปความก้าวหน้าการดำเนินงาน, และรายละเอียดเชิงลึกของโครงการแบบ Real-time</p>
                                    </div>
                                    <div class="stamp">
                                        เอกสารรายงานระบบประเมินราคา (Smart Estimation Dashboard Report)
                                    </div>
                                </div>
                            </body>
                            </html>
                        `);
                        printWindow.document.close();
                    }
                }, 800);
            });
        }
    });

    // Excel Import/Export triggers
    const btnExportExcel = document.getElementById('btn-export-excel');
    if (btnExportExcel) {
        btnExportExcel.addEventListener('click', async () => {
            if (!state.activeProjectId) return;
            try {
                showGlobalSpinner(state.currentLanguage === 'en' ? 'Exporting Excel...' : 'กำลังส่งออก Excel...');
                const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/export-excel`);
                const blob = await res.blob();
                const url = window.URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = `Project_${state.activeProjectId}_Estimates.xlsx`;
                document.body.appendChild(a);
                a.click();
                a.remove();
                window.URL.revokeObjectURL(url);
                showToast(state.currentLanguage === 'en' ? 'Excel exported successfully' : 'ส่งออกไฟล์ Excel เรียบร้อยแล้ว', 'success');
            } catch (err) {
                console.error(err);
                showToast(state.currentLanguage === 'en' ? 'Failed to export Excel' : 'เกิดข้อผิดพลาดในการส่งออก Excel', 'error');
            } finally {
                hideGlobalSpinner();
            }
        });
    }

    const btnImportExcel = document.getElementById('btn-import-excel');
    const inputImportExcel = document.getElementById('input-import-excel');
    if (btnImportExcel && inputImportExcel) {
        btnImportExcel.addEventListener('click', () => {
            inputImportExcel.click();
        });

        inputImportExcel.addEventListener('change', async (e) => {
            const file = e.target.files[0];
            if (!file) return;

            const formData = new FormData();
            formData.append('excel', file);

            try {
                showGlobalSpinner(state.currentLanguage === 'en' ? 'Importing Excel data...' : 'กำลังนำเข้าและซิงค์ข้อมูลจาก Excel...');
                const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/import-excel`, {
                    method: 'POST',
                    body: formData
                });
                const data = await res.json();

                showToast(state.currentLanguage === 'en' ? 'Excel imported successfully' : 'นำเข้าและซิงค์ข้อมูลจาก Excel เรียบร้อยแล้ว', 'success');
                await fetchActiveProjectDetails();
                renderWorkspace();
            } catch (err) {
                console.error(err);
                showToast(err.message || (state.currentLanguage === 'en' ? 'Failed to import Excel' : 'เกิดข้อผิดพลาดในการนำเข้า Excel'), 'error');
            } finally {
                inputImportExcel.value = '';
                hideGlobalSpinner();
            }
        });
    }

    // Supplier Manager Database Modal
    document.getElementById('btn-open-supplier-manager').addEventListener('click', openSupplierManagerModal);
    document.getElementById('btn-close-supplier-manager-modal').addEventListener('click', closeSupplierManagerModal);
    document.getElementById('supplier-manager-search').addEventListener('input', debounce(filterSuppliers, 300));
    document.getElementById('btn-add-supplier').addEventListener('click', () => openSupplierDetailModal());

    // Supplier Detail Form Actions
    document.getElementById('btn-close-supplier-detail-modal').addEventListener('click', closeSupplierDetailModal);
    document.getElementById('btn-close-supplier-detail-footer').addEventListener('click', closeSupplierDetailModal);
    document.getElementById('form-supplier-detail').addEventListener('submit', handleSupplierDetailSubmit);

    // Contractor Directory Manager Modal
    document.getElementById('btn-open-contractor-manager').addEventListener('click', () => {
        document.getElementById('contractor-dropdown-menu')?.classList.remove('active');
        openContractorManagerModal();
    });
    document.getElementById('btn-close-contractor-manager-modal').addEventListener('click', closeContractorManagerModal);
    document.getElementById('contractor-manager-search').addEventListener('input', debounce(filterContractors, 300));
    document.getElementById('btn-add-contractor').addEventListener('click', () => openContractorDetailModal());

    // Contractor Detail Form Actions
    document.getElementById('btn-close-contractor-detail-modal').addEventListener('click', closeContractorDetailModal);
    document.getElementById('btn-close-contractor-detail-footer').addEventListener('click', closeContractorDetailModal);
    document.getElementById('form-contractor-detail').addEventListener('submit', handleContractorDetailSubmit);

    // Contractors Dropdown Toggle
    const contractorDropdownBtn = document.getElementById('btn-contractor-dropdown-trigger');
    const contractorDropdownMenu = document.getElementById('contractor-dropdown-menu');
    if (contractorDropdownBtn && contractorDropdownMenu) {
        contractorDropdownBtn.addEventListener('click', (e) => {
            e.stopPropagation();
            contractorDropdownMenu.classList.toggle('active');
            document.getElementById('export-dropdown-menu')?.classList.remove('active');
            document.getElementById('project-selector-dropdown')?.classList.remove('active');
        });
        document.addEventListener('click', (e) => {
            if (!contractorDropdownMenu.contains(e.target) && e.target !== contractorDropdownBtn) {
                contractorDropdownMenu.classList.remove('active');
            }
        });
    }

    // Contractor RFQ List Modal
    document.getElementById('btn-open-project-rfq').addEventListener('click', () => {
        document.getElementById('contractor-dropdown-menu')?.classList.remove('active');
        openProjectRfqModal();
    });
    const rfqDirectBtn = document.getElementById('btn-open-project-rfq-direct');
    if (rfqDirectBtn) {
        rfqDirectBtn.addEventListener('click', () => {
            openProjectRfqModal();
        });
    }
    document.getElementById('btn-close-project-rfq-modal').addEventListener('click', closeProjectRfqModal);
    document.getElementById('rfq-list-search').addEventListener('input', debounce(filterRfqList, 300));
    document.getElementById('btn-create-rfq-trigger').addEventListener('click', openCreateRfqModal);

    // Create RFQ Dialog
    document.getElementById('btn-close-create-rfq-modal').addEventListener('click', closeCreateRfqModal);
    document.getElementById('btn-cancel-create-rfq').addEventListener('click', closeCreateRfqModal);
    document.getElementById('form-create-rfq').addEventListener('submit', handleCreateRfqSubmit);

    // Custom RFQ Confirmation Dialog Listeners
    document.getElementById('btn-close-rfq-confirm-modal').addEventListener('click', () => {
        document.getElementById('modal-rfq-confirm').classList.remove('active');
    });
    document.getElementById('btn-cancel-rfq-confirm').addEventListener('click', () => {
        document.getElementById('modal-rfq-confirm').classList.remove('active');
    });
    document.getElementById('btn-submit-rfq-confirm').addEventListener('click', submitRfqQuotationConfirmed);

    // Activity Log Modal
    document.getElementById('btn-open-activity-log').addEventListener('click', openActivityLogModal);
    document.getElementById('btn-close-activity-log-modal').addEventListener('click', closeActivityLogModal);
    document.getElementById('activity-log-search').addEventListener('input', debounce(filterActivityLog, 300));
    document.getElementById('activity-log-date-from').addEventListener('change', filterActivityLog);
    document.getElementById('activity-log-date-to').addEventListener('change', filterActivityLog);
    document.getElementById('btn-activity-log-clear-dates').addEventListener('click', () => {
        document.getElementById('activity-log-date-from').value = '';
        document.getElementById('activity-log-date-to').value = '';
        filterActivityLog();
    });
    document.getElementById('btn-activity-log-prev-page').addEventListener('click', () => {
        if (state.activityLogPage > 1) {
            state.activityLogPage--;
            fetchAndRenderActivityLog();
        }
    });
    document.getElementById('btn-activity-log-next-page').addEventListener('click', () => {
        const totalPages = Math.max(Math.ceil(state.activityLogTotal / state.activityLogLimit), 1);
        if (state.activityLogPage < totalPages) {
            state.activityLogPage++;
            fetchAndRenderActivityLog();
        }
    });

    // Department Reports Modal
    document.getElementById('btn-open-reports').addEventListener('click', openReportsModal);
    document.getElementById('btn-close-reports-modal').addEventListener('click', closeReportsModal);
    document.getElementById('btn-close-reports-footer').addEventListener('click', closeReportsModal);

    // Internal Chat Modal
    document.getElementById('btn-open-chat').addEventListener('click', openChatModal);
    document.getElementById('btn-close-chat-modal').addEventListener('click', closeChatModal);
    document.getElementById('btn-new-conversation').addEventListener('click', openNewConversationModal);
    document.getElementById('btn-close-new-conversation-modal').addEventListener('click', closeNewConversationModal);
    document.getElementById('new-conversation-search').addEventListener('input', debounce(filterNewConversationUserList, 200));
    document.getElementById('btn-toggle-group-mode').addEventListener('click', toggleGroupChatMode);
    document.getElementById('btn-submit-group-chat').addEventListener('click', handleSubmitGroupChat);
    document.getElementById('form-chat-send').addEventListener('submit', handleChatSendSubmit);

    // Group members management listeners
    document.getElementById('btn-manage-group').addEventListener('click', openGroupMembersModal);
    document.getElementById('btn-close-group-members-modal').addEventListener('click', closeGroupMembersModal);
    document.getElementById('btn-submit-invite').addEventListener('click', handleInviteMember);

    // Audio recording listeners
    document.getElementById('btn-chat-mic').addEventListener('click', () => {
        const isRecording = state.mediaRecorder && state.mediaRecorder.state === 'recording';
        if (isRecording) {
            stopVoiceRecording(true); // Send
        } else {
            startVoiceRecording();
        }
    });
    document.getElementById('btn-chat-mic-cancel').addEventListener('click', () => stopVoiceRecording(false));
    document.getElementById('btn-chat-mic-send').addEventListener('click', () => stopVoiceRecording(true));

    // Chat search listeners
    document.getElementById('chat-search-input').addEventListener('input', debounce(async () => {
        await fetchAndRenderConversations();
    }, 200));

    // Message search listeners
    document.getElementById('btn-chat-message-search-toggle').addEventListener('click', () => {
        const container = document.getElementById('chat-message-search-container');
        const isSearchVisible = container.style.display === 'flex';
        if (isSearchVisible) {
            container.style.display = 'none';
            document.getElementById('chat-message-search-input').value = '';
            document.getElementById('btn-chat-message-search-clear').style.display = 'none';
            fetchAndRenderChatMessages();
        } else {
            container.style.display = 'flex';
            document.getElementById('chat-message-search-input').focus();
        }
    });

    document.getElementById('chat-message-search-input').addEventListener('input', debounce(() => {
        const val = document.getElementById('chat-message-search-input').value;
        document.getElementById('btn-chat-message-search-clear').style.display = val ? 'inline-block' : 'none';
        fetchAndRenderChatMessages();
    }, 200));

    document.getElementById('btn-chat-message-search-clear').addEventListener('click', () => {
        document.getElementById('chat-message-search-input').value = '';
        document.getElementById('btn-chat-message-search-clear').style.display = 'none';
        fetchAndRenderChatMessages();
    });

    // Chat Emoji Popover trigger
    document.getElementById('btn-chat-emoji').addEventListener('click', () => {
        const popover = document.getElementById('chat-emoji-popover');
        popover.style.display = popover.style.display === 'none' ? 'flex' : 'none';
    });

    // Close Emoji popover on click outside
    document.addEventListener('click', (e) => {
        const popover = document.getElementById('chat-emoji-popover');
        const emojiBtn = document.getElementById('btn-chat-emoji');
        if (popover && popover.style.display === 'flex' && !popover.contains(e.target) && e.target !== emojiBtn && !emojiBtn.contains(e.target)) {
            popover.style.display = 'none';
        }
    });

    // Chat Image Upload trigger & upload event
    document.getElementById('btn-chat-image').addEventListener('click', () => {
        document.getElementById('chat-image-input').click();
    });

    document.getElementById('chat-image-input').addEventListener('change', async (e) => {
        const file = e.target.files[0];
        if (file) {
            await handleChatImageUpload(file);
        }
    });

    // Announcement Acknowledgment Modal
    const ackAnnBtn = document.getElementById('btn-acknowledge-announcement');
    if (ackAnnBtn) {
        ackAnnBtn.addEventListener('click', handleAcknowledgeAnnouncement);
    }

    // My Profile / Change Password Modal
    document.getElementById('btn-open-my-profile').addEventListener('click', openMyProfileModal);
    document.getElementById('btn-close-my-profile-modal').addEventListener('click', closeMyProfileModal);
    document.getElementById('btn-close-my-profile-footer').addEventListener('click', closeMyProfileModal);
    document.getElementById('form-my-profile').addEventListener('submit', handleMyProfileSubmit);

    // RFQ Detail / Quotation Form Modal
    document.getElementById('btn-close-rfq-detail-modal').addEventListener('click', closeRfqDetailModal);
    document.getElementById('btn-close-rfq-detail-footer').addEventListener('click', closeRfqDetailModal);
    document.getElementById('btn-rfq-save-draft').addEventListener('click', handleSaveRfqDraft);
    document.getElementById('btn-rfq-submit').addEventListener('click', handleRfqSubmit);
    document.getElementById('btn-rfq-select-quote-file').addEventListener('click', () => document.getElementById('rfq-quote-file-input').click());
    document.getElementById('rfq-quote-file-input').addEventListener('change', handleRfqQuoteFileSelected);
    document.getElementById('btn-rfq-remove-quote-file').addEventListener('click', handleRfqRemoveQuoteFile);
    document.getElementById('btn-rfq-print-preview').addEventListener('click', printRfqQuotation);

    // Update supplier website link on dropdown change
    document.getElementById('detail-supplier-id').addEventListener('change', (e) => {
        updateSupplierWebsiteLink(e.target.value);
    });

    // Supplier quote file selection trigger
    const supplierQuoteInput = document.getElementById('product-supplier-quote-file');
    document.getElementById('btn-trigger-supplier-quote-input').addEventListener('click', () => supplierQuoteInput.click());
    supplierQuoteInput.addEventListener('change', handleSupplierQuoteSelection);

    // Project Approval toggle
    document.getElementById('btn-approve-project').addEventListener('click', handleProjectApprovalToggle);

    // Proposal Letter Editor triggers
    document.getElementById('btn-edit-proposal-letter').addEventListener('click', openProposalEditor);
    document.getElementById('btn-close-proposal-editor-modal').addEventListener('click', closeProposalEditor);
    document.getElementById('btn-print-proposal-letter').addEventListener('click', () => {
        document.body.classList.add('print-mode-proposal');
        window.print();
    });

    // Project Approval attachments list trigger
    document.getElementById('btn-open-attachments').addEventListener('click', openApprovalAttachmentsModal);
    document.getElementById('btn-close-attachments-modal').addEventListener('click', closeApprovalAttachmentsModal);
    document.getElementById('btn-close-attachments-footer').addEventListener('click', closeApprovalAttachmentsModal);

    // Project Documents Vault trigger
    document.getElementById('btn-open-project-docs').addEventListener('click', openProjectDocsModal);
    document.getElementById('btn-close-project-docs-modal').addEventListener('click', closeProjectDocsModal);
    document.getElementById('btn-close-project-docs-footer').addEventListener('click', closeProjectDocsModal);

    // PDF Embedded Viewer close trigger
    document.getElementById('btn-close-pdf-viewer-modal').addEventListener('click', closePdfViewer);

    // Image lightbox Modal close
    document.getElementById('btn-close-lightbox').addEventListener('click', () => {
        document.getElementById('modal-lightbox').classList.remove('active');
    });

    // Pagination Controls Listeners
    document.getElementById('btn-explorer-prev-page').addEventListener('click', () => {
        if (state.explorerCurrentPage > 1) {
            state.explorerCurrentPage--;
            renderExplorerProductsPagination();
        }
    });
    document.getElementById('btn-explorer-next-page').addEventListener('click', () => {
        const totalPages = Math.ceil(state.explorerProducts.length / state.explorerPageSize) || 1;
        if (state.explorerCurrentPage < totalPages) {
            state.explorerCurrentPage++;
            renderExplorerProductsPagination();
        }
    });
    document.getElementById('btn-manager-prev-page').addEventListener('click', () => {
        if (state.managerCurrentPage > 1) {
            state.managerCurrentPage--;
            renderManagerProductsPagination();
        }
    });
    document.getElementById('btn-manager-next-page').addEventListener('click', () => {
        const totalPages = Math.ceil(state.managerProducts.length / state.managerPageSize) || 1;
        if (state.managerCurrentPage < totalPages) {
            state.managerCurrentPage++;
            renderManagerProductsPagination();
        }
    });

    // Cleanup print classes after document prints
    window.onafterprint = () => {
        document.body.classList.remove('print-mode-quotation');
        document.body.classList.remove('print-mode-bom');
        document.body.classList.remove('print-mode-proposal');
        document.body.classList.remove('print-mode-free-issue');
    };

    // Image URL input changes to update preview
    document.getElementById('product-image-url').addEventListener('input', (e) => {
        const url = e.target.value.trim();
        const preview = document.getElementById('product-image-preview');
        if (url) {
            // Reset selected file if URL is pasted/entered
            state.imageFileToUpload = null;
            document.getElementById('product-image-file').value = '';

            preview.innerHTML = `<img src="${url}" alt="URL Preview" style="max-width:100%; max-height:100%; object-fit:contain;" onerror="this.src=''; this.parentNode.innerHTML='<i class=\'fa-regular fa-image placeholder-icon\'></i>';">`;
        } else {
            preview.innerHTML = '<i class="fa-regular fa-image placeholder-icon"></i>';
        }
    });

    // Capture clipboard paste events for product image
    document.addEventListener('paste', (e) => {
        const modal = document.getElementById('modal-product-detail');
        if (!modal || !modal.classList.contains('active')) return;

        const clipboardData = e.clipboardData || (e.originalEvent && e.originalEvent.clipboardData);
        if (!clipboardData) return;

        let imageFile = null;

        // 1. Try files list first (covers file explorer copies)
        if (clipboardData.files && clipboardData.files.length > 0) {
            for (let i = 0; i < clipboardData.files.length; i++) {
                const file = clipboardData.files[i];
                if (file.type && file.type.startsWith('image/')) {
                    imageFile = file;
                    break;
                }
            }
        }

        // 2. Try items list (covers direct screenshot/browser copies)
        if (!imageFile && clipboardData.items && clipboardData.items.length > 0) {
            for (let i = 0; i < clipboardData.items.length; i++) {
                const item = clipboardData.items[i];
                if (item.type && item.type.startsWith('image/')) {
                    imageFile = item.getAsFile();
                    if (imageFile) {
                        break;
                    }
                }
            }
        }

        if (imageFile) {
            // Prevent default paste to prevent inserting filename or image text into focused inputs if any
            e.preventDefault();

            state.imageFileToUpload = imageFile;
            document.getElementById('product-image-url').value = ''; // clear url input if pasting file

            const reader = new FileReader();
            reader.onload = (event) => {
                const preview = document.getElementById('product-image-preview');
                if (preview) {
                    preview.innerHTML = `<img src="${event.target.result}" alt="Pasted Preview" style="max-width:100%; max-height:100%; object-fit:contain;">`;
                }
            };
            reader.readAsDataURL(imageFile);
            showToast(state.currentLanguage === 'en' ? 'Image pasted from clipboard' : 'วางรูปภาพจากคลิปบอร์ดแล้ว');
        }
    }, true);

    // Click on preview box to paste image from clipboard directly
    document.getElementById('product-image-preview').addEventListener('click', async () => {
        if (navigator.clipboard && navigator.clipboard.read) {
            try {
                const clipboardItems = await navigator.clipboard.read();
                for (const item of clipboardItems) {
                    for (const type of item.types) {
                        if (type.startsWith('image/')) {
                            const blob = await item.getType(type);
                            const file = new File([blob], 'clipboard-image.png', { type });

                            state.imageFileToUpload = file;
                            document.getElementById('product-image-url').value = '';

                            const reader = new FileReader();
                            reader.onload = (event) => {
                                document.getElementById('product-image-preview').innerHTML = `<img src="${event.target.result}" alt="Pasted Image" style="max-width:100%; max-height:100%; object-fit:contain;">`;
                            };
                            reader.readAsDataURL(file);
                            showToast(state.currentLanguage === 'en' ? 'Image pasted from clipboard' : 'วางรูปภาพจากคลิปบอร์ดแล้ว');
                            return;
                        }
                    }
                }
            } catch (err) {
                console.warn('Direct clipboard read failed, focusing for Ctrl+V fallback:', err);
                document.getElementById('product-image-preview').focus();
            }
        } else {
            document.getElementById('product-image-preview').focus();
        }
    });

    // Admin Panel Modal Listeners
    const openAdminBtn = document.getElementById('btn-open-admin-panel');
    if (openAdminBtn) openAdminBtn.addEventListener('click', openAdminPanelModal);

    document.getElementById('btn-close-admin-modal').addEventListener('click', closeAdminPanelModal);
    document.getElementById('btn-close-admin-footer').addEventListener('click', closeAdminPanelModal);
    document.getElementById('btn-add-user').addEventListener('click', openAddUserModal);
    document.getElementById('btn-refresh-admin-users').addEventListener('click', fetchAdminUsers);
    document.getElementById('btn-close-add-user-modal').addEventListener('click', closeAddUserModal);
    document.getElementById('btn-cancel-add-user').addEventListener('click', closeAddUserModal);
    document.getElementById('form-add-user').addEventListener('submit', handleNewUserSubmit);

    // Super Admin System Panel Modal Listeners
    const openSystemBtn = document.getElementById('btn-open-system-panel');
    if (openSystemBtn) openSystemBtn.addEventListener('click', openSystemPanel);

    document.getElementById('btn-close-system-modal').addEventListener('click', closeSystemPanel);
    document.getElementById('btn-close-system-footer').addEventListener('click', closeSystemPanel);
    document.getElementById('btn-save-schedule-config').addEventListener('click', saveBackupScheduleConfig);
    document.getElementById('btn-trigger-manual-backup').addEventListener('click', triggerManualBackup);
    document.getElementById('btn-trigger-db-repair').addEventListener('click', triggerDbRepair);
    document.getElementById('form-restore-upload').addEventListener('submit', handleRestoreUpload);

    document.getElementById('tab-users-btn').addEventListener('click', () => switchAdminTab('users'));
    document.getElementById('tab-permissions-btn').addEventListener('click', () => switchAdminTab('permissions'));

    document.getElementById('btn-admin-refresh').addEventListener('click', handleAdminPanelRefresh);

    // Legacy announcements listeners commented out to let announcements.js manage it
    // const openAnnouncementsBtn = document.getElementById('btn-open-announcements');
    // if (openAnnouncementsBtn) openAnnouncementsBtn.addEventListener('click', openAnnouncementsManagerModal);
    // document.getElementById('btn-close-announcements-manager-modal').addEventListener('click', closeAnnouncementsManagerModal);
    // document.getElementById('btn-close-announcements-manager-footer').addEventListener('click', closeAnnouncementsManagerModal);
    // document.getElementById('btn-add-announcement').addEventListener('click', () => openAnnouncementDetailModal());
    // document.getElementById('btn-close-announcement-detail-modal').addEventListener('click', closeAnnouncementDetailModal);
    // document.getElementById('btn-cancel-announcement-detail').addEventListener('click', closeAnnouncementDetailModal);
    // document.getElementById('form-announcement-detail').addEventListener('submit', handleAnnouncementDetailSubmit);

    document.getElementById('admin-select-project').addEventListener('change', (e) => {
        fetchProjectPermissions(e.target.value);
    });

    // Initialize project documents vault drag & drop dropzone
    setupDocsDropzone();

    // Initialize project progress update event listeners and dropzone
    document.getElementById('btn-open-project-progress').addEventListener('click', openProjectProgressModal);
    document.getElementById('btn-close-project-progress-modal').addEventListener('click', closeProjectProgressModal);
    document.getElementById('btn-close-project-progress-footer').addEventListener('click', closeProjectProgressModal);
    document.getElementById('btn-new-progress-trigger').addEventListener('click', () => {
        clearProgressForm();
        document.getElementById('progress-form-panel').style.display = 'flex';
        document.getElementById('modal-project-progress').classList.add('form-open');
        setCurrentProgressTimestamp();
        buildProgressSystemDropdown(); // Rebuild systems dropdown
    });
    document.getElementById('btn-cancel-progress-form').addEventListener('click', () => {
        document.getElementById('progress-form-panel').style.display = 'none';
        document.getElementById('modal-project-progress').classList.remove('form-open');
        clearProgressForm();
    });
    document.getElementById('btn-progress-toggle-camera').addEventListener('click', toggleProgressCamera);
    document.getElementById('btn-progress-camera-snap').addEventListener('click', snapProgressPhoto);
    document.getElementById('form-project-progress').addEventListener('submit', handleProgressFormSubmit);
    setupProgressImageDropzone();

    // Initialize FAT event listeners
    document.getElementById('btn-open-project-fat').addEventListener('click', openProjectFatModal);
    document.getElementById('btn-close-project-fat-modal').addEventListener('click', closeProjectFatModal);
    document.getElementById('btn-close-project-fat-footer').addEventListener('click', closeProjectFatModal);
    document.getElementById('btn-new-fat-trigger').addEventListener('click', openCreateFatModal);
    document.getElementById('btn-print-all-fat').addEventListener('click', printAllFatReports);
    document.getElementById('btn-close-create-fat-modal').addEventListener('click', closeCreateFatModal);
    document.getElementById('btn-cancel-create-fat').addEventListener('click', closeCreateFatModal);
    document.getElementById('form-create-fat-report').addEventListener('submit', handleCreateFatSubmit);

    // Mobile drawer toggles for FAT and Test Script
    document.getElementById('btn-toggle-fat-sidebar').addEventListener('click', () => {
        const sidebar = document.querySelector('#modal-project-fat .fat-sidebar');
        if (sidebar) sidebar.classList.toggle('drawer-active');
    });
    document.getElementById('btn-toggle-test-script-sidebar').addEventListener('click', () => {
        const sidebar = document.querySelector('#modal-project-test-script .test-script-sidebar');
        if (sidebar) sidebar.classList.toggle('drawer-active');
    });

    // Container management and filter listeners
    document.getElementById('fat-filter-container').addEventListener('change', fetchAndRenderFatReportsList);
    document.getElementById('btn-add-container-no').addEventListener('click', handleAddContainerNo);
    document.getElementById('fat-select-container').addEventListener('change', (e) => {
        const inputNew = document.getElementById('fat-input-container-new');
        if (e.target.value === '__NEW__') {
            inputNew.style.display = 'block';
            inputNew.value = '';
            inputNew.focus();
        } else {
            inputNew.style.display = 'none';
        }
    });

    // Initialize Test Script event listeners
    document.getElementById('btn-open-project-test-script').addEventListener('click', openProjectTestScriptModal);
    document.getElementById('btn-close-project-test-script-modal').addEventListener('click', closeProjectTestScriptModal);
    document.getElementById('btn-close-project-test-script-footer').addEventListener('click', closeProjectTestScriptModal);

    // Listen for custom system option selection
    document.getElementById('progress-system-select').addEventListener('change', (e) => {
        const customInput = document.getElementById('progress-system-custom');
        if (e.target.value === 'CUSTOM') {
            customInput.style.display = 'block';
            customInput.required = true;
            customInput.focus();
        } else {
            customInput.style.display = 'none';
            customInput.required = false;
            customInput.value = '';
        }
    });

    // Listen for print progress report click
    document.getElementById('btn-print-progress-report').addEventListener('click', triggerPrintProgressReport);
    document.getElementById('btn-refresh-progress-list').addEventListener('click', fetchAndRenderProgressList);

    // Initialize Web Speech API
    initSpeechRecognition();
}

// ==========================================
// Authentication handlers
// ==========================================

async function handleLogin(e) {
    e.preventDefault();
    const username = document.getElementById('login-username').value;
    const password = document.getElementById('login-password').value;

    try {
        const res = await fetch(`${API_BASE}/login`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ username, password })
        });

        if (!res.ok) {
            const err = await res.json();
            const errMsg = err.error === 'Username หรือ Password ไม่ถูกต้อง' ? t('alert_login_failed') : (err.error || t('alert_login_failed'));
            throw new Error(errMsg);
        }

        const user = await res.json();
        // Store JWT token separately
        if (user.token) {
            localStorage.setItem('authToken', user.token);
        }
        localStorage.setItem('currentUser', JSON.stringify({ id: user.id, username: user.username, role: user.role }));
        showToast(t('toast_login_success'));
        checkSession();
        resetIdleTimer();
    } catch (err) {
        showToast(err.message, 'error');
    }
}

async function handleLogout() {
    if (state.currentUser) {
        const userId = state.currentUser.id;
        const key = `modifiedProjects_${userId}`;
        let modifiedProjects = [];
        try {
            modifiedProjects = JSON.parse(localStorage.getItem(key)) || [];
        } catch (e) {
            modifiedProjects = [];
        }

        try {
            await fetch(`${API_BASE}/logout`, {
                method: 'POST',
                headers: {
                    ...getHeaders()
                },
                body: JSON.stringify({ userId, modifiedProjects })
            });
            localStorage.removeItem(key);
        } catch (err) {
            console.error('Failed to report logout revisions:', err);
        }
    }

    localStorage.removeItem('authToken');
    localStorage.removeItem('currentUser');
    state.currentUser = null;
    state.activeProjectId = null;
    state.activeProject = null;
    state.activeProjectSummary = null;
    if (state.chatUnreadPollInterval) {
        clearInterval(state.chatUnreadPollInterval);
        state.chatUnreadPollInterval = null;
    }
    if (state.announcementPollInterval) {
        clearInterval(state.announcementPollInterval);
        state.announcementPollInterval = null;
    }
    if (state.contractorProjectsPollInterval) {
        clearInterval(state.contractorProjectsPollInterval);
        state.contractorProjectsPollInterval = null;
    }
    stopChatThreadPolling();
    checkSession();
    showToast(t('toast_logout_success'));
}

function openMyProfileModal() {
    if (!state.currentUser) return;
    document.getElementById('form-my-profile').reset();
    document.getElementById('my-profile-username').value = state.currentUser.username;
    document.getElementById('my-profile-role').value = translateRole(state.currentUser.role);
    document.getElementById('modal-my-profile').classList.add('active');
}

function closeMyProfileModal() {
    document.getElementById('modal-my-profile').classList.remove('active');
}

async function handleMyProfileSubmit(e) {
    e.preventDefault();
    const submitBtn = e.target.querySelector('button[type="submit"]');
    const originalText = submitBtn ? submitBtn.innerHTML : '';

    const currentPassword = document.getElementById('my-profile-current-password').value;
    const newPassword = document.getElementById('my-profile-new-password').value;
    const confirmPassword = document.getElementById('my-profile-confirm-password').value;

    if (newPassword !== confirmPassword) {
        showToast(state.currentLanguage === 'en' ? 'New password and confirmation do not match' : 'รหัสผ่านใหม่และการยืนยันไม่ตรงกัน', 'error');
        return;
    }

    if (submitBtn) {
        submitBtn.disabled = true;
        submitBtn.innerHTML = state.currentLanguage === 'en' ? '<i class="fa-solid fa-spinner fa-spin"></i> Saving...' : '<i class="fa-solid fa-spinner fa-spin"></i> กำลังบันทึก...';
    }

    try {
        const res = await authFetch(`${API_BASE}/users/me/password`, {
            method: 'PUT',
            body: JSON.stringify({ currentPassword, newPassword })
        });
        const data = await res.json();
        if (!res.ok) {
            throw new Error(data.error || (state.currentLanguage === 'en' ? 'Failed to update password' : 'ไม่สามารถบันทึกรหัสผ่านใหม่ได้'));
        }
        showToast(state.currentLanguage === 'en' ? 'Password updated successfully' : 'บันทึกรหัสผ่านใหม่เรียบร้อยแล้ว');
        closeMyProfileModal();
    } catch (err) {
        showToast(err.message, 'error');
    } finally {
        if (submitBtn) {
            submitBtn.disabled = false;
            submitBtn.innerHTML = originalText;
        }
    }
}

// ==========================================
// Project CRUD Operations
// ==========================================

async function fetchProjects() {
    try {
        const showDeleted = document.getElementById('chk-show-deleted-projects')?.checked || false;
        const res = await authFetch(`${API_BASE}/projects?show_deleted=${showDeleted}`);
        state.projects = await res.json();
        renderSidebar();
    } catch (err) {
        showToast(t('toast_error_permission'), 'error');
    }
}

function renderSidebar() {
    const container = document.getElementById('project-dropdown-list');
    if (!container) return;
    container.innerHTML = '';

    if (state.projects.length === 0) {
        container.innerHTML = `<p style="padding: 20px; font-size: 0.85rem; color: #cbd5e1; text-align: center;">${state.currentLanguage === 'en' ? 'No projects in system' : 'ไม่มีโครงการในระบบ'}</p>`;
        return;
    }

    // Read current search query
    const searchQuery = (document.getElementById('project-dropdown-search')?.value || '').toLowerCase().trim();

    const filteredProjects = state.projects.filter(project => {
        const name = (project.name || '').toLowerCase();
        const client = (project.client_name || '').toLowerCase();
        return name.includes(searchQuery) || client.includes(searchQuery);
    });

    filteredProjects.sort((a, b) => {
        const nameA = ((state.currentUser && state.currentUser.role === 'contractor' && a.external_name) ? a.external_name : a.name) || '';
        const nameB = ((state.currentUser && state.currentUser.role === 'contractor' && b.external_name) ? b.external_name : b.name) || '';
        return nameA.localeCompare(nameB, undefined, { sensitivity: 'base' });
    });

    if (filteredProjects.length === 0) {
        container.innerHTML = `<p style="padding: 20px; font-size: 0.85rem; color: #94a3b8; text-align: center;">${state.currentLanguage === 'en' ? 'No matching projects' : 'ไม่พบโครงการที่ค้นหา'}</p>`;
        return;
    }

    filteredProjects.forEach(project => {
        const isActive = project.id === state.activeProjectId;
        const item = document.createElement('button');
        item.type = 'button';
        item.className = `dropdown-item-project ${isActive ? 'active' : ''}`;
        const hasPendingBadge = project.has_pending_rfq ? `<span class="badge bg-danger" style="background-color:#ef4444; color:white; font-size:0.65rem; font-weight:700; padding:1px 4px; border-radius:10px; margin-left:6px; animation: pulse 2s infinite;">New</span>` : '';
        item.innerHTML = `
            <div class="dropdown-item-project-left">
                <div class="dropdown-item-project-name">${escapeHtml((state.currentUser && state.currentUser.role === 'contractor' && project.external_name) ? project.external_name : project.name)} ${hasPendingBadge}</div>
                <div class="dropdown-item-project-client"><i class="fa-regular fa-building" style="font-size:0.7rem;"></i> ${escapeHtml(project.client_name || (state.currentLanguage === 'en' ? 'Not Specified' : 'ไม่ระบุลูกค้า'))}</div>
            </div>
            <div class="dropdown-item-project-right">
                <span class="dropdown-item-project-price">${formatCurrency(project.total_quote)}</span>
                <span class="badge-rev">REV ${project.current_revision || 0}</span>
            </div>
        `;
        item.addEventListener('click', () => {
            selectProject(project.id);
            const projSelectorDropdown = document.getElementById('project-selector-dropdown');
            if (projSelectorDropdown) projSelectorDropdown.classList.remove('active');
        });
        container.appendChild(item);
    });

    // Update global badge
    const hasAnyPending = state.projects.some(p => p.has_pending_rfq);
    const globalBadge = document.getElementById('project-selector-global-badge');
    if (globalBadge) {
        globalBadge.style.display = hasAnyPending ? 'inline-block' : 'none';
    }
}

async function selectProject(id) {
    state.activeProjectId = id;
    state.selectedRfqId = null; // Reset RFQ selection on project switch
    renderSidebar();
    showGlobalSpinner(state.currentLanguage === 'en' ? 'Loading project details...' : 'กำลังโหลดข้อมูลโครงการ...');
    try {
        await Promise.all([
            fetchActiveProjectDetails(),
            fetchActiveProjectDocs()
        ]);
    } catch (err) {
        console.error(err);
    } finally {
        hideGlobalSpinner();
    }
    renderWorkspace();
}

async function fetchActiveProjectDetails() {
    if (!state.activeProjectId) return;
    try {
        let url = `${API_BASE}/projects/${state.activeProjectId}/summary?mode=${state.workspaceMode}`;
        if (state.selectedRfqId) {
            url += `&rfq_id=${state.selectedRfqId}`;
        }
        const res = await authFetch(url);
        state.activeProjectSummary = await res.json();
        
        // Auto-initialize selectedRfqId on first project load
        if (!state.selectedRfqId && state.activeProjectSummary.latest_rfq_id) {
            state.selectedRfqId = state.activeProjectSummary.latest_rfq_id;
        }

        state.activeProject = {
            id: state.activeProjectSummary.id,
            name: state.activeProjectSummary.name,
            client_name: state.activeProjectSummary.client_name,
            description: state.activeProjectSummary.description
        };
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load project summary' : 'ไม่สามารถโหลดข้อมูลสรุปโครงการได้', 'error');
    }
}

function renderWorkspace() {
    const emptyState = document.getElementById('empty-workspace-state');
    const activeState = document.getElementById('project-workspace-active');

    const selectedProjNameSpan = document.getElementById('current-project-selector-name');
    if (selectedProjNameSpan) {
        if (state.activeProjectId && state.activeProjectSummary) {
            selectedProjNameSpan.textContent = `${state.activeProjectSummary.name} [REV ${state.activeProjectSummary.current_revision || 0}]`;
        } else {
            selectedProjNameSpan.textContent = t('select_project_placeholder');
        }
    }

    if (!state.activeProjectId || !state.activeProjectSummary) {
        emptyState.style.display = 'flex';
        activeState.style.display = 'none';
        applyRoleBasedUI();
        return;
    }

    emptyState.style.display = 'none';
    activeState.style.display = 'flex';

    // Show/hide soft-deleted warning banner
    const isDeleted = state.activeProjectSummary.is_deleted === 1;
    const deletedBanner = document.getElementById('deleted-project-banner');
    const restoreBtn = document.getElementById('btn-restore-project');
    if (deletedBanner) {
        if (isDeleted) {
            deletedBanner.style.display = 'flex';
            // Only creator, admin, or superadmin can restore
            const isCreator = state.activeProjectSummary.created_by === state.currentUser?.id;
            const isAdmin = state.currentUser?.role === 'admin' || state.currentUser?.role === 'superadmin';
            if (isCreator || isAdmin) {
                restoreBtn.style.display = 'inline-flex';
            } else {
                restoreBtn.style.display = 'none';
            }
        } else {
            deletedBanner.style.display = 'none';
        }
    }

    // Set text headers and status badge
    const isContractor = state.currentUser && state.currentUser.role === 'contractor';
    const displayProjectName = (isContractor && state.activeProjectSummary.external_name)
        ? state.activeProjectSummary.external_name
        : state.activeProjectSummary.name;
    document.getElementById('active-project-name').textContent = displayProjectName;
    document.getElementById('active-project-rev').textContent = `REV ${state.activeProjectSummary.current_revision || 0}`;

    const typeBadge = document.getElementById('active-project-type');
    if (typeBadge) {
        if (state.activeProjectSummary.project_type) {
            typeBadge.textContent = state.activeProjectSummary.project_type;
            typeBadge.style.display = 'inline-block';
        } else {
            typeBadge.style.display = 'none';
        }
    }
    document.getElementById('active-project-client').innerHTML = `<i class="fa-regular fa-building"></i> ${t('project_client_label')} ${escapeHtml(state.activeProjectSummary.client_name || (state.currentLanguage === 'en' ? 'Not Specified' : 'ไม่ระบุ'))}`;
    document.getElementById('active-project-desc').textContent = state.activeProjectSummary.description || (state.currentLanguage === 'en' ? 'No project details provided' : 'ไม่มีรายละเอียดโครงการ');

    const rfqBadge = document.getElementById('contractor-rfq-ref-badge');
    if (rfqBadge) {
        const isContractor = state.currentUser && state.currentUser.role === 'contractor';
        if (isContractor && state.activeProjectSummary.latest_rfq_number) {
            rfqBadge.textContent = state.currentLanguage === 'en' 
                ? `RFQ Ref: ${state.activeProjectSummary.latest_rfq_number}` 
                : `อ้างอิง RFQ: ${state.activeProjectSummary.latest_rfq_number}`;
            rfqBadge.style.display = 'inline-block';
        } else {
            rfqBadge.style.display = 'none';
        }
    }

    // Project Approval status UI
    const isApproved = state.activeProjectSummary.status === 'อนุมัติแล้ว';
    const statusBadge = document.getElementById('active-project-status');
    const statusSelect = document.getElementById('active-project-status-select');
    const approveBtn = document.getElementById('btn-approve-project');
    const userRole = state.currentUser ? state.currentUser.role : 'user';

    const allowedStatusRoles = ['admin', 'superadmin', 'supervisor', 'estimate', 'production', 'procurment', 'sale', 'excusive', 'stock'];
    const canChangeStatus = state.currentUser && allowedStatusRoles.includes(userRole);
    
    const statusStyles = {
        'รอดำเนินการ': { bg: '#fef3c7', text: '#92400e', transKey: 'status_pending' },
        'อนุมัติแล้ว': { bg: '#d1fae5', text: '#065f46', transKey: 'status_approved' },
        'กำลังดำเนินงาน': { bg: '#e0f2fe', text: '#0369a1', transKey: 'status_in_progress' },
        'เสร็จสิ้น': { bg: '#d1fae5', text: '#065f46', transKey: 'status_completed' },
        'ยกเลิก': { bg: '#fee2e2', text: '#b91c1c', transKey: 'status_cancelled' }
    };
    
    const curStatus = state.activeProjectSummary.status || 'รอดำเนินการ';
    const styleObj = statusStyles[curStatus] || { bg: '#fef3c7', text: '#92400e', transKey: 'status_pending' };
    
    statusBadge.textContent = t(styleObj.transKey);
    statusBadge.style.backgroundColor = styleObj.bg;
    statusBadge.style.color = styleObj.text;
    
    if (canChangeStatus) {
        statusBadge.style.display = 'none';
        if (statusSelect) {
            statusSelect.style.display = 'inline-block';
            statusSelect.value = curStatus;
            statusSelect.style.backgroundColor = styleObj.bg;
            statusSelect.style.color = styleObj.text;
            statusSelect.style.borderColor = styleObj.text;
        }
    } else {
        statusBadge.style.display = 'inline-block';
        if (statusSelect) statusSelect.style.display = 'none';
    }

    if (isApproved) {
        approveBtn.innerHTML = `<i class="fa-solid fa-rotate-left"></i> ${state.currentLanguage === 'en' ? 'Cancel Approval' : 'ยกเลิกการอนุมัติ'}`;
        approveBtn.className = 'btn btn-danger-outline btn-sm';
    } else {
        approveBtn.innerHTML = `<i class="fa-solid fa-check-double"></i> ${t('btn_approve_project')}`;
        approveBtn.className = 'btn btn-success btn-sm';
    }

    if (isReadOnlyRole(userRole)) {
        approveBtn.style.display = 'none';
    } else {
        approveBtn.style.display = 'inline-flex';
    }

    // Render Stats
    const isProdMode = state.workspaceMode === 'production' || state.workspaceMode === 'product-supply';
    const totalCost = state.activeProjectSummary.production_cost_total;
    const totalQuote = state.activeProjectSummary.price_total;
    const totalProfit = totalQuote - totalCost;
    const margin = totalQuote > 0 ? (totalProfit / totalQuote) * 100 : 0;

    document.getElementById('summary-total-cost').textContent = formatCurrency(totalCost);
    document.getElementById('summary-cost-material').textContent = formatCurrency(state.activeProjectSummary.production_cost_material);
    document.getElementById('summary-cost-labour').textContent = formatCurrency(state.activeProjectSummary.production_cost_labour);

    document.getElementById('summary-total-quote').textContent = formatCurrency(totalQuote);
    document.getElementById('summary-quote-material').textContent = formatCurrency(state.activeProjectSummary.price_material);
    document.getElementById('summary-quote-labour').textContent = formatCurrency(state.activeProjectSummary.price_labour);

    const profitEl = document.getElementById('summary-total-profit');
    const marginEl = document.getElementById('summary-profit-margin');
    const profitCard = document.getElementById('stat-profit-card');
    const labelEl = document.getElementById('profit-card-label');

    profitEl.textContent = formatCurrency(totalProfit);
    marginEl.textContent = `${margin.toFixed(2)}%`;

    if (totalProfit >= 0) {
        profitCard.className = 'stat-card profit profit-state';
        labelEl.textContent = state.currentLanguage === 'en' ? 'Project Profit (Profit)' : 'กำไรโครงการ (Profit)';
    } else {
        profitCard.className = 'stat-card profit loss-state';
        labelEl.textContent = state.currentLanguage === 'en' ? 'Project Loss (Loss)' : 'ขาดทุนโครงการ (Loss)';
    }

    // Toggle visibility of Cost and Profit cards in Estimate mode
    const costCard = document.querySelector('.stat-card.cost');
    const summaryGrid = document.querySelector('.summary-cards-grid');
    if (costCard) {
        costCard.style.display = state.workspaceMode === 'estimate' ? 'none' : 'flex';
    }
    if (profitCard) {
        profitCard.style.display = state.workspaceMode === 'estimate' ? 'none' : 'flex';
    }
    if (summaryGrid) {
        if (state.workspaceMode === 'estimate') {
            summaryGrid.classList.add('estimate-mode');
        } else {
            summaryGrid.classList.remove('estimate-mode');
        }
    }
    // Sync tab button active classes
    document.querySelectorAll('.workspace-mode-tabs .btn-mode-tab').forEach(btn => {
        if (btn.id === `btn-mode-${state.workspaceMode}`) {
            btn.className = 'btn btn-sm btn-primary btn-mode-tab active';
        } else {
            btn.className = 'btn btn-sm btn-outline btn-mode-tab';
        }
    });

    const sectionList = document.getElementById('sections-list-container');
    const sectionsHeader = document.querySelector('.sections-container-header');
    const compareContainer = document.getElementById('compare-mode-container');
    const supplierCompareContainer = document.getElementById('supplier-compare-mode-container');

    if (state.workspaceMode === 'compare') {
        if (sectionList) sectionList.style.display = 'none';
        if (sectionsHeader) sectionsHeader.style.display = 'none';
        if (supplierCompareContainer) supplierCompareContainer.style.display = 'none';
        if (compareContainer) {
            compareContainer.style.display = 'block';
            renderComparisonMode();
        }
    } else if (state.workspaceMode === 'supplier-compare') {
        if (sectionList) sectionList.style.display = 'none';
        if (sectionsHeader) sectionsHeader.style.display = 'none';
        if (compareContainer) compareContainer.style.display = 'none';
        if (supplierCompareContainer) {
            supplierCompareContainer.style.display = 'block';
            renderSupplierComparisonMode();
        }
    } else {
        if (compareContainer) compareContainer.style.display = 'none';
        if (supplierCompareContainer) supplierCompareContainer.style.display = 'none';
        if (sectionList) sectionList.style.display = 'block';
        if (sectionsHeader) sectionsHeader.style.display = 'flex';
        renderSections();
    }

    applyRoleBasedUI();
}

function openProjectModal(project = null) {
    const modal = document.getElementById('modal-project');
    const title = document.getElementById('project-modal-title');
    const form = document.getElementById('form-project');
    const typeSelect = document.getElementById('project-type');

    form.reset();

    if (project) {
        title.textContent = t('modal_project_edit_title');
        document.getElementById('project-modal-id').value = project.id;
        document.getElementById('project-name').value = project.name;
        document.getElementById('project-client').value = project.client_name || '';
        document.getElementById('project-external-name').value = project.external_name || '';
        document.getElementById('project-description').value = project.description || '';
        if (typeSelect) {
            typeSelect.value = project.project_type || '';
            typeSelect.disabled = true;
        }
    } else {
        title.textContent = t('modal_project_create_title');
        document.getElementById('project-modal-id').value = '';
        document.getElementById('project-external-name').value = '';
        if (typeSelect) {
            typeSelect.value = '';
            typeSelect.disabled = false;
        }
    }

    modal.classList.add('active');
}

function closeProjectModal() {
    document.getElementById('modal-project').classList.remove('active');
}

async function handleProjectSubmit(e) {
    e.preventDefault();
    const id = document.getElementById('project-modal-id').value;

    const formData = new FormData();
    formData.append('name', document.getElementById('project-name').value);
    formData.append('client_name', document.getElementById('project-client').value);
    formData.append('external_name', document.getElementById('project-external-name').value);
    formData.append('description', document.getElementById('project-description').value);
    const typeSelect = document.getElementById('project-type');
    if (typeSelect) {
        formData.append('project_type', typeSelect.value);
    }

    try {
        let res;
        if (id) {
            res = await authFetch(`${API_BASE}/projects/${id}`, {
                method: 'PUT',
                body: formData
            });
            showToast(t('toast_project_updated'));
        } else {
            res = await authFetch(`${API_BASE}/projects`, {
                method: 'POST',
                body: formData
            });
            showToast(t('toast_project_created'));
        }

        const project = await res.json();
        closeProjectModal();
        await fetchProjects();
        selectProject(project.id);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to save project' : 'ไม่สามารถบันทึกข้อมูลโครงการได้', 'error');
    }
}

async function handleDeleteProject() {
    if (!state.activeProjectId) return;

    // First ask for password confirmation
    const password = prompt(t('enter_password_delete'));
    if (password === null) return; // User cancelled
    if (password.trim() === '') {
        showToast(t('toast_error_required'), 'error');
        return;
    }

    if (!confirm(t('confirm_delete_project'))) return;

    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}`, {
            method: 'DELETE',
            headers: {
                'x-confirm-password': password
            }
        });

        if (!res.ok) {
            const err = await res.json();
            throw new Error(err.error || t('toast_error_permission'));
        }

        showToast(t('toast_project_deleted'));
        state.activeProjectId = null;
        state.activeProject = null;
        state.activeProjectSummary = null;
        await fetchProjects();
        if (state.projects.length > 0) {
            selectProject(state.projects[0].id);
        } else {
            renderWorkspace();
        }
    } catch (err) {
        showToast(err.message === 'Incorrect password' ? t('alert_wrong_password') : err.message, 'error');
    }
}

async function handleRestoreProject() {
    if (!state.activeProjectId) return;
    if (!confirm(t('confirm_restore_project'))) return;

    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/restore`, {
            method: 'POST'
        });

        if (!res.ok) {
            const err = await res.json();
            throw new Error(err.error || t('toast_error_permission'));
        }

        showToast(t('toast_project_restored'));
        // Refresh project list and active details
        await fetchProjects();
        await fetchActiveProjectDetails();
        renderWorkspace();
    } catch (err) {
        showToast(err.message, 'error');
    }
}

async function handleCloneProject() {
    if (!state.activeProjectId) return;
    if (!confirm(t('confirm_clone_project'))) return;

    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/clone`, {
            method: 'POST'
        });

        if (!res.ok) {
            throw new Error('Failed to clone project');
        }

        const clonedProject = await res.json();
        showToast(state.currentLanguage === 'en' ? 'Project cloned successfully' : 'โคลนโครงการสำเร็จแล้ว');

        await fetchProjects();
        selectProject(clonedProject.id);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to clone project' : 'ไม่สามารถโคลนโครงการได้', 'error');
    }
}

// ==========================================
// Subsection & Takeoff Operations
// ==========================================

function renderSections() {
    const container = document.getElementById('sections-list-container');
    container.innerHTML = '';

    const sections = state.activeProjectSummary.sections || [];

    if (sections.length === 0) {
        container.innerHTML = `
            <div class="empty-section-state" style="border: 1px dashed var(--border-color); border-radius: var(--radius-md); padding: 40px;">
                <i class="fa-solid fa-sitemap"></i>
                <p>${state.currentLanguage === 'en' ? 'No systems in this project' : 'ยังไม่มีระบบงานในโครงการนี้'}</p>
                <button class="btn btn-outline btn-sm" id="btn-add-section-empty" style="margin-top: 10px;">
                    <i class="fa-solid fa-plus"></i> ${state.currentLanguage === 'en' ? 'Add First System' : 'เพิ่มระบบงานแรก'}
                </button>
            </div>
        `;

        if (state.currentUser && isReadOnlyRole(state.currentUser.role)) {
            document.getElementById('btn-add-section-empty').style.display = 'none';
        } else {
            document.getElementById('btn-add-section-empty').addEventListener('click', openSubsectionModal);
        }
        return;
    }

    const role = state.currentUser ? state.currentUser.role : 'user';

    sections.forEach(sec => {
        const panel = document.createElement('div');
        panel.className = 'subsection-panel';
        panel.dataset.sectionId = sec.id;

        const isProdMode = state.workspaceMode === 'production' || state.workspaceMode === 'product-supply';
        const costTotal = sec.production_cost_total;
        const priceTotal = sec.price_total;
        const profitTotal = priceTotal - costTotal;
        const marginPercent = priceTotal > 0 ? (profitTotal / priceTotal) * 100 : 0;
        const isProfit = profitTotal >= 0;

        const costMat = sec.production_cost_material || 0;
        const costLab = sec.production_cost_labour || 0;
        const priceMat = sec.price_material || 0;
        const priceLab = sec.price_labour || 0;

        const isCollapsed = state.collapsedSections.has(Number(sec.id));
        const iconMarkup = isCollapsed ? '<i class="fa-solid fa-chevron-right"></i>' : '<i class="fa-solid fa-chevron-down"></i>';
        const displayStyle = isCollapsed ? 'none' : 'block';

        const hasSpec = sec.has_spec === 1 || !!sec.spec_name;
        let specMarkup = '';
        if (hasSpec) {
            specMarkup = `
                <button class="btn btn-outline btn-sm btn-view-sec-spec" style="display:inline-flex; align-items:center; gap:6px;" onclick="openSectionPdfViewer(${sec.id}, '${escapeJsString(sec.name)}')">
                    <i class="fa-solid fa-file-pdf text-danger"></i> <span style="max-width: 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;">${escapeHtml(sec.spec_name)}</span>
                </button>
            `;
        } else {
            if (role === 'admin' || role === 'superadmin' || role === 'supervisor' || role === 'estimate') {
                specMarkup = `
                    <button class="btn btn-outline btn-sm btn-upload-sec-spec" onclick="document.getElementById('input-sec-spec-${sec.id}').click()">
                        <i class="fa-solid fa-file-upload"></i> ${state.currentLanguage === 'en' ? 'Upload Spec' : 'อัปโหลดสเปก PDF'}
                    </button>
                    <input type="file" id="input-sec-spec-${sec.id}" style="display:none;" accept=".pdf" onchange="handleSectionSpecUpload(event, ${sec.id})">
                `;
            }
        }

        const disabledAttr = (isReadOnlyRole(role) || (state.activeProjectSummary && state.activeProjectSummary.is_deleted === 1)) ? 'disabled' : '';

        panel.innerHTML = `
            <div class="subsection-header">
                <div class="subsection-title-area" style="cursor: pointer; display: flex; align-items: center; gap: 8px;">
                    <span class="collapse-icon" id="collapse-icon-${sec.id}" style="color: var(--text-muted); font-size: 0.9rem; width: 16px; display: inline-block; text-align: center;">
                        ${iconMarkup}
                    </span>
                    <h3 style="margin: 0; display: flex; align-items: center; gap: 6px;">
                        <span>${escapeHtml(sec.name)}</span>
                        ${isReadOnlyRole(role) ? '' : `
                        <span class="edit-sec-name-btn" title="${state.currentLanguage === 'en' ? 'Rename' : 'แก้ไขชื่อ'}" data-section-id="${sec.id}" data-section-name="${escapeHtml(sec.name)}" onmouseover="this.style.color='var(--primary-color)'" onmouseout="this.style.color='var(--text-muted)'" style="color: var(--text-muted); cursor: pointer; padding: 2px 6px; font-size: 0.85rem; display: inline-flex; align-items: center; justify-content: center; transition: color 0.2s;">
                             <i class="fa-solid fa-pen-to-square"></i>
                        </span>
                        `}
                    </h3>
                    <span class="subsection-badge-count" id="badge-count-${sec.id}">${sec.items_count} ${t('badge_items_count')}</span>
                </div>
                <div class="subsection-summary-info">
                    <span class="sub-sum-cost">
                        ${state.currentLanguage === 'en' ? 'Cost' : 'ทุน'}: <b>${formatCurrency(costTotal)}</b>
                        ${(role === 'admin' || role === 'superadmin' || role === 'supervisor') ? `
                        <span style="font-size:0.725rem; font-weight:normal; color:var(--text-muted); margin-left:4px;">
                            (Mat: ${formatCurrency(costMat)} / Lab: ${formatCurrency(costLab)})
                        </span>` : ''}
                    </span>
                    <span class="sub-sum-quote">
                        ${state.currentLanguage === 'en' ? 'Quote' : 'เสนอราคา'}: <b>${formatCurrency(priceTotal)}</b>
                        <span style="font-size:0.725rem; font-weight:normal; color:var(--text-muted); margin-left:4px;">
                            (Mat: ${formatCurrency(priceMat)} / Lab: ${formatCurrency(priceLab)})
                        </span>
                    </span>
                    <span class="sub-sum-profit ${isProfit ? 'profit' : 'loss'}">
                        ${isProfit ? (state.currentLanguage === 'en' ? 'Profit' : 'กำไร') : (state.currentLanguage === 'en' ? 'Loss' : 'ขาดทุน')}: <b>${formatCurrency(profitTotal)} (${marginPercent.toFixed(1)}%)</b>
                    </span>
                    
                    <div class="profit-adjuster-wrapper" style="display: ${isProdMode ? 'none' : 'inline-flex'}; align-items: center; gap: 4px; background: var(--bg-panel); padding: 2px 6px; border-radius: var(--radius-sm); border: 1px solid var(--border-color); margin-left: 8px;">
                        <span style="font-size: 0.8rem; font-weight: 600; color: var(--text-muted);">${state.currentLanguage === 'en' ? 'Adjust Profit' : 'ปรับกำไร'}:</span>
                        <input type="number" step="0.5" class="profit-adjust-input" data-section-id="${sec.id}" value="${(typeof marginPercent === 'number' && !isNaN(marginPercent)) ? marginPercent.toFixed(1) : (sec.profit_percent || 0)}" ${disabledAttr} style="width: 50px; border: none; background: transparent; text-align: center; font-weight: 700; color: var(--text-main); font-size: 0.85rem; padding: 0;" />
                        <span style="font-size: 0.8rem; font-weight: 700; color: var(--text-muted);">%</span>
                    </div>
                    <div class="subsection-actions" style="display:flex; gap:8px; align-items:center;">
                        ${specMarkup}
                        ${isReadOnlyRole(role) ? '' : `
                        <button class="btn btn-outline btn-sm btn-move-section-up" data-section-id="${sec.id}" style="color: var(--text-muted); padding: 6px 10px;" title="${state.currentLanguage === 'en' ? 'Move Up' : 'เลื่อนขึ้น'}">
                            <i class="fa-solid fa-arrow-up"></i>
                        </button>
                        <button class="btn btn-outline btn-sm btn-move-section-down" data-section-id="${sec.id}" style="color: var(--text-muted); padding: 6px 10px;" title="${state.currentLanguage === 'en' ? 'Move Down' : 'เลื่อนลง'}">
                            <i class="fa-solid fa-arrow-down"></i>
                        </button>
                        ${(role === 'admin' || role === 'superadmin' || role === 'estimate') ? `
                        <button class="btn btn-outline btn-sm btn-revert-section-prices" data-section-id="${sec.id}" style="color: #6366f1; border-color: #c7d2fe; padding: 6px 10px;" title="${state.currentLanguage === 'en' ? 'Reset all items in this system to catalog prices' : 'คืนค่าราคาทุกสินค้าในระบบงานนี้จากแคตตาล็อก'}">
                            <i class="fa-solid fa-rotate-left"></i> ${state.currentLanguage === 'en' ? 'Undo Price' : 'คืนค่าราคา'}
                        </button>
                        ` : ''}
                        <button class="btn btn-primary btn-sm btn-add-item-to-sec" data-section-id="${sec.id}" data-section-name="${escapeHtml(sec.name)}">
                            <i class="fa-solid fa-cart-plus"></i> ${state.currentLanguage === 'en' ? 'Select Product' : 'เลือกสินค้า'}
                        </button>
                        <button class="btn btn-danger-outline btn-sm btn-delete-section" data-section-id="${sec.id}">
                            <i class="fa-solid fa-trash-can"></i> ${state.currentLanguage === 'en' ? 'Delete System' : 'ลบระบบงาน'}
                        </button>
                        `}
                    </div>
                </div>
            </div>
            
            <div class="takeoff-table-wrapper" style="display: ${displayStyle};">
                <table class="takeoff-table mode-${state.workspaceMode}">
                    <thead>
                        <tr>
                            <th width="60">${t('th_image')}</th>
                            <th>${state.currentLanguage === 'en' ? 'Brand / Product Description / Model / Spec' : 'แบรนด์ / รายละเอียดสินค้า / รุ่น / เอกสาร'}</th>
                            <th width="75" class="text-center">${t('label_qty')}</th>
                            <th width="50" class="text-center">${t('th_unit')}</th>
                            <th width="70" class="text-center">${t('label_free_issue')}</th>
                            <th width="95" class="text-right">${t('th_cost_mt')}</th>
                            <th width="95" class="text-right">${t('th_cost_lb')}</th>
                            <th width="95" class="text-right">
                                ${(state.workspaceMode === 'production' || state.workspaceMode === 'product-supply') 
                                    ? (state.currentLanguage === 'en' ? 'Material Sale Price (฿)' : 'ราคาขายวัสดุ (฿)') 
                                    : (t('letter_table_mt') + ' (฿)')}
                            </th>
                            <th width="95" class="text-right">
                                ${(state.workspaceMode === 'production' || state.workspaceMode === 'product-supply') 
                                    ? (state.currentLanguage === 'en' ? 'Labour Sale Price (฿)' : 'ราคาขายค่าแรง (฿)') 
                                    : (t('letter_table_lb') + ' (฿)')}
                            </th>
                            <th width="70" class="text-center">${t('label_prod_discount')}</th>
                            <th width="105" class="text-right">${state.currentLanguage === 'en' ? 'Total Cost (฿)' : 'ทุนรวม (฿)'}</th>
                            <th width="105" class="text-right">${state.currentLanguage === 'en' ? 'Total Sale (฿)' : 'ขายรวม (฿)'}</th>
                            <th width="105" class="text-right">${state.currentLanguage === 'en' ? 'Profit (฿)' : 'กำไร (฿)'}</th>
                            <th width="45" class="text-center">${t('table_action_delete')}</th>
                        </tr>
                    </thead>
                    <tbody id="tbody-section-items-${sec.id}">
                        <!-- Takeoff items populated dynamically -->
                    </tbody>
                </table>
            </div>
        `;

        container.appendChild(panel);

        // Hide panel buttons for read-only user role or deleted project
        if (isReadOnlyRole(role) || (state.activeProjectSummary && state.activeProjectSummary.is_deleted === 1)) {
            panel.querySelector('.subsection-actions').style.display = 'none';
        }

        loadSectionItems(sec.id);
    });

    // Bind click events to section title areas for collapse/expand
    container.querySelectorAll('.subsection-title-area').forEach(titleArea => {
        titleArea.addEventListener('click', (e) => {
            if (e.target.closest('.edit-sec-name-btn')) {
                return;
            }
            const panel = titleArea.closest('.subsection-panel');
            const sectionId = panel.dataset.sectionId;
            toggleSectionCollapse(titleArea, sectionId);
        });
    });

    // Bind click events to edit section name buttons
    container.querySelectorAll('.edit-sec-name-btn').forEach(btn => {
        btn.addEventListener('click', (e) => {
            e.stopPropagation();
            const sectionId = Number(btn.dataset.sectionId);
            const sectionName = btn.dataset.sectionName;
            openSubsectionModalForEdit(e, sectionId, sectionName);
        });
    });

    // Add event listeners for section level buttons
    document.querySelectorAll('.btn-add-item-to-sec').forEach(btn => {
        btn.addEventListener('click', (e) => {
            const sectionId = e.currentTarget.dataset.sectionId;
            const sectionName = e.currentTarget.dataset.sectionName;
            openExplorerModal(sectionId, sectionName);
        });
    });

    document.querySelectorAll('.btn-delete-section').forEach(btn => {
        btn.addEventListener('click', handleDeleteSection);
    });

    document.querySelectorAll('.btn-move-section-up').forEach(btn => {
        btn.addEventListener('click', async (e) => {
            e.stopPropagation();
            const panel = e.currentTarget.closest('.subsection-panel');
            const parent = panel.parentNode;
            const prev = panel.previousElementSibling;
            if (prev && prev.classList.contains('subsection-panel')) {
                parent.insertBefore(panel, prev);
                await saveNewSectionsOrder(parent);
            }
        });
    });

    document.querySelectorAll('.btn-move-section-down').forEach(btn => {
        btn.addEventListener('click', async (e) => {
            e.stopPropagation();
            const panel = e.currentTarget.closest('.subsection-panel');
            const parent = panel.parentNode;
            const next = panel.nextElementSibling;
            if (next && next.classList.contains('subsection-panel')) {
                parent.insertBefore(next, panel);
                await saveNewSectionsOrder(parent);
            }
        });
    });
    document.querySelectorAll('.btn-revert-section-prices').forEach(btn => {
        btn.addEventListener('click', async (e) => {
            e.stopPropagation();
            const sectionId = e.currentTarget.dataset.sectionId;
            
            if (!confirm(state.currentLanguage === 'en' 
                ? 'Are you sure you want to reset all items in this system back to their catalog price defaults?' 
                : 'คุณแน่ใจหรือไม่ว่าต้องการคืนค่าราคาและต้นทุนของทุกสินค้าในระบบงานนี้กลับไปเป็นค่าเริ่มต้นจากแคตตาล็อก?')) {
                return;
            }
            
            showToast(state.currentLanguage === 'en' ? 'Resetting system pricing...' : 'กำลังคืนค่าราคาของระบบงาน...');
            
            try {
                const res = await authFetch(`${API_BASE}/sections/${sectionId}/reset-prices`, {
                    method: 'PUT'
                });
                
                if (!res.ok) {
                    throw new Error('Reset failed');
                }
                
                showToast(state.currentLanguage === 'en' ? 'System pricing reset from catalog!' : 'คืนค่าราคาของระบบงานสำเร็จ!');
                
                if (state.activeProjectId) {
                    await fetchActiveProjectDetails();
                    renderWorkspace();
                }
            } catch (err) {
                console.error(err);
                showToast(state.currentLanguage === 'en' ? 'Failed to reset system pricing' : 'ไม่สามารถคืนค่าราคาของระบบงานได้', 'error');
            }
        });
    });

    document.querySelectorAll('.profit-adjust-input').forEach(input => {
        input.addEventListener('change', async (e) => {
            const sectionId = e.target.dataset.sectionId;
            const profitVal = parseFloat(e.target.value) || 0;
            
            showToast(state.currentLanguage === 'en' ? 'Updating profit margin...' : 'กำลังปรับสัดส่วนกำไร...');
            
            try {
                const res = await authFetch(`${API_BASE}/sections/${sectionId}/profit`, {
                    method: 'PUT',
                    body: JSON.stringify({ profit_percent: profitVal })
                });
                
                if (!res.ok) {
                    throw new Error('Update failed');
                }
                
                showToast(state.currentLanguage === 'en' ? 'Profit margin updated!' : 'ปรับสัดส่วนกำไรสำเร็จ!');
                
                if (state.activeProjectId) {
                    await fetchActiveProjectDetails();
                    renderWorkspace();
                }
            } catch (err) {
                console.error(err);
                showToast(state.currentLanguage === 'en' ? 'Failed to update profit margin' : 'ไม่สามารถปรับสัดส่วนกำไรได้', 'error');
            }
        });
        
        input.addEventListener('click', (e) => {
            e.stopPropagation();
        });
    });
}

async function saveNewSectionsOrder(container) {
    const panels = Array.from(container.querySelectorAll('.subsection-panel'));
    const sectionIds = panels.map(p => p.dataset.sectionId).filter(id => id);

    try {
        await authFetch(`${API_BASE}/projects/${state.activeProjectId}/reorder-sections`, {
            method: 'PUT',
            body: JSON.stringify({ sectionIds })
        });
    } catch (err) {
        console.error('Failed to save new sections order:', err);
        showToast(state.currentLanguage === 'en' ? 'Failed to save systems order' : 'ไม่สามารถจัดเก็บตำแหน่งของระบบงานได้', 'error');
    }
}

async function saveNewItemsOrder(sectionId, tbodyEl) {
    const rows = Array.from(tbodyEl.querySelectorAll('tr'));
    const itemIds = rows.map(r => r.dataset.itemId).filter(id => id);

    try {
        await authFetch(`${API_BASE}/sections/${sectionId}/reorder-items`, {
            method: 'PUT',
            body: JSON.stringify({ itemIds })
        });
    } catch (err) {
        console.error('Failed to save new items order:', err);
        showToast(state.currentLanguage === 'en' ? 'Failed to save items order' : 'ไม่สามารถจัดเก็บตำแหน่งของรายการสินค้าได้', 'error');
    }
}

function toggleSectionCollapse(elementOrId, sectionId) {
    let id;
    let panel;
    
    if (elementOrId && (elementOrId instanceof HTMLElement || elementOrId.tagName)) {
        panel = elementOrId.closest('.subsection-panel');
        id = Number(sectionId || (panel ? panel.dataset.sectionId : 0));
    } else if (elementOrId && elementOrId.target) {
        panel = elementOrId.currentTarget.closest('.subsection-panel');
        id = Number(sectionId || (panel ? panel.dataset.sectionId : 0));
    } else {
        id = Number(elementOrId);
        panel = document.querySelector(`.subsection-panel[data-section-id="${id}"]`);
    }

    if (!panel && id) {
        panel = document.querySelector(`.subsection-panel[data-section-id="${id}"]`);
    }
    
    if (!panel) {
        console.error('toggleSectionCollapse: subsection-panel not found for', elementOrId, sectionId);
        return;
    }

    if (!id && panel) {
        id = Number(panel.dataset.sectionId);
    }
    
    const tableWrapper = panel.querySelector('.takeoff-table-wrapper');
    const icon = panel.querySelector('.collapse-icon');

    console.log('toggleSectionCollapse - id:', id, 'panel:', panel, 'tableWrapper:', tableWrapper, 'icon:', icon);

    if (state.collapsedSections.has(id)) {
        state.collapsedSections.delete(id);
        if (tableWrapper) tableWrapper.style.display = 'block';
        if (icon) icon.innerHTML = '<i class="fa-solid fa-chevron-down"></i>';
    } else {
        state.collapsedSections.add(id);
        if (tableWrapper) tableWrapper.style.display = 'none';
        if (icon) icon.innerHTML = '<i class="fa-solid fa-chevron-right"></i>';
    }
}
window.toggleSectionCollapse = toggleSectionCollapse;
window.openSubsectionModalForEdit = openSubsectionModalForEdit;
window.openSectionPdfViewer = openSectionPdfViewer;
window.handleSectionSpecUpload = handleSectionSpecUpload;
window.handleDeletePdfDirect = handleDeletePdfDirect;
window.openPdfViewer = openPdfViewer;
window.handleFatCheckboxChange = handleFatCheckboxChange;
window.openLightbox = openLightbox;
window.openSupplierQuoteViewer = openSupplierQuoteViewer;
window.handleDeleteSupplierQuoteDirect = handleDeleteSupplierQuoteDirect;

async function loadSectionItems(sectionId) {
    try {
        let url = `${API_BASE}/sections/${sectionId}/items`;
        if (state.selectedRfqId) {
            url += `?rfq_id=${state.selectedRfqId}`;
        }
        const res = await authFetch(url);
        const items = await res.json();

        const tbody = document.getElementById(`tbody-section-items-${sectionId}`);
        tbody.innerHTML = '';

        if (items.length === 0) {
            tbody.innerHTML = `
                <tr>
                    <td colspan="14" class="empty-section-state">
                        <i class="fa-solid fa-list-check"></i>
                        <p>${state.currentLanguage === 'en' ? 'No items takeoff in this system. Click "Select Product" above to add items.' : 'ไม่มีสินค้าที่ถูกถอดจำนวนในระบบงานนี้ คลิกที่ปุ่ม "เลือกสินค้า" ด้านบนเพื่อเพิ่มรายการ'}</p>
                    </td>
                </tr>
            `;
            return;
        }

        const role = state.currentUser ? state.currentUser.role : 'user';

        items.forEach(item => {
            const tr = document.createElement('tr');
            tr.dataset.itemId = item.id;
            tr.dataset.brand = item.brand || '';
            tr.dataset.description = item.description || '';
            tr.dataset.type = item.type || '';
            tr.dataset.unit = item.unit || '';
            tr.dataset.prodGroup = item.prod_group || '';
            tr.dataset.smNo = item.sm_no || '';
            if (item.is_free_issue) {
                tr.classList.add('free-issue-row');
            }

            let qty = parseFloat(item.qty) || 0;
            let costMat = item.is_free_issue ? 0 : (parseFloat(item.cost_material) || 0);
            let costLab = parseFloat(item.cost_labour) || 0;
            let priceMat = item.is_free_issue ? 0 : (parseFloat(item.price_material) || 0);
            let priceLab = parseFloat(item.price_labour) || 0;
            const discount = parseFloat(item.discount) || 0;

            if (state.workspaceMode === 'production' || state.workspaceMode === 'product-supply') {
                qty = item.production_qty !== null ? (parseFloat(item.production_qty) || 0) : qty;
                if (state.workspaceMode === 'product-supply') {
                    costMat = item.is_free_issue ? 0 : (item.production_cost_material !== null ? (parseFloat(item.production_cost_material) || 0) : (parseFloat(item.supplier_price) || 0));
                } else {
                    costMat = item.is_free_issue ? 0 : (item.production_cost_material !== null ? (parseFloat(item.production_cost_material) || 0) : costMat);
                }
                costLab = item.production_cost_labour !== null ? (parseFloat(item.production_cost_labour) || 0) : costLab;
                priceMat = item.is_free_issue ? 0 : (parseFloat(item.price_material) || 0);
                priceLab = parseFloat(item.price_labour) || 0;
            }

            const totalCost = (costMat + costLab) * qty;
            const totalQuote = (priceMat + priceLab) * qty * (1 - discount / 100);
            const profit = totalQuote - totalCost;
            const isProfit = profit >= 0;

            // Render Product image from LONGBLOB router
            let imgHtml = `<div class="thumbnail-placeholder"><i class="fa-regular fa-image"></i></div>`;
            if (item.has_image && item.product_id) {
                const imgUrl = withAuthToken(`${API_BASE}/products/${item.product_id}/image?t=${Date.now()}`);
                imgHtml = `<img src="${imgUrl}" class="product-thumbnail" alt="Product" onclick="openLightbox('${imgUrl}')">`;
            }

            // PDF spec sheet icon trigger
            let pdfLinkHtml = '';
            if (item.has_pdf && item.product_id) {
                pdfLinkHtml = `
                    <div class="pdf-spec-link" title="${state.currentLanguage === 'en' ? 'Open Product Datasheet (PDF)' : 'เปิดดูคู่มือเทคนิคสินค้า (PDF Datasheet)'}" 
                         data-product-id="${item.product_id}" data-description="${escapeHtml(item.description)}">
                        <i class="fa-solid fa-file-pdf text-danger" style="pointer-events: none;"></i>
                    </div>
                `;
            }

            const freeIssueBadge = item.is_free_issue ? `
                <span class="badge" style="font-size:0.65rem; padding: 2px 6px; border-radius: 4px; background-color:#fee2e2; color:#ef4444; border: 1px solid #fca5a5; font-weight:600; margin-left: 6px;">Free Issue</span>
            ` : '';

            const isProdMode = state.workspaceMode === 'production' || state.workspaceMode === 'product-supply';
            const inputStyle = isProdMode ? 'background-color: #eff6ff; border-color: #3b82f6; color: #1e3a8a;' : '';

            tr.innerHTML = `
                <td>
                    <div class="product-thumb-cell">
                        ${imgHtml}
                    </div>
                </td>
                <td>
                    <div class="product-details-cell">
                        <div class="prod-title" style="display:flex; align-items:center; gap:8px; flex-wrap: wrap;">
                            ${escapeHtml(item.description)}
                            ${pdfLinkHtml}
                            ${freeIssueBadge}
                        </div>
                        <div class="prod-meta">
                            <span><b>SM No.:</b> ${escapeHtml(item.sm_no || '-')}</span> | 
                            <span><b>${t('th_brand')}:</b> ${escapeHtml(item.brand || '-')}</span> | 
                            <span><b>${state.currentLanguage === 'en' ? 'Model' : 'รุ่น'}:</b> ${escapeHtml(item.model || '-')}</span> | 
                            <span><b>${state.currentLanguage === 'en' ? 'Type' : 'ประเภท'}:</b> ${escapeHtml(item.type || '-')}</span> |
                            <span><b>${state.currentLanguage === 'en' ? 'Group' : 'กลุ่ม'}:</b> ${escapeHtml(item.prod_group || '-')}</span>
                            ${['superadmin', 'excusive', 'admin', 'estimate', 'procurment', 'procurement_manager'].includes(role) ? ` | <span style="color: #4f46e5; font-weight: 600;"><b>Supplier Price:</b> ${formatCurrency(item.supplier_price || 0)}</span>` : ''}
                        </div>
                    </div>
                </td>
                <td class="text-center">
                    <input type="number" step="any" class="qty-input table-number-input" data-field="qty" value="${qty}" style="${inputStyle}">
                </td>
                <td class="text-center">${escapeHtml(item.unit || '-')}</td>
                <td class="text-center">
                    <input type="checkbox" class="free-issue-checkbox" data-field="is_free_issue" ${item.is_free_issue ? 'checked' : ''} ${isProdMode ? 'disabled' : ''}>
                </td>
                <td class="text-right">
                    <input type="number" step="0.01" class="table-number-input" data-field="cost_material" value="${costMat}" data-org-value="${item.cost_material || 0}" ${item.is_free_issue ? 'disabled' : ''} style="${inputStyle}">
                </td>
                <td class="text-right">
                    <input type="number" step="0.01" class="table-number-input" data-field="cost_labour" value="${costLab}" style="${inputStyle}">
                </td>
                <td class="text-right">
                    <input type="number" step="0.01" class="table-number-input" data-field="price_material" value="${priceMat}" data-org-value="${item.price_material || 0}" ${item.is_free_issue || isProdMode ? 'disabled' : ''}>
                </td>
                <td class="text-right">
                    <input type="number" step="0.01" class="table-number-input" data-field="price_labour" value="${priceLab}" ${isProdMode ? 'disabled' : ''}>
                </td>
                <td class="text-center">
                    <input type="number" step="0.01" class="discount-input table-number-input" data-field="discount" value="${discount}" ${isProdMode ? 'disabled' : ''}>
                </td>
                <td class="text-right font-bold">${formatNumber(totalCost)}</td>
                <td class="text-right font-bold text-primary-color">${formatNumber(totalQuote)}</td>
                <td class="text-right font-bold" style="color: ${isProfit ? 'var(--success)' : 'var(--danger)'}">
                    ${formatNumber(profit)}
                </td>
                <td class="text-center">
                    <div style="display: inline-flex; gap: 6px; align-items: center; justify-content: center;">
                        ${(item.product_id && (role === 'admin' || role === 'superadmin' || role === 'estimate')) ? `
                            <button class="btn-icon btn-sm btn-revert-item-price" data-item-id="${item.id}" style="color: #6366f1; cursor: pointer;" title="${state.currentLanguage === 'en' ? 'Reset to Catalog Price' : 'คืนค่าราคาจากแคตตาล็อก'}">
                                <i class="fa-solid fa-rotate-left"></i>
                            </button>
                        ` : ''}
                        <button class="btn-icon btn-sm btn-sort-item-up" data-item-id="${item.id}" style="color: var(--text-muted); cursor: pointer;" title="${state.currentLanguage === 'en' ? 'Move Up' : 'เลื่อนขึ้น'}">
                            <i class="fa-solid fa-arrow-up"></i>
                        </button>
                        <button class="btn-icon btn-sm btn-sort-item-down" data-item-id="${item.id}" style="color: var(--text-muted); cursor: pointer;" title="${state.currentLanguage === 'en' ? 'Move Down' : 'เลื่อนลง'}">
                            <i class="fa-solid fa-arrow-down"></i>
                        </button>
                        <button class="btn-icon btn-danger-icon btn-sm btn-delete-item" data-item-id="${item.id}">
                            <i class="fa-solid fa-trash"></i>
                        </button>
                    </div>
                </td>
            `;

            // Disable buttons and inputs if viewer user or project is deleted
            if (role === 'contractor' && !(state.activeProjectSummary && state.activeProjectSummary.is_deleted === 1)) {
                tr.querySelectorAll('.table-number-input').forEach(inp => {
                    const field = inp.dataset.field;
                    if (field === 'price_material' || field === 'price_labour') {
                        inp.disabled = false;
                        inp.addEventListener('change', handleInlineItemEdit);
                    } else {
                        inp.disabled = true;
                    }
                });
                tr.querySelector('.free-issue-checkbox').disabled = true;
                tr.querySelector('.btn-delete-item').style.display = 'none';
                const upBtn = tr.querySelector('.btn-sort-item-up');
                const downBtn = tr.querySelector('.btn-sort-item-down');
                if (upBtn) upBtn.style.display = 'none';
                if (downBtn) downBtn.style.display = 'none';
            } else if (isReadOnlyRole(role) || (state.activeProjectSummary && state.activeProjectSummary.is_deleted === 1)) {
                tr.querySelectorAll('.table-number-input').forEach(inp => inp.disabled = true);
                tr.querySelector('.free-issue-checkbox').disabled = true;
                tr.querySelector('.btn-delete-item').style.display = 'none';
                const upBtn = tr.querySelector('.btn-sort-item-up');
                const downBtn = tr.querySelector('.btn-sort-item-down');
                if (upBtn) upBtn.style.display = 'none';
                if (downBtn) downBtn.style.display = 'none';
            } else {
                tr.querySelectorAll('.table-number-input').forEach(input => {
                    input.addEventListener('change', handleInlineItemEdit);
                });
                tr.querySelector('.btn-delete-item').addEventListener('click', handleDeleteItem);
                
                const revertBtn = tr.querySelector('.btn-revert-item-price');
                if (revertBtn) {
                    revertBtn.addEventListener('click', async () => {
                        if (!confirm(state.currentLanguage === 'en' 
                            ? 'Are you sure you want to reset this item\'s pricing back to the catalog defaults?' 
                            : 'คุณแน่ใจหรือไม่ว่าต้องการคืนค่าราคาและต้นทุนของรายการนี้กลับไปเป็นค่าเริ่มต้นจากแคตตาล็อก?')) {
                            return;
                        }
                        
                        try {
                            const res = await authFetch(`${API_BASE}/items/${item.id}/reset-price`, {
                                method: 'PUT'
                            });
                            if (!res.ok) {
                                throw new Error('Reset failed');
                            }
                            
                            showToast(state.currentLanguage === 'en' ? 'Item pricing reset from catalog!' : 'คืนค่าราคาจากแคตตาล็อกสำเร็จ!');
                            await fetchActiveProjectDetails();
                            renderWorkspace();
                        } catch (err) {
                            console.error(err);
                            showToast(state.currentLanguage === 'en' ? 'Failed to reset item pricing' : 'ไม่สามารถคืนค่าราคาจากแคตตาล็อกได้', 'error');
                        }
                    });
                }

                const upBtn = tr.querySelector('.btn-sort-item-up');
                if (upBtn) {
                    upBtn.addEventListener('click', async (e) => {
                        const btn = e.currentTarget;
                        const trRow = btn.closest('tr');
                        const tbodyEl = trRow.parentNode;
                        const prevRow = trRow.previousElementSibling;
                        if (prevRow) {
                            tbodyEl.insertBefore(trRow, prevRow);
                            await saveNewItemsOrder(sectionId, tbodyEl);
                        }
                    });
                }

                const downBtn = tr.querySelector('.btn-sort-item-down');
                if (downBtn) {
                    downBtn.addEventListener('click', async (e) => {
                        const btn = e.currentTarget;
                        const trRow = btn.closest('tr');
                        const tbodyEl = trRow.parentNode;
                        const nextRow = trRow.nextElementSibling;
                        if (nextRow) {
                            tbodyEl.insertBefore(nextRow, trRow);
                            await saveNewItemsOrder(sectionId, tbodyEl);
                        }
                    });
                }

                // Supervisor cannot edit product prices or properties
                if (role === 'supervisor') {
                    tr.querySelector('[data-field="cost_material"]').disabled = true;
                    tr.querySelector('[data-field="cost_labour"]').disabled = true;
                    tr.querySelector('[data-field="price_material"]').disabled = true;
                    tr.querySelector('[data-field="price_labour"]').disabled = true;
                }

                // Bind Free Issue Checkbox Change Listener
                tr.querySelector('.free-issue-checkbox').addEventListener('change', async (e) => {
                    const checkbox = e.target;
                    const tr = checkbox.closest('tr');
                    const costInput = tr.querySelector('[data-field="cost_material"]');
                    const priceInput = tr.querySelector('[data-field="price_material"]');
                    const role = state.currentUser ? state.currentUser.role : 'user';

                    if (checkbox.checked) {
                        tr.classList.add('free-issue-row');
                        costInput.dataset.orgValue = costInput.value;
                        priceInput.dataset.orgValue = priceInput.value;
                        costInput.value = 0;
                        priceInput.value = 0;
                        costInput.disabled = true;
                        priceInput.disabled = true;
                    } else {
                        tr.classList.remove('free-issue-row');
                        costInput.value = costInput.dataset.orgValue || 0;
                        priceInput.value = priceInput.dataset.orgValue || 0;
                        if (role !== 'supervisor' && role !== 'user') {
                            costInput.disabled = false;
                            priceInput.disabled = false;
                        }
                    }
                    await handleInlineItemEdit({ target: checkbox });
                });
            }

            tbody.appendChild(tr);
        });
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load subsection items' : 'ไม่สามารถโหลดรายการสินค้าในส่วนย่อยได้', 'error');
    }
}

function openSubsectionModal() {
    document.getElementById('form-subsection').reset();
    document.getElementById('subsection-modal-id').value = '';

    const select = document.getElementById('subsection-name');
    const existingTemp = select.querySelector('.temp-option');
    if (existingTemp) existingTemp.remove();
    select.value = '';

    document.getElementById('subsection-custom-name-group').style.display = 'none';
    document.getElementById('subsection-custom-name').value = '';
    document.getElementById('subsection-custom-name').required = false;

    document.getElementById('subsection-auto-populate-group').style.display = 'flex';
    document.getElementById('subsection-auto-populate').checked = false;

    const title = document.getElementById('subsection-modal-title');
    const submitBtn = document.getElementById('btn-submit-subsection');

    title.textContent = t('modal_sub_title');
    title.setAttribute('data-i18n', 'modal_sub_title');

    submitBtn.textContent = t('btn_add_sub');
    submitBtn.setAttribute('data-i18n', 'btn_add_sub');

    document.getElementById('modal-subsection').classList.add('active');
}

function openSubsectionModalForEdit(e, sectionId, sectionName) {
    if (e) {
        e.stopPropagation();
    }

    document.getElementById('form-subsection').reset();
    document.getElementById('subsection-modal-id').value = sectionId;

    document.getElementById('subsection-custom-name-group').style.display = 'none';
    document.getElementById('subsection-custom-name').value = '';
    document.getElementById('subsection-custom-name').required = false;

    document.getElementById('subsection-auto-populate-group').style.display = 'none';
    document.getElementById('subsection-auto-populate').checked = false;

    const select = document.getElementById('subsection-name');

    // Check if the sectionName is already in the select options
    let found = false;
    for (let i = 0; i < select.options.length; i++) {
        if (select.options[i].value === sectionName) {
            found = true;
            break;
        }
    }

    // If not found, add a temporary option
    if (!found) {
        const existingTemp = select.querySelector('.temp-option');
        if (existingTemp) existingTemp.remove();

        const tempOpt = document.createElement('option');
        tempOpt.value = sectionName;
        tempOpt.textContent = sectionName;
        tempOpt.className = 'temp-option';
        select.appendChild(tempOpt);
    }

    select.value = sectionName;

    const title = document.getElementById('subsection-modal-title');
    const submitBtn = document.getElementById('btn-submit-subsection');

    title.textContent = t('modal_sub_title_edit');
    title.setAttribute('data-i18n', 'modal_sub_title_edit');

    submitBtn.textContent = t('btn_save_changes');
    submitBtn.setAttribute('data-i18n', 'btn_save_changes');

    document.getElementById('modal-subsection').classList.add('active');
}

function closeSubsectionModal() {
    document.getElementById('modal-subsection').classList.remove('active');
}

async function handleSubsectionSubmit(e) {
    e.preventDefault();
    if (!state.activeProjectId) return;

    const id = document.getElementById('subsection-modal-id').value;
    let name = document.getElementById('subsection-name').value;
    if (name === '__custom__') {
        name = document.getElementById('subsection-custom-name').value.trim();
    }
    try {
        if (id) {
            // Edit mode
            await authFetch(`${API_BASE}/sections/${id}`, {
                method: 'PUT',
                body: JSON.stringify({ name })
            });
            markProjectModified(state.activeProjectId);
            showToast(state.currentLanguage === 'en' ? 'System renamed successfully' : 'แก้ไขชื่อระบบงานสำเร็จแล้ว');
        } else {
            // Create mode
            const auto_populate = document.getElementById('subsection-auto-populate').checked;
            await authFetch(`${API_BASE}/projects/${state.activeProjectId}/sections`, {
                method: 'POST',
                body: JSON.stringify({ name, auto_populate })
            });
            markProjectModified(state.activeProjectId);
            showToast(t('toast_section_created'));
        }
        closeSubsectionModal();
        await fetchActiveProjectDetails();
        renderWorkspace();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Operation failed' : 'ดำเนินการไม่สำเร็จ', 'error');
    }
}

let allSystemTemplates = [];

const DEFAULT_SYSTEM_TEMPLATES = {};

async function populateSystemDropdowns() {
    try {
        const res = await authFetch(`${API_BASE}/system-templates`);
        allSystemTemplates = await res.json();

        const allNames = new Set();
        allSystemTemplates.forEach(t => {
            if (t.system_name) {
                allNames.add(t.system_name);
            }
        });

        const defaultNames = [];
        defaultNames.forEach(name => {
            allNames.add(name);
        });

        // 1. Populate template-select-system
        const templateSelect = document.getElementById('template-select-system');
        if (templateSelect) {
            const currentVal = templateSelect.value;
            templateSelect.innerHTML = '';
            allNames.forEach(name => {
                const opt = document.createElement('option');
                opt.value = name;
                opt.textContent = name;
                templateSelect.appendChild(opt);
            });
            const optCustom = document.createElement('option');
            optCustom.value = '__custom__';
            optCustom.dataset.i18n = 'opt_custom_system';
            optCustom.textContent = state.currentLanguage === 'en' ? '+ Add New System Template...' : '+ เพิ่มระบบงานใหม่...';
            templateSelect.appendChild(optCustom);

            if (currentVal && allNames.has(currentVal)) {
                templateSelect.value = currentVal;
            } else {
                templateSelect.selectedIndex = 0;
            }
        }

        // 2. Populate subsection-name
        const subSelect = document.getElementById('subsection-name');
        if (subSelect) {
            const currentVal = subSelect.value;
            subSelect.innerHTML = '';

            // Add placeholder option
            const optPlaceholder = document.createElement('option');
            optPlaceholder.value = '';
            optPlaceholder.dataset.i18n = 'placeholder_sub_name';
            optPlaceholder.textContent = state.currentLanguage === 'en' ? '-- Select System Name --' : '-- เลือกชื่อระบบงาน --';
            subSelect.appendChild(optPlaceholder);

            allNames.forEach(name => {
                const opt = document.createElement('option');
                opt.value = name;
                opt.textContent = name;
                subSelect.appendChild(opt);
            });

            const optCustom = document.createElement('option');
            optCustom.value = '__custom__';
            optCustom.dataset.i18n = 'option_custom_system';
            optCustom.style.fontWeight = 'bold';
            optCustom.style.color = 'var(--primary-color)';
            optCustom.textContent = state.currentLanguage === 'en' ? '+ Custom Name...' : '+ ระบุเอง (Custom)...';
            subSelect.appendChild(optCustom);

            if (currentVal && allNames.has(currentVal)) {
                subSelect.value = currentVal;
            } else {
                subSelect.selectedIndex = 0;
            }
        }
        applyLanguage();
    } catch (err) {
        console.error('Failed to populate system dropdowns:', err);
    }
}

async function openTemplateManagerModal() {
    const templateSelect = document.getElementById('template-select-system');
    const saveBtn = document.getElementById('btn-save-system-template');
    const catalogBtn = document.getElementById('btn-template-select-catalog');

    const cloneBtn = document.getElementById('btn-template-clone');
    const renameGroup = document.getElementById('template-rename-group');
    if (state.currentUser && isReadOnlyRole(state.currentUser.role)) {
        saveBtn.style.display = 'none';
        if (catalogBtn) catalogBtn.style.display = 'none';
        if (cloneBtn) cloneBtn.style.display = 'none';
        if (renameGroup) renameGroup.style.display = 'none';
    } else {
        saveBtn.style.display = 'inline-block';
        if (catalogBtn) catalogBtn.style.display = 'inline-block';
        if (cloneBtn) cloneBtn.style.display = 'inline-block';
        if (renameGroup) renameGroup.style.display = 'block';
    }

    try {
        await populateSystemDropdowns();

        document.getElementById('template-custom-system-group').style.display = 'none';
        document.getElementById('template-custom-system-name').value = '';

        if (templateSelect.options.length > 0) {
            templateSelect.selectedIndex = 0;
            loadTemplateItemsForSelectedSystem();
        }

        document.getElementById('modal-template-manager').classList.add('active');
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load templates' : 'ไม่สามารถโหลดเทมเพลตระบบงานได้', 'error');
    }
}

function closeTemplateManagerModal() {
    document.getElementById('modal-template-manager').classList.remove('active');
}

function loadTemplateItemsForSelectedSystem() {
    const systemName = document.getElementById('template-select-system').value;
    const container = document.getElementById('template-items-list-container');
    container.innerHTML = '';

    let items = [];
    const templateObj = allSystemTemplates.find(t => t.system_name === systemName);
    if (templateObj) {
        items = templateObj.items;
    } else if (DEFAULT_SYSTEM_TEMPLATES[systemName]) {
        items = DEFAULT_SYSTEM_TEMPLATES[systemName];
    }

    const renameInput = document.getElementById('template-system-name-input');
    const renameGroup = document.getElementById('template-rename-group');
    const customGroup = document.getElementById('template-custom-system-group');
    const customInput = document.getElementById('template-custom-system-name');

    if (systemName === '__custom__') {
        if (renameGroup) renameGroup.style.display = 'none';
        if (renameInput) renameInput.value = '';
        if (customGroup) customGroup.style.display = 'block';
        if (customInput) {
            customInput.required = true;
            setTimeout(() => {
                try { customInput.focus(); } catch (e) {}
            }, 50);
        }
    } else {
        if (renameGroup) renameGroup.style.display = 'block';
        if (renameInput) renameInput.value = systemName;
        if (customGroup) customGroup.style.display = 'none';
        if (customInput) {
            customInput.value = '';
            customInput.required = false;
        }
    }

    items.forEach(item => {
        addTemplateItemRowDOM(item);
    });

    if (items.length === 0) {
        container.innerHTML = `<div class="text-muted text-center" style="padding: 20px;" data-i18n="no_template_items">ไม่มีสินค้าในเทมเพลตนี้</div>`;
        applyLanguage();
    }
}

function addTemplateItemRowDOM(value = '') {
    const container = document.getElementById('template-items-list-container');

    const placeholder = container.querySelector('[data-i18n="no_template_items"]');
    if (placeholder) placeholder.remove();

    let desc = '';
    let brand = '';
    let model = '';
    let type = '';
    let unit = 'Set';
    let prodGroup = '';
    let qty = 1;

    if (typeof value === 'string') {
        desc = value;
    } else if (value && typeof value === 'object') {
        desc = value.description || '';
        brand = value.brand || '';
        model = value.model || '';
        type = value.type || '';
        unit = value.unit || 'Set';
        prodGroup = value.prod_group || '';
        qty = parseFloat(value.qty) || 1;
    }

    const row = document.createElement('div');
    row.style.display = 'flex';
    row.style.alignItems = 'center';
    row.style.justifyContent = 'space-between';
    row.style.gap = '12px';
    row.style.padding = '12px';
    row.style.border = '1px solid var(--border-color)';
    row.style.borderRadius = 'var(--radius-md)';
    row.style.backgroundColor = 'var(--card-bg)';
    row.className = 'template-item-row';

    row.dataset.brand = brand;
    row.dataset.model = model;
    row.dataset.type = type;
    row.dataset.unit = unit;
    row.dataset.prodGroup = prodGroup;

    const infoCol = document.createElement('div');
    infoCol.style.flex = '1';
    infoCol.style.display = 'flex';
    infoCol.style.flexDirection = 'column';
    infoCol.style.gap = '4px';

    const descInput = document.createElement('input');
    descInput.type = 'text';
    descInput.className = 'form-control template-item-input';
    descInput.value = desc;
    descInput.placeholder = state.currentLanguage === 'en' ? 'Item description' : 'ชื่อสินค้า/รายละเอียด';
    descInput.style.fontWeight = '600';
    descInput.style.fontSize = '0.95rem';
    descInput.style.border = 'none';
    descInput.style.borderBottom = '1px dashed var(--border-color)';
    descInput.style.borderRadius = '0';
    descInput.style.padding = '2px 0';
    descInput.style.backgroundColor = 'transparent';
    descInput.style.color = 'var(--text-main)';
    if (state.currentUser && isReadOnlyRole(state.currentUser.role)) {
        descInput.readOnly = true;
    }

    const metaText = document.createElement('div');
    metaText.style.fontSize = '0.75rem';
    metaText.style.color = 'var(--text-muted)';
    const brandLabel = state.currentLanguage === 'en' ? 'Brand' : 'แบรนด์';
    const modelLabel = state.currentLanguage === 'en' ? 'Model' : 'รุ่น';
    const typeLabel = state.currentLanguage === 'en' ? 'Type' : 'ประเภท';
    const groupLabel = state.currentLanguage === 'en' ? 'Group' : 'กลุ่ม';
    metaText.innerHTML = `
        ${brandLabel}: ${escapeHtml(brand || '-')} | 
        ${modelLabel}: ${escapeHtml(model || '-')} | 
        ${typeLabel}: ${escapeHtml(type || '-')} | 
        ${groupLabel}: ${escapeHtml(prodGroup || '-')}
    `;

    infoCol.appendChild(descInput);
    infoCol.appendChild(metaText);

    const actionCol = document.createElement('div');
    actionCol.style.display = 'flex';
    actionCol.style.alignItems = 'center';
    actionCol.style.gap = '10px';

    const qtyInput = document.createElement('input');
    qtyInput.type = 'number';
    qtyInput.className = 'form-control template-item-qty';
    qtyInput.value = qty;
    qtyInput.min = '0.01';
    qtyInput.step = 'any';
    qtyInput.style.width = '65px';
    qtyInput.style.padding = '6px';
    qtyInput.style.textAlign = 'center';
    qtyInput.style.border = '1px solid var(--border-color)';
    qtyInput.style.borderRadius = 'var(--radius-sm)';
    qtyInput.style.backgroundColor = 'var(--bg-main)';
    qtyInput.style.color = 'var(--text-main)';
    if (state.currentUser && isReadOnlyRole(state.currentUser.role)) {
        qtyInput.readOnly = true;
    }

    const unitLabel = document.createElement('span');
    unitLabel.style.fontSize = '0.85rem';
    unitLabel.style.color = 'var(--text-muted)';
    unitLabel.style.minWidth = '30px';
    unitLabel.textContent = unit;

    const deleteBtn = document.createElement('button');
    deleteBtn.type = 'button';
    deleteBtn.className = 'btn btn-danger-outline btn-sm';
    deleteBtn.style.padding = '8px 12px';
    deleteBtn.innerHTML = '<i class="fa-solid fa-trash"></i>';
    deleteBtn.onclick = () => {
        row.remove();
        if (container.querySelectorAll('.template-item-row').length === 0) {
            container.innerHTML = `<div class="text-muted text-center" style="padding: 20px;" data-i18n="no_template_items">ไม่มีสินค้าในเทมเพลตนี้</div>`;
            applyLanguage();
        }
    };

    const upBtn = document.createElement('button');
    upBtn.type = 'button';
    upBtn.className = 'btn btn-outline btn-sm';
    upBtn.style.padding = '8px 12px';
    upBtn.style.borderColor = 'var(--border-color)';
    upBtn.style.color = 'var(--text-muted)';
    upBtn.innerHTML = '<i class="fa-solid fa-arrow-up"></i>';
    upBtn.onclick = () => {
        const prev = row.previousElementSibling;
        if (prev && prev.classList.contains('template-item-row')) {
            container.insertBefore(row, prev);
        }
    };

    const downBtn = document.createElement('button');
    downBtn.type = 'button';
    downBtn.className = 'btn btn-outline btn-sm';
    downBtn.style.padding = '8px 12px';
    downBtn.style.borderColor = 'var(--border-color)';
    downBtn.style.color = 'var(--text-muted)';
    downBtn.innerHTML = '<i class="fa-solid fa-arrow-down"></i>';
    downBtn.onclick = () => {
        const next = row.nextElementSibling;
        if (next && next.classList.contains('template-item-row')) {
            container.insertBefore(next, row);
        }
    };

    if (state.currentUser && isReadOnlyRole(state.currentUser.role)) {
        deleteBtn.style.display = 'none';
        upBtn.style.display = 'none';
        downBtn.style.display = 'none';
    }

    actionCol.appendChild(qtyInput);
    actionCol.appendChild(unitLabel);
    actionCol.appendChild(upBtn);
    actionCol.appendChild(downBtn);
    actionCol.appendChild(deleteBtn);

    row.appendChild(infoCol);
    row.appendChild(actionCol);
    container.appendChild(row);
}

async function saveSystemTemplate() {
    const select = document.getElementById('template-select-system');
    const systemName = select.value;

    let finalSystemName = systemName;
    let isRename = false;
    let templateId = null;

    if (systemName === '__custom__') {
        const customName = document.getElementById('template-custom-system-name').value.trim();
        if (!customName) {
            showToast(state.currentLanguage === 'en' ? 'Please enter a system name' : 'กรุณาระบุชื่อระบบงานใหม่', 'error');
            return;
        }
        finalSystemName = customName;
    } else {
        const renameInput = document.getElementById('template-system-name-input');
        if (renameInput) {
            const newName = renameInput.value.trim();
            if (!newName) {
                showToast(state.currentLanguage === 'en' ? 'System name cannot be empty' : 'ชื่อระบบงานต้องไม่ว่างเปล่า', 'error');
                return;
            }
            if (newName !== systemName) {
                finalSystemName = newName;
                isRename = true;
                const templateObj = allSystemTemplates.find(t => t.system_name === systemName);
                if (templateObj) {
                    templateId = templateObj.id;
                }
            }
        }
    }

    const rows = document.querySelectorAll('.template-item-row');
    const items = [];

    rows.forEach(row => {
        const descInput = row.querySelector('.template-item-input');
        const qtyInput = row.querySelector('.template-item-qty');
        if (!descInput || !qtyInput) return;

        const description = descInput.value.trim();
        const qty = parseFloat(qtyInput.value) || 1;

        if (description) {
            items.push({
                description,
                qty,
                brand: row.dataset.brand || '',
                model: row.dataset.model || '',
                type: row.dataset.type || '',
                unit: row.dataset.unit || 'Set',
                prod_group: row.dataset.prodGroup || ''
            });
        }
    });

    try {
        let res;
        if (isRename && templateId) {
            res = await authFetch(`${API_BASE}/system-templates/id/${templateId}`, {
                method: 'PUT',
                body: JSON.stringify({ system_name: finalSystemName, items })
            });
        } else {
            res = await authFetch(`${API_BASE}/system-templates/${encodeURIComponent(finalSystemName)}`, {
                method: 'PUT',
                body: JSON.stringify({ items })
            });
        }

        if (res.ok) {
            showToast(state.currentLanguage === 'en' ? 'Template saved successfully' : 'บันทึกเทมเพลตระบบงานสำเร็จแล้ว');

            // Re-populate dropdowns
            await populateSystemDropdowns();

            // Set active selection
            select.value = finalSystemName;
            document.getElementById('template-custom-system-group').style.display = 'none';
            document.getElementById('template-custom-system-name').value = '';

            closeTemplateManagerModal();
        } else {
            throw new Error('Save failed');
        }
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to save template' : 'ไม่สามารถบันทึกเทมเพลตได้', 'error');
    }
}

async function handleDeleteSection(e) {
    const btn = e.target.closest('.btn-delete-section');
    if (!btn) return;
    const id = btn.dataset.sectionId;
    console.log("handleDeleteSection triggered for ID:", id);
    if (!confirm(t('confirm_delete_section'))) return;

    try {
        await authFetch(`${API_BASE}/sections/${id}`, { method: 'DELETE' });
        markProjectModified(state.activeProjectId);
        showToast(t('toast_section_deleted'));
        await fetchActiveProjectDetails();
        renderWorkspace();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Delete failed' : 'ลบไม่สำเร็จ', 'error');
    }
}

async function handleInlineItemEdit(e) {
    const input = e.target;
    const tr = input.closest('tr');
    const itemId = tr.dataset.itemId;
    const role = state.currentUser ? state.currentUser.role : 'user';

    const qty = parseFloat(tr.querySelector('[data-field="qty"]').value) || 0;
    const cost_material = parseFloat(tr.querySelector('[data-field="cost_material"]').value) || 0;
    const cost_labour = parseFloat(tr.querySelector('[data-field="cost_labour"]').value) || 0;
    const price_material = parseFloat(tr.querySelector('[data-field="price_material"]').value) || 0;
    const price_labour = parseFloat(tr.querySelector('[data-field="price_labour"]').value) || 0;
    const discount = parseFloat(tr.querySelector('[data-field="discount"]').value) || 0;
    const is_free_issue = tr.querySelector('.free-issue-checkbox').checked ? 1 : 0;

    const brand = tr.dataset.brand || '';
    const type = tr.dataset.type || '';
    const description = tr.dataset.description || '';
    const unit = tr.dataset.unit || '';
    const prod_group = tr.dataset.prodGroup || '';
    const sm_no = tr.dataset.smNo || '';

    let payload = {};
    if (state.workspaceMode === 'production' || state.workspaceMode === 'product-supply') {
        payload = {
            production_qty: qty,
            production_cost_material: cost_material,
            production_cost_labour: cost_labour,
            production_price_material: price_material,
            production_price_labour: price_labour
        };
    } else {
        payload = {
            qty,
            cost_material,
            cost_labour,
            price_material,
            price_labour,
            discount,
            brand,
            description,
            type,
            unit,
            is_free_issue,
            prod_group,
            sm_no
        };
    }

    try {
        const res = await authFetch(`${API_BASE}/items/${itemId}`, {
            method: 'PUT',
            body: JSON.stringify(payload)
        });

        if (!res.ok) throw new Error('Update failed');

        await fetchActiveProjectDetails();

        const isProdMode = state.workspaceMode === 'production' || state.workspaceMode === 'product-supply';
        const totalCost = state.activeProjectSummary.production_cost_total;
        const totalQuote = state.activeProjectSummary.price_total;
        const totalProfit = totalQuote - totalCost;
        const margin = totalQuote > 0 ? (totalProfit / totalQuote) * 100 : 0;

        document.getElementById('summary-total-cost').textContent = formatCurrency(totalCost);
        document.getElementById('summary-cost-material').textContent = formatCurrency(state.activeProjectSummary.production_cost_material);
        document.getElementById('summary-cost-labour').textContent = formatCurrency(state.activeProjectSummary.production_cost_labour);
        document.getElementById('summary-total-quote').textContent = formatCurrency(totalQuote);
        document.getElementById('summary-quote-material').textContent = formatCurrency(state.activeProjectSummary.price_material);
        document.getElementById('summary-quote-labour').textContent = formatCurrency(state.activeProjectSummary.price_labour);

        const profitEl = document.getElementById('summary-total-profit');
        const marginEl = document.getElementById('summary-profit-margin');
        const profitCard = document.getElementById('stat-profit-card');
        const labelEl = document.getElementById('profit-card-label');
        profitEl.textContent = formatCurrency(totalProfit);
        marginEl.textContent = `${margin.toFixed(2)}%`;
        if (totalProfit >= 0) {
            profitCard.className = 'stat-card profit profit-state';
            labelEl.textContent = state.currentLanguage === 'en' ? 'Project Profit (Profit)' : 'กำไรโครงการ (Profit)';
        } else {
            profitCard.className = 'stat-card profit loss-state';
            labelEl.textContent = state.currentLanguage === 'en' ? 'Project Loss (Loss)' : 'ขาดทุนโครงการ (Loss)';
        }

        await fetchProjects();

        const totalCostRow = (cost_material + cost_labour) * qty;
        const totalQuoteRow = (price_material + price_labour) * qty * (1 - discount / 100);
        const profitRow = totalQuoteRow - totalCostRow;

        tr.cells[10].innerText = formatNumber(totalCostRow);
        tr.cells[11].innerText = formatNumber(totalQuoteRow);
        tr.cells[12].innerText = formatNumber(profitRow);
        tr.cells[12].style.color = profitRow >= 0 ? 'var(--success)' : 'var(--danger)';

        // Update section summary headers directly
        const secSummary = state.activeProjectSummary.sections.find(s => s.id === parseInt(tr.closest('.subsection-panel').dataset.sectionId));
        if (secSummary) {
            const panel = tr.closest('.subsection-panel');
            const role = state.currentUser ? state.currentUser.role : 'user';
            
            const secCostTotal = secSummary.production_cost_total;
            const secPriceTotal = secSummary.price_total;
            const secProfitVal = secPriceTotal - secCostTotal;
            const isSecProfit = secProfitVal >= 0;
            const secMarginVal = secPriceTotal > 0 ? (secProfitVal / secPriceTotal) * 100 : 0;

            // Update Cost span directly to preserve Mat/Lab details
            const costSpan = panel.querySelector('.sub-sum-cost');
            if (costSpan) {
                const costMatVal = secSummary.production_cost_material || 0;
                const costLabVal = secSummary.production_cost_labour || 0;
                costSpan.innerHTML = (state.currentLanguage === 'en' ? 'Cost' : 'ทุน') + ': <b>' + formatCurrency(secCostTotal) + '</b>' +
                    ((role === 'admin' || role === 'superadmin' || role === 'supervisor') ? 
                    ' <span style="font-size:0.725rem; font-weight:normal; color:var(--text-muted); margin-left:4px;">(Mat: ' + formatCurrency(costMatVal) + ' / Lab: ' + formatCurrency(costLabVal) + ')</span>' : '');
            }

            // Update Quote span directly to preserve Mat/Lab details
            const quoteSpan = panel.querySelector('.sub-sum-quote');
            if (quoteSpan) {
                const priceMatVal = secSummary.price_material || 0;
                const priceLabVal = secSummary.price_labour || 0;
                quoteSpan.innerHTML = (state.currentLanguage === 'en' ? 'Quote' : 'เสนอราคา') + ': <b>' + formatCurrency(secPriceTotal) + '</b>' +
                    ' <span style="font-size:0.725rem; font-weight:normal; color:var(--text-muted); margin-left:4px;">(Mat: ' + formatCurrency(priceMatVal) + ' / Lab: ' + formatCurrency(priceLabVal) + ')</span>';
            }

            // Update Profit span directly
            const profitSpan = panel.querySelector('.sub-sum-profit');
            if (profitSpan) {
                profitSpan.className = 'sub-sum-profit ' + (isSecProfit ? 'profit' : 'loss');
                profitSpan.innerHTML = (isSecProfit ? (state.currentLanguage === 'en' ? 'Profit' : 'กำไร') : (state.currentLanguage === 'en' ? 'Loss' : 'ขาดทุน')) + ': <b>' + formatCurrency(secProfitVal) + ' (' + secMarginVal.toFixed(1) + '%)</b>';
            }

            // Update Profit Adjuster input value
            const adjustInput = panel.querySelector('.profit-adjust-input');
            if (adjustInput) {
                adjustInput.value = (typeof secMarginVal === 'number' && !isNaN(secMarginVal)) ? secMarginVal.toFixed(1) : (secSummary.profit_percent || 0);
            }
        }
        
        markProjectModified(state.activeProjectId);
        showToast(t('toast_item_updated'));
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to update' : 'ไม่สามารถอัปเดตข้อมูลได้', 'error');
    }
}

async function handleDeleteItem(e) {
    const btn = e.target.closest('.btn-delete-item');
    if (!btn) return;
    const id = btn.dataset.itemId;
    console.log("handleDeleteItem triggered for ID:", id);
    if (!confirm(t('confirm_delete_item'))) return;

    try {
        await authFetch(`${API_BASE}/items/${id}`, { method: 'DELETE' });
        markProjectModified(state.activeProjectId);
        showToast(t('toast_item_deleted'));
        await fetchActiveProjectDetails();
        renderWorkspace();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Delete failed' : 'ลบไม่สำเร็จ', 'error');
    }
}

// ==========================================
// Catalog Explorer Modal (Add items to takeoff)
// ==========================================

async function openExplorerModal(sectionId, sectionName) {
    state.isSelectingForTemplate = false;
    state.selectedSectionId = sectionId;
    document.getElementById('target-section-name').textContent = sectionName;
    document.getElementById('explorer-search').value = '';

    buildCategoryDropdown('explorer-category-select');
    buildGroupDropdown('explorer-group-select');
    buildSystemDropdown('explorer-system-select');
    await filterExplorerProducts();
    document.getElementById('modal-catalog-explorer').classList.add('active');
}

async function openExplorerModalForTemplate() {
    state.selectedSectionId = null;
    state.isSelectingForTemplate = true;

    const systemName = document.getElementById('template-select-system').value;
    document.getElementById('target-section-name').textContent = systemName;
    document.getElementById('explorer-search').value = '';

    buildCategoryDropdown('explorer-category-select');
    buildGroupDropdown('explorer-group-select');
    buildSystemDropdown('explorer-system-select');
    await filterExplorerProducts();
    document.getElementById('modal-catalog-explorer').classList.add('active');
}

function closeExplorerModal() {
    state.isSelectingForTemplate = false;
    document.getElementById('modal-catalog-explorer').classList.remove('active');
}

async function filterExplorerProducts() {
    const searchVal = document.getElementById('explorer-search').value;
    const catVal = document.getElementById('explorer-category-select').value;
    const groupVal = document.getElementById('explorer-group-select').value;
    const systemVal = document.getElementById('explorer-system-select').value;

    let url = `${API_BASE}/products?`;
    if (searchVal) url += `q=${encodeURIComponent(searchVal)}&`;
    if (catVal) url += `category=${encodeURIComponent(catVal)}&`;
    if (groupVal) url += `group=${encodeURIComponent(groupVal)}&`;
    if (systemVal) url += `system=${encodeURIComponent(systemVal)}&`;

    try {
        const res = await authFetch(url);
        const products = await res.json();

        state.explorerProducts = products;
        state.explorerCurrentPage = 1;
        renderExplorerProductsPagination();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to search catalog products' : 'ไม่สามารถค้นหาข้อมูลสินค้าได้', 'error');
    }
}

function renderExplorerProductsPagination() {
    const products = state.explorerProducts || [];
    const page = state.explorerCurrentPage;
    const pageSize = state.explorerPageSize;

    const totalItems = products.length;
    const totalPages = Math.ceil(totalItems / pageSize) || 1;

    if (state.explorerCurrentPage > totalPages) state.explorerCurrentPage = totalPages;
    if (state.explorerCurrentPage < 1) state.explorerCurrentPage = 1;

    const startIndex = (state.explorerCurrentPage - 1) * pageSize;
    const endIndex = Math.min(startIndex + pageSize, totalItems);

    const paginatedProducts = products.slice(startIndex, endIndex);

    // Update pagination labels
    document.getElementById('explorer-page-start').textContent = totalItems === 0 ? 0 : startIndex + 1;
    document.getElementById('explorer-page-end').textContent = endIndex;
    document.getElementById('explorer-total-items').textContent = totalItems;

    // Enable/disable buttons
    document.getElementById('btn-explorer-prev-page').disabled = state.explorerCurrentPage <= 1;
    document.getElementById('btn-explorer-next-page').disabled = state.explorerCurrentPage >= totalPages;

    renderExplorerProducts(paginatedProducts);
}

function renderExplorerProducts(products) {
    const tbody = document.getElementById('explorer-products-tbody');
    tbody.innerHTML = '';
    const role = state.currentUser ? state.currentUser.role : 'user';

    if (products.length === 0) {
        tbody.innerHTML = `<tr><td colspan="9" style="padding: 30px; text-align: center; color: var(--text-muted);">${state.currentLanguage === 'en' ? 'No products found in catalog' : 'ไม่พบสินค้าในแคตตาล็อก'}</td></tr>`;
        return;
    }

    products.forEach(p => {
        const tr = document.createElement('tr');

        let imgHtml = `<div class="thumbnail-placeholder"><i class="fa-regular fa-image"></i></div>`;
        if (p.has_image) {
            const imgUrl = withAuthToken(`${API_BASE}/products/${p.id}/image?t=${Date.now()}`);
            imgHtml = `<img src="${imgUrl}" class="product-thumbnail" alt="Product" onclick="openLightbox('${imgUrl}')">`;
        }

        let pdfLinkHtml = '';
        if (p.has_pdf) {
            pdfLinkHtml = `
                <div class="pdf-spec-link" title="${state.currentLanguage === 'en' ? 'Open Product Datasheet (PDF)' : 'เปิดดูคู่มือเทคนิคสินค้า (PDF Datasheet)'}" 
                     data-product-id="${p.id}" data-description="${escapeHtml(p.description)}">
                    <i class="fa-solid fa-file-pdf text-danger" style="pointer-events: none;"></i>
                </div>
            `;
        }

        tr.innerHTML = `
            <td>
                <div class="product-thumb-cell">
                    ${imgHtml}
                </div>
            </td>
            <td><b>${escapeHtml(p.sm_no || '-')}</b></td>
            <td><b>${escapeHtml(p.brand || '-')}</b></td>
            <td>
                <div style="font-weight: 500; display:flex; align-items:center; gap:8px;">
                    ${escapeHtml(p.description)}
                    ${pdfLinkHtml}
                </div>
                <div style="font-size: 0.75rem; color: var(--text-muted); margin-top: 2px; display: flex; flex-wrap: wrap; gap: 8px;">
                    <span><b>${state.currentLanguage === 'en' ? 'Category' : 'หมวดหมู่'}:</b> ${escapeHtml(p.category || '-')}</span>
                    ${p.prod_group ? `<span>| <b>${state.currentLanguage === 'en' ? 'Group' : 'กลุ่ม'}:</b> ${escapeHtml(p.prod_group)}</span>` : ''}
                    ${p.prod_system ? `<span>| <b>${state.currentLanguage === 'en' ? 'System' : 'ระบบ'}:</b> ${escapeHtml(p.prod_system)}</span>` : ''}
                    ${p.weight ? `<span>| <b>${state.currentLanguage === 'en' ? 'Weight' : 'น้ำหนัก'}:</b> ${p.weight} ${state.currentLanguage === 'en' ? 'kg' : 'กก.'}</span>` : ''}
                    ${p.supplier_name ? `<span>| <b>${state.currentLanguage === 'en' ? 'Distributor' : 'ตัวแทนจำหน่าย'}:</b> ${escapeHtml(p.supplier_name)}</span>` : ''}
                    ${p.lead_time ? `<span>| <b>${state.currentLanguage === 'en' ? 'Lead Time' : 'ระยะเวลาจัดหา'}:</b> ${escapeHtml(p.lead_time)}</span>` : ''}
                    ${['superadmin', 'excusive', 'admin', 'estimate', 'procurment', 'procurement_manager'].includes(role) ? `<span>| <b style="color: #4f46e5;">Supplier Price:</b> <span style="color: #4f46e5; font-weight: 600;">${formatCurrency(p.supplier_price || 0)}</span></span>` : ''}
                </div>
            </td>
            <td>${escapeHtml(p.model || '-')}</td>
            <td>${escapeHtml(p.type || '-')}</td>
            <td class="text-right">${formatNumber(p.mt_cost)}</td>
            <td class="text-right">${formatNumber(p.lb_cost)}</td>
            <td class="text-center">${escapeHtml(p.unit || '-')}</td>
            <td class="text-center">
                <button class="btn btn-primary btn-sm btn-add-prod-to-takeoff" data-product-id="${p.id}">
                    <i class="fa-solid fa-plus"></i> ${t('table_action_add')}
                </button>
            </td>
        `;

        tr.querySelector('.btn-add-prod-to-takeoff').addEventListener('click', () => handleAddProductToTakeoff(p));
        tbody.appendChild(tr);
    });
}

async function handleAddProductToTakeoff(product) {
    if (state.isSelectingForTemplate) {
        addTemplateItemRowDOM(product);
        showToast(state.currentLanguage === 'en'
            ? `Added "${product.description}" to template`
            : `เพิ่ม "${product.description}" ลงในเทมเพลตแล้ว`);
        return;
    }

    if (!state.selectedSectionId) return;

    try {
        // Fetch existing items in the section first to see if this product is already added
        const resList = await authFetch(`${API_BASE}/sections/${state.selectedSectionId}/items`);
        const items = await resList.json();
        const existingItem = items.find(item => item.product_id == product.id);

        if (existingItem) {
            // Update quantity of the existing item
            const payload = {
                qty: (parseFloat(existingItem.qty) || 0) + 1,
                discount: existingItem.discount || 0,
                is_free_issue: existingItem.is_free_issue || 0,
                cost_material: existingItem.cost_material,
                cost_labour: existingItem.cost_labour,
                price_material: existingItem.price_material,
                price_labour: existingItem.price_labour,
                brand: existingItem.brand,
                description: existingItem.description,
                type: existingItem.type,
                model: existingItem.model,
                unit: existingItem.unit,
                prod_group: existingItem.prod_group
            };

            await authFetch(`${API_BASE}/items/${existingItem.id}`, {
                method: 'PUT',
                body: JSON.stringify(payload)
            });
            markProjectModified(state.activeProjectId);
            showToast(state.currentLanguage === 'en' ? 'Item quantity increased' : 'เพิ่มจำนวนสินค้าในส่วนย่อยเรียบร้อยแล้ว');
        } else {
            // Create a new item
            const payload = {
                product_id: product.id,
                brand: product.brand,
                description: product.description,
                type: product.type,
                model: product.model,
                sm_no: product.sm_no || null,
                qty: 1,
                unit: product.unit,
                cost_material: product.mt_cost,
                cost_labour: product.lb_cost,
                price_material: product.mt_qou,
                price_labour: product.lb_qou,
                discount: product.discount,
                prod_group: product.prod_group
            };

            await authFetch(`${API_BASE}/sections/${state.selectedSectionId}/items`, {
                method: 'POST',
                body: JSON.stringify(payload)
            });
            markProjectModified(state.activeProjectId);
            showToast(t('toast_item_added'));
        }

        await fetchActiveProjectDetails();
        renderWorkspace();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Operation failed' : 'ดำเนินการไม่สำเร็จ', 'error');
    }
}

// ==========================================
// Catalog Manager (Database management & Upload)
// ==========================================

async function openCatalogManagerModal() {
    document.getElementById('catalog-manager-search').value = '';
    buildCategoryDropdown('catalog-manager-category');
    buildGroupDropdown('catalog-manager-group');
    buildSystemDropdown('catalog-manager-system');
    await filterManagerProducts();
    document.getElementById('modal-catalog-manager').classList.add('active');
}

function closeCatalogManagerModal() {
    document.getElementById('modal-catalog-manager').classList.remove('active');
}

async function filterManagerProducts(keepPage = false) {
    const searchVal = document.getElementById('catalog-manager-search').value;
    const catVal = document.getElementById('catalog-manager-category').value;
    const groupVal = document.getElementById('catalog-manager-group').value;
    const systemVal = document.getElementById('catalog-manager-system').value;

    let url = `${API_BASE}/products?`;
    if (searchVal) url += `q=${encodeURIComponent(searchVal)}&`;
    if (catVal) url += `category=${encodeURIComponent(catVal)}&`;
    if (groupVal) url += `group=${encodeURIComponent(groupVal)}&`;
    if (systemVal) url += `system=${encodeURIComponent(systemVal)}&`;

    try {
        const res = await authFetch(url);
        const products = await res.json();

        state.managerProducts = products;
        if (!keepPage) {
            state.managerCurrentPage = 1;
        }
        renderManagerProductsPagination();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load catalog warehouse' : 'เกิดข้อผิดพลาดในการโหลดรายการคลังสินค้า', 'error');
    }
}

function renderManagerProductsPagination() {
    const products = state.managerProducts || [];
    const page = state.managerCurrentPage;
    const pageSize = state.managerPageSize;

    const totalItems = products.length;
    const totalPages = Math.ceil(totalItems / pageSize) || 1;

    if (state.managerCurrentPage > totalPages) state.managerCurrentPage = totalPages;
    if (state.managerCurrentPage < 1) state.managerCurrentPage = 1;

    const startIndex = (state.managerCurrentPage - 1) * pageSize;
    const endIndex = Math.min(startIndex + pageSize, totalItems);

    const paginatedProducts = products.slice(startIndex, endIndex);

    // Update pagination labels
    document.getElementById('manager-page-start').textContent = totalItems === 0 ? 0 : startIndex + 1;
    document.getElementById('manager-page-end').textContent = endIndex;
    document.getElementById('manager-total-items').textContent = totalItems;

    // Enable/disable buttons
    document.getElementById('btn-manager-prev-page').disabled = state.managerCurrentPage <= 1;
    document.getElementById('btn-manager-next-page').disabled = state.managerCurrentPage >= totalPages;

    renderManagerProducts(paginatedProducts);
}

function renderManagerProducts(products) {
    const tbody = document.getElementById('catalog-manager-tbody');
    tbody.innerHTML = '';

    if (products.length === 0) {
        tbody.innerHTML = `<tr><td colspan="10" style="padding: 30px; text-align: center; color: var(--text-muted);">${state.currentLanguage === 'en' ? 'No products found in warehouse' : 'ไม่พบสินค้าในระบบคลัง'}</td></tr>`;
        return;
    }

    const role = state.currentUser ? state.currentUser.role : 'user';

    products.forEach(p => {
        const tr = document.createElement('tr');

        let imgHtml = `<div class="thumbnail-placeholder"><i class="fa-regular fa-image"></i></div>`;
        if (p.has_image) {
            const imgUrl = withAuthToken(`${API_BASE}/products/${p.id}/image?t=${Date.now()}`);
            imgHtml = `<img src="${imgUrl}" class="product-thumbnail" alt="Product" onclick="openLightbox('${imgUrl}')">`;
        }

        let pdfLinkHtml = '';
        if (p.has_pdf) {
            pdfLinkHtml = `
                <div class="pdf-spec-link" title="${state.currentLanguage === 'en' ? 'Open Product Datasheet (PDF)' : 'เปิดดูคู่มือเทคนิคสินค้า (PDF Datasheet)'}" 
                     data-product-id="${p.id}" data-description="${escapeHtml(p.description)}">
                    <i class="fa-solid fa-file-pdf text-danger" style="pointer-events: none;"></i>
                </div>
            `;
        }

        tr.innerHTML = `
            <td>
                <div class="product-thumb-cell">
                    ${imgHtml}
                </div>
            </td>
            <td><b>${escapeHtml(p.sm_no || '-')}</b></td>
            <td><b>${escapeHtml(p.brand || '-')}</b></td>
            <td>
                <div style="font-weight: 500; display:flex; align-items:center; gap:8px;">
                    ${escapeHtml(p.description)}
                    ${pdfLinkHtml}
                </div>
                <div style="font-size: 0.75rem; color: var(--text-muted); margin-top: 2px; display: flex; flex-wrap: wrap; gap: 8px;">
                    <span><b>${state.currentLanguage === 'en' ? 'Category' : 'หมวดหมู่'}:</b> ${escapeHtml(p.category || '-')}</span>
                    ${p.prod_group ? `<span>| <b>${state.currentLanguage === 'en' ? 'Group' : 'กลุ่ม'}:</b> ${escapeHtml(p.prod_group)}</span>` : ''}
                    ${p.prod_system ? `<span>| <b>${state.currentLanguage === 'en' ? 'System' : 'ระบบ'}:</b> ${escapeHtml(p.prod_system)}</span>` : ''}
                    ${p.weight ? `<span>| <b>${state.currentLanguage === 'en' ? 'Weight' : 'น้ำหนัก'}:</b> ${p.weight} ${state.currentLanguage === 'en' ? 'kg' : 'กก.'}</span>` : ''}
                    ${p.supplier_name ? `<span>| <b>${state.currentLanguage === 'en' ? 'Distributor' : 'ตัวแทนจำหน่าย'}:</b> ${escapeHtml(p.supplier_name)}</span>` : ''}
                    ${p.lead_time ? `<span>| <b>${state.currentLanguage === 'en' ? 'Lead Time' : 'ระยะเวลาจัดหา'}:</b> ${escapeHtml(p.lead_time)}</span>` : ''}
                </div>
            </td>
            <td>${escapeHtml(p.model || '-')}</td>
            <td>${escapeHtml(p.type || '-')}</td>
            <td class="text-right">
                <div>${state.currentLanguage === 'en' ? 'Mat' : 'วัสดุ'}: <b>${formatNumber(p.mt_cost)}</b></div>
                <div style="font-size:0.75rem; color:var(--text-muted);">${state.currentLanguage === 'en' ? 'Lab' : 'ค่าแรง'}: <b>${formatNumber(p.lb_cost)}</b></div>
            </td>
            <td class="text-right text-primary-color">
                <div>${state.currentLanguage === 'en' ? 'Mat' : 'วัสดุ'}: <b>${formatNumber(p.mt_qou)}</b></div>
                <div style="font-size:0.75rem; color:var(--text-muted);">${state.currentLanguage === 'en' ? 'Lab' : 'ค่าแรง'}: <b>${formatNumber(p.lb_qou)}</b></div>
            </td>
            <td class="text-center">${escapeHtml(p.unit || '-')}</td>
            <td class="text-center" style="white-space: nowrap;">
                <div class="row-actions">
                    <button class="btn-icon btn-edit-catalog-prod" data-product-id="${p.id}" title="${t('table_action_edit')}">
                        <i class="fa-solid fa-edit"></i>
                    </button>
                    <button class="btn-icon btn-clone-catalog-prod" data-product-id="${p.id}" title="${t('table_action_clone')}">
                        <i class="fa-solid fa-copy"></i>
                    </button>
                    <button class="btn-icon btn-danger-icon btn-delete-catalog-prod" data-product-id="${p.id}" title="${t('table_action_delete')}">
                        <i class="fa-solid fa-trash"></i>
                    </button>
                </div>
            </td>
        `;

        const isCatalogWriter = (role === 'admin' || role === 'superadmin' || role === 'supervisor' || role === 'estimate');
        if (!isCatalogWriter) {
            tr.querySelector('.btn-edit-catalog-prod').style.display = 'none';
            tr.querySelector('.btn-clone-catalog-prod').style.display = 'none';
            tr.querySelector('.btn-delete-catalog-prod').style.display = 'none';
        } else {
            tr.querySelector('.btn-edit-catalog-prod').addEventListener('click', () => openProductDetailModal(p));
            tr.querySelector('.btn-clone-catalog-prod').addEventListener('click', () => handleCloneCatalogProduct(p.id));
            tr.querySelector('.btn-delete-catalog-prod').addEventListener('click', () => handleDeleteCatalogProduct(p.id));
        }

        tbody.appendChild(tr);
    });
}

function switchProductDetailTab(targetCardId) {
    // Hide all form cards in product detail modal
    const cards = document.querySelectorAll('#modal-product-detail .form-card');
    cards.forEach(card => {
        card.style.display = 'none';
    });

    // Show the targeted form card
    const targetCard = document.getElementById(targetCardId.replace('#', ''));
    if (targetCard) {
        targetCard.style.display = 'block';
    }

    // Set active class on corresponding tab
    document.querySelectorAll('.product-detail-tabs .tab-item').forEach(tab => {
        const href = tab.getAttribute('href');
        if (href === targetCardId) {
            tab.classList.add('active');
        } else {
            tab.classList.remove('active');
        }
    });
}

async function openProductDetailModal(product = null) {
    state.editingCatalogProduct = product;
    state.imageFileToUpload = null;
    state.pdfFileToUpload = null;
    state.quoteFileToUpload = null;

    const modal = document.getElementById('modal-product-detail');
    const title = document.getElementById('product-detail-title');
    const form = document.getElementById('form-product-detail');
    const previewBox = document.getElementById('product-image-preview');
    const pdfStatus = document.getElementById('product-pdf-status');
    const quoteStatus = document.getElementById('product-supplier-quote-status');

    form.reset();
    
    // Reset active tab and show only basic info card
    switchProductDetailTab('#card-basic-info');
    const modalBody = document.querySelector('.product-detail-body');
    if (modalBody) modalBody.scrollTop = 0;

    document.getElementById('product-image-url').value = '';
    document.getElementById('product-pdf-url').value = '';
    previewBox.innerHTML = '<i class="fa-regular fa-image placeholder-icon"></i>';
    pdfStatus.innerHTML = `<i class="fa-solid fa-file-pdf text-muted"></i> ${t('status_no_file')}`;
    quoteStatus.innerHTML = `<i class="fa-solid fa-file-invoice text-muted"></i> ${t('status_no_quote')}`;

    // Fetch and populate supplier dropdown
    await fetchSuppliers();
    const supplierDropdown = document.getElementById('detail-supplier-id');
    supplierDropdown.innerHTML = `<option value="">${t('select_supplier_placeholder')}</option>`;
    state.suppliers.forEach(s => {
        const option = document.createElement('option');
        option.value = s.id;
        option.textContent = s.name;
        supplierDropdown.appendChild(option);
    });

    if (product) {
        title.textContent = t('modal_prod_detail_edit');
        document.getElementById('product-detail-id').value = product.id;
        document.getElementById('detail-sm-no').value = product.sm_no || '';
        document.getElementById('detail-brand').value = product.brand || '';
        document.getElementById('detail-description').value = product.description || '';
        document.getElementById('detail-type').value = product.type || '';
        document.getElementById('detail-model').value = product.model || '';
        document.getElementById('detail-category').value = product.category || '';
        document.getElementById('detail-group').value = product.prod_group || '';
        document.getElementById('detail-system').value = product.prod_system || '';
        document.getElementById('detail-unit').value = product.unit || '';
        document.getElementById('detail-weight').value = product.weight || '';
        document.getElementById('detail-mt-cost').value = product.mt_cost || '';
        document.getElementById('detail-lb-cost').value = product.lb_cost || '';
        document.getElementById('detail-mt-qou').value = product.mt_qou || '';
        document.getElementById('detail-lb-qou').value = product.lb_qou || '';
        document.getElementById('detail-discount').value = product.discount || '';

        document.getElementById('detail-supplier-id').value = product.supplier_id || '';
        document.getElementById('detail-supplier-price').value = product.supplier_price || '';
        document.getElementById('detail-lead-time').value = product.lead_time || '';

        updateSupplierWebsiteLink(product.supplier_id);

        if (product.has_image) {
            previewBox.innerHTML = `<img src="${withAuthToken(`${API_BASE}/products/${product.id}/image?t=${Date.now()}`)}" alt="Preview" style="max-width:100%; max-height:100%; object-fit:contain;">`;
        }
        if (product.has_pdf) {
            pdfStatus.innerHTML = `
                <div style="display:flex; align-items:center; gap:10px;">
                    <span style="color: var(--primary-color); font-weight:600; cursor:pointer;" 
                          onclick="openPdfViewer(${product.id}, '${escapeJsString(product.description)}')">
                        <i class="fa-solid fa-file-pdf text-danger"></i> ${state.currentLanguage === 'en' ? 'Open Manual (PDF)' : 'เปิดดูคู่มือเทคนิค (PDF)'}
                    </span>
                    <button type="button" class="btn btn-danger-outline btn-sm" onclick="handleDeletePdfDirect(${product.id})">
                        <i class="fa-solid fa-trash-can"></i> ${state.currentLanguage === 'en' ? 'Delete' : 'ลบไฟล์'}
                    </button>
                </div>
            `;
        }
        if (product.has_supplier_quote) {
            quoteStatus.innerHTML = `
                <div style="display:flex; align-items:center; gap:10px;">
                    <span style="color: var(--primary-color); font-weight:600; cursor:pointer;" 
                          onclick="openSupplierQuoteViewer(${product.id}, '${escapeJsString(product.description)}')">
                        <i class="fa-solid fa-file-invoice text-success"></i> ${state.currentLanguage === 'en' ? 'Open Quotation' : 'เปิดดูใบเสนอราคา'}
                    </span>
                    <button type="button" class="btn btn-danger-outline btn-sm" onclick="handleDeleteSupplierQuoteDirect(${product.id})">
                        <i class="fa-solid fa-trash-can"></i> ${state.currentLanguage === 'en' ? 'Delete' : 'ลบไฟล์'}
                    </button>
                </div>
            `;
        }
    } else {
        title.textContent = t('modal_prod_detail_create');
        document.getElementById('product-detail-id').value = '';
        document.getElementById('detail-supplier-id').value = '';
        document.getElementById('detail-supplier-price').value = '';
        document.getElementById('detail-supplier-website-wrapper').style.display = 'none';
    }

    modal.classList.add('active');
}

function closeProductDetailModal() {
    document.getElementById('modal-product-detail').classList.remove('active');
}

function handleImageSelection(e) {
    const file = e.target.files[0];
    if (!file) return;

    state.imageFileToUpload = file;

    const reader = new FileReader();
    reader.onload = function (e) {
        document.getElementById('product-image-preview').innerHTML = `<img src="${e.target.result}" alt="Preview" style="max-width:100%; max-height:100%; object-fit:contain;">`;
    };
    reader.readAsDataURL(file);
}

function handlePdfSelection(e) {
    const file = e.target.files[0];
    if (!file) return;

    state.pdfFileToUpload = file;
    document.getElementById('product-pdf-status').innerHTML = `
        <span class="text-success"><i class="fa-solid fa-file-circle-check"></i> ${state.currentLanguage === 'en' ? 'Ready to upload' : 'พร้อมอัปโหลด'}: ${escapeHtml(file.name)}</span>
    `;
}

async function handleProductDetailSubmit(e) {
    e.preventDefault();

    const id = document.getElementById('product-detail-id').value;
    const payload = {
        brand: document.getElementById('detail-brand').value,
        description: document.getElementById('detail-description').value,
        type: document.getElementById('detail-type').value,
        model: document.getElementById('detail-model').value,
        sm_no: document.getElementById('detail-sm-no').value,
        category: document.getElementById('detail-category').value,
        prod_group: document.getElementById('detail-group').value,
        prod_system: document.getElementById('detail-system').value,
        unit: document.getElementById('detail-unit').value,
        weight: parseFloat(document.getElementById('detail-weight').value) || 0,
        mt_cost: parseFloat(document.getElementById('detail-mt-cost').value) || 0,
        lb_cost: parseFloat(document.getElementById('detail-lb-cost').value) || 0,
        mt_qou: parseFloat(document.getElementById('detail-mt-qou').value) || 0,
        lb_qou: parseFloat(document.getElementById('detail-lb-qou').value) || 0,
        discount: parseFloat(document.getElementById('detail-discount').value) || 0,
        supplier_id: document.getElementById('detail-supplier-id').value || null,
        supplier_price: parseFloat(document.getElementById('detail-supplier-price').value) || 0,
        lead_time: document.getElementById('detail-lead-time').value || null,
        details: ''
    };

    try {
        let product;
        if (id) {
            const res = await authFetch(`${API_BASE}/products/${id}`, {
                method: 'PUT',
                body: JSON.stringify(payload)
            });
            product = await res.json();
            showToast(t('toast_catalog_updated'));
        } else {
            const res = await authFetch(`${API_BASE}/products`, {
                method: 'POST',
                body: JSON.stringify(payload)
            });
            product = await res.json();
            showToast(t('toast_catalog_updated'));
        }

        // Image Upload directly to database
        if (state.imageFileToUpload) {
            const formData = new FormData();
            formData.append('image', state.imageFileToUpload);
            await authFetch(`${API_BASE}/products/${product.id}/upload`, {
                method: 'POST',
                body: formData
            });
            showToast(state.currentLanguage === 'en' ? 'Product image uploaded' : 'อัปโหลดรูปภาพสินค้าเข้าระบบฐานข้อมูลแล้ว');
        } else {
            const imageUrl = document.getElementById('product-image-url').value.trim();
            if (imageUrl) {
                await authFetch(`${API_BASE}/products/${product.id}/upload-image-url`, {
                    method: 'POST',
                    body: JSON.stringify({ url: imageUrl })
                });
                showToast(state.currentLanguage === 'en' ? 'Product image downloaded and saved' : 'ดาวน์โหลดและบันทึกรูปภาพสินค้าเข้าระบบแล้ว');
            }
        }

        // PDF Upload directly to database
        if (state.pdfFileToUpload) {
            const formData = new FormData();
            formData.append('pdf', state.pdfFileToUpload);
            await authFetch(`${API_BASE}/products/${product.id}/upload-pdf`, {
                method: 'POST',
                body: formData
            });
            showToast(state.currentLanguage === 'en' ? 'PDF manual uploaded' : 'อัปโหลดไฟล์ PDF คู่มือเข้าระบบฐานข้อมูลแล้ว');
        } else {
            const pdfUrl = document.getElementById('product-pdf-url').value.trim();
            if (pdfUrl) {
                await authFetch(`${API_BASE}/products/${product.id}/upload-pdf-url`, {
                    method: 'POST',
                    body: JSON.stringify({ url: pdfUrl })
                });
                showToast(state.currentLanguage === 'en' ? 'Technical manual downloaded and saved' : 'ดาวน์โหลดและบันทึกคู่มือเทคนิคเรียบร้อยแล้ว');
            }
        }

        // Supplier Quote Upload directly to database
        if (state.quoteFileToUpload) {
            const formData = new FormData();
            formData.append('quote', state.quoteFileToUpload);
            await authFetch(`${API_BASE}/products/${product.id}/upload-supplier-quote`, {
                method: 'POST',
                body: formData
            });
            showToast(state.currentLanguage === 'en' ? 'Supplier quote document uploaded' : 'อัปโหลดเอกสารใบเสนอราคาผู้จัดจำหน่ายแล้ว');
        }

        closeProductDetailModal();
        await fetchCategories();
        await fetchGroups();
        await fetchSystems();
        
        buildCategoryDropdown('catalog-manager-category');
        buildGroupDropdown('catalog-manager-group');
        buildSystemDropdown('catalog-manager-system');
        buildCategoryDropdown('explorer-category-select');
        buildGroupDropdown('explorer-group-select');
        buildSystemDropdown('explorer-system-select');

        await filterManagerProducts(true);

        if (state.activeProjectId) {
            await fetchActiveProjectDetails();
            renderWorkspace();
        }
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Error saving product information' : 'เกิดข้อผิดพลาดในการบันทึกข้อมูลสินค้า', 'error');
    }
}

async function handleDeleteCatalogProduct(id) {
    if (!confirm(t('confirm_delete_product_catalog'))) return;

    try {
        await authFetch(`${API_BASE}/products/${id}`, { method: 'DELETE' });
        showToast(state.currentLanguage === 'en' ? 'Product deleted successfully' : 'ลบสินค้าสำเร็จ');
        await filterManagerProducts();
        if (state.activeProjectId) {
            await fetchActiveProjectDetails();
            renderWorkspace();
        }
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to delete product' : 'ไม่สามารถลบสินค้าได้', 'error');
    }
}

async function handleCloneCatalogProduct(id) {
    if (!confirm(state.currentLanguage === 'en' ? 'Are you sure you want to clone this product?' : 'คุณแน่ใจหรือไม่ว่าต้องการโคลนสินค้าชิ้นนี้?')) return;

    try {
        const res = await authFetch(`${API_BASE}/products/${id}/clone`, {
            method: 'POST'
        });
        if (!res.ok) {
            const err = await res.json();
            throw new Error(err.error || 'Failed to clone product');
        }

        showToast(state.currentLanguage === 'en' ? 'Product cloned successfully' : 'โคลนสินค้าสำเร็จแล้ว');

        await filterManagerProducts();
        if (state.activeProjectId) {
            await fetchActiveProjectDetails();
            renderWorkspace();
        }
    } catch (err) {
        console.error(err);
        showToast(err.message, 'danger');
    }
}

async function handleDeletePdfDirect(productId) {
    if (!confirm(t('confirm_delete_pdf_sheet'))) return;
    try {
        await authFetch(`${API_BASE}/products/${productId}/pdf`, { method: 'DELETE' });
        showToast(t('toast_pdf_deleted'));

        // Refresh detail form
        const res = await authFetch(`${API_BASE}/products?q=`);
        const list = await res.json();
        const updatedProd = list.find(p => p.id === productId);
        openProductDetailModal(updatedProd);

        await filterManagerProducts();
        if (state.activeProjectId) {
            await fetchActiveProjectDetails();
            renderWorkspace();
        }
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to delete file' : 'ไม่สามารถลบไฟล์ได้', 'error');
    }
}

// ==========================================
// Embedded PDF Datasheet Viewer Modal
// ==========================================

function openPdfViewer(productId, productDesc) {
    const viewerModal = document.getElementById('modal-pdf-viewer');
    const iframe = document.getElementById('pdf-viewer-iframe');
    const htmlContainer = document.getElementById('doc-viewer-html-container');
    const title = document.getElementById('pdf-viewer-title');
    const subtitle = document.getElementById('pdf-viewer-subtitle');
    const deleteBtn = document.getElementById('btn-delete-pdf-from-viewer');

    iframe.style.display = 'block';
    if (htmlContainer) {
        htmlContainer.style.display = 'none';
    }

    title.textContent = state.currentLanguage === 'en' ? `Product Datasheet: ${productDesc}` : `คู่มือสเปกสินค้า: ${productDesc}`;
    if (subtitle) {
        subtitle.textContent = t('modal_viewer_subtitle');
    }

    // Set dynamic URL loading the binary stream from database
    const pdfUrl = withAuthToken(`${API_BASE}/products/${productId}/pdf`);
    iframe.src = pdfUrl;
    const newTabBtn = document.getElementById('btn-open-pdf-new-tab');
    if (newTabBtn) {
        newTabBtn.href = pdfUrl;
        newTabBtn.style.display = 'inline-flex';
    }

    // Admin or Super Admin only delete capability
    if (state.currentUser && (state.currentUser.role === 'admin' || state.currentUser.role === 'superadmin' || state.currentUser.role === 'supervisor' || state.currentUser.role === 'estimate')) {
        deleteBtn.style.display = 'inline-flex';
        // Remove previous listeners
        const newBtn = deleteBtn.cloneNode(true);
        deleteBtn.parentNode.replaceChild(newBtn, deleteBtn);
        newBtn.addEventListener('click', async () => {
            if (confirm(state.currentLanguage === 'en' ? `Are you sure you want to delete the PDF datasheet for "${productDesc}"?` : `คุณต้องการลบสเปกสินค้า PDF ของ "${productDesc}" ใช่หรือไม่?`)) {
                try {
                    await authFetch(`${API_BASE}/products/${productId}/pdf`, { method: 'DELETE' });
                    showToast(t('toast_pdf_deleted'));
                    closePdfViewer();
                    await filterManagerProducts();
                    if (state.activeProjectId) {
                        await fetchActiveProjectDetails();
                        renderWorkspace();
                    }
                } catch (err) {
                    showToast(state.currentLanguage === 'en' ? 'Failed to delete PDF datasheet' : 'ลบไฟล์สเปก PDF ไม่สำเร็จ', 'error');
                }
            }
        });
    } else {
        deleteBtn.style.display = 'none';
    }

    const editBtn = document.getElementById('btn-edit-pdf-datasheet');
    const saveBtn = document.getElementById('btn-save-pdf-datasheet');
    const cancelBtn = document.getElementById('btn-cancel-edit-pdf-datasheet');

    if (editBtn) {
        const canWrite = state.currentUser && (state.currentUser.role === 'admin' || state.currentUser.role === 'superadmin' || state.currentUser.role === 'supervisor' || state.currentUser.role === 'estimate');
        editBtn.style.display = canWrite ? 'inline-flex' : 'none';
        saveBtn.style.display = 'none';
        cancelBtn.style.display = 'none';

        const newEditBtn = editBtn.cloneNode(true);
        editBtn.parentNode.replaceChild(newEditBtn, editBtn);
        newEditBtn.addEventListener('click', () => {
            startPdfAnnotation(productId, withAuthToken(`${API_BASE}/products/${productId}/pdf`), productDesc);
        });
    }

    viewerModal.classList.add('active');
}

function openProjectPdfViewer(projectId, type, filename) {
    const viewerModal = document.getElementById('modal-pdf-viewer');
    const iframe = document.getElementById('pdf-viewer-iframe');
    const htmlContainer = document.getElementById('doc-viewer-html-container');
    const title = document.getElementById('pdf-viewer-title');
    const subtitle = document.getElementById('pdf-viewer-subtitle');
    const deleteBtn = document.getElementById('btn-delete-pdf-from-viewer');

    iframe.style.display = 'block';
    if (htmlContainer) {
        htmlContainer.style.display = 'none';
    }

    title.textContent = state.currentLanguage === 'en'
        ? (type === 'drawing' ? `Project Drawing: ${filename}` : `Project Specification: ${filename}`)
        : (type === 'drawing' ? `แบบแปลนโครงการ: ${filename}` : `สเปกโครงการ: ${filename}`);
    if (subtitle) {
        subtitle.textContent = state.currentLanguage === 'en'
            ? (type === 'drawing' ? 'Project Drawing (PDF)' : 'Project Specification Sheet (PDF)')
            : (type === 'drawing' ? 'แบบแปลนโครงการ (PDF)' : 'เอกสารสเปกโครงการ (PDF)');
    }

    const pdfUrl = withAuthToken(`${API_BASE}/projects/${projectId}/${type}`);
    iframe.src = pdfUrl;
    const newTabBtn = document.getElementById('btn-open-pdf-new-tab');
    if (newTabBtn) {
        newTabBtn.href = pdfUrl;
        newTabBtn.style.display = 'inline-flex';
    }
    deleteBtn.style.display = 'none';

    viewerModal.classList.add('active');
}

function closePdfViewer() {
    const viewerModal = document.getElementById('modal-pdf-viewer');
    const iframe = document.getElementById('pdf-viewer-iframe');
    const htmlContainer = document.getElementById('doc-viewer-html-container');
    const annoContainer = document.getElementById('pdf-annotation-container');
    
    const editBtn = document.getElementById('btn-edit-pdf-datasheet');
    const saveBtn = document.getElementById('btn-save-pdf-datasheet');
    const cancelBtn = document.getElementById('btn-cancel-edit-pdf-datasheet');

    // Clear src to stop browser resource loading in background
    iframe.src = '';
    const newTabBtn = document.getElementById('btn-open-pdf-new-tab');
    if (newTabBtn) {
        newTabBtn.href = '';
        newTabBtn.style.display = 'none';
    }
    if (htmlContainer) {
        htmlContainer.innerHTML = '';
    }

    iframe.style.display = 'block';
    if (htmlContainer) htmlContainer.style.display = 'none';
    if (annoContainer) annoContainer.style.display = 'none';

    if (editBtn) editBtn.style.display = 'none';
    if (saveBtn) saveBtn.style.display = 'none';
    if (cancelBtn) cancelBtn.style.display = 'none';

    // Reset editing state
    annoPdfDoc = null;
    annoDrawingData = {};

    viewerModal.classList.remove('active');
}

// ==========================================
// PDF Annotation State & Actions (Highlighting & Pen Tool)
// ==========================================
let annoPdfDoc = null;
let annoCurrentPage = 1;
let annoTotalPages = 1;
let annoDrawingData = {}; // pageNum -> DataURL string
let annoIsDrawing = false;
let annoCurrentTool = 'highlight'; // 'highlight', 'pen', 'eraser'
let annoCurrentColor = '#ffff00';
let annoCurrentSize = 10;
let annoPdfUrl = '';
let annoProductId = null;
let annoLastX = 0;
let annoLastY = 0;

async function startPdfAnnotation(productId, url, productDesc) {
    annoProductId = productId;
    annoPdfUrl = url;
    
    showToast(state.currentLanguage === 'en' ? 'Loading PDF for editing...' : 'กำลังโหลด PDF เพื่อไฮไลต์...');
    
    try {
        pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.worker.min.js';
        annoPdfDoc = await pdfjsLib.getDocument(url).promise;
        annoTotalPages = annoPdfDoc.numPages;
        annoCurrentPage = 1;
        annoDrawingData = {};
        
        // Hide iframe, show annotation workbench
        document.getElementById('pdf-viewer-iframe').style.display = 'none';
        document.getElementById('pdf-annotation-container').style.display = 'flex';
        
        // Update title
        document.getElementById('pdf-viewer-title').textContent = state.currentLanguage === 'en' ? `Edit Datasheet: ${productDesc}` : `แก้ไขและไฮไลต์สเปก: ${productDesc}`;

        // Toggle header buttons
        document.getElementById('btn-edit-pdf-datasheet').style.display = 'none';
        document.getElementById('btn-save-pdf-datasheet').style.display = 'inline-flex';
        document.getElementById('btn-cancel-edit-pdf-datasheet').style.display = 'inline-flex';
        document.getElementById('btn-delete-pdf-from-viewer').style.display = 'none';

        // Reset tool defaults
        setAnnoTool('highlight');

        // Render page 1
        await annoRenderPage(1);
        
    } catch (err) {
        console.error(err);
        showToast(state.currentLanguage === 'en' ? 'Failed to load PDF for editing' : 'โหลด PDF เพื่อแก้ไขไม่สำเร็จ', 'error');
    }
}

async function annoRenderPage(pageNum) {
    annoCurrentPage = pageNum;
    document.getElementById('anno-page-num').textContent = state.currentLanguage === 'en' ? `Page ${pageNum} / ${annoTotalPages}` : `หน้า ${pageNum} / ${annoTotalPages}`;
    
    const page = await annoPdfDoc.getPage(pageNum);
    const viewport = page.getViewport({ scale: 1.5 });
    
    const pdfCanvas = document.getElementById('pdf-canvas');
    const pdfCtx = pdfCanvas.getContext('2d');
    pdfCanvas.width = viewport.width;
    pdfCanvas.height = viewport.height;
    
    const drawingCanvas = document.getElementById('drawing-canvas');
    const drawingCtx = drawingCanvas.getContext('2d');
    drawingCanvas.width = viewport.width;
    drawingCanvas.height = viewport.height;
    
    // Render PDF page into pdfCanvas
    await page.render({ canvasContext: pdfCtx, viewport: viewport }).promise;
    
    // Clear drawing canvas and load saved drawing for this page if any
    drawingCtx.clearRect(0, 0, drawingCanvas.width, drawingCanvas.height);
    if (annoDrawingData[pageNum]) {
        const img = new Image();
        img.onload = () => {
            drawingCtx.drawImage(img, 0, 0);
        };
        img.src = annoDrawingData[pageNum];
    }
}

async function saveAnnotatedPdf() {
    showToast(state.currentLanguage === 'en' ? 'Generating PDF...' : 'กำลังประมวลผลไฟล์ PDF...');
    try {
        const { jsPDF } = window.jspdf;
        
        const refCanvas = document.getElementById('pdf-canvas');
        const pdf = new jsPDF({
            orientation: refCanvas.width > refCanvas.height ? 'landscape' : 'portrait',
            unit: 'px',
            format: [refCanvas.width, refCanvas.height]
        });
        
        for (let i = 1; i <= annoTotalPages; i++) {
            if (i > 1) {
                pdf.addPage([refCanvas.width, refCanvas.height]);
            }
            
            const page = await annoPdfDoc.getPage(i);
            const viewport = page.getViewport({ scale: 1.5 });
            
            const tempCanvas = document.createElement('canvas');
            tempCanvas.width = viewport.width;
            tempCanvas.height = viewport.height;
            const tempCtx = tempCanvas.getContext('2d');
            
            // Draw PDF page content
            await page.render({ canvasContext: tempCtx, viewport: viewport }).promise;
            
            // Draw overlay highlights/annotations if any
            if (annoDrawingData[i]) {
                await new Promise((resolve) => {
                    const img = new Image();
                    img.onload = () => {
                        tempCtx.drawImage(img, 0, 0);
                        resolve();
                    };
                    img.src = annoDrawingData[i];
                });
            }
            
            const imgData = tempCanvas.toDataURL('image/jpeg', 0.9);
            pdf.addImage(imgData, 'JPEG', 0, 0, refCanvas.width, refCanvas.height);
        }
        
        const pdfBlob = pdf.output('blob');
        
        // Upload the new PDF blob back to the server product endpoint
        const formData = new FormData();
        formData.append('pdf', pdfBlob, `datasheet-edited-${Date.now()}.pdf`);
        
        showToast(state.currentLanguage === 'en' ? 'Uploading edited datasheet...' : 'กำลังอัปโหลดไฟล์คู่มือใหม่...');
        
        const response = await authFetch(`${API_BASE}/products/${annoProductId}/upload-pdf`, {
            method: 'POST',
            body: formData
        });
        
        if (!response.ok) {
            throw new Error(state.currentLanguage === 'en' ? 'Upload failed' : 'อัปโหลดไม่สำเร็จ');
        }
        
        showToast(state.currentLanguage === 'en' ? 'Datasheet successfully annotated and saved!' : 'บันทึกการไฮไลต์สเปกเรียบร้อยแล้ว!');
        
        // Reload products view and close viewer
        await filterManagerProducts();
        if (state.activeProjectId) {
            await fetchActiveProjectDetails();
            renderWorkspace();
        }
        
        closePdfViewer();
        
    } catch (err) {
        console.error(err);
        showToast(state.currentLanguage === 'en' ? 'Failed to save annotated PDF' : 'เกิดข้อผิดพลาดในการบันทึกไฟล์ PDF', 'error');
    }
}

function cancelPdfEdit() {
    // Hide annotation container, show iframe
    document.getElementById('pdf-annotation-container').style.display = 'none';
    document.getElementById('pdf-viewer-iframe').style.display = 'block';
    
    // Toggle header buttons
    const deleteBtn = document.getElementById('btn-delete-pdf-from-viewer');
    const role = state.currentUser ? state.currentUser.role : 'user';
    const canWrite = ['admin', 'superadmin', 'supervisor', 'estimate'].includes(role);
    
    document.getElementById('btn-edit-pdf-datasheet').style.display = canWrite ? 'inline-flex' : 'none';
    document.getElementById('btn-save-pdf-datasheet').style.display = 'none';
    document.getElementById('btn-cancel-edit-pdf-datasheet').style.display = 'none';
    document.getElementById('btn-delete-pdf-from-viewer').style.display = canWrite ? 'inline-flex' : 'none';
    
    // Reset title back
    const title = document.getElementById('pdf-viewer-title');
    title.textContent = state.currentLanguage === 'en' ? 'Product Datasheet' : 'เปิดดูคู่มือเทคนิคสินค้า';

    // Clear state
    annoPdfDoc = null;
    annoDrawingData = {};
}

function initPdfAnnotationEvents() {
    const drawingCanvas = document.getElementById('drawing-canvas');
    if (!drawingCanvas) return;
    
    const ctx = drawingCanvas.getContext('2d');
    
    function getMousePos(e) {
        const rect = drawingCanvas.getBoundingClientRect();
        const clientX = e.touches ? e.touches[0].clientX : e.clientX;
        const clientY = e.touches ? e.touches[0].clientY : e.clientY;
        return {
            x: ((clientX - rect.left) / rect.width) * drawingCanvas.width,
            y: ((clientY - rect.top) / rect.height) * drawingCanvas.height
        };
    }
    
    function startDrawing(e) {
        e.preventDefault();
        annoIsDrawing = true;
        const pos = getMousePos(e);
        annoLastX = pos.x;
        annoLastY = pos.y;
    }
    
    function draw(e) {
        if (!annoIsDrawing) return;
        e.preventDefault();
        const pos = getMousePos(e);
        
        ctx.beginPath();
        ctx.moveTo(annoLastX, annoLastY);
        ctx.lineTo(pos.x, pos.y);
        
        if (annoCurrentTool === 'highlight') {
            ctx.globalCompositeOperation = 'source-over';
            ctx.strokeStyle = annoCurrentColor;
            ctx.lineWidth = annoCurrentSize;
            ctx.globalAlpha = 0.4;
            ctx.lineCap = 'round';
            ctx.lineJoin = 'round';
        } else if (annoCurrentTool === 'pen') {
            ctx.globalCompositeOperation = 'source-over';
            ctx.strokeStyle = annoCurrentColor;
            ctx.lineWidth = annoCurrentSize;
            ctx.globalAlpha = 1.0;
            ctx.lineCap = 'round';
            ctx.lineJoin = 'round';
        } else if (annoCurrentTool === 'eraser') {
            ctx.globalCompositeOperation = 'destination-out';
            ctx.lineWidth = annoCurrentSize;
            ctx.globalAlpha = 1.0;
            ctx.lineCap = 'round';
            ctx.lineJoin = 'round';
        }
        
        ctx.stroke();
        
        annoLastX = pos.x;
        annoLastY = pos.y;
    }
    
    function stopDrawing() {
        if (annoIsDrawing) {
            annoIsDrawing = false;
            annoDrawingData[annoCurrentPage] = drawingCanvas.toDataURL();
        }
    }
    
    drawingCanvas.addEventListener('mousedown', startDrawing);
    drawingCanvas.addEventListener('mousemove', draw);
    drawingCanvas.addEventListener('mouseup', stopDrawing);
    drawingCanvas.addEventListener('mouseout', stopDrawing);
    
    drawingCanvas.addEventListener('touchstart', startDrawing, { passive: false });
    drawingCanvas.addEventListener('touchmove', draw, { passive: false });
    drawingCanvas.addEventListener('touchend', stopDrawing);
    
    document.getElementById('btn-anno-tool-highlight').addEventListener('click', () => {
        setAnnoTool('highlight');
    });
    document.getElementById('btn-anno-tool-pen').addEventListener('click', () => {
        setAnnoTool('pen');
    });
    document.getElementById('btn-anno-tool-eraser').addEventListener('click', () => {
        setAnnoTool('eraser');
    });
    document.getElementById('btn-anno-clear').addEventListener('click', () => {
        if (confirm(state.currentLanguage === 'en' ? 'Are you sure you want to clear all drawings on this page?' : 'คุณต้องการล้างรูปวาดทั้งหมดในหน้านี้ใช่หรือไม่?')) {
            ctx.clearRect(0, 0, drawingCanvas.width, drawingCanvas.height);
            delete annoDrawingData[annoCurrentPage];
        }
    });
    
    const colorInput = document.getElementById('anno-color');
    colorInput.addEventListener('input', (e) => {
        annoCurrentColor = e.target.value;
    });
    
    const sizeSelect = document.getElementById('anno-size');
    sizeSelect.addEventListener('change', (e) => {
        annoCurrentSize = parseInt(e.target.value);
    });
    
    document.getElementById('btn-anno-prev').addEventListener('click', async () => {
        if (annoCurrentPage > 1) {
            annoDrawingData[annoCurrentPage] = drawingCanvas.toDataURL();
            await annoRenderPage(annoCurrentPage - 1);
        }
    });
    
    document.getElementById('btn-anno-next').addEventListener('click', async () => {
        if (annoCurrentPage < annoTotalPages) {
            annoDrawingData[annoCurrentPage] = drawingCanvas.toDataURL();
            await annoRenderPage(annoCurrentPage + 1);
        }
    });
}

function setAnnoTool(tool) {
    annoCurrentTool = tool;
    document.getElementById('btn-anno-tool-highlight').classList.remove('active');
    document.getElementById('btn-anno-tool-pen').classList.remove('active');
    document.getElementById('btn-anno-tool-eraser').classList.remove('active');
    
    if (tool === 'highlight') {
        document.getElementById('btn-anno-tool-highlight').classList.add('active');
        document.getElementById('anno-color').value = '#ffff00';
        annoCurrentColor = '#ffff00';
    } else if (tool === 'pen') {
        document.getElementById('btn-anno-tool-pen').classList.add('active');
        document.getElementById('anno-color').value = '#ff0000';
        annoCurrentColor = '#ff0000';
    } else if (tool === 'eraser') {
        document.getElementById('btn-anno-tool-eraser').classList.add('active');
    }
}

// Function to preview documents (PDF, Word, Excel) inside the app
function openDocumentPreview(docId, fileName, fileType, isTestScript = false) {
    const viewerModal = document.getElementById('modal-pdf-viewer');
    const iframe = document.getElementById('pdf-viewer-iframe');
    const htmlContainer = document.getElementById('doc-viewer-html-container');
    const title = document.getElementById('pdf-viewer-title');
    const subtitle = document.getElementById('pdf-viewer-subtitle');
    const deleteBtn = document.getElementById('btn-delete-pdf-from-viewer');

    title.textContent = state.currentLanguage === 'en' ? `Preview File: ${fileName}` : `แสดงตัวอย่างไฟล์: ${fileName}`;
    if (subtitle) {
        subtitle.textContent = isTestScript
            ? (state.currentLanguage === 'en' ? 'Test Script Preview' : 'ตัวอย่างแนวทางการทดสอบ')
            : (state.currentLanguage === 'en' ? 'Project Document Preview' : 'ตัวอย่างเอกสารโครงการ');
    }
    deleteBtn.style.display = 'none';

    const type = fileType.toLowerCase();
    const url = isTestScript ? `${API_BASE}/test-scripts/files/${docId}` : `${API_BASE}/documents/${docId}`;

    if (type === 'pdf') {
        iframe.style.display = 'block';
        htmlContainer.style.display = 'none';
        const pdfUrl = withAuthToken(url);
        iframe.src = pdfUrl;
        const newTabBtn = document.getElementById('btn-open-pdf-new-tab');
        if (newTabBtn) {
            newTabBtn.href = pdfUrl;
            newTabBtn.style.display = 'inline-flex';
        }
        viewerModal.classList.add('active');
    } else if (['png', 'jpg', 'jpeg', 'gif', 'webp'].includes(type)) {
        iframe.style.display = 'none';
        htmlContainer.style.display = 'block';
        htmlContainer.innerHTML = `<div style="text-align:center; padding:10px;"><img src="${withAuthToken(url)}" style="max-width:100%; max-height:70vh; object-fit:contain; border:1px solid var(--border-color); border-radius:var(--radius-sm);"></div>`;
        viewerModal.classList.add('active');
    } else if (['docx', 'xlsx', 'xls'].includes(type)) {
        iframe.style.display = 'none';
        htmlContainer.style.display = 'block';
        htmlContainer.innerHTML = `<div style="padding:40px; text-align:center; color:var(--text-muted);"><i class="fa-solid fa-spinner fa-spin" style="font-size:2rem; margin-bottom:10px; color:var(--primary-color);"></i><p>กำลังโหลดเอกสาร...</p></div>`;
        viewerModal.classList.add('active');

        authFetch(url)
            .then(res => {
                if (!res.ok) throw new Error('Failed to load file');
                return res.arrayBuffer();
            })
            .then(arrayBuffer => {
                if (type === 'docx') {
                    // Render DOCX using Mammoth
                    mammoth.convertToHtml({ arrayBuffer: arrayBuffer })
                        .then(result => {
                            htmlContainer.innerHTML = `<div class="docx-preview-content" style="max-width:800px; margin:0 auto; color:var(--text-dark); line-height:1.6; font-size:0.95rem; text-align:left;">${result.value || '<p style="text-align:center; color:var(--text-muted);">ไม่มีเนื้อหาในเอกสารนี้</p>'}</div>`;
                        })
                        .catch(err => {
                            console.error(err);
                            htmlContainer.innerHTML = `<div style="padding:40px; text-align:center; color:var(--text-muted);"><i class="fa-solid fa-circle-exclamation" style="font-size:2rem; margin-bottom:10px; color:var(--danger);"></i><p>ไม่สามารถแปลงเอกสาร Word นี้ได้ กรุณาดาวน์โหลดเพื่อเปิดดู</p></div>`;
                        });
                } else {
                    // Render Excel using SheetJS
                    const data = new Uint8Array(arrayBuffer);
                    const workbook = XLSX.read(data, { type: 'array' });
                    htmlContainer.innerHTML = '';

                    if (workbook.SheetNames.length > 0) {
                        const tabsContainer = document.createElement('div');
                        tabsContainer.style.display = 'flex';
                        tabsContainer.style.gap = '8px';
                        tabsContainer.style.marginBottom = '20px';
                        tabsContainer.style.borderBottom = '2px solid var(--border-color)';
                        tabsContainer.style.paddingBottom = '8px';
                        tabsContainer.style.overflowX = 'auto';

                        const sheetsContentContainer = document.createElement('div');

                        workbook.SheetNames.forEach((sheetName, index) => {
                            const tabBtn = document.createElement('button');
                            tabBtn.className = 'btn btn-sm ' + (index === 0 ? 'btn-primary' : 'btn-outline');
                            tabBtn.style.padding = '4px 12px';
                            tabBtn.style.fontSize = '0.8rem';
                            tabBtn.textContent = sheetName;

                            const sheet = workbook.Sheets[sheetName];
                            const htmlTable = (sheet && sheet['!ref']) 
                                ? XLSX.utils.sheet_to_html(sheet, { header: '', footer: '' }) 
                                : `<div style="padding: 20px; text-align: center; color: var(--text-muted);">${state.currentLanguage === 'en' ? 'No data in this sheet' : 'ไม่มีข้อมูลในชีทนี้'}</div>`;

                            const sheetDiv = document.createElement('div');
                            sheetDiv.style.display = index === 0 ? 'block' : 'none';
                            sheetDiv.style.overflow = 'auto';
                            sheetDiv.innerHTML = `<div class="excel-table-wrapper" style="width:100%; border: 1px solid var(--border-color); border-radius: var(--radius-sm); overflow:auto;">${htmlTable}</div>`;
                            sheetsContentContainer.appendChild(sheetDiv);

                            tabBtn.addEventListener('click', () => {
                                Array.from(tabsContainer.children).forEach(btn => {
                                    btn.className = 'btn btn-sm btn-outline';
                                });
                                tabBtn.className = 'btn btn-sm btn-primary';

                                Array.from(sheetsContentContainer.children).forEach(div => {
                                    div.style.display = 'none';
                                });
                                sheetDiv.style.display = 'block';
                            });

                            tabsContainer.appendChild(tabBtn);
                        });

                        htmlContainer.appendChild(tabsContainer);
                        htmlContainer.appendChild(sheetsContentContainer);

                        const styleEl = document.createElement('style');
                        styleEl.innerHTML = `
                            .excel-table-wrapper table {
                                width: 100%;
                                border-collapse: collapse;
                                font-size: 0.85rem;
                            }
                            .excel-table-wrapper th, .excel-table-wrapper td {
                                border: 1px solid #e2e8f0;
                                padding: 8px 12px;
                                text-align: left;
                                white-space: nowrap;
                            }
                            .excel-table-wrapper tr:nth-child(even) {
                                background-color: #f8fafc;
                            }
                        `;
                        htmlContainer.appendChild(styleEl);
                    } else {
                        htmlContainer.innerHTML = `<p style="text-align:center; color:var(--text-muted); padding:40px;">ไม่มีหน้าชีทในเอกสาร Excel นี้</p>`;
                    }
                }
            })
            .catch(err => {
                console.error(err);
                htmlContainer.innerHTML = `<div style="padding:40px; text-align:center; color:var(--text-muted);"><i class="fa-solid fa-circle-exclamation" style="font-size:2rem; margin-bottom:10px; color:var(--danger);"></i><p>ไม่สามารถดาวน์โหลดไฟล์เพื่อแสดงตัวอย่างได้ กรุณาดาวน์โหลดผ่านปุ่มด้านข้าง</p></div>`;
            });
    } else {
        // Unsupported preview types (e.g. .doc, .zip, .rar, .dwg)
        iframe.style.display = 'none';
        htmlContainer.style.display = 'block';
        htmlContainer.innerHTML = `
            <div style="padding:40px; text-align:center; color:var(--text-muted);">
                <i class="fa-solid fa-file-circle-exclamation" style="font-size:3rem; margin-bottom:15px; color:var(--warning);"></i>
                <h4 style="margin-bottom:8px; color:var(--text-dark);">ไม่สามารถแสดงตัวอย่างไฟล์นี้ได้</h4>
                <p>ไฟล์ประเภท .${type} ไม่รองรับการเปิดอ่านในหน้าต่างแอปโดยตรง กรุณาดาวน์โหลดเพื่อเปิดดู</p>
                <a href="${url}" download class="btn btn-primary btn-sm" style="margin-top:15px; display:inline-flex; align-items:center; gap:8px;">
                    <i class="fa-solid fa-download"></i> ดาวน์โหลดไฟล์
                </a>
            </div>
        `;
        viewerModal.classList.add('active');
    }
}

function openSectionPdfViewer(sectionId, sectionName) {
    const viewerModal = document.getElementById('modal-pdf-viewer');
    const iframe = document.getElementById('pdf-viewer-iframe');
    const htmlContainer = document.getElementById('doc-viewer-html-container');
    const title = document.getElementById('pdf-viewer-title');
    const subtitle = document.getElementById('pdf-viewer-subtitle');
    const deleteBtn = document.getElementById('btn-delete-pdf-from-viewer');

    iframe.style.display = 'block';
    if (htmlContainer) {
        htmlContainer.style.display = 'none';
    }

    title.textContent = state.currentLanguage === 'en' ? `Section Spec: ${sectionName}` : `เอกสารสเปกส่วนย่อย: ${sectionName}`;
    if (subtitle) {
        subtitle.textContent = state.currentLanguage === 'en' ? 'Technical Specification Sheet for this Project Sub-section' : 'เอกสารรายละเอียดทางเทคนิคสำหรับส่วนย่อยโครงการนี้';
    }

    const pdfUrl = withAuthToken(`${API_BASE}/sections/${sectionId}/spec`);
    iframe.src = pdfUrl;
    const newTabBtn = document.getElementById('btn-open-pdf-new-tab');
    if (newTabBtn) {
        newTabBtn.href = pdfUrl;
        newTabBtn.style.display = 'inline-flex';
    }

    const role = state.currentUser ? state.currentUser.role : 'user';
    if (role === 'admin' || role === 'superadmin' || role === 'supervisor' || role === 'estimate') {
        deleteBtn.style.display = 'inline-flex';
        const newBtn = deleteBtn.cloneNode(true);
        deleteBtn.parentNode.replaceChild(newBtn, deleteBtn);
        newBtn.addEventListener('click', async () => {
            if (confirm(state.currentLanguage === 'en' ? `Are you sure you want to delete the spec PDF for "${sectionName}"?` : `คุณต้องการลบสเปก PDF ของส่วนย่อย "${sectionName}" ใช่หรือไม่?`)) {
                try {
                    const res = await authFetch(`${API_BASE}/sections/${sectionId}/spec`, { method: 'DELETE' });
                    if (!res.ok) throw new Error('Delete failed');
                    showToast(state.currentLanguage === 'en' ? 'Section spec PDF deleted successfully' : 'ลบเอกสารสเปกส่วนย่อยสำเร็จแล้ว');
                    closePdfViewer();
                    await fetchActiveProjectDetails();
                    renderWorkspace();
                } catch (err) {
                    console.error(err);
                    showToast(state.currentLanguage === 'en' ? 'Failed to delete section spec' : 'ไม่สามารถลบเอกสารสเปกได้', 'error');
                }
            }
        });
    } else {
        deleteBtn.style.display = 'none';
    }

    viewerModal.classList.add('active');
}

async function handleSectionSpecUpload(event, sectionId) {
    const file = event.target.files[0];
    if (!file) return;

    if (file.type !== 'application/pdf') {
        showToast(state.currentLanguage === 'en' ? 'Only PDF files are allowed' : 'อนุญาตเฉพาะไฟล์ PDF เท่านั้น', 'danger');
        return;
    }

    const formData = new FormData();
    formData.append('spec', file);

    try {
        showToast(state.currentLanguage === 'en' ? 'Uploading section spec...' : 'กำลังอัปโหลดเอกสารสเปก...', 'info');
        const res = await authFetch(`${API_BASE}/sections/${sectionId}/spec`, {
            method: 'POST',
            body: formData
        });

        if (!res.ok) {
            const err = await res.json();
            throw new Error(err.error || 'Upload failed');
        }

        showToast(state.currentLanguage === 'en' ? 'Section spec PDF uploaded successfully' : 'อัปโหลดเอกสารสเปกส่วนย่อยสำเร็จแล้ว');
        await fetchActiveProjectDetails();
        renderWorkspace();
    } catch (err) {
        console.error(err);
        showToast(err.message, 'danger');
    }
}

// ==========================================
// Project Approval Attachments Modal
// ==========================================

async function openApprovalAttachmentsModal() {
    if (!state.activeProjectId || !state.activeProjectSummary) return;

    const tbody = document.getElementById('attachments-list-tbody');
    tbody.innerHTML = '';

    // Query items in active project subsections
    try {
        const sections = state.activeProjectSummary.sections || [];
        const uniqueProducts = new Map();

        for (let sec of sections) {
            const res = await authFetch(`${API_BASE}/sections/${sec.id}/items`);
            const items = await res.json();

            items.forEach(item => {
                if (item.has_pdf && item.product_id) {
                    uniqueProducts.set(item.product_id, {
                        id: item.product_id,
                        brand: item.brand,
                        description: item.description,
                        type: item.type,
                        model: item.model
                    });
                }
            });
        }

        const productsList = Array.from(uniqueProducts.values());
        const sectionSpecs = sections.filter(s => !!s.spec_name);

        if (productsList.length === 0 && sectionSpecs.length === 0) {
            const noAttachmentsText = state.currentLanguage === 'en'
                ? 'No products or subsections in this quotation have a technical manual (PDF Datasheet) attached.'
                : 'ไม่มีสินค้าหรือส่วนย่อยใดในเอกสารเสนอราคานี้ที่มีเอกสารข้อมูลเทคนิค (PDF) แนบไว้';
            tbody.innerHTML = `
                <tr>
                    <td colspan="3" style="padding:30px; text-align:center; color:var(--text-muted);">
                        <i class="fa-solid fa-file-excel" style="font-size:1.5rem; margin-bottom:8px; display:block;">
                        </i>${noAttachmentsText}
                    </td>
                </tr>`;
        } else {
            // Render section specs
            sectionSpecs.forEach(sec => {
                const tr = document.createElement('tr');
                tr.innerHTML = `
                    <td><b>${state.currentLanguage === 'en' ? 'System Spec' : 'เอกสารแนบระบบงาน'}</b></td>
                    <td>
                        <div style="font-weight:500;">${escapeHtml(sec.name)} (Specification)</div>
                        <div style="font-size:0.75rem; color:var(--text-muted); margin-top:2px;">
                            ${state.currentLanguage === 'en' ? 'Filename' : 'ชื่อไฟล์'}: ${escapeHtml(sec.spec_name)}
                        </div>
                    </td>
                    <td class="text-center">
                        <div style="display:flex; justify-content:center; gap:8px;">
                            <button class="btn btn-outline btn-sm" onclick="openSectionPdfViewer(${sec.id}, '${escapeJsString(sec.name)}')">
                                <i class="fa-solid fa-eye"></i> ${state.currentLanguage === 'en' ? 'View' : 'เปิดดู'}
                            </button>
                            <a href="${withAuthToken(`${API_BASE}/sections/${sec.id}/spec`)}" download class="btn btn-primary btn-sm" style="text-decoration:none;">
                                <i class="fa-solid fa-download"></i> ${state.currentLanguage === 'en' ? 'Download' : 'โหลด'}
                            </a>
                        </div>
                    </td>
                `;
                tbody.appendChild(tr);
            });

            // Render product specs
            productsList.forEach(p => {
                const tr = document.createElement('tr');
                tr.innerHTML = `
                    <td><b>${escapeHtml(p.brand || '-')}</b></td>
                    <td>
                        <div style="font-weight:500;">${escapeHtml(p.description)}</div>
                        <div style="font-size:0.75rem; color:var(--text-muted); margin-top:2px;">
                            ${state.currentLanguage === 'en' ? 'Model' : 'รุ่น'}: ${escapeHtml(p.model || '-')} | 
                            ${state.currentLanguage === 'en' ? 'Type' : 'ประเภท'}: ${escapeHtml(p.type || '-')}
                        </div>
                    </td>
                    <td class="text-center">
                        <div style="display:flex; justify-content:center; gap:8px;">
                            <button class="btn btn-outline btn-sm" onclick="openPdfViewer(${p.id}, '${escapeJsString(p.description)}')">
                                <i class="fa-solid fa-eye"></i> ${state.currentLanguage === 'en' ? 'View' : 'เปิดดู'}
                            </button>
                            <a href="${withAuthToken(`${API_BASE}/products/${p.id}/pdf`)}" download class="btn btn-primary btn-sm" style="text-decoration:none;">
                                <i class="fa-solid fa-download"></i> ${state.currentLanguage === 'en' ? 'Download' : 'โหลด'}
                            </a>
                        </div>
                    </td>
                `;
                tbody.appendChild(tr);
            });
        }

        document.getElementById('modal-approval-attachments').classList.add('active');
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Error loading attachments list' : 'เกิดข้อผิดพลาดในการโหลดรายการเอกสารแนบ', 'error');
    }
}

function closeApprovalAttachmentsModal() {
    document.getElementById('modal-approval-attachments').classList.remove('active');
}

// ==========================================
// Project Document Vault & File Explorer Controls
// ==========================================

async function openProjectDocsModal() {
    if (!state.activeProjectId || !state.activeProjectSummary) return;

    // Set title
    document.getElementById('project-docs-title').textContent =
        state.currentLanguage === 'en'
            ? `Project Documents Vault: ${state.activeProjectSummary.name}`
            : `คลังเอกสารประกอบโครงการ: ${state.activeProjectSummary.name}`;

    // Reset folder path to root
    state.currentDocFolderPath = '/';
    document.getElementById('input-search-docs').value = ''; // clear search

    // Hide write controls for contractor
    const isContractor = state.currentUser && state.currentUser.role === 'contractor';
    const createFolderBtn = document.getElementById('btn-create-doc-folder');
    const dropzone = document.getElementById('docs-drop-zone');
    if (createFolderBtn) createFolderBtn.style.display = isContractor ? 'none' : 'inline-flex';
    if (dropzone) dropzone.style.display = isContractor ? 'none' : 'flex';

    // Load documents
    await fetchActiveProjectDocs();

    // Render
    renderProjectDocs();

    // Open modal
    document.getElementById('modal-project-docs').classList.add('active');
}

function closeProjectDocsModal() {
    document.getElementById('modal-project-docs').classList.remove('active');
}

async function fetchActiveProjectDocs() {
    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/documents`);
        if (!res.ok) throw new Error('Failed to fetch documents');
        state.activeProjectDocs = await res.json();
        updateProjectDocsBadge();
    } catch (err) {
        console.error(err);
        showToast(state.currentLanguage === 'en' ? 'Failed to load project documents' : 'โหลดเอกสารโครงการไม่สำเร็จ', 'error');
    }
}

function updateProjectDocsBadge() {
    const badge = document.getElementById('project-docs-count-badge');
    if (!badge) return;
    const files = state.activeProjectDocs && state.activeProjectDocs.files ? state.activeProjectDocs.files : [];
    if (files.length > 0) {
        badge.textContent = files.length;
        badge.style.display = 'inline-block';
    } else {
        badge.style.display = 'none';
    }
}

function renderProjectDocs() {
    const isContractor = state.currentUser && state.currentUser.role === 'contractor';
    const folders = state.activeProjectDocs.folders || [];
    const files = state.activeProjectDocs.files || [];
    const searchVal = document.getElementById('input-search-docs').value.toLowerCase().trim();

    // 1. Render sidebar folder list
    const folderList = document.getElementById('docs-folder-list');
    folderList.innerHTML = '';

    // Add Root "/" folder
    const rootActive = state.currentDocFolderPath === '/';
    const rootDiv = document.createElement('div');
    rootDiv.className = `docs-folder-item ${rootActive ? 'active' : ''}`;
    rootDiv.innerHTML = `
        <span style="display:flex; align-items:center; gap:8px; min-width:0; overflow:hidden;">
            <i class="fa-solid fa-folder" style="color:#eab308; flex-shrink:0;"></i>
            <span style="flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">Root (/)</span>
        </span>
    `;
    rootDiv.addEventListener('click', () => {
        state.currentDocFolderPath = '/';
        renderProjectDocs();
    });
    folderList.appendChild(rootDiv);

    // Helper function for hierarchical folder path comparison
    function compareFolderPaths(pathA, pathB) {
        const segmentsA = pathA.split('/').filter(p => !!p);
        const segmentsB = pathB.split('/').filter(p => !!p);
        const minLength = Math.min(segmentsA.length, segmentsB.length);

        for (let i = 0; i < minLength; i++) {
            const segA = segmentsA[i];
            const segB = segmentsB[i];
            if (segA.toLowerCase() !== segB.toLowerCase()) {
                return segA.localeCompare(segB, undefined, { sensitivity: 'base', numeric: true });
            }
        }
        return segmentsA.length - segmentsB.length;
    }

    // Sort folders hierarchically (groups subfolders under their parents)
    folders.sort((a, b) => compareFolderPaths(a.folder_path, b.folder_path));
    folders.forEach(f => {
        const isActive = state.currentDocFolderPath === f.folder_path;
        const div = document.createElement('div');
        div.className = `docs-folder-item ${isActive ? 'active' : ''}`;

        // Calculate depth of folder path for indentation (e.g. /CATALOG is 1, /CATALOG/customer is 2)
        const parts = f.folder_path.split('/').filter(p => !!p);
        const depth = parts.length;
        div.style.paddingLeft = `${depth * 16 + 12}px`;

        // Short name for displaying inside the folder list
        const folderName = f.folder_path.substring(f.folder_path.lastIndexOf('/') + 1);

        div.innerHTML = `
            <span style="display:flex; align-items:center; gap:8px; min-width:0; overflow:hidden;">
                <i class="fa-solid fa-folder" style="color:#eab308; flex-shrink:0;"></i>
                <span style="flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;" title="${escapeHtml(folderName)}">${escapeHtml(folderName)}</span>
            </span>
            <i class="fa-solid fa-trash-can folder-delete-btn" style="flex-shrink:0; ${isContractor ? 'display:none;' : ''}" title="${state.currentLanguage === 'en' ? 'Delete folder' : 'ลบโฟลเดอร์'}"></i>
        `;

        div.querySelector('span').addEventListener('click', (e) => {
            const searchInput = document.getElementById('input-search-docs');
            if (searchInput) searchInput.value = '';
            state.currentDocFolderPath = f.folder_path;
            renderProjectDocs();
        });

        div.querySelector('.folder-delete-btn').addEventListener('click', async (e) => {
            e.stopPropagation();
            if (confirm(state.currentLanguage === 'en'
                ? `Are you sure you want to delete folder "${folderName}" and ALL files inside it?`
                : `คุณแน่ใจหรือไม่ว่าต้องการลบโฟลเดอร์ "${folderName}" และไฟล์ทั้งหมดที่อยู่ข้างใน?`)) {
                try {
                    const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/folders?path=${encodeURIComponent(f.folder_path)}`, {
                        method: 'DELETE'
                    });
                    if (!res.ok) throw new Error('Delete failed');
                    showToast(state.currentLanguage === 'en' ? 'Folder deleted' : 'ลบโฟลเดอร์สำเร็จแล้ว');
                    if (state.currentDocFolderPath.startsWith(f.folder_path)) {
                        state.currentDocFolderPath = '/';
                    }
                    await fetchActiveProjectDocs();
                    renderProjectDocs();
                } catch (err) {
                    console.error(err);
                    showToast(err.message, 'danger');
                }
            }
        });

        folderList.appendChild(div);
    });

    // 2. Render breadcrumbs
    const breadcrumbs = document.getElementById('docs-breadcrumb-container');
    breadcrumbs.innerHTML = '';

    const parts = state.currentDocFolderPath.split('/').filter(p => !!p);

    // Add Root breadcrumb
    const rootLink = document.createElement('span');
    rootLink.style.cursor = 'pointer';
    rootLink.style.color = 'var(--primary-color)';
    rootLink.innerHTML = `<i class="fa-solid fa-house" style="margin-right:4px;"></i>Root`;
    rootLink.addEventListener('click', () => {
        const searchInput = document.getElementById('input-search-docs');
        if (searchInput) searchInput.value = '';
        state.currentDocFolderPath = '/';
        renderProjectDocs();
    });
    breadcrumbs.appendChild(rootLink);

    let pathAcc = '';
    parts.forEach((part, index) => {
        pathAcc += '/' + part;

        const arrow = document.createElement('span');
        arrow.style.color = 'var(--text-muted)';
        arrow.innerHTML = ' <i class="fa-solid fa-chevron-right" style="font-size:0.75rem;"></i> ';
        breadcrumbs.appendChild(arrow);

        const partLink = document.createElement('span');
        const isLast = index === parts.length - 1;

        if (!isLast) {
            partLink.style.cursor = 'pointer';
            partLink.style.color = 'var(--primary-color)';
            const targetPath = pathAcc;
            partLink.addEventListener('click', () => {
                const searchInput = document.getElementById('input-search-docs');
                if (searchInput) searchInput.value = '';
                state.currentDocFolderPath = targetPath;
                renderProjectDocs();
            });
        } else {
            partLink.style.color = 'var(--text-dark)';
            partLink.style.fontWeight = '600';
        }
        partLink.textContent = part;
        breadcrumbs.appendChild(partLink);
    });

    // 3. Render files/subfolders in table
    const tbody = document.getElementById('project-docs-tbody');
    tbody.innerHTML = '';

    // Filter files in this current folder path
    let currentFiles = files.filter(f => f.file_path === state.currentDocFolderPath);

    // Filter folders that are direct children of this current folder path
    let childFolders = [];
    folders.forEach(f => {
        if (f.folder_path === state.currentDocFolderPath) return;

        if (state.currentDocFolderPath === '/') {
            const relative = f.folder_path.substring(1);
            if (!relative.includes('/')) {
                childFolders.push(f);
            }
        } else {
            if (f.folder_path.startsWith(state.currentDocFolderPath + '/')) {
                const relative = f.folder_path.substring(state.currentDocFolderPath.length + 1);
                if (!relative.includes('/')) {
                    childFolders.push(f);
                }
            }
        }
    });

    // Apply search filter
    if (searchVal) {
        currentFiles = files.filter(f => f.file_name.toLowerCase().includes(searchVal));
        childFolders = []; // hide subfolders in search results
    }

    // Render parent directory ".." row if not in root
    if (state.currentDocFolderPath !== '/' && !searchVal) {
        const tr = document.createElement('tr');
        tr.className = 'folder-row';
        tr.innerHTML = `
            <td colspan="6" style="padding:12px 10px;">
                <div style="display:flex; align-items:center; gap:10px; width:100%;">
                    <i class="fa-solid fa-arrow-turn-up" style="transform:rotate(-90deg); color:var(--primary-color); font-size:1.1rem; flex-shrink:0;"></i>
                    <span style="font-weight:600; font-size:0.95rem; color:var(--primary-color);">.. (Parent Directory)</span>
                </div>
            </td>
        `;
        tr.addEventListener('click', () => {
            const searchInput = document.getElementById('input-search-docs');
            if (searchInput) searchInput.value = '';
            const lastSlash = state.currentDocFolderPath.lastIndexOf('/');
            state.currentDocFolderPath = lastSlash === 0 ? '/' : state.currentDocFolderPath.substring(0, lastSlash);
            renderProjectDocs();
        });
        tbody.appendChild(tr);
    }

    // Render child subfolders
    childFolders.forEach(cf => {
        const folderName = cf.folder_path.substring(cf.folder_path.lastIndexOf('/') + 1);
        const tr = document.createElement('tr');
        tr.className = 'folder-row';
        tr.innerHTML = `
            <td style="padding:10px; font-weight:500;">
                <div style="display:flex; align-items:flex-start; gap:10px; width:100%;">
                    <i class="fa-solid fa-folder" style="color:#eab308; font-size:1.15rem; margin-top:2px; flex-shrink:0;"></i>
                    <span style="font-weight:600; font-size:0.95rem; color:var(--text-dark); word-break:break-word; line-height:1.4;" title="${escapeHtml(folderName)}">${escapeHtml(folderName)}</span>
                </div>
            </td>
            <td style="padding:10px;" class="text-right">-</td>
            <td style="padding:10px; color:var(--text-muted); font-size:0.8rem;">-</td>
            <td style="padding:10px; color:var(--text-muted); font-size:0.8rem;">-</td>
            <td style="padding:10px; color:var(--text-muted); font-size:0.8rem;">-</td>
            <td style="padding:10px;" class="text-center">
                <button class="btn btn-sm btn-outline btn-delete-folder-row" title="${state.currentLanguage === 'en' ? 'Delete folder' : 'ลบโฟลเดอร์'}" style="padding: 2px 6px; ${isContractor ? 'display:none;' : ''}">
                    <i class="fa-solid fa-trash-can text-danger"></i>
                </button>
            </td>
        `;

        tr.querySelector('td:first-child').addEventListener('click', () => {
            const searchInput = document.getElementById('input-search-docs');
            if (searchInput) searchInput.value = '';
            state.currentDocFolderPath = cf.folder_path;
            renderProjectDocs();
        });

        tr.querySelector('.btn-delete-folder-row').addEventListener('click', async (e) => {
            e.stopPropagation();
            if (confirm(state.currentLanguage === 'en'
                ? `Are you sure you want to delete folder "${folderName}" and ALL files inside it?`
                : `คุณแน่ใจหรือไม่ว่าต้องการลบโฟลเดอร์ "${folderName}" และไฟล์ทั้งหมดที่อยู่ข้างใน?`)) {
                try {
                    const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/folders?path=${encodeURIComponent(cf.folder_path)}`, {
                        method: 'DELETE'
                    });
                    if (!res.ok) throw new Error('Delete failed');
                    showToast(state.currentLanguage === 'en' ? 'Folder deleted' : 'ลบโฟลเดอร์สำเร็จแล้ว');
                    await fetchActiveProjectDocs();
                    renderProjectDocs();
                } catch (err) {
                    console.error(err);
                    showToast(err.message, 'danger');
                }
            }
        });
        tbody.appendChild(tr);
    });

    // Render files
    if (currentFiles.length === 0 && childFolders.length === 0) {
        const tr = document.createElement('tr');
        tr.innerHTML = `
            <td colspan="6" style="padding: 30px; text-align: center; color: var(--text-muted);">
                <i class="fa-solid fa-folder-open" style="font-size:2rem; margin-bottom:8px; display:block; color:#ccc;"></i>
                ${state.currentLanguage === 'en' ? 'No files or folders in this directory' : 'ไม่มีไฟล์หรือโฟลเดอร์ในสารบบนี้'}
            </td>
        `;
        tbody.appendChild(tr);
    } else {
        currentFiles.forEach(f => {
            const tr = document.createElement('tr');
            tr.className = 'file-row';

            let iconClass = 'fa-file';
            let iconColor = 'var(--text-muted)';
            const type = f.file_type.toLowerCase();
            if (type === 'pdf') {
                iconClass = 'fa-file-pdf';
                iconColor = '#ef4444';
            } else if (['xls', 'xlsx'].includes(type)) {
                iconClass = 'fa-file-excel';
                iconColor = '#22c55e';
            } else if (['doc', 'docx'].includes(type)) {
                iconClass = 'fa-file-word';
                iconColor = '#2563eb';
            } else if (type === 'dwg') {
                iconClass = 'fa-file-lines';
                iconColor = '#3b82f6';
            } else if (['zip', 'rar'].includes(type)) {
                iconClass = 'fa-file-zipper';
                iconColor = '#a855f7';
            }

            const sizeStr = formatBytes(f.file_size);
            const dateStr = parseDbDate(f.uploaded_at).toLocaleString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH');

            const canChangeLevel = state.currentUser && (
                state.currentUser.role === 'admin' || 
                state.currentUser.role === 'superadmin' || 
                (state.currentUser.username && f.uploaded_by && state.currentUser.username.toLowerCase() === f.uploaded_by.toLowerCase())
            );

            let levelCellHtml = '';
            if (canChangeLevel) {
                levelCellHtml = `
                    <select class="form-control change-doc-level-select" data-doc-id="${f.id}" style="padding: 2px 4px; font-size: 0.75rem; border-radius: var(--radius-sm); border: 1px solid var(--border-color); background-color: var(--bg-panel); color: var(--text-main);">
                        <option value="public" ${f.doc_level === 'public' ? 'selected' : ''}>${t('doc_level_public')}</option>
                        <option value="internal" ${(!f.doc_level || f.doc_level === 'internal') ? 'selected' : ''}>${t('doc_level_internal')}</option>
                        <option value="confidential" ${f.doc_level === 'confidential' ? 'selected' : ''}>${t('doc_level_confidential')}</option>
                        <option value="executive" ${f.doc_level === 'executive' ? 'selected' : ''}>${t('doc_level_executive')}</option>
                    </select>
                `;
            } else {
                const currentLevel = f.doc_level || 'internal';
                let badgeClass = 'bg-success-light text-success';
                if (currentLevel === 'confidential') badgeClass = 'bg-warning-light text-warning';
                else if (currentLevel === 'executive') badgeClass = 'bg-danger-light text-danger';
                else if (currentLevel === 'public') badgeClass = 'bg-info-light text-info';

                levelCellHtml = `
                    <span class="badge ${badgeClass}" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600;">
                        ${t('doc_level_' + currentLevel)}
                    </span>
                `;
            }

            const canDelete = canChangeLevel;

            tr.innerHTML = `
                <td style="padding:10px;">
                    <div style="display:flex; align-items:flex-start; gap:10px; width:100%;">
                        <i class="fa-solid ${iconClass}" style="color:${iconColor}; font-size:1.15rem; margin-top:2px; flex-shrink:0;"></i>
                        <span class="file-name-preview-btn" data-id="${f.id}" data-name="${escapeHtml(f.file_name)}" data-type="${type}" style="font-weight:600; font-size:0.95rem; color:var(--primary-color); cursor:pointer; word-break:break-word; line-height:1.4;" title="${state.currentLanguage === 'en' ? 'Click to preview' : 'คลิกเพื่อแสดงตัวอย่าง'}">${escapeHtml(f.file_name)}</span>
                    </div>
                </td>
                <td style="padding:10px;" class="text-right">${sizeStr}</td>
                <td style="padding:10px; color:var(--text-dark); font-size:0.8rem;">${dateStr}</td>
                <td style="padding:10px;">${levelCellHtml}</td>
                <td style="padding:10px; color:var(--text-dark); font-size:0.8rem;">${escapeHtml(f.uploaded_by)}</td>
                <td style="padding:10px;" class="text-center">
                    <div style="display:flex; justify-content:center; gap:6px;">
                        <button class="btn btn-sm btn-outline btn-preview-file-row" data-id="${f.id}" data-name="${escapeHtml(f.file_name)}" data-type="${type}" title="${state.currentLanguage === 'en' ? 'Preview' : 'ดูตัวอย่าง'}" style="padding: 2px 6px;">
                            <i class="fa-solid fa-eye text-primary-color"></i>
                        </button>
                        <a href="${withAuthToken(`${API_BASE}/documents/${f.id}`)}" download class="btn btn-sm btn-outline" title="${state.currentLanguage === 'en' ? 'Download' : 'ดาวน์โหลด'}" style="padding: 2px 6px;">
                            <i class="fa-solid fa-download text-success"></i>
                        </a>
                        <button class="btn btn-sm btn-outline btn-delete-file-row" data-id="${f.id}" title="${state.currentLanguage === 'en' ? 'Delete' : 'ลบ'}" style="padding: 2px 6px; ${canDelete ? '' : 'display:none;'}">
                            <i class="fa-solid fa-trash-can text-danger"></i>
                        </button>
                    </div>
                </td>
            `;

            // Bind click to preview triggers
            tr.querySelectorAll('.file-name-preview-btn, .btn-preview-file-row').forEach(el => {
                el.addEventListener('click', (e) => {
                    e.preventDefault();
                    e.stopPropagation();
                    const docId = el.getAttribute('data-id');
                    const name = el.getAttribute('data-name');
                    const fType = el.getAttribute('data-type');
                    openDocumentPreview(docId, name, fType);
                });
            });

            tr.querySelector('.btn-delete-file-row').addEventListener('click', async (e) => {
                if (confirm(state.currentLanguage === 'en'
                    ? `Are you sure you want to delete file "${f.file_name}"?`
                    : `คุณต้องการลบไฟล์ "${f.file_name}" ใช่หรือไม่?`)) {
                    try {
                        const res = await authFetch(`${API_BASE}/documents/${f.id}`, { method: 'DELETE' });
                        if (!res.ok) throw new Error('Delete failed');
                        showToast(state.currentLanguage === 'en' ? 'File deleted' : 'ลบไฟล์สำเร็จแล้ว');
                        await fetchActiveProjectDocs();
                        renderProjectDocs();
                    } catch (err) {
                        console.error(err);
                        showToast(err.message, 'danger');
                    }
                }
            });

            // Bind change listener for level dropdown
            tr.querySelectorAll('.change-doc-level-select').forEach(el => {
                el.addEventListener('change', async (e) => {
                    const docId = e.target.getAttribute('data-doc-id');
                    const newLevel = e.target.value;
                    try {
                        const res = await authFetch(`${API_BASE}/documents/${docId}/level`, {
                            method: 'PUT',
                            body: JSON.stringify({ doc_level: newLevel })
                        });
                        if (!res.ok) throw new Error('Failed to update document level');
                        showToast(state.currentLanguage === 'en' ? 'Document level updated' : 'อัปเดตระดับสิทธิ์เอกสารสำเร็จแล้ว');
                        await fetchActiveProjectDocs();
                        renderProjectDocs();
                    } catch (err) {
                        console.error(err);
                        showToast(err.message, 'danger');
                    }
                });
            });

            tbody.appendChild(tr);
        });
    }
}

function setupDocsDropzone() {
    const dropzone = document.getElementById('docs-drop-zone');
    const fileInput = document.getElementById('input-upload-project-docs');

    if (!dropzone || !fileInput) return;

    // Clicking dropzone triggers file input
    dropzone.addEventListener('click', () => fileInput.click());

    fileInput.addEventListener('change', (e) => {
        handleDocsUpload(e.target.files);
        fileInput.value = ''; // reset
    });

    // Drag and drop events
    ['dragenter', 'dragover'].forEach(eventName => {
        dropzone.addEventListener(eventName, (e) => {
            e.preventDefault();
            e.stopPropagation();
            dropzone.classList.add('dragover');
        }, false);
    });

    ['dragleave', 'drop'].forEach(eventName => {
        dropzone.addEventListener(eventName, (e) => {
            e.preventDefault();
            e.stopPropagation();
            dropzone.classList.remove('dragover');
        }, false);
    });

    dropzone.addEventListener('drop', (e) => {
        const dt = e.dataTransfer;
        const files = dt.files;
        handleDocsUpload(files);
    }, false);

    // Create virtual folder click binding
    document.getElementById('btn-create-doc-folder').addEventListener('click', async () => {
        const name = prompt(state.currentLanguage === 'en' ? 'Enter folder name:' : 'กรุณาใส่ชื่อโฟลเดอร์:');
        if (!name) return;
        const cleanedName = name.replace(/[\/\\?%*:|"<>]/g, '').trim();
        if (!cleanedName) {
            showToast(state.currentLanguage === 'en' ? 'Invalid folder name' : 'ชื่อโฟลเดอร์ไม่ถูกต้อง', 'danger');
            return;
        }

        const pathPrefix = state.currentDocFolderPath === '/' ? '' : state.currentDocFolderPath;
        const targetFolderPath = pathPrefix + '/' + cleanedName;

        const folders = state.activeProjectDocs.folders || [];
        const exists = folders.some(f => f.folder_path.toLowerCase() === targetFolderPath.toLowerCase());
        if (exists) {
            showToast(state.currentLanguage === 'en' ? 'Folder already exists' : 'โฟลเดอร์นี้มีอยู่แล้ว', 'danger');
            return;
        }

        try {
            const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/folders`, {
                method: 'POST',
                body: JSON.stringify({ folder_path: targetFolderPath })
            });
            if (!res.ok) {
                const err = await res.json();
                throw new Error(err.error || 'Failed to create folder');
            }

            showToast(state.currentLanguage === 'en' ? 'Folder created' : 'สร้างโฟลเดอร์สำเร็จแล้ว');
            await fetchActiveProjectDocs();
            renderProjectDocs();
        } catch (err) {
            console.error(err);
            showToast(err.message, 'danger');
        }
    });

    // Real-time search filter binding
    document.getElementById('input-search-docs').addEventListener('input', () => {
        renderProjectDocs();
    });
}

// ==========================================
// Project Progress Updates Logic
// ==========================================

async function openProjectProgressModal() {
    if (!state.activeProjectId || !state.activeProjectSummary) return;

    document.getElementById('project-progress-title').textContent =
        state.currentLanguage === 'en'
            ? `Project Progress: ${state.activeProjectSummary.name}`
            : `ความคืบหน้าโครงการ: ${state.activeProjectSummary.name}`;

    // Reset state & form
    clearProgressForm();
    document.getElementById('progress-form-panel').style.display = 'none';

    // Open modal
    document.getElementById('modal-project-progress').classList.add('active');

    // Fetch and render
    await fetchAndRenderProgressList();
    buildProgressSystemDropdown();
}

function closeProjectProgressModal() {
    stopProgressCamera();
    clearProgressForm();
    const modal = document.getElementById('modal-project-progress');
    modal.classList.remove('active');
    modal.classList.remove('form-open');
}

// ==========================================
// FAT (FACTORY ACCEPTANCE TEST) CLIENT LOGIC
// ==========================================

let activeFatReportId = null;

async function openProjectFatModal() {
    if (!state.activeProjectId || !state.activeProjectSummary) return;

    // Open modal
    document.getElementById('modal-project-fat').classList.add('active');

    // Check role and toggle new report button visibility
    const role = state.currentUser ? state.currentUser.role : 'user';
    const newBtn = document.getElementById('btn-new-fat-trigger');
    const allowedRoles = ['superadmin', 'admin', 'supervisor', 'qc', 'qa', 'contractor', 'ee_manager', 'me_manager', 'excusive', 'procurment', 'stock'];
    if (newBtn) {
        newBtn.style.display = allowedRoles.includes(role) ? 'block' : 'none';
    }

    // Reset Detail view
    activeFatReportId = null;
    document.getElementById('fat-detail-pane').innerHTML = `
        <div style="text-align: center; color: var(--text-muted); margin: auto; display: flex; flex-direction: column; align-items: center; gap: 12px;">
            <i class="fa-solid fa-clipboard-list" style="font-size: 3rem; color: var(--border-color);"></i>
            <p data-i18n="fat_select_report_prompt">${state.currentLanguage === 'en' ? 'Please select a FAT report from the list on the left, or create a new one.' : 'กรุณาเลือกรายงาน FAT จากรายการด้านซ้าย หรือสร้างใหม่'}</p>
        </div>
    `;

    await fetchAndRenderFatReportsList();
}

function closeProjectFatModal() {
    document.getElementById('modal-project-fat').classList.remove('active');
}

async function openCreateFatModal() {
    const modal = document.getElementById('modal-create-fat-report');
    modal.classList.add('active');

    // Set default testing date to today
    const today = new Date().toISOString().split('T')[0];
    document.getElementById('fat-input-date').value = today;

    // Clear type & text inputs
    document.getElementById('fat-select-type').value = '';
    document.getElementById('fat-input-container-new').value = '';
    document.getElementById('fat-input-container-new').style.display = 'none';

    // Default other fields
    let containerVal = '';
    let panelVal = '';
    let locationVal = '';
    let ratedVal = '';
    let voltageVal = '';
    let dateVal = today;
    let instrModelVal = '';
    let instrSnVal = '';
    let instrExpVal = '';

    // Gather existing containers
    let existingContainers = [];
    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/fat-reports`);
        if (res.ok) {
            const reports = await res.json();
            if (reports && reports.length > 0) {
                // Collect unique container names from reports
                const reportContainers = reports.map(r => r.container_no).filter(Boolean).map(c => c.trim());
                const savedContainers = JSON.parse(localStorage.getItem('project_containers_' + state.activeProjectId) || '[]');
                existingContainers = Array.from(new Set([...reportContainers, ...savedContainers])).sort();

                // Populate from the most recent FAT report (ordered DESC by created_at)
                const latest = reports[0];
                if (latest.container_no) containerVal = latest.container_no;
                if (latest.panel_type) panelVal = latest.panel_type;
                if (latest.location) locationVal = latest.location;
                if (latest.rated) ratedVal = latest.rated;
                if (latest.voltage) voltageVal = latest.voltage;
                
                if (latest.testing_date) {
                    try {
                        const d = parseDbDate(latest.testing_date);
                        dateVal = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
                    } catch (e) {}
                }
                
                if (latest.instrument_model) instrModelVal = latest.instrument_model;
                if (latest.instrument_sn) instrSnVal = latest.instrument_sn;
                if (latest.instrument_expire) {
                    try {
                        const d = parseDbDate(latest.instrument_expire);
                        instrExpVal = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
                    } catch (e) {}
                }
            }
        }
    } catch (err) {
        console.error("Failed to load last FAT report for auto-fill:", err);
    }

    // Override containerVal if filtered in the sidebar
    const filterContainer = document.getElementById('fat-filter-container');
    if (filterContainer && filterContainer.value) {
        containerVal = filterContainer.value;
    }

    // Populate fat-select-container dropdown options
    const selectContainer = document.getElementById('fat-select-container');
    if (selectContainer) {
        selectContainer.innerHTML = '';

        const defaultOpt = document.createElement('option');
        defaultOpt.value = '';
        defaultOpt.textContent = state.currentLanguage === 'en' ? '-- Select Container --' : '-- เลือกตู้คอนเทนเนอร์ --';
        selectContainer.appendChild(defaultOpt);

        existingContainers.forEach(c => {
            const opt = document.createElement('option');
            opt.value = c;
            opt.textContent = c;
            selectContainer.appendChild(opt);
        });

        const newOpt = document.createElement('option');
        newOpt.value = '__NEW__';
        newOpt.textContent = state.currentLanguage === 'en' ? '+ Add New Container' : '+ เพิ่มหมายเลขตู้ใหม่';
        selectContainer.appendChild(newOpt);

        // Set selection
        if (containerVal) {
            if (existingContainers.includes(containerVal)) {
                selectContainer.value = containerVal;
                document.getElementById('fat-input-container-new').style.display = 'none';
            } else {
                selectContainer.value = '__NEW__';
                document.getElementById('fat-input-container-new').style.display = 'block';
                document.getElementById('fat-input-container-new').value = containerVal;
            }
        } else {
            selectContainer.value = '';
            document.getElementById('fat-input-container-new').style.display = 'none';
        }
    }

    document.getElementById('fat-input-date').value = dateVal;
    document.getElementById('fat-input-panel').value = panelVal;
    document.getElementById('fat-input-location').value = locationVal;
    document.getElementById('fat-input-rated').value = ratedVal;
    document.getElementById('fat-input-voltage').value = voltageVal;
    document.getElementById('fat-input-instr-model').value = instrModelVal;
    document.getElementById('fat-input-instr-sn').value = instrSnVal;
    document.getElementById('fat-input-instr-exp').value = instrExpVal;
}

function closeCreateFatModal() {
    document.getElementById('modal-create-fat-report').classList.remove('active');
}

async function handleCreateFatSubmit(e) {
    e.preventDefault();
    if (!state.activeProjectId) return;

    const report_type = document.getElementById('fat-select-type').value;
    const testing_date = document.getElementById('fat-input-date').value;
    
    const selectVal = document.getElementById('fat-select-container').value;
    let container_no = '';
    if (selectVal === '__NEW__') {
        container_no = document.getElementById('fat-input-container-new').value.trim();
    } else {
        container_no = selectVal.trim();
    }

    if (!container_no) {
        showToast(state.currentLanguage === 'en' ? 'Please select or enter a Container Number' : 'กรุณาเลือกหรือระบุหมายเลขตู้คอนเทนเนอร์', 'error');
        return;
    }

    // Persist new container number to local storage
    if (selectVal === '__NEW__' && container_no) {
        const list = JSON.parse(localStorage.getItem('project_containers_' + state.activeProjectId) || '[]');
        if (!list.includes(container_no)) {
            list.push(container_no);
            localStorage.setItem('project_containers_' + state.activeProjectId, JSON.stringify(list));
        }
    }

    const panel_type = document.getElementById('fat-input-panel').value.trim();
    const location = document.getElementById('fat-input-location').value.trim();
    const rated = document.getElementById('fat-input-rated').value.trim();
    const voltage = document.getElementById('fat-input-voltage').value.trim();
    const instrument_model = document.getElementById('fat-input-instr-model').value.trim();
    const instrument_sn = document.getElementById('fat-input-instr-sn').value.trim();
    const instrument_expire = document.getElementById('fat-input-instr-exp').value.trim();

    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/fat-reports`, {
            method: 'POST',
            body: JSON.stringify({
                report_type,
                testing_date,
                container_no,
                panel_type,
                location,
                rated,
                voltage,
                instrument_model,
                instrument_sn,
                instrument_expire
            })
        });

        if (res.ok) {
            showToast(state.currentLanguage === 'en' ? 'FAT Report created' : 'สร้างรายงาน FAT สำเร็จแล้ว');
            closeCreateFatModal();

            const newReport = await res.json();
            await loadFatReportDetails(newReport.id);
        } else {
            const err = await res.json();
            showToast(err.error || 'Failed to create report', 'error');
        }
    } catch (err) {
        console.error(err);
        showToast(state.currentLanguage === 'en' ? 'Network error' : 'เกิดข้อผิดพลาดในการเชื่อมต่อ', 'error');
    }
}

async function fetchAndRenderFatReportsList() {
    const container = document.getElementById('fat-reports-list-container');
    if (!container) return;
    container.innerHTML = `<div style="text-align:center; padding: 20px;"><i class="fa-solid fa-spinner fa-spin" style="color:var(--primary-color);"></i></div>`;

    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/fat-reports`);
        if (!res.ok) throw new Error('Failed to fetch');
        const reports = await res.json();

        // Populate the container filter dropdown
        populateFatContainerDropdown(reports);

        // Filter reports by selected container
        const filterContainer = document.getElementById('fat-filter-container');
        const selectedContainer = filterContainer ? filterContainer.value : '';
        const filteredReports = selectedContainer ? reports.filter(r => r.container_no === selectedContainer) : reports;

        container.innerHTML = '';
        if (filteredReports.length === 0) {
            container.innerHTML = `<div style="text-align:center; color:var(--text-muted); font-size:0.85rem; padding: 20px;">${state.currentLanguage === 'en' ? 'No reports found' : 'ไม่มีรายงาน FAT'}</div>`;
            return;
        }

        const role = state.currentUser ? state.currentUser.role : 'user';
        const allowedRoles = ['superadmin', 'admin', 'supervisor', 'qc', 'qa', 'contractor'];
        const canDelete = allowedRoles.includes(role);

        filteredReports.forEach(r => {
            const item = document.createElement('div');
            item.className = `fat-report-list-item ${activeFatReportId === r.id ? 'active' : ''}`;

            const formattedDate = r.testing_date ? parseDbDate(r.testing_date).toLocaleDateString('th-TH') : '-';

            const deleteBtnMarkup = canDelete ? `
                <button class="btn-delete-fat" data-id="${r.id}" title="${state.currentLanguage === 'en' ? 'Delete Report' : 'ลบรายงาน'}">
                    <i class="fa-solid fa-trash-can"></i>
                </button>
            ` : '';

            item.innerHTML = `
                <div style="font-weight:600; color:var(--text-dark); display:flex; justify-content:space-between; align-items:center;">
                    <span>${escapeHtml(r.report_type)}</span>
                    ${deleteBtnMarkup}
                </div>
                <div style="font-size:0.75rem; color:var(--text-muted); margin-top: 4px;">
                    <div><i class="fa-regular fa-calendar" style="width:14px;"></i> ${formattedDate}</div>
                    <div style="margin-top: 2px;"><i class="fa-solid fa-box" style="width:14px;"></i> ${escapeHtml(r.container_no || '-')}</div>
                </div>
            `;

            item.addEventListener('click', () => loadFatReportDetails(r.id));

            const deleteBtn = item.querySelector('.btn-delete-fat');
            if (deleteBtn) {
                deleteBtn.addEventListener('click', (e) => {
                    e.stopPropagation();
                    handleDeleteFatReport(r.id);
                });
            }

            container.appendChild(item);
        });
    } catch (err) {
        console.error(err);
        container.innerHTML = `<div style="text-align:center; color:var(--danger); font-size:0.85rem; padding: 20px;">Error loading list</div>`;
    }
}

function populateFatContainerDropdown(reports) {
    const dropdown = document.getElementById('fat-filter-container');
    if (!dropdown) return;

    const currentSelection = dropdown.value;

    // Gather unique container numbers from reports
    const reportContainers = reports.map(r => r.container_no).filter(Boolean).map(c => c.trim());
    
    // Gather container numbers from local storage
    const savedContainers = JSON.parse(localStorage.getItem('project_containers_' + state.activeProjectId) || '[]');

    // Merge and filter duplicates
    const allContainers = Array.from(new Set([...reportContainers, ...savedContainers])).sort();

    dropdown.innerHTML = `<option value="">${state.currentLanguage === 'en' ? '-- All Containers --' : '-- ตู้ทั้งหมด --'}</option>`;
    allContainers.forEach(c => {
        const option = document.createElement('option');
        option.value = c;
        option.textContent = c;
        dropdown.appendChild(option);
    });

    // Restore selection
    if (allContainers.includes(currentSelection)) {
        dropdown.value = currentSelection;
    } else {
        dropdown.value = '';
    }
}

function handleAddContainerNo() {
    const promptMsg = state.currentLanguage === 'en' ? 'Enter New Container Number (e.g. No.4):' : 'ระบุหมายเลขตู้คอนเทนเนอร์ใหม่ (เช่น No.4):';
    const name = prompt(promptMsg);
    if (!name || !name.trim()) return;

    const containerNo = name.trim();
    const list = JSON.parse(localStorage.getItem('project_containers_' + state.activeProjectId) || '[]');
    if (!list.includes(containerNo)) {
        list.push(containerNo);
        localStorage.setItem('project_containers_' + state.activeProjectId, JSON.stringify(list));
    }

    // Set dropdown selection and refresh list
    const dropdown = document.getElementById('fat-filter-container');
    if (dropdown) {
        // We will call fetchAndRenderFatReportsList which repopulates dropdown and filters
        dropdown.value = containerNo;
        // Wait, since dropdown.value is not in the DOM options list yet, we add it temporarily or rely on populate to restore it
        const tempOpt = document.createElement('option');
        tempOpt.value = containerNo;
        tempOpt.textContent = containerNo;
        dropdown.appendChild(tempOpt);
        dropdown.value = containerNo;
    }

    fetchAndRenderFatReportsList();
}

async function handleDeleteFatReport(id) {
    const role = state.currentUser ? state.currentUser.role : 'user';
    const allowedRoles = ['superadmin', 'admin', 'supervisor', 'qc', 'qa', 'contractor'];
    if (!allowedRoles.includes(role)) {
        showToast(state.currentLanguage === 'en' ? 'Insufficient permissions' : 'ไม่มีสิทธิ์ในการลบรายงาน FAT', 'danger');
        return;
    }
    if (!confirm(state.currentLanguage === 'en' ? 'Are you sure you want to delete this FAT report?' : 'คุณแน่ใจหรือไม่ว่าต้องการลบรายงาน FAT นี้?')) return;

    try {
        const res = await authFetch(`${API_BASE}/fat-reports/${id}`, {
            method: 'DELETE'
        });
        if (res.ok) {
            showToast(state.currentLanguage === 'en' ? 'FAT Report deleted' : 'ลบรายงาน FAT เรียบร้อยแล้ว');
            if (activeFatReportId === id) {
                activeFatReportId = null;
                document.getElementById('fat-detail-pane').innerHTML = `
                    <div style="text-align: center; color: var(--text-muted); margin: auto; display: flex; flex-direction: column; align-items: center; gap: 12px;">
                        <i class="fa-solid fa-clipboard-list" style="font-size: 3rem; color: var(--border-color);"></i>
                        <p data-i18n="fat_select_report_prompt">${state.currentLanguage === 'en' ? 'Please select a FAT report from the list on the left, or create a new one.' : 'กรุณาเลือกรายงาน FAT จากรายการด้านซ้าย หรือสร้างใหม่'}</p>
                    </div>
                `;
            }
            await fetchAndRenderFatReportsList();
        } else {
            showToast('Delete failed', 'error');
        }
    } catch (err) {
        console.error(err);
    }
}

async function loadFatReportDetails(reportId) {
    activeFatReportId = reportId;

    // Close mobile drawer if active
    const sidebar = document.querySelector('#modal-project-fat .fat-sidebar');
    if (sidebar) sidebar.classList.remove('drawer-active');

    // Highlight list item without re-rendering everything
    document.querySelectorAll('.fat-report-list-item').forEach(el => {
        el.style.borderColor = 'var(--border-color)';
        el.style.background = 'white';
    });

    // Re-render only list active state styles locally
    const itemsList = document.querySelectorAll('.fat-report-list-item');
    // Just fetch active fat items now
    const detailPane = document.getElementById('fat-detail-pane');
    detailPane.innerHTML = `<div style="text-align:center; padding: 100px 0;"><i class="fa-solid fa-spinner fa-spin" style="font-size: 2.5rem; color:var(--primary-color);"></i><p style="margin-top:10px; color:var(--text-muted);">กำลังโหลดรายละเอียด...</p></div>`;

    try {
        // Fetch report metadata
        const resReports = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/fat-reports`);
        const reports = await resReports.json();
        const report = reports.find(r => r.id === reportId);
        if (!report) throw new Error('Report not found');

        // Fetch report items
        const resItems = await authFetch(`${API_BASE}/fat-reports/${reportId}/items`);
        const items = await resItems.json();
        state.currentFatReportItems = items;

        let testingDateVal = '';
        if (report.testing_date) {
            const d = parseDbDate(report.testing_date);
            testingDateVal = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
        }
        const role = state.currentUser ? state.currentUser.role : 'user';
        const allowedRoles = ['superadmin', 'admin', 'supervisor', 'qc', 'qa', 'contractor'];
        const disabledAttr = allowedRoles.includes(role) ? '' : 'disabled';

        const models = (report.instrument_model || '').split('|');
        const sns = (report.instrument_sn || '').split('|');
        const exps = (report.instrument_expire || '').split('|');
        const maxLen = Math.max(models.length, sns.length, exps.length, 1);

        let lastItemNo = '';
        items.forEach(item => {
            const isTestedBy = item.item_no && item.item_no.toLowerCase().includes('tested');
            if (!isTestedBy && item.item_no && item.item_no.includes('.')) {
                lastItemNo = item.item_no;
            }
        });

        let calculatedTestedByItemNo = '3.6';
        if (lastItemNo) {
            const parts = lastItemNo.split('.');
            if (parts.length === 2) {
                const major = parseInt(parts[0]);
                const minor = parseInt(parts[1]);
                if (!isNaN(major) && !isNaN(minor)) {
                    calculatedTestedByItemNo = `${major}.${minor + 1}`;
                }
            }
        }

        const saveBtnMarkup = allowedRoles.includes(role) ? `
            <button class="btn btn-primary btn-sm" id="btn-save-fat-active" style="display:flex; align-items:center; gap:6px;">
                <i class="fa-solid fa-save"></i> ${state.currentLanguage === 'en' ? 'Save Results' : 'บันทึกข้อมูล'}
            </button>
        ` : '';

        detailPane.innerHTML = `
            <div style="display:flex; justify-content:space-between; align-items:center; border-bottom: 2px solid var(--border-color); padding-bottom: 12px; margin-bottom: 20px;">
                <div>
                    <h2 style="margin:0; color:var(--text-dark);">${escapeHtml(report.report_type)}</h2>
                    <span style="font-size:0.85rem; color:var(--text-muted);">${state.currentLanguage === 'en' ? 'FAT Checklist and testing records' : 'ตารางตรวจสอบและบันทึกผลการทดสอบ FAT'}</span>
                </div>
                <div style="display:flex; gap:8px;">
                    <button class="btn btn-success btn-sm" id="btn-print-fat-active" style="display:flex; align-items:center; gap:6px;">
                        <i class="fa-solid fa-print"></i> ${state.currentLanguage === 'en' ? 'Print Report' : 'พิมพ์รายงาน'}
                    </button>
                    ${saveBtnMarkup}
                </div>
            </div>
            
            <div class="a4-preview-page">
                <div class="report-header">
                    <div class="report-title">${escapeHtml(report.report_type)} TESTING</div>
                    <div style="font-size:16px; font-weight:bold;">FACTORY ACCEPTANCE TEST REPORT</div>
                </div>

                <form id="form-fat-detail-header" style="margin-bottom: 0;">
                    <table class="meta-table">
                        <tr>
                            <td class="meta-label">PROJECT NAME:</td>
                            <td class="meta-val">${escapeHtml(state.activeProjectSummary.name || '-')}</td>
                            <td class="meta-label">TESTING DATE:</td>
                            <td class="meta-val">
                                <input type="date" id="det-fat-date" class="formal-input" value="${testingDateVal}" ${disabledAttr}>
                            </td>
                        </tr>
                        <tr>
                            <td class="meta-label">CONTAINER NO:</td>
                            <td class="meta-val">
                                <input type="text" id="det-fat-container" class="formal-input" value="${escapeHtml(report.container_no || '')}" ${disabledAttr} placeholder="-">
                            </td>
                            <td class="meta-label">PANEL TYPE:</td>
                            <td class="meta-val">
                                <input type="text" id="det-fat-panel" class="formal-input" value="${escapeHtml(report.panel_type || '')}" ${disabledAttr} placeholder="-">
                            </td>
                        </tr>
                        <tr>
                            <td class="meta-label">LOCATION:</td>
                            <td class="meta-val">
                                <input type="text" id="det-fat-location" class="formal-input" value="${escapeHtml(report.location || '')}" ${disabledAttr} placeholder="-">
                            </td>
                            <td class="meta-label">RATED:</td>
                            <td class="meta-val">
                                <input type="text" id="det-fat-rated" class="formal-input" value="${escapeHtml(report.rated || '')}" ${disabledAttr} placeholder="-">
                            </td>
                        </tr>
                        <tr>
                            <td class="meta-label">VOLTAGE:</td>
                            <td class="meta-val">
                                <input type="text" id="det-fat-voltage" class="formal-input" value="${escapeHtml(report.voltage || '')}" ${disabledAttr} placeholder="-">
                            </td>
                            <td class="meta-label">INSTRUMENT:</td>
                            <td class="meta-val">
                                <input type="text" class="formal-input fat-instr-model-input" value="${escapeHtml(models[0] || '')}" ${disabledAttr} placeholder="-">
                            </td>
                        </tr>
                        <tr>
                            <td class="meta-label">SERIAL NO:</td>
                            <td class="meta-val">
                                <input type="text" class="formal-input fat-instr-sn-input" value="${escapeHtml(sns[0] || '')}" ${disabledAttr} placeholder="-">
                            </td>
                            <td class="meta-label">EXPIRE DATE:</td>
                            <td class="meta-val" style="position: relative;">
                                <input type="text" class="formal-input fat-instr-exp-input" value="${escapeHtml(exps[0] || '')}" ${disabledAttr} placeholder="-">
                            </td>
                        </tr>
                        ${(() => {
                            let rows = '';
                            for (let i = 1; i < maxLen; i++) {
                                rows += `
                                    <tr class="instrument-extra-row">
                                        <td class="meta-label"></td>
                                        <td class="meta-val"></td>
                                        <td class="meta-label">INSTRUMENT:</td>
                                        <td class="meta-val">
                                            <input type="text" class="formal-input fat-instr-model-input" value="${escapeHtml(models[i] || '')}" ${disabledAttr} placeholder="-">
                                        </td>
                                    </tr>
                                    <tr class="instrument-extra-row">
                                        <td class="meta-label">SERIAL NO:</td>
                                        <td class="meta-val">
                                            <input type="text" class="formal-input fat-instr-sn-input" value="${escapeHtml(sns[i] || '')}" ${disabledAttr} placeholder="-">
                                        </td>
                                        <td class="meta-label">EXPIRE DATE:</td>
                                        <td class="meta-val" style="position: relative;">
                                            <input type="text" class="formal-input fat-instr-exp-input" value="${escapeHtml(exps[i] || '')}" ${disabledAttr} placeholder="-">
                                            ${role !== 'user' ? `
                                                <button type="button" class="btn-delete-instrument" style="position: absolute; right: -35px; top: 50%; transform: translateY(-50%); background: none; border: none; color: var(--text-muted); cursor: pointer; padding: 5px;" onclick="this.closest('tr').previousElementSibling.remove(); this.closest('tr').remove();">
                                                    <i class="fa-solid fa-trash-can" style="color:var(--danger)"></i>
                                                </button>
                                            ` : ''}
                                        </td>
                                    </tr>
                                `;
                            }
                            return rows;
                        })()}
                    </table>
                    ${role !== 'user' ? `
                        <div style="text-align: right; margin-top: 5px; margin-bottom: 15px;">
                            <button type="button" class="btn btn-outline btn-sm" id="btn-add-instrument-row">
                                <i class="fa-solid fa-plus"></i> เพิ่มเครื่องมือวัด (Add Instrument)
                            </button>
                        </div>
                    ` : ''}
                </form>
                
                <table class="formal-checklist-table" id="table-fat-items">
                    <thead>
                        <tr>
                            <th width="48" class="text-center" style="text-align: center !important;">ลำดับ (Item)</th>
                            <th style="text-align: left !important; padding-left: 8px !important;">หัวข้อการทดสอบ / รายละเอียด (Test Condition / Description)</th>
                            <th width="35" class="text-center">Pass</th>
                            <th width="35" class="text-center">Fail</th>
                            <th width="196">หมายเหตุ / ค่าที่วัดได้ (Remarks / Value)</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${(() => {
                            let photoCounter = 0;
                            const photoIndexMap = {};
                            items.forEach(it => {
                                const isHeader = !it.item_no || (!it.item_no.includes('.') && !it.description);
                                if (!isHeader && it.photo) {
                                    photoCounter++;
                                    photoIndexMap[it.id] = photoCounter;
                                }
                            });
                            return items.map(item => {
                                const isHeader = !item.item_no || (!item.item_no.includes('.') && !item.description);
                                const rowBg = isHeader ? '#f2f2f2' : 'transparent';
                                const rowFontWeight = isHeader ? 'bold' : 'normal';
                                
                                const isTestedByRow = item.item_no && item.item_no.toLowerCase().includes('tested');
                                const displayItemNo = isTestedByRow ? calculatedTestedByItemNo : item.item_no;
                                const photoIndex = photoIndexMap[item.id];

                                return `
                                    <tr class="fat-item-row" data-id="${item.id}" style="background:${rowBg}; font-weight:${rowFontWeight};">
                                        <td style="font-weight:600; text-align:center;">${escapeHtml(displayItemNo || '')}</td>
                                        <td>
                                            <div style="font-weight:bold; font-size:${report.report_type === 'AIR CONDITION INSPECTION' ? '15px' : '14px'};">
                                                ${escapeHtml(item.title || '')}
                                                ${item.description ? `<span style="font-weight:normal; font-size:${report.report_type === 'AIR CONDITION INSPECTION' ? '15px' : '13px'}; color:#444;">${item.title ? ' - ' : ''}${formatInlineDescription(item.description, item.id, disabledAttr)}</span>` : ''}
                                            </div>
                                        </td>
                                        <td class="text-center">
                                            ${isHeader ? '' : `
                                                <label class="print-chk-label">
                                                    <input type="checkbox" class="fat-chk-pass" ${item.result_pass === 1 ? 'checked' : ''} ${disabledAttr} onchange="handleFatCheckboxChange(this, 'pass')">
                                                    <span>&#10003;</span>
                                                </label>
                                            `}
                                        </td>
                                        <td class="text-center">
                                            ${isHeader ? '' : `
                                                <label class="print-chk-label">
                                                    <input type="checkbox" class="fat-chk-fail" ${item.result_fail === 1 ? 'checked' : ''} ${disabledAttr} onchange="handleFatCheckboxChange(this, 'fail')">
                                                    <span>&#10007;</span>
                                                </label>
                                            `}
                                        </td>
                                        <td class="text-center" style="vertical-align: middle;">
                                            ${isHeader ? '' : `
                                                <div style="display:flex; align-items:center; justify-content:center; gap:6px;">
                                                    ${item.photos && item.photos.length > 0 ? `
                                                        <div style="display:flex; flex-direction:column; gap:4px; align-items:center;">
                                                            <div style="display:flex; flex-wrap:wrap; gap:4px; justify-content:center; max-width:200px;">
                                                                ${item.photos.map((photoId, idx) => `
                                                                    <div style="display:flex; align-items:center; gap:2px; background:var(--bg-hover); padding:2px 4px; border-radius:4px; border:1px solid var(--border-color);">
                                                                        <span style="font-size:10px; font-weight:bold; color:var(--primary-color);">#${idx + 1}</span>
                                                                        <button type="button" class="btn btn-outline btn-xs" onclick="viewFatPhoto('${photoId}')" style="padding:1px 3px; font-size:9px; line-height:1; height:auto;">ดู</button>
                                                                        ${allowedRoles.includes(role) ? `
                                                                            <button type="button" class="btn btn-outline-danger btn-xs" onclick="deleteFatPhoto(${reportId}, ${item.id}, '${photoId}')" style="padding:1px 3px; font-size:9px; line-height:1; height:auto; color:var(--danger); border-color:var(--danger);"><i class="fa-solid fa-xmark"></i></button>
                                                                        ` : ''}
                                                                    </div>
                                                                `).join('')}
                                                            </div>
                                                            ${allowedRoles.includes(role) && item.photos.length < 10 ? `
                                                                <button type="button" class="btn btn-outline btn-xs" onclick="triggerFatPhotoUpload(${reportId}, ${item.id})" style="padding:2px 5px; font-size:10px; display:flex; align-items:center; gap:2px; height:auto; line-height:1;">
                                                                    <i class="fa-solid fa-plus"></i> เพิ่มรูป (${item.photos.length}/10)
                                                                </button>
                                                            ` : ''}
                                                        </div>
                                                    ` : `
                                                        ${allowedRoles.includes(role) ? `
                                                            <button type="button" class="btn btn-outline btn-xs" onclick="triggerFatPhotoUpload(${reportId}, ${item.id})" style="padding:3px 6px; font-size:11px; display:flex; align-items:center; gap:4px; height:auto; line-height:1.2;">
                                                                <i class="fa-solid fa-camera"></i> แนบรูป (0/10)
                                                            </button>
                                                        ` : '<span style="color:#999; font-size:11px;">ไม่มีรูป</span>'}
                                                    `}
                                                </div>
                                            `}
                                        </td>
                                    </tr>
                                `;
                            }).join('');
                        })()}
                    </tbody>
                </table>

                <div style="margin-top: 50px; display: flex; justify-content: space-between; padding: 0 40px;">
                    <div style="text-align: center; width: 250px;">
                        <p style="font-weight: bold; margin-bottom: 50px; color: #000;">TESTED BY</p>
                        <div style="border-bottom: 1px solid #000; width: 200px; margin: 0 auto;"></div>
                        <p style="font-size: 14px; margin-top: 6px; color: #000;">(....................................................)</p>
                        <p style="font-size: 14px; color: #000; margin-top: 3px;">วันที่: ....../....../......</p>
                    </div>
                    <div style="text-align: center; width: 250px;">
                        <p style="font-weight: bold; margin-bottom: 50px; color: #000;">WITNESSED BY (CLIENT)</p>
                        <div style="border-bottom: 1px solid #000; width: 200px; margin: 0 auto;"></div>
                        <p style="font-size: 14px; margin-top: 6px; color: #000;">(....................................................)</p>
                        <p style="font-size: 14px; color: #000; margin-top: 3px;">วันที่: ....../....../......</p>
                    </div>
                </div>
            </div>
        `;

        // Bind button events
        if (allowedRoles.includes(role)) {
            document.getElementById('btn-save-fat-active').addEventListener('click', () => saveFatReportResults(reportId));
            
            document.getElementById('btn-add-instrument-row').addEventListener('click', () => {
                const metaTable = document.querySelector('.meta-table');
                const tbody = metaTable.querySelector('tbody') || metaTable;
                const newRows = document.createElement('tbody');
                newRows.innerHTML = `
                    <tr class="instrument-extra-row">
                        <td class="meta-label"></td>
                        <td class="meta-val"></td>
                        <td class="meta-label">INSTRUMENT:</td>
                        <td class="meta-val">
                            <input type="text" class="formal-input fat-instr-model-input" value="" placeholder="-">
                        </td>
                    </tr>
                    <tr class="instrument-extra-row">
                        <td class="meta-label">SERIAL NO:</td>
                        <td class="meta-val">
                            <input type="text" class="formal-input fat-instr-sn-input" value="" placeholder="-">
                        </td>
                        <td class="meta-label">EXPIRE DATE:</td>
                        <td class="meta-val" style="position: relative;">
                            <input type="text" class="formal-input fat-instr-exp-input" value="" placeholder="-">
                            <button type="button" class="btn-delete-instrument" style="position: absolute; right: -35px; top: 50%; transform: translateY(-50%); background: none; border: none; color: var(--text-muted); cursor: pointer; padding: 5px;" onclick="this.closest('tr').previousElementSibling.remove(); this.closest('tr').remove();">
                                <i class="fa-solid fa-trash-can" style="color:var(--danger)"></i>
                            </button>
                        </td>
                    </tr>
                `;
                Array.from(newRows.children).forEach(child => tbody.appendChild(child));
            });
        }
        document.getElementById('btn-print-fat-active').addEventListener('click', () => {
            // Extract latest header values from DOM
            const dateInput = document.getElementById('det-fat-date').value;
            const containerInput = document.getElementById('det-fat-container').value.trim();
            const panelInput = document.getElementById('det-fat-panel').value.trim();
            const locationInput = document.getElementById('det-fat-location').value.trim();
            const ratedInput = document.getElementById('det-fat-rated').value.trim();
            const voltageInput = document.getElementById('det-fat-voltage').value.trim();
            
            const instrModelInputs = document.querySelectorAll('.fat-instr-model-input');
            const instrSnInputs = document.querySelectorAll('.fat-instr-sn-input');
            const instrExpInputs = document.querySelectorAll('.fat-instr-exp-input');

            const models = Array.from(instrModelInputs).map(input => input.value.trim());
            const sns = Array.from(instrSnInputs).map(input => input.value.trim());
            const exps = Array.from(instrExpInputs).map(input => input.value.trim());

            const updatedReport = {
                ...report,
                testing_date: dateInput,
                container_no: containerInput,
                panel_type: panelInput,
                location: locationInput,
                rated: ratedInput,
                voltage: voltageInput,
                instrument_model: models.join('|'),
                instrument_sn: sns.join('|'),
                instrument_expire: exps.join('|')
            };

            // Extract latest items from DOM (including inline inputs)
            const rows = document.querySelectorAll('.fat-item-row');
            const updatedItems = Array.from(rows).map(row => {
                const id = parseInt(row.dataset.id);
                const passChk = row.querySelector('.fat-chk-pass');
                const failChk = row.querySelector('.fat-chk-fail');
                const remarksInput = row.querySelector('.fat-input-remarks');
                const inlineValInput = row.querySelector('.fat-inline-val');
                const inlineBracketValInput = row.querySelector('.fat-inline-bracket-val');
                
                const origItem = items.find(it => it.id === id) || {};
                let description = origItem.description || '';

                if (inlineValInput) {
                    const newVal = inlineValInput.value.trim();
                    const regex = /(\.\.\.+)\s*([0-9\.]*)\s*(\.\.\.+)/;
                    description = description.replace(regex, (match, p1, p2, p3) => {
                        return `${p1}${newVal}${p3}`;
                    });
                } else if (inlineBracketValInput) {
                    const inputs = Array.from(row.querySelectorAll('.fat-inline-bracket-val'));
                    let replacementIndex = 0;
                    const regex = /\[([X0-9a-zA-Z\s\.\-\|]*)\]/g;
                    description = (origItem.description || '').replace(regex, (match, innerVal) => {
                        const input = inputs[replacementIndex++];
                        if (input) {
                            const newVal = input.value.trim();
                            const isPlaceholder = /^[X\|]+$/i.test(innerVal.trim());
                            const originalPlaceholder = isPlaceholder ? innerVal : 'XXXXXX';
                            const displayVal = newVal === '' ? originalPlaceholder : newVal;
                            return `[${displayVal}]`;
                        }
                        return match;
                    });
                }

                return {
                    ...origItem,
                    id: id,
                    result_pass: passChk && passChk.checked ? 1 : 0,
                    result_fail: failChk && failChk.checked ? 1 : 0,
                    remarks: remarksInput ? remarksInput.value.trim() : '',
                    description: description
                };
            });

            // If user has edit permissions, auto-save to DB before printing
            const role = state.currentUser ? state.currentUser.role : 'user';
            const allowedRoles = ['superadmin', 'admin', 'supervisor', 'qc', 'qa', 'contractor'];
            if (allowedRoles.includes(role)) {
                const header = {
                    testing_date: dateInput,
                    container_no: containerInput,
                    panel_type: panelInput,
                    location: locationInput,
                    rated: ratedInput,
                    voltage: voltageInput,
                    instrument_model: models.join('|'),
                    instrument_sn: sns.join('|'),
                    instrument_expire: exps.join('|')
                };

                authFetch(`${API_BASE}/fat-reports/${reportId}/items`, {
                    method: 'PUT',
                    body: JSON.stringify({ header, items: updatedItems })
                }).then(res => {
                    if (res.ok) {
                        // Reload data in-memory to keep state in sync
                        loadFatReportDetails(reportId).then(() => {
                            printFatReport(updatedReport, updatedItems);
                        });
                    } else {
                        printFatReport(updatedReport, updatedItems);
                    }
                }).catch(err => {
                    console.error('Auto-save error before print:', err);
                    printFatReport(updatedReport, updatedItems);
                });
            } else {
                printFatReport(updatedReport, updatedItems);
            }
        });
    } catch (err) {
        console.error(err);
        detailPane.innerHTML = `<div style="text-align:center; padding: 100px 0; color:var(--danger);">Error loading details</div>`;
    }
}

function handleFatCheckboxChange(checkbox, type) {
    const row = checkbox.closest('.fat-item-row');
    if (type === 'pass' && checkbox.checked) {
        row.querySelector('.fat-chk-fail').checked = false;
    } else if (type === 'fail' && checkbox.checked) {
        row.querySelector('.fat-chk-pass').checked = false;
    }
}

window.formatInlineDescription = function(desc, itemId, disabledAttr) {
    if (!desc) return '';
    
    // 1. Dot pattern (e.g., ...2000...)
    const dotRegex = /(\.\.\.+)\s*([0-9\.]*)\s*(\.\.\.+)/;
    let match = desc.match(dotRegex);
    if (match) {
        const value = match[2];
        const inputHtml = `<input type="text" class="fat-inline-val" data-item-id="${itemId}" value="${escapeHtml(value)}" ${disabledAttr} style="width: 60px; text-align: center; border: none; border-bottom: 1px dotted #000; font-weight: bold; background: transparent; color: inherit; font-size: inherit; font-family: inherit;">`;
        return desc.replace(dotRegex, `${match[1]}${inputHtml}${match[3]}`);
    }
    
    // 2. Bracket pattern (e.g., [XXXXXXX]) - match all globally in a loop
    const bracketRegex = /\[([X0-9a-zA-Z\s\.\-\|]*)\]/g;
    let matchArr;
    let index = 0;
    
    const inputs = [];
    while ((matchArr = bracketRegex.exec(desc)) !== null) {
        let value = matchArr[1] || '';
        const isPlaceholder = /^[X\|]+$/i.test(value.trim());
        const displayVal = isPlaceholder ? '' : value;
        const placeholder = isPlaceholder ? value : '';
        const inputHtml = `<input type="text" class="fat-inline-bracket-val" data-item-id="${itemId}" data-index="${index}" value="${escapeHtml(displayVal)}" placeholder="${escapeHtml(placeholder)}" ${disabledAttr} style="width: 80px; text-align: center; border: none; border-bottom: 1px dotted #000; font-weight: bold; background: transparent; color: inherit; font-size: inherit; font-family: inherit;">`;
        inputs.push(inputHtml);
        index++;
    }
    
    if (inputs.length > 0) {
        let replacementIndex = 0;
        return desc.replace(/\[([X0-9a-zA-Z\s\.\-\|]*)\]/g, () => {
            return inputs[replacementIndex++];
        });
    }
    
    return escapeHtml(desc);
};

window.formatInlineDescriptionPrint = function(desc) {
    if (!desc) return '';
    
    // 1. Dot pattern
    const dotRegex = /(\.\.\.+)\s*([0-9\.]*)\s*(\.\.\.+)/;
    let match = desc.match(dotRegex);
    if (match) {
        const value = match[2];
        return desc.replace(dotRegex, `${match[1]}<strong>${escapeHtml(value)}</strong>${match[3]}`);
    }
    
    // 2. Bracket pattern - match all globally in a loop
    const bracketRegex = /\[([X0-9a-zA-Z\s\.\-\|]*)\]/g;
    let matchArr;
    const strongs = [];
    while ((matchArr = bracketRegex.exec(desc)) !== null) {
        let value = matchArr[1] || '';
        const isPlaceholder = /^[X\|]+$/i.test(value.trim());
        const displayVal = isPlaceholder ? '_______' : value;
        strongs.push(`<strong>${escapeHtml(displayVal)}</strong>`);
    }
    
    if (strongs.length > 0) {
        let replacementIndex = 0;
        return desc.replace(/\[([X0-9a-zA-Z\s\.\-\|]*)\]/g, () => {
            return strongs[replacementIndex++];
        });
    }
    
    return escapeHtml(desc);
};

window.triggerFatPhotoUpload = function(reportId, itemId) {
    const input = document.createElement('input');
    input.type = 'file';
    input.accept = 'image/*';
    input.setAttribute('capture', 'environment'); // Open camera directly on mobile devices
    input.onchange = async (e) => {
        const file = e.target.files[0];
        if (!file) return;
        
        try {
            showToast('กำลังบีบอัดรูปภาพ...', 'info');
            const compressedFile = await compressFatPhoto(file, 100); // Target max 100KB
            
            const formData = new FormData();
            formData.append('image', compressedFile);
            
            showToast('กำลังอัปโหลดรูปภาพ...', 'info');
            const res = await fetch(`${API_BASE}/fat-reports/${reportId}/items/${itemId}/upload`, {
                method: 'POST',
                headers: {
                    ...getAuthHeader()
                },
                body: formData
            });
            if (res.ok) {
                showToast('อัปโหลดรูปภาพสำเร็จ');
                await loadFatReportDetails(reportId);
            } else {
                const err = await res.json();
                showToast(err.error || 'Failed to upload photo', 'error');
            }
        } catch (err) {
            console.error(err);
            showToast('Error uploading photo', 'error');
        }
    };
    input.click();
};

function compressFatPhoto(file, maxSizeKB) {
    return new Promise((resolve) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = function(event) {
            const img = new Image();
            img.src = event.target.result;
            img.onload = function() {
                const canvas = document.createElement('canvas');
                let width = img.width;
                let height = img.height;
                
                const MAX_WIDTH = 1000;
                const MAX_HEIGHT = 1000;
                if (width > height) {
                    if (width > MAX_WIDTH) {
                        height = Math.round((height * MAX_WIDTH) / width);
                        width = MAX_WIDTH;
                    }
                } else {
                    if (height > MAX_HEIGHT) {
                        width = Math.round((width * MAX_HEIGHT) / height);
                        height = MAX_HEIGHT;
                    }
                }
                
                canvas.width = width;
                canvas.height = height;
                const ctx = canvas.getContext('2d');
                ctx.drawImage(img, 0, 0, width, height);
                
                let quality = 0.8;
                const checkSize = (blob) => {
                    if (blob.size <= maxSizeKB * 1024 || quality <= 0.2) {
                        const compressedFile = new File([blob], file.name.replace(/\.[^/.]+$/, "") + ".jpg", {
                            type: 'image/jpeg',
                            lastModified: Date.now()
                        });
                        resolve(compressedFile);
                    } else {
                        quality -= 0.1;
                        canvas.toBlob(checkSize, 'image/jpeg', quality);
                    }
                };
                canvas.toBlob(checkSize, 'image/jpeg', quality);
            };
        };
    });
}

window.viewFatPhoto = function(photoId) {
    const overlay = document.createElement('div');
    overlay.style = 'position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.85); z-index:9999; display:flex; align-items:center; justify-content:center; cursor:pointer;';
    overlay.innerHTML = `
        <div style="position:relative; max-width:90%; max-height:90%;">
            <img src="${withAuthToken(`${API_BASE}/fat-reports/photos/${photoId}`)}" style="max-width:100%; max-height:90vh; border:4px solid white; border-radius:4px; box-shadow:0 10px 25px rgba(0,0,0,0.5);">
            <button style="position:absolute; top:-15px; right:-15px; background:red; color:white; border:none; border-radius:50%; width:30px; height:30px; font-weight:bold; cursor:pointer; display:flex; align-items:center; justify-content:center; font-size:16px;">&times;</button>
        </div>
    `;
    overlay.onclick = () => overlay.remove();
    document.body.appendChild(overlay);
};

window.deleteFatPhoto = async function(reportId, itemId, photoId) {
    if (!confirm('คุณต้องการลบรูปภาพนี้ใช่หรือไม่?')) return;
    try {
        const url = `${API_BASE}/fat-reports/${reportId}/items/${itemId}/photo?photoId=${photoId}`;
        const res = await authFetch(url, {
            method: 'DELETE'
        });
        if (res.ok) {
            showToast('ลบรูปภาพสำเร็จ');
            await loadFatReportDetails(reportId);
        } else {
            showToast('Failed to delete photo', 'error');
        }
    } catch (err) {
        console.error(err);
        showToast('Error deleting photo', 'error');
    }
};

async function saveFatReportResults(reportId) {
    const dateInput = document.getElementById('det-fat-date').value;
    const containerInput = document.getElementById('det-fat-container').value.trim();
    const panelInput = document.getElementById('det-fat-panel').value.trim();
    const locationInput = document.getElementById('det-fat-location').value.trim();
    const ratedInput = document.getElementById('det-fat-rated').value.trim();
    const voltageInput = document.getElementById('det-fat-voltage').value.trim();
    const instrModelInputs = document.querySelectorAll('.fat-instr-model-input');
    const instrSnInputs = document.querySelectorAll('.fat-instr-sn-input');
    const instrExpInputs = document.querySelectorAll('.fat-instr-exp-input');

    const models = Array.from(instrModelInputs).map(input => input.value.trim());
    const sns = Array.from(instrSnInputs).map(input => input.value.trim());
    const exps = Array.from(instrExpInputs).map(input => input.value.trim());

    const instrModelInput = models.join('|');
    const instrSnInput = sns.join('|');
    const instrExpInput = exps.join('|');

    const header = {
        testing_date: dateInput,
        container_no: containerInput,
        panel_type: panelInput,
        location: locationInput,
        rated: ratedInput,
        voltage: voltageInput,
        instrument_model: instrModelInput,
        instrument_sn: instrSnInput,
        instrument_expire: instrExpInput
    };

    const rows = document.querySelectorAll('.fat-item-row');
    const items = [];

    rows.forEach(row => {
        const id = parseInt(row.dataset.id);
        const passChk = row.querySelector('.fat-chk-pass');
        const failChk = row.querySelector('.fat-chk-fail');
        const inlineValInput = row.querySelector('.fat-inline-val');
        const inlineBracketValInput = row.querySelector('.fat-inline-bracket-val');
        
        const origItem = state.currentFatReportItems.find(it => it.id === id) || {};
        let description = origItem.description || '';
        
        if (inlineValInput) {
            const newVal = inlineValInput.value.trim();
            const regex = /(\.\.\.+)\s*([0-9\.]*)\s*(\.\.\.+)/;
            description = description.replace(regex, (match, p1, p2, p3) => {
                return `${p1}${newVal}${p3}`;
            });
        } else if (inlineBracketValInput) {
            const inputs = Array.from(row.querySelectorAll('.fat-inline-bracket-val'));
            let replacementIndex = 0;
            const regex = /\[([X0-9a-zA-Z\s\.\-\|]*)\]/g;
            description = (origItem.description || '').replace(regex, (match, innerVal) => {
                const input = inputs[replacementIndex++];
                if (input) {
                    const newVal = input.value.trim();
                    const isPlaceholder = /^[X\|]+$/i.test(innerVal.trim());
                    const originalPlaceholder = isPlaceholder ? innerVal : 'XXXXXX';
                    const displayVal = newVal === '' ? originalPlaceholder : newVal;
                    return `[${displayVal}]`;
                }
                return match;
            });
        }

        if (passChk && failChk) {
            items.push({
                id: id,
                result_pass: passChk.checked ? 1 : 0,
                result_fail: failChk.checked ? 1 : 0,
                remarks: origItem.remarks || '',
                description: description
            });
        }
    });

    try {
        const res = await authFetch(`${API_BASE}/fat-reports/${reportId}/items`, {
            method: 'PUT',
            body: JSON.stringify({ header, items })
        });

        if (res.ok) {
            showToast(state.currentLanguage === 'en' ? 'FAT Report saved successfully' : 'บันทึกข้อมูลการทดสอบ FAT สำเร็จแล้ว');
            await loadFatReportDetails(reportId);
        } else {
            showToast('Save failed', 'error');
        }
    } catch (err) {
        console.error(err);
        showToast('Error saving data', 'error');
    }
}

const FAT_LOGO_BASE64 = 'data:image/png;base64,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';

function printFatReport(report, items) {
    const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
    const win = window.open('', '_blank');
    const testingDateStr = report.testing_date ? parseDbDate(report.testing_date).toLocaleDateString('th-TH') : '-';
    
    const models = (report.instrument_model || '').split('|');
    const sns = (report.instrument_sn || '').split('|');
    const exps = (report.instrument_expire || '').split('|');
    const maxLen = Math.max(models.length, sns.length, exps.length, 1);

    let lastItemNo = '';
    items.forEach(item => {
        const isTestedBy = item.item_no && item.item_no.toLowerCase().includes('tested');
        if (!isTestedBy && item.item_no && item.item_no.includes('.')) {
            lastItemNo = item.item_no;
        }
    });

    let calculatedTestedByItemNo = '3.6';
    if (lastItemNo) {
        const parts = lastItemNo.split('.');
        if (parts.length === 2) {
            const major = parseInt(parts[0]);
            const minor = parseInt(parts[1]);
            if (!isNaN(major) && !isNaN(minor)) {
                calculatedTestedByItemNo = `${major}.${minor + 1}`;
            }
        }
    }

    win.document.write(`
        <html>
        <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>FAT Report - ${escapeHtml(report.report_type)}</title>
            <style>
                body {
                    font-family: "TH Sarabun New", "Angsana New", "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
                    padding: 20px;
                    padding-top: 0;
                    color: #000;
                    font-size: 11px;
                    line-height: 1.03;
                    font-weight: bold;
                    zoom: 95%;
                }
                .report-header {
                    text-align: center;
                    margin-bottom: 5px;
                    border-bottom: 2px solid #000;
                    padding-bottom: 4px;
                }
                .report-title {
                    font-size: 22px;
                    font-weight: bold;
                    margin: 2px 0;
                    text-transform: uppercase;
                }
                .report-subtitle {
                    font-size: 18px;
                    font-weight: bold;
                    margin: 2px 0;
                }
                .meta-table {
                    width: 100%;
                    border-collapse: collapse;
                    margin-bottom: 6px;
                    table-layout: fixed;
                }
                .meta-table td {
                    padding: 1px 4px;
                    border: 1px solid #000;
                }
                .meta-table td:nth-child(1) {
                    width: 120px;
                    font-weight: bold;
                    background: #f2f2f2;
                }
                .meta-table td:nth-child(2) {
                    /* Column 2 is flexible */
                }
                .meta-table td:nth-child(3) {
                    width: 120px;
                    font-weight: bold;
                    background: #f2f2f2;
                }
                .meta-table td:nth-child(4) {
                    width: 240px;
                }
                .checklist-table {
                    width: 100%;
                    border-collapse: collapse;
                    margin-top: 5px;
                    margin-bottom: 5px;
                    table-layout: fixed;
                }
                .checklist-table th, .checklist-table td {
                    border: 1px solid #000;
                    padding: 1px 2px;
                    text-align: left;
                }
                .checklist-table th {
                    background: #f2f2f2;
                    font-weight: bold;
                    text-align: center;
                }
                .checklist-table th:nth-child(1), .checklist-table td:nth-child(1) {
                    width: 40px;
                    text-align: center;
                }
                .checklist-table th:nth-child(2), .checklist-table td:nth-child(2) {
                    /* Column 2 is flexible */
                }
                .checklist-table th:nth-child(3), .checklist-table td:nth-child(3) {
                    width: 45px;
                    text-align: center;
                }
                .checklist-table th:nth-child(4), .checklist-table td:nth-child(4) {
                    width: 45px;
                    text-align: center;
                }
                .checklist-table th:nth-child(5), .checklist-table td:nth-child(5) {
                    width: 150px;
                }
                .checklist-table td div {
                    font-size: 11px !important;
                }
                .checklist-table td span {
                    font-size: 11px !important;
                    font-weight: bold !important;
                }
                .checklist-table.scale-large th {
                    font-size: 13px !important;
                }
                .checklist-table.scale-large td div,
                .checklist-table.scale-large td span {
                    font-size: 13px !important;
                }
                .text-center {
                    text-align: center !important;
                }
                .sign-section {
                    margin-top: 5px;
                    display: flex;
                    justify-content: space-between;
                    padding: 0 40px;
                }
                .sign-section div p:first-child {
                    margin-bottom: 15px !important;
                }
                @page {
                    margin-top: 12mm;
                    margin-bottom: 8mm;
                    margin-left: 0.4in;
                    margin-right: 0.4in;
                }
                @media print {
                    body {
                        padding-top: 0 !important;
                        padding-left: 0 !important;
                        padding-right: 0 !important;
                        padding-bottom: 0 !important;
                        margin: 0 !important;
                    }
                    .print-page-wrapper {
                        height: 260mm !important;
                        position: relative !important;
                    }
                    .no-print { display: none; }
                }
                .print-page-wrapper {
                    padding: 20px;
                    padding-top: 0;
                    height: 260mm;
                    position: relative;
                    box-sizing: border-box;
                    page-break-after: always;
                }
                .page-footer {
                    position: absolute;
                    bottom: -15mm;
                    right: 20px;
                    width: calc(100% - 40px);
                    text-align: right;
                    font-size: 11px;
                    font-weight: bold;
                    border-top: 1px dashed #ccc;
                    padding-top: 4px;
                }
                .scale-90 {
                    zoom: 90% !important;
                }
            </style>
        </head>
        <body>
            <div class="print-page-wrapper ${report.report_type === 'CRAC INSPECTION' ? 'scale-90' : ''}">
            <div class="report-header" style="text-align: center; border-bottom: 2px solid #000; padding-bottom: 4px; margin-bottom: 5px;">
                <img src="${FAT_LOGO_BASE64}" style="width: 100%; max-height: 80px; object-fit: contain; margin-bottom: 5px;">
                <div class="report-title">${escapeHtml(report.report_type)} TESTING</div>
                <div class="report-subtitle">FACTORY ACCEPTANCE TEST REPORT</div>
            </div>
            
            <table class="meta-table">
                <tr>
                    <td class="meta-label">PROJECT NAME:</td>
                    <td class="meta-val">${escapeHtml(state.activeProjectSummary.name || '-')}</td>
                    <td class="meta-label">TESTING DATE:</td>
                    <td class="meta-val">${testingDateStr}</td>
                </tr>
                <tr>
                    <td class="meta-label">CONTAINER NO:</td>
                    <td class="meta-val">${escapeHtml(report.container_no || '-')}</td>
                    <td class="meta-label">PANEL TYPE:</td>
                    <td class="meta-val">${escapeHtml(report.panel_type || '-')}</td>
                </tr>
                <tr>
                    <td class="meta-label">LOCATION:</td>
                    <td class="meta-val">${escapeHtml(report.location || '-')}</td>
                    <td class="meta-label">RATED:</td>
                    <td class="meta-val">${escapeHtml(report.rated || '-')}</td>
                </tr>
                <tr>
                    <td class="meta-label">VOLTAGE:</td>
                    <td class="meta-val">${escapeHtml(report.voltage || '-')}</td>
                    <td class="meta-label">INSTRUMENT:</td>
                    <td class="meta-val">${escapeHtml(models[0] || '-')}</td>
                </tr>
                <tr>
                    <td class="meta-label">SERIAL NO:</td>
                    <td class="meta-val">${escapeHtml(sns[0] || '-')}</td>
                    <td class="meta-label">EXPIRE DATE:</td>
                    <td class="meta-val">${escapeHtml(exps[0] || '-')}</td>
                </tr>
                ${(() => {
                    let rows = '';
                    for (let i = 1; i < maxLen; i++) {
                        rows += `
                            <tr>
                                <td class="meta-label"></td>
                                <td class="meta-val"></td>
                                <td class="meta-label">INSTRUMENT:</td>
                                <td class="meta-val">${escapeHtml(models[i] || '-')}</td>
                            </tr>
                            <tr>
                                <td class="meta-label">SERIAL NO:</td>
                                <td class="meta-val">${escapeHtml(sns[i] || '-')}</td>
                                <td class="meta-label">EXPIRE DATE:</td>
                                <td class="meta-val">${escapeHtml(exps[i] || '-')}</td>
                            </tr>
                        `;
                    }
                    return rows;
                })()}
            </table>
            
            <table class="checklist-table ${report.report_type === 'AIR CONDITION INSPECTION' ? 'scale-large' : ''}" style="margin-top: 15px;">
                <thead>
                    <tr>
                        <th width="30" style="text-align: center;">ลำดับ (ITEM)</th>
                        <th style="text-align: left; padding-left: 8px;">TEST CONDITION / DESCRIPTION</th>
                        <th width="30">PASS</th>
                        <th width="30">FAIL</th>
                        <th width="140">PHOTO / REMARK</th>
                    </tr>
                </thead>
                <tbody>
                    ${(() => {
                        let photoCounter = 0;
                        const photoIndexMap = {}; // Maps itemId -> array of overall photo numbers (e.g. [1, 2])
                        items.forEach(it => {
                            const isHeader = !it.item_no || (!it.item_no.includes('.') && !it.description);
                            if (!isHeader && it.photos && it.photos.length > 0) {
                                photoIndexMap[it.id] = [];
                                it.photos.forEach(() => {
                                    photoCounter++;
                                    photoIndexMap[it.id].push(photoCounter);
                                });
                            }
                        });
                        return items.filter(item => {
                            if (item.item_no && item.item_no.toLowerCase().includes('tested')) {
                                return false;
                            }
                            return true;
                        }).map(item => {
                            const isHeader = !item.item_no || (!item.item_no.includes('.') && !item.description);
                            const bgStyle = isHeader ? 'style="background:#f2f2f2; font-weight:bold;"' : '';
                            
                            const isTestedByRow = item.item_no && item.item_no.toLowerCase().includes('tested');
                            const displayItemNo = isTestedByRow ? calculatedTestedByItemNo : item.item_no;
                            
                            const photoIndices = photoIndexMap[item.id] || [];
                            const photoStr = photoIndices.length > 0 ? `รูปภาพที่ ${photoIndices.join(', ')}` : '';
                            const remarkStr = item.remarks || '';
                            const photoVal = [photoStr, remarkStr].filter(Boolean).join(' / ');

                            return `
                                <tr ${bgStyle}>
                                    <td class="text-center" style="font-weight:bold;">${escapeHtml(displayItemNo || '')}</td>
                                    <td>
                                        <div style="font-weight:bold; font-size:${report.report_type === 'AIR CONDITION INSPECTION' ? '13px' : '11px'}; color:#000;">
                                            ${escapeHtml(item.title || '')}
                                            ${item.description ? `<span style="font-weight:bold; font-size:${report.report_type === 'AIR CONDITION INSPECTION' ? '13px' : '11px'}; color:#000;">${item.title ? ' - ' : ''}${formatInlineDescriptionPrint(item.description)}</span>` : ''}
                                        </div>
                                    </td>
                                    <td class="text-center" style="font-size:16px; font-weight:bold; color:#000;">
                                        ${item.result_pass === 1 ? '&#10003;' : ''}
                                    </td>
                                    <td class="text-center" style="font-size:16px; font-weight:bold; color:#000;">
                                        ${item.result_fail === 1 ? '&#10007;' : ''}
                                    </td>
                                    <td class="text-center" style="font-weight:bold;">${photoVal}</td>
                                </tr>
                            `;
                        }).join('');
                    })()}
                </tbody>
            </table>
            
            <div class="sign-section">
                <div style="text-align: center; width: 250px;">
                    <p style="font-weight: bold; margin-bottom: 50px;">TESTED BY</p>
                    <div style="border-bottom: 1px solid #000; width: 200px; margin: 0 auto;"></div>
                    <p style="font-size: 14px; margin-top: 6px; color: #000;">(....................................................)</p>
                    <p style="font-size: 14px; color: #000; margin-top: 3px;">วันที่: ....../....../......</p>
                </div>
                <div style="text-align: center; width: 250px;">
                    <p style="font-weight: bold; margin-bottom: 50px;">WITNESSED BY (CLIENT)</p>
                    <div style="border-bottom: 1px solid #000; width: 200px; margin: 0 auto;"></div>
                    <p style="font-size: 14px; margin-top: 6px; color: #000;">(....................................................)</p>
                    <p style="font-size: 14px; color: #000; margin-top: 3px;">วันที่: ....../....../......</p>
                </div>
            
            <div class="page-footer">หน้าที่ 1</div>
            </div>
            </div>
            
            ${(() => {
                const photosToPrint = [];
                items.forEach(it => {
                    if (it.photos && it.photos.length > 0) {
                        it.photos.forEach((photoId, idx) => {
                            photosToPrint.push({
                                item_no: it.item_no,
                                title: it.title,
                                photoId: photoId,
                                index: idx + 1,
                                total: it.photos.length
                            });
                        });
                    }
                });

                if (photosToPrint.length === 0) return '';
                
                const photoChunks = [];
                for (let i = 0; i < photosToPrint.length; i += 4) {
                    photoChunks.push(photosToPrint.slice(i, i + 4));
                }

                let curPage = 1;
                let html = '';
                
                photoChunks.forEach((chunk, chunkIdx) => {
                    curPage++;
                    html += `
                        <div class="print-page-wrapper">
                            <div class="report-header" style="margin-bottom: 20px; text-align: center; border-bottom: 2px solid #000; padding-bottom: 4px;">
                                <img src="${FAT_LOGO_BASE64}" style="width: 100%; max-height: 80px; object-fit: contain; margin-bottom: 5px;">
                                <div class="report-title">${escapeHtml(report.report_type)} TESTING</div>
                                <div class="report-subtitle">FACTORY ACCEPTANCE TEST REPORT</div>
                            </div>
                            <h2 style="text-align: center; border-bottom: 2px solid #000; padding-bottom: 8px; margin-bottom: 20px; font-size: 16px;">
                                ATTACHED PHOTOS (รูปภาพประกอบรายงานการทดสอบ)
                            </h2>
                            <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px;">
                                ${chunk.map((item, idx) => {
                                    const overallPhotoIndex = (chunkIdx * 4) + idx + 1;
                                    return `
                                        <div style="border: 1px solid #000; padding: 6px; text-align: center; break-inside: avoid; background: #fff;">
                                            <div style="font-weight: bold; font-size: 12px; margin-bottom: 6px; text-align: left; border-bottom: 1px solid #000; padding-bottom: 2px;">
                                                รูปภาพที่ ${overallPhotoIndex}: ข้อ ${item.item_no || ''} ${escapeHtml(item.title || '')} (${item.index}/${item.total})
                                            </div>
                                            <div style="height: 200px; display: flex; align-items: center; justify-content: center; background: #fafafa;">
                                                <img src="${withAuthToken(`${window.location.origin}${API_BASE}/fat-reports/photos/${item.photoId}`)}" style="max-width: 100%; max-height: 100%; object-fit: contain; border: 1px solid #000;">
                                            </div>
                                        </div>
                                    `;
                                }).join('')}
                            </div>
                            <div class="page-footer">หน้าที่ ${curPage}</div>
                        </div>
                    `;
                });
                return html;
            })()}
        </body>
        </html>
    `);
    win.document.close();
    win.focus();

    const imgs = win.document.querySelectorAll('img');
    if (imgs.length > 0) {
        let loadedCount = 0;
        const triggerPrint = () => {
            loadedCount++;
            if (loadedCount === imgs.length) {
                win.print();
                if (!isMobile) win.close();
            }
        };
        imgs.forEach(img => {
            if (img.complete) {
                triggerPrint();
            } else {
                img.onload = triggerPrint;
                img.onerror = triggerPrint;
            }
        });
        setTimeout(() => {
            if (loadedCount < imgs.length) {
                win.print();
                if (!isMobile) win.close();
            }
        }, 1500);
    } else {
        win.print();
        if (!isMobile) win.close();
    }
}

async function printAllFatReports() {
    const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
    try {
        const resReports = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/fat-reports`);
        if (!resReports.ok) throw new Error('Failed to fetch reports');
        const reports = await resReports.json();

        // Filter by currently selected container in the sidebar
        const filterVal = document.getElementById('fat-filter-container') ? document.getElementById('fat-filter-container').value : '';
        const filteredReports = filterVal ? reports.filter(r => r.container_no === filterVal) : reports;

        if (filteredReports.length === 0) {
            alert(state.currentLanguage === 'en' ? 'No reports to print' : 'ไม่มีรายงานสำหรับพิมพ์');
            return;
        }

        const reportsWithItems = [];
        for (const report of filteredReports) {
            const resItems = await authFetch(`${API_BASE}/fat-reports/${report.id}/items`);
            if (resItems.ok) {
                const items = await resItems.json();
                reportsWithItems.push({ report, items });
            }
        }

        // Sort reports chronologically by creation date (oldest first)
        reportsWithItems.reverse();

        const win = window.open('', '_blank');
        if (!win) {
            alert('Please allow popups to print');
            return;
        }

        let pageCounter = 0;
        let bodyHtml = '';

        reportsWithItems.forEach((rObj, reportIdx) => {
            const report = rObj.report;
            const items = rObj.items;

            pageCounter++;

            const testingDateStr = report.testing_date ? parseDbDate(report.testing_date).toLocaleDateString('th-TH') : '-';
            
            const models = report.instrument_model ? report.instrument_model.split(',') : [];
            const sns = report.instrument_sn ? report.instrument_sn.split(',') : [];
            const exps = report.instrument_expire ? report.instrument_expire.split(',') : [];
            const maxLen = Math.max(models.length, sns.length, exps.length, 1);

            let calculatedTestedByItemNo = '4';
            const lastNoRow = items.filter(it => it.item_no && it.item_no.includes('.')).pop();
            if (lastNoRow && lastNoRow.item_no) {
                const parts = lastNoRow.item_no.split('.');
                if (parts.length === 2) {
                    const major = parseInt(parts[0]);
                    const minor = parseInt(parts[1]);
                    if (!isNaN(major) && !isNaN(minor)) {
                        calculatedTestedByItemNo = `${major}.${minor + 1}`;
                    }
                }
            }

            let metaRows = `
                <tr>
                    <td class="meta-label">PROJECT NAME:</td>
                    <td class="meta-val">${escapeHtml(state.activeProjectSummary.name || '-')}</td>
                    <td class="meta-label">TESTING DATE:</td>
                    <td class="meta-val">${testingDateStr}</td>
                </tr>
                <tr>
                    <td class="meta-label">CONTAINER NO:</td>
                    <td class="meta-val">${escapeHtml(report.container_no || '-')}</td>
                    <td class="meta-label">PANEL TYPE:</td>
                    <td class="meta-val">${escapeHtml(report.panel_type || '-')}</td>
                </tr>
                <tr>
                    <td class="meta-label">LOCATION:</td>
                    <td class="meta-val">${escapeHtml(report.location || '-')}</td>
                    <td class="meta-label">RATED:</td>
                    <td class="meta-val">${escapeHtml(report.rated || '-')}</td>
                </tr>
                <tr>
                    <td class="meta-label">VOLTAGE:</td>
                    <td class="meta-val">${escapeHtml(report.voltage || '-')}</td>
                    <td class="meta-label">INSTRUMENT:</td>
                    <td class="meta-val">${escapeHtml(models[0] || '-')}</td>
                </tr>
                <tr>
                    <td class="meta-label">SERIAL NO:</td>
                    <td class="meta-val">${escapeHtml(sns[0] || '-')}</td>
                    <td class="meta-label">EXPIRE DATE:</td>
                    <td class="meta-val">${escapeHtml(exps[0] || '-')}</td>
                </tr>
            `;

            for (let i = 1; i < maxLen; i++) {
                metaRows += `
                    <tr>
                        <td class="meta-label"></td>
                        <td class="meta-val"></td>
                        <td class="meta-label">INSTRUMENT:</td>
                        <td class="meta-val">${escapeHtml(models[i] || '-')}</td>
                    </tr>
                    <tr>
                        <td class="meta-label">SERIAL NO:</td>
                        <td class="meta-val">${escapeHtml(sns[i] || '-')}</td>
                        <td class="meta-label">EXPIRE DATE:</td>
                        <td class="meta-val">${escapeHtml(exps[i] || '-')}</td>
                    </tr>
                `;
            }

            const filteredItems = items.filter(item => {
                if (item.item_no && item.item_no.toLowerCase().includes('tested')) {
                    return false;
                }
                return true;
            });

            let reportPhotoCounter = 0;
            const photoIndexMap = {}; // Maps itemId -> array of overall photo numbers (e.g. [1, 2])
            filteredItems.forEach(it => {
                const isHeader = !it.item_no || (!it.item_no.includes('.') && !it.description);
                if (!isHeader && it.photos && it.photos.length > 0) {
                    photoIndexMap[it.id] = [];
                    it.photos.forEach(() => {
                        reportPhotoCounter++;
                        photoIndexMap[it.id].push(reportPhotoCounter);
                    });
                }
            });

            // Checklist page
            bodyHtml += `
                <div class="print-page-wrapper ${report.report_type === 'CRAC INSPECTION' ? 'scale-90' : ''}">
                    <div class="report-header" style="text-align: center; border-bottom: 2px solid #000; padding-bottom: 4px; margin-bottom: 5px;">
                        <img src="${FAT_LOGO_BASE64}" style="width: 100%; max-height: 80px; object-fit: contain; margin-bottom: 5px;">
                        <div class="report-title">${escapeHtml(report.report_type)} TESTING</div>
                        <div class="report-subtitle">FACTORY ACCEPTANCE TEST REPORT</div>
                    </div>
                    
                    <table class="meta-table">
                        ${metaRows}
                    </table>
                    
                    <table class="checklist-table ${report.report_type === 'AIR CONDITION INSPECTION' ? 'scale-large' : ''}">
                        <thead>
                            <tr>
                                <th width="40" style="text-align: center;">ลำดับ (ITEM)</th>
                                <th style="text-align: left; padding-left: 8px;">TEST CONDITION / DESCRIPTION</th>
                                <th width="45">PASS</th>
                                <th width="45">FAIL</th>
                                <th width="150">PHOTO / REMARK</th>
                            </tr>
                        </thead>
                        <tbody>
                            ${filteredItems.map(item => {
                                const isHeader = !item.item_no || (!item.item_no.includes('.') && !item.description);
                                const bgStyle = isHeader ? 'style="background:#f2f2f2; font-weight:bold;"' : '';
                                const isTestedByRow = item.item_no && item.item_no.toLowerCase().includes('tested');
                                const displayItemNo = isTestedByRow ? calculatedTestedByItemNo : item.item_no;
                                
                                const photoIndices = photoIndexMap[item.id] || [];
                                const photoStr = photoIndices.length > 0 ? `รูปภาพที่ ${photoIndices.join(', ')}` : '';
                                const remarkStr = item.remarks || '';
                                const photoVal = [photoStr, remarkStr].filter(Boolean).join(' / ');

                                return `
                                    <tr ${bgStyle}>
                                        <td class="text-center" style="font-weight:bold;">${escapeHtml(displayItemNo || '')}</td>
                                        <td>
                                            <div style="font-weight:bold; font-size:${report.report_type === 'AIR CONDITION INSPECTION' ? '13px' : '11px'}; color:#000;">
                                                ${escapeHtml(item.title || '')}
                                                ${item.description ? `<span style="font-weight:bold; font-size:${report.report_type === 'AIR CONDITION INSPECTION' ? '13px' : '11px'}; color:#000;">${item.title ? ' - ' : ''}${formatInlineDescriptionPrint(item.description)}</span>` : ''}
                                            </div>
                                        </td>
                                        <td class="text-center" style="font-size:16px; font-weight:bold; color:#000;">
                                            ${item.result_pass === 1 ? '&#10003;' : ''}
                                        </td>
                                        <td class="text-center" style="font-size:16px; font-weight:bold; color:#000;">
                                            ${item.result_fail === 1 ? '&#10007;' : ''}
                                        </td>
                                        <td class="text-center" style="font-weight:bold;">${photoVal}</td>
                                    </tr>
                                `;
                            }).join('')}
                        </tbody>
                    </table>
                    
                    <div class="sign-section">
                        <div style="text-align: center; width: 250px;">
                            <p style="font-weight: bold; margin-bottom: 50px;">TESTED BY</p>
                            <div style="border-bottom: 1px solid #000; width: 200px; margin: 0 auto;"></div>
                            <p style="font-size: 14px; margin-top: 6px; color: #000;">(....................................................)</p>
                            <p style="font-size: 14px; color: #000; margin-top: 3px;">วันที่: ....../....../......</p>
                        </div>
                        <div style="text-align: center; width: 250px;">
                            <p style="font-weight: bold; margin-bottom: 50px;">WITNESSED BY (CLIENT)</p>
                            <div style="border-bottom: 1px solid #000; width: 200px; margin: 0 auto;"></div>
                            <p style="font-size: 14px; margin-top: 6px; color: #000;">(....................................................)</p>
                            <p style="font-size: 14px; color: #000; margin-top: 3px;">วันที่: ....../....../......</p>
                        </div>
                    </div>

                    <div class="page-footer">หน้าที่ ${pageCounter}</div>
                </div>
            `;

            // Photo pages
            const photosToPrint = [];
            filteredItems.forEach(it => {
                if (it.photos && it.photos.length > 0) {
                    it.photos.forEach((photoId, idx) => {
                        photosToPrint.push({
                            item_no: it.item_no,
                            title: it.title,
                            photoId: photoId,
                            index: idx + 1,
                            total: it.photos.length
                        });
                    });
                }
            });
            
            if (photosToPrint.length > 0) {
                const photoChunks = [];
                for (let i = 0; i < photosToPrint.length; i += 4) {
                    photoChunks.push(photosToPrint.slice(i, i + 4));
                }

                photoChunks.forEach((chunk, chunkIdx) => {
                    pageCounter++;
                    bodyHtml += `
                        <div class="print-page-wrapper">
                            <div class="report-header" style="margin-bottom: 20px; text-align: center; border-bottom: 2px solid #000; padding-bottom: 4px;">
                                <img src="${FAT_LOGO_BASE64}" style="width: 100%; max-height: 80px; object-fit: contain; margin-bottom: 5px;">
                                <div class="report-title">${escapeHtml(report.report_type)} TESTING</div>
                                <div class="report-subtitle">FACTORY ACCEPTANCE TEST REPORT</div>
                            </div>
                            <h2 style="text-align: center; border-bottom: 2px solid #000; padding-bottom: 8px; margin-bottom: 20px; font-size: 16px;">
                                ATTACHED PHOTOS (รูปภาพประกอบรายงานการทดสอบ)
                            </h2>
                            <div style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px;">
                                ${chunk.map((item, idx) => {
                                    const overallPhotoIndex = (chunkIdx * 4) + idx + 1;
                                    return `
                                        <div style="border: 1px solid #000; padding: 6px; text-align: center; break-inside: avoid; background: #fff;">
                                            <div style="font-weight: bold; font-size: 12px; margin-bottom: 6px; text-align: left; border-bottom: 1px solid #000; padding-bottom: 2px;">
                                                รูปภาพที่ ${overallPhotoIndex}: ข้อ ${item.item_no || ''} ${escapeHtml(item.title || '')} (${item.index}/${item.total})
                                            </div>
                                            <div style="height: 200px; display: flex; align-items: center; justify-content: center; background: #fafafa;">
                                                <img src="${withAuthToken(`${window.location.origin}${API_BASE}/fat-reports/photos/${item.photoId}`)}" style="max-width: 100%; max-height: 100%; object-fit: contain; border: 1px solid #000;">
                                            </div>
                                        </div>
                                    `;
                                }).join('')}
                            </div>
                            <div class="page-footer">หน้าที่ ${pageCounter}</div>
                        </div>
                    `;
                });
            }
        });

        win.document.write(`
            <html>
            <head>
                <meta charset="utf-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>FAT Report Package - Project ${escapeHtml(state.activeProjectSummary.name || '')}</title>
                <style>
                    body {
                        font-family: "TH Sarabun New", "Angsana New", "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
                        padding: 0;
                        margin: 0;
                        color: #000;
                        font-weight: bold;
                        zoom: 95%;
                    }
                    .print-page-wrapper {
                        padding: 20px;
                        padding-top: 0;
                        height: 260mm;
                        position: relative;
                        box-sizing: border-box;
                        page-break-after: always;
                    }
                    .report-header {
                        text-align: center;
                        margin-bottom: 5px;
                        border-bottom: 2px solid #000;
                        padding-bottom: 4px;
                    }
                    .report-title {
                        font-size: 22px;
                        font-weight: bold;
                        margin: 2px 0;
                        text-transform: uppercase;
                    }
                    .report-subtitle {
                        font-size: 18px;
                        font-weight: bold;
                        margin: 2px 0;
                    }
                    .meta-table {
                        width: 100%;
                        border-collapse: collapse;
                        margin-bottom: 6px;
                        table-layout: fixed;
                    }
                    .meta-table td {
                        padding: 1px 4px;
                        border: 1px solid #000;
                    }
                    .meta-table td:nth-child(1) {
                        width: 120px;
                        font-weight: bold;
                        background: #f2f2f2;
                    }
                    .meta-table td:nth-child(3) {
                        width: 120px;
                        font-weight: bold;
                        background: #f2f2f2;
                    }
                    .meta-table td:nth-child(4) {
                        width: 240px;
                    }
                    .checklist-table {
                        width: 100%;
                        border-collapse: collapse;
                        margin-top: 5px;
                        margin-bottom: 5px;
                        table-layout: fixed;
                    }
                    .checklist-table th, .checklist-table td {
                        border: 1px solid #000;
                        padding: 1px 2px;
                        text-align: left;
                    }
                    .checklist-table th {
                        background: #f2f2f2;
                        font-weight: bold;
                        text-align: center;
                    }
                    .checklist-table th:nth-child(1), .checklist-table td:nth-child(1) {
                        width: 40px;
                        text-align: center;
                    }
                    .checklist-table th:nth-child(3), .checklist-table td:nth-child(3) {
                        width: 45px;
                        text-align: center;
                    }
                    .checklist-table th:nth-child(4), .checklist-table td:nth-child(4) {
                        width: 45px;
                        text-align: center;
                    }
                    .checklist-table th:nth-child(5), .checklist-table td:nth-child(5) {
                        width: 150px;
                    }
                    .checklist-table td div {
                        font-size: 11px !important;
                    }
                    .checklist-table td span {
                        font-size: 11px !important;
                        font-weight: bold !important;
                    }
                    .checklist-table.scale-large th {
                        font-size: 13px !important;
                    }
                    .checklist-table.scale-large td div,
                    .checklist-table.scale-large td span {
                        font-size: 13px !important;
                    }
                    .text-center {
                        text-align: center !important;
                    }
                    .sign-section {
                        margin-top: 5px;
                        display: flex;
                        justify-content: space-between;
                        padding: 0 40px;
                    }
                    .sign-section div p:first-child {
                        margin-bottom: 15px !important;
                    }
                    .page-footer {
                        position: absolute;
                        bottom: -15mm;
                        right: 20px;
                        width: calc(100% - 40px);
                        text-align: right;
                        font-size: 11px;
                        font-weight: bold;
                        border-top: 1px dashed #ccc;
                        padding-top: 4px;
                    }
                    .scale-90 {
                        zoom: 90% !important;
                    }
                    @page {
                        margin-top: 12mm;
                        margin-bottom: 8mm;
                        margin-left: 0.4in;
                        margin-right: 0.4in;
                    }
                    @media print {
                        .print-page-wrapper {
                            padding-top: 0 !important;
                            padding-left: 0 !important;
                            padding-right: 0 !important;
                            padding-bottom: 0 !important;
                            margin: 0 !important;
                            height: 260mm !important;
                            position: relative !important;
                        }
                        .no-print { display: none; }
                    }
                </style>
            </head>
            <body>
                ${bodyHtml}
            </body>
            </html>
        `);
        win.document.close();
        win.focus();

        const imgs = win.document.querySelectorAll('img');
        if (imgs.length > 0) {
            let loadedCount = 0;
            const triggerPrint = () => {
                loadedCount++;
                if (loadedCount === imgs.length) {
                    win.print();
                    if (!isMobile) win.close();
                }
            };
            imgs.forEach(img => {
                if (img.complete) {
                    triggerPrint();
                } else {
                    img.onload = triggerPrint;
                    img.onerror = triggerPrint;
                }
            });
            setTimeout(() => {
                if (loadedCount < imgs.length) {
                    win.print();
                    if (!isMobile) win.close();
                }
            }, 2500);
        } else {
            win.print();
            if (!isMobile) win.close();
        }
    } catch (err) {
        console.error(err);
        alert(state.currentLanguage === 'en' ? 'Failed to generate print package' : 'เกิดข้อผิดพลาดในการสร้างเอกสารพิมพ์');
    }
}

// ==========================================
// TEST SCRIPT CLIENT LOGIC
// ==========================================

let activeTestScriptReportId = null;

async function openProjectTestScriptModal() {
    if (!state.activeProjectId || !state.activeProjectSummary) return;

    // Open modal
    document.getElementById('modal-project-test-script').classList.add('active');

    // Reset Detail view
    activeTestScriptReportId = null;
    document.getElementById('test-script-detail-pane').innerHTML = `
        <div style="text-align: center; color: var(--text-muted); margin: auto; display: flex; flex-direction: column; align-items: center; gap: 12px;">
            <i class="fa-solid fa-file-contract" style="font-size: 3rem; color: var(--border-color);"></i>
            <p data-i18n="test_script_select_prompt">${state.currentLanguage === 'en' ? 'Please select a test script item from the list on the left.' : 'กรุณาเลือกรายการแนวทางการทดสอบจากรายการด้านซ้าย'}</p>
        </div>
    `;

    await fetchAndRenderTestScriptsList();
}

function closeProjectTestScriptModal() {
    document.getElementById('modal-project-test-script').classList.remove('active');
}

async function fetchAndRenderTestScriptsList() {
    const container = document.getElementById('test-script-list-container');
    if (!container) return;
    container.innerHTML = `<div style="text-align:center; padding: 20px;"><i class="fa-solid fa-spinner fa-spin" style="color:var(--primary-color);"></i></div>`;

    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/test-scripts`);
        if (!res.ok) throw new Error('Failed to fetch');
        const scripts = await res.json();

        container.innerHTML = '';
        if (scripts.length === 0) {
            container.innerHTML = `<div style="text-align:center; color:var(--text-muted); font-size:0.85rem; padding: 20px;">${state.currentLanguage === 'en' ? 'No test scripts found (Please create a FAT report first)' : 'ไม่มีแนวทางการทดสอบ (กรุณาสร้างรายงาน FAT ก่อน)'}</div>`;
            return;
        }

        scripts.forEach(s => {
            const item = document.createElement('div');
            item.className = `test-script-list-item ${activeTestScriptReportId === s.id ? 'active' : ''}`;
            
            // Format creation date
            const dateStr = s.created_at ? parseDbDate(s.created_at).toLocaleDateString('th-TH') : '-';

            item.innerHTML = `
                <div style="font-weight:600; color:var(--text-dark); display:flex; justify-content:space-between; align-items:center; gap:8px;">
                    <span style="word-break:break-word; text-align:left;">${escapeHtml(s.report_type)}</span>
                    <span class="badge" style="font-size:0.75rem; padding: 2px 8px; border-radius: 12px; background: ${s.file_count > 0 ? '#10b981' : '#6b7280'}; color: white; flex-shrink:0;">
                        <i class="fa-solid fa-paperclip"></i> ${s.file_count}
                    </span>
                </div>
                <div style="font-size:0.75rem; color:var(--text-muted); text-align:left; margin-top:2px;">
                    <i class="fa-regular fa-calendar" style="margin-right:4px;"></i> ${dateStr}
                </div>
            `;

            item.addEventListener('click', () => {
                // Remove active class from all items
                container.querySelectorAll('.test-script-list-item').forEach(el => el.classList.remove('active'));
                item.classList.add('active');
                loadTestScriptDetails(s.id, s.report_type);
            });

            container.appendChild(item);
        });
    } catch (err) {
        console.error(err);
        container.innerHTML = `<div style="text-align:center; color:var(--danger); font-size:0.85rem; padding: 20px;">${state.currentLanguage === 'en' ? 'Failed to load test scripts' : 'โหลดแนวทางการทดสอบไม่สำเร็จ'}</div>`;
    }
}

async function loadTestScriptDetails(reportId, reportType) {
    activeTestScriptReportId = reportId;

    // Close mobile drawer if active
    const sidebar = document.querySelector('#modal-project-test-script .test-script-sidebar');
    if (sidebar) sidebar.classList.remove('drawer-active');

    const pane = document.getElementById('test-script-detail-pane');
    if (!pane) return;

    pane.innerHTML = `<div style="text-align:center; padding: 40px;"><i class="fa-solid fa-spinner fa-spin fa-2x" style="color:var(--primary-color);"></i></div>`;

    try {
        const res = await authFetch(`${API_BASE}/test-scripts/${reportId}/files`);
        if (!res.ok) throw new Error('Failed to fetch files');
        const files = await res.json();

        pane.innerHTML = `
            <div style="display:flex; justify-content:space-between; align-items:center; border-bottom:1px solid var(--border-color); padding-bottom:15px; margin-bottom:20px; gap:15px;">
                <h4 style="margin:0; font-size:1.25rem; color:var(--primary-color); display:flex; align-items:center; gap:8px; word-break:break-all;">
                    <i class="fa-solid fa-file-contract"></i> ${escapeHtml(reportType)}
                </h4>
                <div style="flex-shrink:0;">
                    <input type="file" id="test-script-file-uploader" style="display:none;" multiple accept=".pdf,.doc,.docx,.xls,.xlsx,.png,.jpg,.jpeg,.gif,.webp">
                    <button class="btn btn-primary btn-sm" id="btn-upload-test-script-trigger" style="display:flex; align-items:center; gap:6px;">
                        <i class="fa-solid fa-cloud-arrow-up"></i> ${state.currentLanguage === 'en' ? 'Upload File' : 'อัปโหลดไฟล์'}
                    </button>
                </div>
            </div>
            
            <div id="test-script-files-table-container">
                ${renderTestScriptFilesTable(files)}
            </div>
        `;

        // Register upload button handlers
        const uploader = document.getElementById('test-script-file-uploader');
        const triggerBtn = document.getElementById('btn-upload-test-script-trigger');
        
        if (triggerBtn && uploader) {
            triggerBtn.addEventListener('click', () => uploader.click());
            uploader.addEventListener('change', (e) => handleTestScriptFilesUpload(e, reportId, reportType));
        }

        // Register preview click handlers
        pane.querySelectorAll('.test-script-file-preview-btn, .btn-preview-test-script').forEach(el => {
            el.addEventListener('click', (e) => {
                e.preventDefault();
                e.stopPropagation();
                const fileId = el.getAttribute('data-id');
                const name = el.getAttribute('data-name');
                const fType = el.getAttribute('data-type');
                openDocumentPreview(fileId, name, fType, true);
            });
        });

    } catch (err) {
        console.error(err);
        pane.innerHTML = `<div style="text-align:center; color:var(--danger); padding:40px;">${state.currentLanguage === 'en' ? 'Error loading files' : 'เกิดข้อผิดพลาดในการโหลดไฟล์'}</div>`;
    }
}

function renderTestScriptFilesTable(files) {
    if (files.length === 0) {
        return `
            <div style="text-align:center; padding:40px; color:var(--text-muted); display:flex; flex-direction:column; align-items:center; gap:8px;">
                <i class="fa-regular fa-folder-open" style="font-size:3rem; color:var(--border-color);"></i>
                <p data-i18n="test_script_no_files">${state.currentLanguage === 'en' ? 'No files uploaded for this test script.' : 'ไม่มีไฟล์สำหรับแนวทางการทดสอบนี้'}</p>
            </div>
        `;
    }

    return `
        <table class="table" style="width:100%; border-collapse:collapse; margin-top:10px;">
            <thead>
                <tr style="border-bottom:2px solid var(--border-color); text-align:left;">
                    <th style="padding:10px 8px;" data-i18n="test_script_file_name_label">${state.currentLanguage === 'en' ? 'File Name' : 'ชื่อไฟล์'}</th>
                    <th style="padding:10px 8px; width:120px;" data-i18n="test_script_file_size_label">${state.currentLanguage === 'en' ? 'File Size' : 'ขนาดไฟล์'}</th>
                    <th style="padding:10px 8px; width:180px;" data-i18n="test_script_uploaded_at_label">${state.currentLanguage === 'en' ? 'Uploaded At' : 'วันที่อัปโหลด'}</th>
                    <th style="padding:10px 8px; width:120px; text-align:center;">Action</th>
                </tr>
            </thead>
            <tbody>
                ${files.map(f => {
                    const dateStr = f.uploaded_at ? parseDbDate(f.uploaded_at).toLocaleString('th-TH') : '-';
                    const sizeStr = formatBytes(f.file_size);
                    const ext = f.file_type.toLowerCase();
                    
                    // Determine file icon
                    let iconClass = 'fa-file';
                    let iconColor = 'var(--text-muted)';
                    if (ext === 'pdf') {
                        iconClass = 'fa-file-pdf';
                        iconColor = '#ef4444';
                    } else if (['doc', 'docx'].includes(ext)) {
                        iconClass = 'fa-file-word';
                        iconColor = '#3b82f6';
                    } else if (['xls', 'xlsx'].includes(ext)) {
                        iconClass = 'fa-file-excel';
                        iconColor = '#22c55e';
                    } else if (['png', 'jpg', 'jpeg', 'gif', 'webp'].includes(ext)) {
                        iconClass = 'fa-file-image';
                        iconColor = '#f59e0b';
                    }

                    return `
                        <tr style="border-bottom:1px solid var(--border-color);">
                            <td style="padding:10px 8px; vertical-align:middle; text-align:left;">
                                <div style="display:flex; align-items:center; gap:8px;">
                                    <i class="fa-solid ${iconClass}" style="font-size:1.2rem; color:${iconColor};"></i>
                                    <span class="test-script-file-preview-btn" data-id="${f.id}" data-name="${escapeHtml(f.file_name)}" data-type="${ext}" style="font-weight:500; color:var(--primary-color); cursor:pointer; word-break:break-all;" title="${state.currentLanguage === 'en' ? 'Click to preview' : 'คลิกเพื่อแสดงตัวอย่าง'}">${escapeHtml(f.file_name)}</span>
                                </div>
                            </td>
                            <td style="padding:10px 8px; vertical-align:middle; text-align:left; font-size:0.85rem; color:var(--text-muted);">${sizeStr}</td>
                            <td style="padding:10px 8px; vertical-align:middle; text-align:left; font-size:0.85rem; color:var(--text-muted);">${dateStr}</td>
                            <td style="padding:10px 8px; vertical-align:middle; text-align:center;">
                                <div style="display:inline-flex; gap:6px;">
                                    <button class="btn btn-outline btn-xs btn-preview-test-script" data-id="${f.id}" data-name="${escapeHtml(f.file_name)}" data-type="${ext}" style="padding:3px 6px; font-size:0.75rem;" title="${state.currentLanguage === 'en' ? 'Preview' : 'แสดงตัวอย่าง'}">
                                        <i class="fa-solid fa-eye text-primary-color"></i>
                                    </button>
                                    <a href="${withAuthToken(`${API_BASE}/test-scripts/files/${f.id}`)}" download class="btn btn-outline btn-xs" style="padding:3px 6px; font-size:0.75rem;" title="${state.currentLanguage === 'en' ? 'Download' : 'ดาวน์โหลด'}">
                                        <i class="fa-solid fa-download text-success"></i>
                                    </a>
                                    <button class="btn btn-danger-outline btn-xs" style="padding:3px 6px; font-size:0.75rem;" onclick="handleDeleteTestScriptFile(${f.id}, ${f.fat_report_id}, '${escapeHtml(f.file_name)}')">
                                        <i class="fa-solid fa-trash text-danger"></i>
                                    </button>
                                </div>
                            </td>
                        </tr>
                    `;
                }).join('')}
            </tbody>
        </table>
    `;
}

async function handleTestScriptFilesUpload(e, reportId, reportType) {
    const files = e.target.files;
    if (files.length === 0) return;

    // Show loading indicator
    const container = document.getElementById('test-script-files-table-container');
    if (container) {
        container.innerHTML = `<div style="text-align:center; padding: 40px;"><i class="fa-solid fa-spinner fa-spin fa-2x" style="color:var(--primary-color);"></i><p style="margin-top:10px; font-size:0.85rem; color:var(--text-muted);">กำลังอัปโหลดไฟล์...</p></div>`;
    }

    try {
        for (const file of files) {
            const formData = new FormData();
            formData.append('file', file);

            const res = await authFetch(`${API_BASE}/test-scripts/${reportId}/files`, {
                method: 'POST',
                body: formData
            });

            if (!res.ok) {
                const err = await res.json();
                throw new Error(err.error || 'Failed to upload file');
            }
        }

        showToast(state.currentLanguage === 'en' ? 'Upload successful' : 'อัปโหลดไฟล์เรียบร้อยแล้ว');
        
        // Reload details and list
        await loadTestScriptDetails(reportId, reportType);
        await fetchAndRenderTestScriptsList();

    } catch (err) {
        console.error(err);
        showToast(err.message || (state.currentLanguage === 'en' ? 'Upload failed' : 'เกิดข้อผิดพลาดในการอัปโหลด'), 'error');
        await loadTestScriptDetails(reportId, reportType);
    }
}

window.handleDeleteTestScriptFile = async function(fileId, reportId, fileName) {
    if (!confirm(state.currentLanguage === 'en' ? `Are you sure you want to delete file "${fileName}"?` : `คุณแน่ใจหรือไม่ว่าต้องการลบไฟล์ "${fileName}"?`)) {
        return;
    }

    try {
        const res = await authFetch(`${API_BASE}/test-scripts/files/${fileId}`, {
            method: 'DELETE'
        });

        if (res.ok) {
            showToast(state.currentLanguage === 'en' ? 'File deleted' : 'ลบไฟล์สำเร็จแล้ว');
            
            // Reload active view and list
            const activeItem = document.querySelector('.test-script-list-item.active');
            const reportType = activeItem ? activeItem.querySelector('div span').textContent : '';
            await loadTestScriptDetails(reportId, reportType);
            await fetchAndRenderTestScriptsList();
        } else {
            const err = await res.json();
            showToast(err.error || 'Failed to delete file', 'error');
        }
    } catch (err) {
        console.error(err);
        showToast(state.currentLanguage === 'en' ? 'Network error' : 'เกิดข้อผิดพลาดในการเชื่อมต่อ', 'error');
    }
};

async function fetchAndRenderProgressList() {
    const listContainer = document.getElementById('progress-timeline-list');
    listContainer.innerHTML = `<div style="padding:40px; text-align:center; color:var(--text-muted);"><i class="fa-solid fa-spinner fa-spin" style="font-size:2rem; margin-bottom:10px; color:var(--primary-color);"></i><p>${state.currentLanguage === 'en' ? 'Loading data...' : 'กำลังโหลดข้อมูล...'}</p></div>`;

    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/progress`);
        if (!res.ok) throw new Error('Failed to load progress list');

        const progressList = await res.json();
        state.projectProgressList = progressList;

        renderProgressTimeline();
    } catch (err) {
        console.error(err);
        listContainer.innerHTML = `<div style="padding:40px; text-align:center; color:var(--danger);"><i class="fa-solid fa-circle-exclamation" style="font-size:2rem; margin-bottom:10px;"></i><p>${state.currentLanguage === 'en' ? 'Failed to load progress list' : 'ไม่สามารถโหลดข้อมูลความคืบหน้าได้'}</p></div>`;
    }
}

function renderProgressTimeline() {
    const listContainer = document.getElementById('progress-timeline-list');
    listContainer.innerHTML = '';

    if (!state.projectProgressList || state.projectProgressList.length === 0) {
        listContainer.innerHTML = `
            <div style="padding: 40px 20px; text-align: center; color: var(--text-muted);">
                <i class="fa-solid fa-chart-line" style="font-size: 2.5rem; margin-bottom: 12px; display: block; color: var(--border-color);"></i>
                ${state.currentLanguage === 'en' ? 'No progress updates recorded yet.' : 'ยังไม่มีบันทึกความคืบหน้าในโครงการนี้'}
            </div>
        `;
        return;
    }

    state.projectProgressList.forEach(item => {
        const card = document.createElement('div');
        card.className = 'progress-card';

        const updateDate = parseDbDate(item.timestamp).toLocaleString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH');

        const progressDescHtml = `
            <div class="progress-card-section">
                <div class="progress-card-section-label">${state.currentLanguage === 'en' ? 'Description' : 'รายละเอียดความคืบหน้า'}</div>
                <div class="progress-card-section-content" style="white-space: pre-wrap;">${escapeHtml(item.progress_desc || '')}</div>
            </div>
        `;

        const issuesHtml = item.issues ? `
            <div class="progress-card-section" style="border-left: 3px solid var(--danger); padding-left: 8px; margin-top:8px;">
                <div class="progress-card-section-label" style="color:var(--danger);">${state.currentLanguage === 'en' ? 'Issues & Obstacles' : 'ปัญหาและอุปสรรค'}</div>
                <div class="progress-card-section-content" style="white-space: pre-wrap;">${escapeHtml(item.issues)}</div>
            </div>
        ` : '';

        const solutionsHtml = item.solutions ? `
            <div class="progress-card-section" style="border-left: 3px solid var(--success); padding-left: 8px; margin-top:8px;">
                <div class="progress-card-section-label" style="color:var(--success);">${state.currentLanguage === 'en' ? 'Action Plan / Solutions' : 'แนวทางแก้ไข'}</div>
                <div class="progress-card-section-content" style="white-space: pre-wrap;">${escapeHtml(item.solutions)}</div>
            </div>
        ` : '';

        const suggestionsHtml = item.suggestions ? `
            <div class="progress-card-section" style="border-left: 3px solid var(--primary-color); padding-left: 8px; margin-top:8px;">
                <div class="progress-card-section-label" style="color:var(--primary-color);">${state.currentLanguage === 'en' ? 'Suggestions' : 'ข้อเสนอแนะ'}</div>
                <div class="progress-card-section-content" style="white-space: pre-wrap;">${escapeHtml(item.suggestions)}</div>
            </div>
        ` : '';

        let actionButtonsHtml = '';
        const isCreator = state.currentUser && state.currentUser.id === item.created_by;
        const isAdmin = state.currentUser && (state.currentUser.role === 'admin' || state.currentUser.role === 'superadmin');
        const isSupervisor = state.currentUser && (state.currentUser.role === 'supervisor' || state.currentUser.role === 'estimate');

        if (isAdmin || isSupervisor || isCreator) {
            actionButtonsHtml = `
                <div class="progress-card-actions">
                    <button class="btn btn-sm btn-outline btn-edit-progress-card" data-id="${item.id}" title="${state.currentLanguage === 'en' ? 'Edit' : 'แก้ไข'}" style="padding: 2px 6px;">
                        <i class="fa-solid fa-edit text-primary-color" style="font-size:0.8rem;"></i>
                    </button>
                    <button class="btn btn-sm btn-outline btn-delete-progress-card" data-id="${item.id}" title="${state.currentLanguage === 'en' ? 'Delete' : 'ลบ'}" style="padding: 2px 6px;">
                        <i class="fa-solid fa-trash-can text-danger" style="font-size:0.8rem;"></i>
                    </button>
                </div>
            `;
        }

        let bodyContentHtml = '';
        if (item.image_name) {
            const imageUrl = withAuthToken(`${API_BASE}/projects/${state.activeProjectId}/progress/${item.id}/image?_ts=${Date.now()}`);
            const titleAttr = item.image_title ? `title="${escapeHtml(item.image_title)}"` : '';
            bodyContentHtml = `
                <div class="progress-card-body-wrapper">
                    <div class="progress-card-left-col">
                        <div class="progress-card-image-box">
                            <img src="${imageUrl}" class="progress-card-img" ${titleAttr} onclick="openLightbox('${imageUrl}')" alt="${escapeHtml(item.image_title || 'Progress Image')}">
                            ${item.image_title ? `<div class="progress-card-img-caption">${escapeHtml(item.image_title)}</div>` : ''}
                        </div>
                    </div>
                    <div class="progress-card-right-col">
                        ${progressDescHtml}
                        ${issuesHtml}
                        ${solutionsHtml}
                        ${suggestionsHtml}
                    </div>
                </div>
            `;
        } else {
            bodyContentHtml = `
                <div class="progress-card-body-wrapper no-image">
                    <div class="progress-card-right-col">
                        ${progressDescHtml}
                        ${issuesHtml}
                        ${solutionsHtml}
                        ${suggestionsHtml}
                    </div>
                </div>
            `;
        }

        const sysName = item.system_name || (state.currentLanguage === 'en' ? 'General' : 'ทั่วไป');

        card.innerHTML = `
            <div class="progress-card-header">
                <div class="progress-card-meta">
                    <span class="progress-meta-item datetime">
                        <i class="fa-solid fa-calendar-day"></i> ${updateDate}
                    </span>
                    <span class="progress-meta-item creator">
                        <i class="fa-solid fa-user-circle"></i> ${state.currentLanguage === 'en' ? 'By' : 'โดย'}: ${escapeHtml(item.creator_name || 'System')}
                    </span>
                    <span class="progress-meta-item system-badge">
                        <i class="fa-solid fa-gears"></i> ${escapeHtml(sysName)}
                    </span>
                </div>
                ${actionButtonsHtml}
            </div>
            ${bodyContentHtml}
        `;

        const editBtn = card.querySelector('.btn-edit-progress-card');
        if (editBtn) {
            editBtn.addEventListener('click', () => {
                openProgressEditForm(item);
            });
        }

        const deleteBtn = card.querySelector('.btn-delete-progress-card');
        if (deleteBtn) {
            deleteBtn.addEventListener('click', () => {
                deleteProgressCard(item.id);
            });
        }

        listContainer.appendChild(card);
    });
}

function openProgressEditForm(item) {
    clearProgressForm();

    document.getElementById('progress-edit-id').value = item.id;
    document.getElementById('progress-form-title').innerHTML = `<i class="fa-solid fa-edit"></i> ${state.currentLanguage === 'en' ? 'Edit Progress Record' : 'แก้ไขข้อมูลความคืบหน้า'}`;

    document.getElementById('progress-image-title').value = item.image_title || '';
    document.getElementById('progress-desc').value = item.progress_desc || '';
    document.getElementById('progress-issues').value = item.issues || '';
    document.getElementById('progress-solutions').value = item.solutions || '';
    document.getElementById('progress-suggestions').value = item.suggestions || '';

    // Set system dropdown
    buildProgressSystemDropdown();
    const systemSelect = document.getElementById('progress-system-select');
    const customInput = document.getElementById('progress-system-custom');
    const itemSystem = item.system_name || 'ทั่วไป';

    let exists = false;
    for (let i = 0; i < systemSelect.options.length; i++) {
        if (systemSelect.options[i].value === itemSystem) {
            systemSelect.value = itemSystem;
            exists = true;
            break;
        }
    }

    if (!exists) {
        systemSelect.value = 'CUSTOM';
        customInput.value = itemSystem;
        customInput.style.display = 'block';
        customInput.required = true;
    } else {
        customInput.value = '';
        customInput.style.display = 'none';
        customInput.required = false;
    }

    if (item.timestamp) {
        const d = parseDbDate(item.timestamp);
        const tzoffset = d.getTimezoneOffset() * 60000;
        const localISOTime = (new Date(d - tzoffset)).toISOString().slice(0, 16);
        document.getElementById('progress-timestamp').value = localISOTime;
    }

    if (item.image_name) {
        const placeholder = document.getElementById('progress-image-preview-placeholder');
        const container = document.getElementById('progress-image-preview-container');
        const img = document.getElementById('progress-image-preview-img');

        img.src = withAuthToken(`${API_BASE}/projects/${state.activeProjectId}/progress/${item.id}/image?_ts=${Date.now()}`);
        placeholder.style.display = 'none';
        container.style.display = 'block';
    }

    document.getElementById('progress-form-panel').style.display = 'flex';
    document.getElementById('modal-project-progress').classList.add('form-open');
    document.getElementById('progress-form-panel').scrollIntoView({ behavior: 'smooth' });
}

async function deleteProgressCard(id) {
    if (confirm(state.currentLanguage === 'en'
        ? 'Are you sure you want to delete this progress update?'
        : 'คุณต้องการลบบันทึกความคืบหน้านี้ใช่หรือไม่?')) {
        try {
            const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/progress/${id}`, {
                method: 'DELETE'
            });
            if (!res.ok) throw new Error('Delete failed');

            showToast(state.currentLanguage === 'en' ? 'Progress update deleted' : 'ลบบันทึกความคืบหน้าแล้ว');
            await fetchAndRenderProgressList();

            const currentEditId = document.getElementById('progress-edit-id').value;
            if (currentEditId == id) {
                document.getElementById('progress-form-panel').style.display = 'none';
                document.getElementById('modal-project-progress').classList.remove('form-open');
                clearProgressForm();
            }
        } catch (err) {
            console.error(err);
            showToast(err.message, 'danger');
        }
    }
}

function clearProgressForm() {
    document.getElementById('form-project-progress').reset();
    document.getElementById('progress-edit-id').value = '';
    document.getElementById('progress-form-title').innerHTML = `<i class="fa-solid fa-plus"></i> ${state.currentLanguage === 'en' ? 'Record New Progress' : 'บันทึกความคืบหน้าใหม่'}`;
    document.getElementById('progress-system-custom').style.display = 'none';
    document.getElementById('progress-system-custom').required = false;
    clearProgressImagePreview();
}

async function toggleProgressCamera() {
    const captureInput = document.getElementById('progress-camera-capture-input');
    if (captureInput) {
        captureInput.click();
    } else {
        showToast(state.currentLanguage === 'en' ? 'Camera not supported' : 'ระบบกล้องไม่รองรับบนอุปกรณ์นี้', 'danger');
    }
}

function stopProgressCamera() {
    const video = document.getElementById('progress-camera-video');
    const container = document.getElementById('progress-camera-container');

    if (state.progressCameraStream) {
        state.progressCameraStream.getTracks().forEach(track => track.stop());
        state.progressCameraStream = null;
    }
    video.srcObject = null;
    container.style.display = 'none';
}

function snapProgressPhoto() {
    const video = document.getElementById('progress-camera-video');

    if (!state.progressCameraStream) return;

    const canvas = document.createElement('canvas');
    canvas.width = video.videoWidth;
    canvas.height = video.videoHeight;
    const context = canvas.getContext('2d');
    context.drawImage(video, 0, 0, canvas.width, canvas.height);

    canvas.toBlob(async (blob) => {
        const timestampStr = new Date().toISOString().replace(/[:.]/g, '-');
        const file = new File([blob], `captured-${timestampStr}.jpg`, { type: 'image/jpeg' });

        await processAndSetProgressImage(file);
        toggleProgressCamera();
    }, 'image/jpeg', 0.9);
}

function setupProgressImageDropzone() {
    const dropzone = document.getElementById('progress-image-dropzone');
    const fileInput = document.getElementById('progress-image-input');

    if (!dropzone || !fileInput) return;

    dropzone.addEventListener('click', (e) => {
        if (e.target.closest('#btn-remove-progress-image')) return;
        fileInput.click();
    });

    fileInput.addEventListener('change', async (e) => {
        if (e.target.files && e.target.files.length > 0) {
            const file = e.target.files[0];
            await processAndSetProgressImage(file);
        }
    });

    ['dragenter', 'dragover'].forEach(eventName => {
        dropzone.addEventListener(eventName, (e) => {
            e.preventDefault();
            e.stopPropagation();
            dropzone.classList.add('hover');
        }, false);
    });

    ['dragleave', 'drop'].forEach(eventName => {
        dropzone.addEventListener(eventName, (e) => {
            e.preventDefault();
            e.stopPropagation();
            dropzone.classList.remove('hover');
        }, false);
    });

    dropzone.addEventListener('drop', async (e) => {
        const dt = e.dataTransfer;
        const files = dt.files;
        if (files && files.length > 0) {
            const file = files[0];
            if (file.type.startsWith('image/')) {
                await processAndSetProgressImage(file);
            } else {
                showToast(state.currentLanguage === 'en' ? 'Only images are supported' : 'รองรับเฉพาะไฟล์รูปภาพเท่านั้น', 'danger');
            }
        }
    }, false);

    const removeBtn = document.getElementById('btn-remove-progress-image');
    if (removeBtn) {
        removeBtn.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();
            clearProgressImagePreview();
        });
    }

    // Mobile native camera capture listener
    const captureInput = document.getElementById('progress-camera-capture-input');
    if (captureInput) {
        captureInput.addEventListener('change', async (e) => {
            if (e.target.files && e.target.files.length > 0) {
                const file = e.target.files[0];
                await processAndSetProgressImage(file);
            }
        });
    }
}

function displayProgressImagePreview(file) {
    const placeholder = document.getElementById('progress-image-preview-placeholder');
    const container = document.getElementById('progress-image-preview-container');
    const img = document.getElementById('progress-image-preview-img');

    const reader = new FileReader();
    reader.onload = (e) => {
        img.src = e.target.result;
        placeholder.style.display = 'none';
        container.style.display = 'block';
    };
    reader.readAsDataURL(file);
}

function clearProgressImagePreview() {
    const placeholder = document.getElementById('progress-image-preview-placeholder');
    const container = document.getElementById('progress-image-preview-container');
    const img = document.getElementById('progress-image-preview-img');
    const fileInput = document.getElementById('progress-image-input');

    state.progressSelectedFile = null;
    fileInput.value = '';
    img.src = '';
    placeholder.style.display = 'block';
    container.style.display = 'none';
}

function setCurrentProgressTimestamp() {
    const input = document.getElementById('progress-timestamp');
    if (input && !input.value) {
        const now = new Date();
        const tzoffset = now.getTimezoneOffset() * 60000;
        const localISOTime = (new Date(now - tzoffset)).toISOString().slice(0, 16);
        input.value = localISOTime;
    }
}

async function handleProgressFormSubmit(e) {
    e.preventDefault();

    const descInput = document.getElementById('progress-desc');
    if (!descInput.value.trim()) {
        showToast(state.currentLanguage === 'en' ? 'Please fill in the progress description' : 'กรุณากรอกคำบรรยายความคืบหน้า', 'danger');
        return;
    }

    const saveBtn = document.getElementById('btn-save-progress-submit');
    const originalText = saveBtn ? saveBtn.innerHTML : 'บันทึก';

    if (saveBtn) {
        saveBtn.disabled = true;
        saveBtn.innerHTML = state.currentLanguage === 'en' ? '<i class="fa-solid fa-spinner fa-spin"></i> Saving...' : '<i class="fa-solid fa-spinner fa-spin"></i> กำลังบันทึก...';
    }

    const idInput = document.getElementById('progress-edit-id');
    const progressId = idInput.value;

    const formData = new FormData();
    formData.append('image_title', document.getElementById('progress-image-title').value.trim());
    formData.append('progress_desc', descInput.value.trim());
    formData.append('issues', document.getElementById('progress-issues').value.trim());
    formData.append('solutions', document.getElementById('progress-solutions').value.trim());
    formData.append('suggestions', document.getElementById('progress-suggestions').value.trim());

    // Add system_name field
    const systemSelect = document.getElementById('progress-system-select');
    let systemName = systemSelect.value;
    if (systemName === 'CUSTOM') {
        const customInput = document.getElementById('progress-system-custom');
        systemName = customInput.value.trim() || 'ทั่วไป';
    }
    formData.append('system_name', systemName);

    const timestampVal = document.getElementById('progress-timestamp').value;
    if (timestampVal) {
        formData.append('timestamp', parseDbDate(timestampVal).toISOString());
    }

    if (state.progressSelectedFile) {
        formData.append('image', state.progressSelectedFile);
    }

    try {
        let url = `${API_BASE}/projects/${state.activeProjectId}/progress`;
        let method = 'POST';

        if (progressId) {
            url += `/${progressId}`;
            method = 'PUT';
        }

        const res = await authFetch(url, {
            method: method,
            body: formData
        });

        if (!res.ok) {
            const err = await res.json();
            throw new Error(err.error || 'Failed to save progress update');
        }

        showToast(state.currentLanguage === 'en' ? 'Progress saved successfully' : 'บันทึกความคืบหน้าสำเร็จแล้ว');

        document.getElementById('progress-form-panel').style.display = 'none';
        document.getElementById('modal-project-progress').classList.remove('form-open');
        clearProgressForm();
        await fetchAndRenderProgressList();
    } catch (err) {
        console.error(err);
        showToast(err.message, 'danger');
    } finally {
        if (saveBtn) {
            saveBtn.disabled = false;
            saveBtn.innerHTML = originalText;
        }
    }
}

// Testing controls setup
if (window.location.search.includes('test=true')) {
    const testContainer = document.getElementById('test-docs-controls');
    if (testContainer) {
        testContainer.style.display = 'flex';
        document.getElementById('btn-test-upload-dwg').addEventListener('click', () => window.TEST_UPLOAD_DOC('layout_plan.dwg'));
        document.getElementById('btn-test-upload-pdf').addEventListener('click', () => window.TEST_UPLOAD_DOC('specifications.pdf'));
        document.getElementById('btn-test-upload-zip').addEventListener('click', () => window.TEST_UPLOAD_DOC('archive_data.zip'));
        document.getElementById('btn-test-upload-xlsx').addEventListener('click', () => window.TEST_UPLOAD_DOC('schedule.xlsx'));
        document.getElementById('btn-test-upload-docx').addEventListener('click', () => window.TEST_UPLOAD_DOC('document.docx'));
    }
}

async function handleDocsUpload(files) {
    if (!files || files.length === 0) return;

    const allowedExtensions = ['pdf', 'xls', 'xlsx', 'dwg', 'rar', 'zip', 'doc', 'docx'];
    const maxSizeBytes = 50 * 1024 * 1024; // 50MB

    const validFiles = [];
    for (let file of files) {
        const ext = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase();
        if (!allowedExtensions.includes(ext)) {
            showToast(state.currentLanguage === 'en'
                ? `File "${file.name}" is not supported. Allowed: PDF, DOC, DOCX, XLS, XLSX, DWG, RAR, ZIP`
                : `ไม่รองรับไฟล์ "${file.name}" (อนุญาตเฉพาะ PDF, DOC, DOCX, XLS, XLSX, DWG, RAR, ZIP)`, 'danger');
            return;
        }
        if (file.size > maxSizeBytes) {
            showToast(state.currentLanguage === 'en'
                ? `File "${file.name}" exceeds the 50MB size limit.`
                : `ไฟล์ "${file.name}" มีขนาดเกิน 50MB`, 'danger');
            return;
        }
        validFiles.push(file);
    }

    if (validFiles.length === 0) return;

    showToast(state.currentLanguage === 'en' ? 'Uploading files...' : 'กำลังอัปโหลดไฟล์...', 'info');

    let successCount = 0;
    const failedFiles = [];

    for (let file of validFiles) {
        const formData = new FormData();
        formData.append('document', file);
        formData.append('file_path', state.currentDocFolderPath);

        try {
            const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/documents`, {
                method: 'POST',
                body: formData
            });
            if (res.ok) {
                successCount++;
            } else {
                const err = await res.json().catch(() => ({}));
                console.error(`Failed to upload ${file.name}:`, err.error);
                failedFiles.push(file.name);
            }
        } catch (err) {
            console.error(err);
            failedFiles.push(file.name);
        }
    }

    if (successCount > 0) {
        showToast(state.currentLanguage === 'en'
            ? `Successfully uploaded ${successCount} files`
            : `อัปโหลดไฟล์สำเร็จแล้ว ${successCount} ไฟล์`);
    } else if (failedFiles.length === 0) {
        showToast(state.currentLanguage === 'en' ? 'Failed to upload files' : 'อัปโหลดไฟล์ไม่สำเร็จ', 'error');
    }

    if (failedFiles.length > 0) {
        const msg = state.currentLanguage === 'en'
            ? `Warning: The following files failed to upload:\n- ${failedFiles.join('\n- ')}`
            : `คำเตือน: ไฟล์ต่อไปนี้อัปโหลดไม่สำเร็จ:\n- ${failedFiles.join('\n- ')}`;
        alert(msg);
    }

    await fetchActiveProjectDocs();
    renderProjectDocs();
}

function formatBytes(bytes, decimals = 2) {
    if (bytes === 0) return '0 Bytes';
    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
    const i = Math.floor(Math.log(bytes) / Math.log(k));
    return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

// ==========================================
// Print reports formatting triggers
// ==========================================

function triggerPrintReport(mode) {
    if (!state.activeProjectSummary) return;

    // Clear print mode classes
    document.body.classList.remove('print-mode-quotation', 'print-mode-bom', 'print-mode-free-issue');

    if (mode === 'quotation') {
        document.body.classList.add('print-mode-quotation');
        document.getElementById('print-doc-title-text').textContent = t('print_title_quote');
    } else if (mode === 'bom') {
        document.body.classList.add('print-mode-bom');
        document.getElementById('print-doc-title-text').textContent = t('print_title_bom');
    } else if (mode === 'free-issue') {
        document.body.classList.add('print-mode-free-issue');
        document.getElementById('print-doc-title-text').textContent = t('print_title_free_issue');
    }

    document.getElementById('print-date').textContent = new Date().toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH');
    document.getElementById('print-doc-number').textContent = `QT-2026-${state.activeProjectSummary.id.toString().padStart(4, '0')}`;
    const displayProjectPrintName = (state.activeProjectSummary.external_name)
        ? state.activeProjectSummary.external_name
        : state.activeProjectSummary.name;
    document.getElementById('print-project-name').textContent = displayProjectPrintName;
    document.getElementById('print-client-name').textContent = state.activeProjectSummary.client_name || '-';
    document.getElementById('print-project-desc').textContent = state.activeProjectSummary.description || '-';

    document.getElementById('print-val-mt-quote').textContent = formatCurrency(state.activeProjectSummary.price_material);
    document.getElementById('print-val-lb-quote').textContent = formatCurrency(state.activeProjectSummary.price_labour);
    document.getElementById('print-val-total-quote').textContent = formatCurrency(state.activeProjectSummary.price_total);

    document.getElementById('print-val-total-cost').textContent = formatCurrency(state.activeProjectSummary.cost_total);
    document.getElementById('print-val-profit').textContent = `${formatCurrency(state.activeProjectSummary.profit)} (${state.activeProjectSummary.profit_margin_percent.toFixed(2)}%)`;

    // Populate sections breakdown table
    const breakdownContainer = document.getElementById('print-sections-breakdown-container');
    if (breakdownContainer) {
        let sectionsHtml = '';

        if (mode === 'quotation') {
            // Detailed items quotation report without individual item pricing (Product Name and Quantity only)
            sectionsHtml = `
                <h3 class="print-section-title" style="margin-top: 25px; margin-bottom: 10px; border-bottom: 2px solid #1e293b; padding-bottom: 4px; font-size: 1.1rem; color: #1e293b; font-family: var(--font-heading);">
                    ${state.currentLanguage === 'en' ? 'Quotation Items Details' : 'รายละเอียดใบเสนอราคาสินค้า'}
                </h3>
                <table class="print-breakdown-table" style="width: 100%; border-collapse: collapse; margin-bottom: 25px; font-size: 0.85rem; font-family: var(--font-body);">
                    <thead>
                        <tr style="background-color: #f1f5f9; border-bottom: 2px solid #1e293b; font-weight: 700; color: #1e293b;">
                            <th style="padding: 8px; text-align: left; border: 1px solid #cbd5e1;">${state.currentLanguage === 'en' ? 'Product Name' : 'ชื่อสินค้า'}</th>
                            <th style="padding: 8px; text-align: center; border: 1px solid #cbd5e1; width: 200px;">${state.currentLanguage === 'en' ? 'Quantity' : 'จำนวน'}</th>
                        </tr>
                    </thead>
                    <tbody>
            `;

            const sections = state.activeProjectSummary.sections || [];
            sections.forEach(sec => {
                const items = sec.items || [];
                if (items.length > 0) {
                    // Show system section name header row
                    sectionsHtml += `
                        <tr style="background-color: #f8fafc; font-weight: 700; border-bottom: 1px solid #cbd5e1;">
                            <td colspan="2" style="padding: 8px; text-align: left; border: 1px solid #cbd5e1; color: var(--primary);">
                                [${state.currentLanguage === 'en' ? 'System' : 'ระบบงาน'}]: ${escapeHtml(sec.name)}
                            </td>
                        </tr>
                    `;
                    items.forEach(item => {
                        const displayDesc = item.brand ? `[${escapeHtml(item.brand)}] ${escapeHtml(item.description)}` : escapeHtml(item.description);
                        sectionsHtml += `
                            <tr style="border-bottom: 1px solid #cbd5e1;">
                                <td style="padding: 8px; text-align: left; border: 1px solid #cbd5e1; padding-left: 20px;">${displayDesc}</td>
                                <td style="padding: 8px; text-align: center; border: 1px solid #cbd5e1;">${item.qty} ${escapeHtml(item.unit)}</td>
                            </tr>
                        `;
                    });
                }
            });

            sectionsHtml += `
                    </tbody>
                </table>
            `;

        } else {
            // General breakdown (BOM or Free Issue summary)
            const isInternal = (mode === 'bom'); // bom shows internal cost & profit, quotation/free-issue does not
            sectionsHtml = `
                <h3 class="print-section-title" style="margin-top: 25px; margin-bottom: 10px; border-bottom: 2px solid #1e293b; padding-bottom: 4px; font-size: 1.1rem; color: #1e293b; font-family: var(--font-heading);">
                    ${state.currentLanguage === 'en' ? 'Summary by System' : 'สรุปประมาณราคาแยกตามระบบงาน'}
                </h3>
                <table class="print-breakdown-table" style="width: 100%; border-collapse: collapse; margin-bottom: 25px; font-size: 0.85rem; font-family: var(--font-body);">
                    <thead>
                        <tr style="background-color: #f1f5f9; border-bottom: 2px solid #1e293b; font-weight: 700; color: #1e293b;">
                            <th style="padding: 8px; text-align: left; border: 1px solid #cbd5e1;">${state.currentLanguage === 'en' ? 'System Name' : 'ระบบงาน'}</th>
                            <th style="padding: 8px; text-align: right; border: 1px solid #cbd5e1; width: 150px;">${state.currentLanguage === 'en' ? 'Material Quote' : 'เสนอราคาค่าวัสดุ'}</th>
                            <th style="padding: 8px; text-align: right; border: 1px solid #cbd5e1; width: 150px;">${state.currentLanguage === 'en' ? 'Labour Quote' : 'เสนอราคาค่าแรง'}</th>
                            <th style="padding: 8px; text-align: right; border: 1px solid #cbd5e1; width: 150px; background-color: #f8fafc;">${state.currentLanguage === 'en' ? 'Total Quote' : 'เสนอราคารวม'}</th>
                            ${isInternal ? `
                            <th style="padding: 8px; text-align: right; border: 1px solid #cbd5e1; width: 150px; color: #0284c7;">${state.currentLanguage === 'en' ? 'Total Cost' : 'ต้นทุนรวม'}</th>
                            <th style="padding: 8px; text-align: right; border: 1px solid #cbd5e1; width: 120px; color: #059669;">${state.currentLanguage === 'en' ? 'Profit' : 'กำไร'}</th>
                            ` : ''}
                        </tr>
                    </thead>
                    <tbody>
            `;

            const sections = state.activeProjectSummary.sections || [];
            sections.forEach(sec => {
                const priceMat = sec.price_material || 0;
                const priceLab = sec.price_labour || 0;
                const priceTotal = sec.price_total || 0;
                const costTotal = sec.cost_total || 0;
                const profit = sec.profit || 0;

                sectionsHtml += `
                    <tr style="border-bottom: 1px solid #cbd5e1;">
                        <td style="padding: 8px; text-align: left; font-weight: 600; border: 1px solid #cbd5e1; color: #334155;">${escapeHtml(sec.name)}</td>
                        <td style="padding: 8px; text-align: right; border: 1px solid #cbd5e1;">${formatCurrency(priceMat)}</td>
                        <td style="padding: 8px; text-align: right; border: 1px solid #cbd5e1;">${formatCurrency(priceLab)}</td>
                        <td style="padding: 8px; text-align: right; font-weight: 700; border: 1px solid #cbd5e1; background-color: #f8fafc; color: #0f172a;">${formatCurrency(priceTotal)}</td>
                        ${isInternal ? `
                        <td style="padding: 8px; text-align: right; border: 1px solid #cbd5e1; color: #0f172a;">${formatCurrency(costTotal)}</td>
                        <td style="padding: 8px; text-align: right; font-weight: 700; border: 1px solid #cbd5e1; color: ${profit >= 0 ? '#15803d' : '#b91c1c'};">${formatCurrency(profit)}</td>
                        ` : ''}
                    </tr>
                `;
            });

            // Overall Grand Total row
            const grandPriceMat = state.activeProjectSummary.price_material || 0;
            const grandPriceLab = state.activeProjectSummary.price_labour || 0;
            const grandPriceTotal = state.activeProjectSummary.price_total || 0;
            const grandCostTotal = state.activeProjectSummary.cost_total || 0;
            const grandProfit = state.activeProjectSummary.profit || 0;

            sectionsHtml += `
                        <tr style="background-color: #e2e8f0; font-weight: 700; border-top: 2px solid #1e293b;">
                            <td style="padding: 10px 8px; text-align: left; border: 1px solid #cbd5e1; color: #0f172a;">${state.currentLanguage === 'en' ? 'Grand Total' : 'ยอดรวมทั้งสิ้น'}</td>
                            <td style="padding: 10px 8px; text-align: right; border: 1px solid #cbd5e1;">${formatCurrency(grandPriceMat)}</td>
                            <td style="padding: 10px 8px; text-align: right; border: 1px solid #cbd5e1;">${formatCurrency(grandPriceLab)}</td>
                            <td style="padding: 10px 8px; text-align: right; border: 1px solid #cbd5e1; background-color: #cbd5e1; color: #0f172a; font-size: 0.95rem;">${formatCurrency(grandPriceTotal)}</td>
                            ${isInternal ? `
                            <td style="padding: 10px 8px; text-align: right; border: 1px solid #cbd5e1; color: #0f172a;">${formatCurrency(grandCostTotal)}</td>
                            <td style="padding: 10px 8px; text-align: right; border: 1px solid #cbd5e1; color: ${grandProfit >= 0 ? '#15803d' : '#b91c1c'}; font-size: 0.95rem;">${formatCurrency(grandProfit)}</td>
                            ` : ''}
                        </tr>
                    </tbody>
                </table>
            `;
        }

        breakdownContainer.innerHTML = sectionsHtml;
    }

    setTimeout(() => {
        window.print();
    }, 150);
}
// ==========================================
// Helper Functions
// ==========================================

async function fetchCategories() {
    try {
        const res = await authFetch(`${API_BASE}/categories`);
        state.categories = await res.json();
    } catch (err) {
        console.error('Error fetching categories', err);
    }
}

async function fetchGroups() {
    try {
        const res = await authFetch(`${API_BASE}/groups`);
        state.groups = await res.json();
    } catch (err) {
        console.error('Error fetching groups', err);
    }
}

async function fetchSystems() {
    try {
        const res = await authFetch(`${API_BASE}/systems`);
        state.systems = await res.json();
    } catch (err) {
        console.error('Error fetching systems', err);
    }
}

function buildCategoryDropdown(selectId) {
    const select = document.getElementById(selectId);
    if (!select) return;
    const prevVal = select.value;
    const firstOption = select.options[0];
    select.innerHTML = '';
    if (firstOption) select.appendChild(firstOption);

    state.categories.forEach(cat => {
        const option = document.createElement('option');
        option.value = cat;
        option.textContent = cat;
        select.appendChild(option);
    });

    if (prevVal && Array.from(select.options).some(opt => opt.value === prevVal)) {
        select.value = prevVal;
    }
}

function buildGroupDropdown(selectId) {
    const select = document.getElementById(selectId);
    if (!select) return;
    const prevVal = select.value;
    const firstOption = select.options[0];
    select.innerHTML = '';
    if (firstOption) select.appendChild(firstOption);

    const groups = state.groups || [];
    groups.forEach(group => {
        const option = document.createElement('option');
        option.value = group;
        option.textContent = group;
        select.appendChild(option);
    });

    if (prevVal && Array.from(select.options).some(opt => opt.value === prevVal)) {
        select.value = prevVal;
    }
}

function buildSystemDropdown(selectId) {
    const select = document.getElementById(selectId);
    if (!select) return;
    const prevVal = select.value;
    const firstOption = select.options[0];
    select.innerHTML = '';
    if (firstOption) select.appendChild(firstOption);

    const systems = state.systems || [];
    systems.forEach(system => {
        const option = document.createElement('option');
        option.value = system;
        option.textContent = system;
        select.appendChild(option);
    });

    if (prevVal && Array.from(select.options).some(opt => opt.value === prevVal)) {
        select.value = prevVal;
    }
}

function openLightbox(src) {
    const lightbox = document.getElementById('modal-lightbox');
    const img = document.getElementById('lightbox-img');
    img.src = src;
    lightbox.classList.add('active');
}

function formatCurrency(val) {
    const num = parseFloat(val) || 0;
    return num.toLocaleString('th-TH', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' ฿';
}

function formatNumber(val) {
    const num = parseFloat(val) || 0;
    return num.toLocaleString('th-TH', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}

function showToast(msg, type = 'success') {
    const toast = document.getElementById('toast');
    const msgEl = document.getElementById('toast-msg');
    const iconEl = document.getElementById('toast-icon');

    msgEl.textContent = msg;

    if (type === 'success') {
        iconEl.className = 'fa-solid fa-circle-check toast-icon';
        iconEl.style.color = 'var(--success)';
    } else {
        iconEl.className = 'fa-solid fa-circle-xmark toast-icon error';
        iconEl.style.color = 'var(--danger)';
    }

    toast.classList.add('active');

    if (toast.timeoutId) clearTimeout(toast.timeoutId);

    toast.timeoutId = setTimeout(() => {
        toast.classList.remove('active');
    }, 3000);
}

function escapeHtml(string) {
    const map = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#039;'
    };
    return String(string).replace(/[&<>"']/g, function (m) { return map[m]; });
}

function escapeJsString(str) {
    return String(str)
        .replace(/\\/g, '\\\\')
        .replace(/'/g, "\\'")
        .replace(/"/g, '\\"')
        .replace(/\n/g, '\\n')
        .replace(/\r/g, '\\r');
}

function debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}

// ==========================================
// 6. PROPOSAL LETTER EDITOR MODAL HANDLERS
// ==========================================

function openProposalEditor() {
    if (!state.activeProjectId || !state.activeProjectSummary) return;

    const editorModal = document.getElementById('modal-proposal-editor');

    // Set metadata fields
    document.getElementById('prop-doc-no').textContent = `QT-2026-${state.activeProjectSummary.id.toString().padStart(4, '0')}`;

    // Formatting current date dynamically
    const options = { day: 'numeric', month: 'long', year: 'numeric' };
    document.getElementById('prop-doc-date').textContent = new Date().toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH', options);

    document.getElementById('prop-client-name').textContent = state.activeProjectSummary.client_name || (state.currentLanguage === 'en' ? 'Not Specified' : 'ไม่ระบุชื่อลูกค้า');
    document.getElementById('prop-project-name').textContent = state.activeProjectSummary.name;
    document.getElementById('prop-submitter-name').textContent = state.currentUser ? translateRole(state.currentUser.role) + ' (' + state.currentUser.username + ')' : t('letter_sig_pm');

    // Populate summary table
    const tbody = document.getElementById('prop-table-tbody');
    tbody.innerHTML = '';

    const sections = state.activeProjectSummary.sections || [];

    if (sections.length === 0) {
        const noSectionsText = state.currentLanguage === 'en' ? 'No systems to summarize in this report.' : 'ยังไม่มีข้อมูลระบบงานเพื่อสรุปรายงาน';
        tbody.innerHTML = `
            <tr>
                <td colspan="4" style="padding: 15px; text-align: center; color: var(--text-muted);">
                    ${noSectionsText}
                </td>
            </tr>
        `;
    } else {
        sections.forEach(sec => {
            const tr = document.createElement('tr');
            tr.innerHTML = `
                <td style="padding: 8px 10px; border-bottom: 1px solid var(--border-color); text-align: left;">
                    ${escapeHtml(sec.name)}
                </td>
                <td style="padding: 8px 10px; border-bottom: 1px solid var(--border-color); text-align: right;">
                    ${formatCurrency(sec.price_material)}
                </td>
                <td style="padding: 8px 10px; border-bottom: 1px solid var(--border-color); text-align: right;">
                    ${formatCurrency(sec.price_labour)}
                </td>
                <td style="padding: 8px 10px; border-bottom: 1px solid var(--border-color); text-align: right; font-weight: 600;">
                    ${formatCurrency(sec.price_total)}
                </td>
            `;
            tbody.appendChild(tr);
        });
    }

    // Set summary totals
    document.getElementById('prop-total-mt').textContent = formatCurrency(state.activeProjectSummary.price_material);
    document.getElementById('prop-total-lb').textContent = formatCurrency(state.activeProjectSummary.price_labour);
    document.getElementById('prop-total-all').textContent = formatCurrency(state.activeProjectSummary.price_total);

    // Set digital stamp display based on project approval status
    const isApproved = state.activeProjectSummary.status === 'อนุมัติแล้ว';
    document.getElementById('prop-approval-stamp').style.display = isApproved ? 'block' : 'none';

    editorModal.classList.add('active');
}

function closeProposalEditor() {
    document.getElementById('modal-proposal-editor').classList.remove('active');
}

async function handleProjectApprovalToggle() {
    if (!state.activeProjectId || !state.activeProjectSummary) return;

    const isApproved = state.activeProjectSummary.status === 'อนุมัติแล้ว';
    const actionEndpoint = isApproved ? 'pending' : 'approve';

    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/${actionEndpoint}`, {
            method: 'POST'
        });

        if (!res.ok) {
            const err = await res.json();
            throw new Error(err.error || 'Failed to toggle project status');
        }

        const resData = await res.json();
        showToast(
            isApproved
                ? (state.currentLanguage === 'en' ? 'Project approval cancelled' : 'ยกเลิกการอนุมัติเรียบร้อยแล้ว')
                : t('toast_project_approved')
        );

        await fetchActiveProjectDetails();
        renderWorkspace();
        await fetchProjects();
    } catch (err) {
        showToast(err.message, 'error');
    }
}

// ==========================================
// Supplier Quotation and CRUD Modal Handlers
// ==========================================

function openSupplierQuoteViewer(productId, productDesc) {
    const viewerModal = document.getElementById('modal-pdf-viewer');
    const iframe = document.getElementById('pdf-viewer-iframe');
    const htmlContainer = document.getElementById('doc-viewer-html-container');
    const title = document.getElementById('pdf-viewer-title');
    const subtitle = document.getElementById('pdf-viewer-subtitle');
    const deleteBtn = document.getElementById('btn-delete-pdf-from-viewer');

    iframe.style.display = 'block';
    if (htmlContainer) {
        htmlContainer.style.display = 'none';
    }

    title.textContent = state.currentLanguage === 'en' ? `Supplier Quotation: ${productDesc}` : `ใบเสนอราคาซัพพลายเออร์: ${productDesc}`;
    if (subtitle) {
        subtitle.textContent = state.currentLanguage === 'en' ? 'Supplier Quote Document' : 'เอกสารใบเสนอราคาผู้จัดจำหน่าย';
    }
    const pdfUrl = withAuthToken(`${API_BASE}/products/${productId}/supplier-quote`);
    iframe.src = pdfUrl;
    const newTabBtn = document.getElementById('btn-open-pdf-new-tab');
    if (newTabBtn) {
        newTabBtn.href = pdfUrl;
        newTabBtn.style.display = 'inline-flex';
    }
    deleteBtn.style.display = 'none';

    viewerModal.classList.add('active');
}

async function handleDeleteSupplierQuoteDirect(productId) {
    if (!confirm(state.currentLanguage === 'en' ? 'Are you sure you want to delete this quote document?' : 'ลบเอกสารใบเสนอราคานี้ใช่หรือไม่?')) return;
    try {
        await authFetch(`${API_BASE}/products/${productId}/supplier-quote`, { method: 'DELETE' });
        showToast(state.currentLanguage === 'en' ? 'Supplier quote document deleted' : 'ลบใบเสนอราคาผู้จัดจำหน่ายเรียบร้อย');

        // Refresh product details
        const res = await authFetch(`${API_BASE}/products?q=`);
        const list = await res.json();
        const updatedProd = list.find(p => p.id === productId);
        openProductDetailModal(updatedProd);

        await filterManagerProducts();
        if (state.activeProjectId) {
            await fetchActiveProjectDetails();
            renderWorkspace();
        }
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to delete file' : 'ไม่สามารถลบไฟล์ได้', 'error');
    }
}

async function openSupplierManagerModal() {
    document.getElementById('supplier-manager-search').value = '';
    await fetchSuppliers();
    renderSuppliersList(state.suppliers);
    document.getElementById('modal-supplier-manager').classList.add('active');
}

function closeSupplierManagerModal() {
    document.getElementById('modal-supplier-manager').classList.remove('active');
}

async function fetchSuppliers() {
    try {
        const res = await authFetch(`${API_BASE}/suppliers`);
        state.suppliers = await res.json();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load suppliers' : 'ไม่สามารถโหลดข้อมูลผู้จัดจำหน่ายได้', 'error');
    }
}

function renderSuppliersList(suppliersList) {
    const tbody = document.getElementById('supplier-manager-tbody');
    tbody.innerHTML = '';

    if (suppliersList.length === 0) {
        tbody.innerHTML = `<tr><td colspan="4" style="padding:30px; text-align:center; color:var(--text-muted);">${state.currentLanguage === 'en' ? 'No suppliers found' : 'ไม่พบข้อมูลผู้จัดจำหน่าย'}</td></tr>`;
        return;
    }

    const role = state.currentUser ? state.currentUser.role : 'user';

    suppliersList.forEach(s => {
        const tr = document.createElement('tr');

        let webLinkHtml = '-';
        if (s.website) {
            webLinkHtml = `
                <a href="${escapeHtml(s.website)}" target="_blank" class="btn btn-outline btn-xs" style="display:inline-flex; align-items:center; gap:4px;">
                    <i class="fa-solid fa-earth-americas"></i> ${state.currentLanguage === 'en' ? 'Visit Website' : 'เปิดเว็บไซต์'}
                </a>
            `;
        }

        tr.innerHTML = `
            <td><b>${escapeHtml(s.name)}</b></td>
            <td>${escapeHtml(s.contact_info || '-').replace(/\n/g, '<br>')}</td>
            <td>${webLinkHtml}</td>
            <td class="text-center">
                <div style="display:flex; justify-content:center; gap:8px;">
                    <button class="btn btn-outline btn-sm btn-edit-supplier" data-supplier-id="${s.id}">
                        <i class="fa-solid fa-edit"></i> <span class="btn-text">${t('table_action_edit')}</span>
                    </button>
                    <button class="btn btn-danger-outline btn-sm btn-delete-supplier" data-supplier-id="${s.id}">
                        <i class="fa-solid fa-trash"></i> <span class="btn-text">${t('table_action_delete')}</span>
                    </button>
                </div>
            </td>
        `;

        const editBtn = tr.querySelector('.btn-edit-supplier');
        const deleteBtn = tr.querySelector('.btn-delete-supplier');

        if (role === 'user') {
            editBtn.style.display = 'none';
            deleteBtn.style.display = 'none';
        } else {
            editBtn.addEventListener('click', () => openSupplierDetailModal(s));
            if (role !== 'admin') {
                deleteBtn.style.display = 'none';
            } else {
                deleteBtn.addEventListener('click', () => handleDeleteSupplier(s.id));
            }
        }

        tbody.appendChild(tr);
    });
}

function filterSuppliers() {
    const query = document.getElementById('supplier-manager-search').value.toLowerCase().trim();
    if (!query) {
        renderSuppliersList(state.suppliers);
        return;
    }
    const filtered = state.suppliers.filter(s =>
        s.name.toLowerCase().includes(query) ||
        (s.contact_info && s.contact_info.toLowerCase().includes(query)) ||
        (s.website && s.website.toLowerCase().includes(query))
    );
    renderSuppliersList(filtered);
}

function openSupplierDetailModal(supplier = null) {
    const modal = document.getElementById('modal-supplier-detail');
    const title = document.getElementById('supplier-detail-title');
    const form = document.getElementById('form-supplier-detail');

    form.reset();

    if (supplier) {
        title.textContent = t('modal_supplier_detail_edit');
        document.getElementById('supplier-detail-id').value = supplier.id;
        document.getElementById('supplier-name').value = supplier.name;
        document.getElementById('supplier-contact').value = supplier.contact_info || '';
        document.getElementById('supplier-website').value = supplier.website || '';
    } else {
        title.textContent = t('modal_supplier_detail_create');
        document.getElementById('supplier-detail-id').value = '';
    }

    modal.classList.add('active');
}

function closeSupplierDetailModal() {
    document.getElementById('modal-supplier-detail').classList.remove('active');
}

async function handleSupplierDetailSubmit(e) {
    e.preventDefault();
    const id = document.getElementById('supplier-detail-id').value;
    const payload = {
        name: document.getElementById('supplier-name').value,
        contact_info: document.getElementById('supplier-contact').value,
        website: document.getElementById('supplier-website').value
    };

    try {
        if (id) {
            await authFetch(`${API_BASE}/suppliers/${id}`, {
                method: 'PUT',
                body: JSON.stringify(payload)
            });
            showToast(t('toast_supplier_updated'));
        } else {
            await authFetch(`${API_BASE}/suppliers`, {
                method: 'POST',
                body: JSON.stringify(payload)
            });
            showToast(t('toast_supplier_created'));
        }
        closeSupplierDetailModal();
        await fetchSuppliers();
        renderSuppliersList(state.suppliers);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to save supplier details' : 'ไม่สามารถบันทึกข้อมูลผู้จัดจำหน่ายได้', 'error');
    }
}

async function handleDeleteSupplier(id) {
    if (!confirm(t('confirm_delete_supplier'))) return;
    try {
        await authFetch(`${API_BASE}/suppliers/${id}`, { method: 'DELETE' });
        showToast(t('toast_supplier_deleted'));
        await fetchSuppliers();
        renderSuppliersList(state.suppliers);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to delete supplier' : 'ไม่สามารถลบผู้จัดจำหน่ายได้', 'error');
    }
}

const CONTRACTOR_WRITE_ROLES = ['superadmin', 'admin', 'procurment', 'procurement_manager'];

async function openContractorManagerModal() {
    document.getElementById('contractor-manager-search').value = '';
    await fetchContractors();
    renderContractorsList(state.contractors);
    document.getElementById('modal-contractor-manager').classList.add('active');
}

function closeContractorManagerModal() {
    document.getElementById('modal-contractor-manager').classList.remove('active');
}

async function fetchContractors() {
    try {
        const res = await authFetch(`${API_BASE}/contractors`);
        state.contractors = await res.json();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load contractors' : 'ไม่สามารถโหลดข้อมูลผู้รับเหมาได้', 'error');
    }
}

function renderContractorsList(contractorsList) {
    const tbody = document.getElementById('contractor-manager-tbody');
    tbody.innerHTML = '';

    if (contractorsList.length === 0) {
        tbody.innerHTML = `<tr><td colspan="5" style="padding:30px; text-align:center; color:var(--text-muted);">${state.currentLanguage === 'en' ? 'No contractors found' : 'ไม่พบข้อมูลผู้รับเหมา'}</td></tr>`;
        return;
    }

    const role = state.currentUser ? state.currentUser.role : 'user';
    const canWrite = CONTRACTOR_WRITE_ROLES.includes(role);

    contractorsList.forEach(c => {
        const tr = document.createElement('tr');

        let webLinkHtml = '-';
        if (c.website) {
            webLinkHtml = `
                <a href="${escapeHtml(c.website)}" target="_blank" class="btn btn-outline btn-xs" style="display:inline-flex; align-items:center; gap:4px;">
                    <i class="fa-solid fa-earth-americas"></i> ${state.currentLanguage === 'en' ? 'Visit Website' : 'เปิดเว็บไซต์'}
                </a>
            `;
        }

        tr.innerHTML = `
            <td><b>${escapeHtml(c.name)}</b></td>
            <td>${c.username ? `<i class="fa-solid fa-user"></i> ${escapeHtml(c.username)}` : '-'}</td>
            <td>${escapeHtml(c.contact_info || '-').replace(/\n/g, '<br>')}</td>
            <td>${webLinkHtml}</td>
            <td class="text-center">
                <div style="display:flex; justify-content:center; gap:8px;">
                    <button class="btn btn-outline btn-sm btn-edit-contractor" data-contractor-id="${c.id}">
                        <i class="fa-solid fa-edit"></i> ${t('table_action_edit')}
                    </button>
                    <button class="btn btn-danger-outline btn-sm btn-delete-contractor" data-contractor-id="${c.id}">
                        <i class="fa-solid fa-trash"></i> ${t('table_action_delete')}
                    </button>
                </div>
            </td>
        `;

        const editBtn = tr.querySelector('.btn-edit-contractor');
        const deleteBtn = tr.querySelector('.btn-delete-contractor');

        if (!canWrite) {
            editBtn.style.display = 'none';
            deleteBtn.style.display = 'none';
        } else {
            editBtn.addEventListener('click', () => openContractorDetailModal(c));
            deleteBtn.addEventListener('click', () => handleDeleteContractor(c.id));
        }

        tbody.appendChild(tr);
    });
}

function filterContractors() {
    const query = document.getElementById('contractor-manager-search').value.toLowerCase().trim();
    if (!query) {
        renderContractorsList(state.contractors);
        return;
    }
    const filtered = state.contractors.filter(c =>
        c.name.toLowerCase().includes(query) ||
        (c.username && c.username.toLowerCase().includes(query)) ||
        (c.contact_info && c.contact_info.toLowerCase().includes(query)) ||
        (c.website && c.website.toLowerCase().includes(query))
    );
    renderContractorsList(filtered);
}

async function populateContractorLinkAccountSelect(currentUserId, currentUsername) {
    const select = document.getElementById('contractor-user-id');
    select.innerHTML = `<option value="">${state.currentLanguage === 'en' ? '-- No linked account --' : '-- ไม่เชื่อมบัญชี --'}</option>`;
    try {
        const res = await authFetch(`${API_BASE}/users`);
        if (!res.ok) throw new Error('forbidden');
        const users = await res.json();
        users.filter(u => u.role === 'contractor').forEach(u => {
            const opt = document.createElement('option');
            opt.value = u.id;
            opt.textContent = u.username;
            select.appendChild(opt);
        });
    } catch (err) {
        // Caller may not have user-management permission; fall back to showing only the currently linked account, if any.
        if (currentUserId && currentUsername) {
            const opt = document.createElement('option');
            opt.value = currentUserId;
            opt.textContent = currentUsername;
            select.appendChild(opt);
        }
    }
    select.value = currentUserId || '';
}

async function openContractorDetailModal(contractor = null) {
    const modal = document.getElementById('modal-contractor-detail');
    const title = document.getElementById('contractor-detail-title');
    const form = document.getElementById('form-contractor-detail');

    form.reset();
    await populateContractorLinkAccountSelect(contractor?.user_id, contractor?.username);

    if (contractor) {
        title.textContent = t('modal_contractor_detail_edit');
        document.getElementById('contractor-detail-id').value = contractor.id;
        document.getElementById('contractor-name').value = contractor.name;
        document.getElementById('contractor-contact').value = contractor.contact_info || '';
        document.getElementById('contractor-website').value = contractor.website || '';
    } else {
        title.textContent = t('modal_contractor_detail_create');
        document.getElementById('contractor-detail-id').value = '';
    }

    modal.classList.add('active');
}

function closeContractorDetailModal() {
    document.getElementById('modal-contractor-detail').classList.remove('active');
}

async function handleContractorDetailSubmit(e) {
    e.preventDefault();
    const id = document.getElementById('contractor-detail-id').value;
    const payload = {
        name: document.getElementById('contractor-name').value,
        contact_info: document.getElementById('contractor-contact').value,
        website: document.getElementById('contractor-website').value,
        user_id: document.getElementById('contractor-user-id').value || null
    };

    try {
        if (id) {
            await authFetch(`${API_BASE}/contractors/${id}`, {
                method: 'PUT',
                body: JSON.stringify(payload)
            });
            showToast(t('toast_contractor_updated'));
        } else {
            await authFetch(`${API_BASE}/contractors`, {
                method: 'POST',
                body: JSON.stringify(payload)
            });
            showToast(t('toast_contractor_created'));
        }
        closeContractorDetailModal();
        await fetchContractors();
        renderContractorsList(state.contractors);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to save contractor details' : 'ไม่สามารถบันทึกข้อมูลผู้รับเหมาได้', 'error');
    }
}

async function handleDeleteContractor(id) {
    if (!confirm(t('confirm_delete_contractor'))) return;
    try {
        await authFetch(`${API_BASE}/contractors/${id}`, { method: 'DELETE' });
        showToast(t('toast_contractor_deleted'));
        await fetchContractors();
        renderContractorsList(state.contractors);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to delete contractor' : 'ไม่สามารถลบผู้รับเหมาได้', 'error');
    }
}

const RFQ_STATUS_LABELS = {
    draft:     { th: 'ฉบับร่าง',   en: 'Draft',     bg: '#e2e8f0', color: '#475569' },
    sent:      { th: 'ส่งแล้ว',     en: 'Sent',      bg: '#dbeafe', color: '#1d4ed8' },
    submitted: { th: 'ส่งราคาแล้ว', en: 'Submitted', bg: '#fef3c7', color: '#92400e' },
    approved:  { th: 'อนุมัติแล้ว', en: 'Approved',  bg: '#d1fae5', color: '#065f46' },
    rejected:  { th: 'ปฏิเสธ',      en: 'Rejected',  bg: '#fee2e2', color: '#991b1b' }
};

function renderRfqStatusBadge(status) {
    const info = RFQ_STATUS_LABELS[status] || RFQ_STATUS_LABELS.draft;
    const label = state.currentLanguage === 'en' ? info.en : info.th;
    return `<span style="font-size:0.75rem; padding:4px 10px; border-radius:12px; font-weight:600; background-color:${info.bg}; color:${info.color};">${label}</span>`;
}

async function openProjectRfqModal() {
    if (!state.activeProjectId) return;
    document.getElementById('rfq-list-search').value = '';
    applyLanguage();
    await fetchAndRenderRfqList();
    document.getElementById('modal-project-rfq').classList.add('active');
}

function closeProjectRfqModal() {
    document.getElementById('modal-project-rfq').classList.remove('active');
}

async function fetchAndRenderRfqList() {
    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/contractor-rfqs`);
        state.rfqList = await res.json();
        renderRfqList(state.rfqList);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load RFQs' : 'ไม่สามารถโหลดข้อมูล RFQ ได้', 'error');
    }
}

function renderRfqList(rfqList) {
    const tbody = document.getElementById('rfq-list-tbody');
    tbody.innerHTML = '';

    if (rfqList.length === 0) {
        tbody.innerHTML = `<tr><td colspan="7" style="padding:30px; text-align:center; color:var(--text-muted);">${state.currentLanguage === 'en' ? 'No RFQs found' : 'ไม่พบข้อมูล RFQ'}</td></tr>`;
        return;
    }

    const role = state.currentUser ? state.currentUser.role : 'user';
    const canWrite = ['superadmin', 'admin', 'supervisor', 'procurment', 'procurement_manager'].includes(role);

    rfqList.forEach(r => {
        const tr = document.createElement('tr');
        const issueDate = r.issue_date ? parseDbDate(r.issue_date).toLocaleString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH') : '-';
        const dueDate = r.due_date ? parseDbDate(r.due_date).toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH') : '-';

        tr.innerHTML = `
            <td><b>${escapeHtml(r.rfq_number)}</b></td>
            <td>${escapeHtml(r.contractor_name)}</td>
            <td>${issueDate}</td>
            <td>${dueDate}</td>
            <td>${renderRfqStatusBadge(r.status)}</td>
            <td>${escapeHtml(r.notes || '-')}</td>
            <td class="text-center">
                <div style="display:flex; justify-content:center; gap:8px;">
                    <button class="btn btn-outline btn-sm btn-edit-rfq" data-rfq-id="${r.id}">
                        <i class="fa-solid fa-edit"></i>
                    </button>
                    <button class="btn btn-danger-outline btn-sm btn-delete-rfq" data-rfq-id="${r.id}" style="${canWrite ? '' : 'display:none;'}">
                        <i class="fa-solid fa-trash"></i>
                    </button>
                </div>
            </td>
        `;

        tr.querySelector('.btn-edit-rfq').addEventListener('click', () => openRfqDetailModal(r.id));
        const deleteBtn = tr.querySelector('.btn-delete-rfq');
        if (canWrite) {
            deleteBtn.addEventListener('click', () => handleDeleteRfq(r.id));
        }

        tbody.appendChild(tr);
    });
}

function filterRfqList() {
    const query = document.getElementById('rfq-list-search').value.toLowerCase().trim();
    if (!query) {
        renderRfqList(state.rfqList);
        return;
    }
    const filtered = state.rfqList.filter(r =>
        r.rfq_number.toLowerCase().includes(query) ||
        r.contractor_name.toLowerCase().includes(query) ||
        (r.notes && r.notes.toLowerCase().includes(query))
    );
    renderRfqList(filtered);
}

async function openCreateRfqModal() {
    document.getElementById('form-create-rfq').reset();
    const select = document.getElementById('create-rfq-contractor');
    select.innerHTML = '';
    await fetchContractors();
    state.contractors.forEach(c => {
        const opt = document.createElement('option');
        opt.value = c.id;
        opt.textContent = c.name;
        select.appendChild(opt);
    });
    document.getElementById('modal-create-rfq').classList.add('active');
}

function closeCreateRfqModal() {
    document.getElementById('modal-create-rfq').classList.remove('active');
}

async function handleCreateRfqSubmit(e) {
    e.preventDefault();
    const payload = {
        contractor_id: document.getElementById('create-rfq-contractor').value,
        due_date: document.getElementById('create-rfq-due-date').value || null,
        notes: document.getElementById('create-rfq-notes').value
    };
    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/contractor-rfqs`, {
            method: 'POST',
            body: JSON.stringify(payload)
        });
        const newRfq = await res.json();
        showToast(t('toast_rfq_created'));
        closeCreateRfqModal();
        await fetchAndRenderRfqList();
        openRfqDetailModal(newRfq.id);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to create RFQ' : 'ไม่สามารถสร้าง RFQ ได้', 'error');
    }
}

async function handleDeleteRfq(id) {
    if (!confirm(t('confirm_delete_rfq'))) return;
    try {
        await authFetch(`${API_BASE}/contractor-rfqs/${id}`, { method: 'DELETE' });
        showToast(t('toast_rfq_deleted'));
        await fetchAndRenderRfqList();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to delete RFQ' : 'ไม่สามารถลบ RFQ ได้', 'error');
    }
}

let currentRfqDetail = null;

async function openRfqDetailModal(rfqId) {
    try {
        const res = await authFetch(`${API_BASE}/contractor-rfqs/${rfqId}`);
        currentRfqDetail = await res.json();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load RFQ detail' : 'ไม่สามารถโหลดข้อมูล RFQ ได้', 'error');
        return;
    }

    document.getElementById('rfq-detail-id').value = currentRfqDetail.id;
    document.getElementById('rfq-detail-issue-date').value = currentRfqDetail.issue_date ? parseDbDate(currentRfqDetail.issue_date).toLocaleString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH') : '';
    document.getElementById('rfq-detail-due-date').value = currentRfqDetail.due_date ? currentRfqDetail.due_date.substring(0, 10) : '';
    document.getElementById('rfq-detail-status').value = currentRfqDetail.status || 'draft';
    document.getElementById('rfq-detail-notes').value = currentRfqDetail.notes || '';

    const fileNameEl = document.getElementById('rfq-quote-file-name');
    const removeBtn = document.getElementById('btn-rfq-remove-quote-file');
    if (currentRfqDetail.quote_file_name) {
        fileNameEl.textContent = currentRfqDetail.quote_file_name;
        removeBtn.style.display = 'inline-flex';
    } else {
        fileNameEl.textContent = state.currentLanguage === 'en' ? 'No file selected' : 'ไม่ได้เลือกไฟล์';
        removeBtn.style.display = 'none';
    }

    const isContractor = state.currentUser && state.currentUser.role === 'contractor';
    const submitBtn = document.getElementById('btn-rfq-submit');
    if (submitBtn) {
        submitBtn.style.display = isContractor ? 'inline-flex' : 'none';
    }

    const modalTitleEl = document.querySelector('#modal-rfq-detail .modal-header h3');
    if (modalTitleEl) {
        const baseTitle = state.currentLanguage === 'en' ? 'Quotation Form' : 'ตารางราคาต่อหน่วยของผู้รับเหมา';
        const revSuffix = (currentRfqDetail.revision_number > 0) ? ` (REV ${currentRfqDetail.revision_number})` : '';
        modalTitleEl.textContent = `${baseTitle} - ${currentRfqDetail.rfq_number}${revSuffix}`;
    }

    renderRfqItemsGrouped(currentRfqDetail.items || []);
    document.getElementById('modal-rfq-detail').classList.add('active');
}

function closeRfqDetailModal() {
    document.getElementById('modal-rfq-detail').classList.remove('active');
    currentRfqDetail = null;
    const isContractor = state.currentUser && state.currentUser.role === 'contractor';
    if (isContractor) {
        applyRoleBasedUI();
    }
}

function renderRfqItemsGrouped(items) {
    const tbody = document.getElementById('rfq-items-tbody');
    tbody.innerHTML = '';

    const groups = new Map();
    items.forEach(item => {
        const key = item.section_name || (state.currentLanguage === 'en' ? 'Uncategorized' : 'ไม่ระบุระบบงาน');
        if (!groups.has(key)) groups.set(key, []);
        groups.get(key).push(item);
    });

    groups.forEach((groupItems, sectionName) => {
        const groupRow = document.createElement('tr');
        groupRow.innerHTML = `
            <td colspan="7" style="background: var(--bg-hover); font-weight:600;">
                <i class="fa-solid fa-folder text-primary-color"></i> ${escapeHtml(sectionName)}
                <span class="rfq-group-subtotal" style="float:right; font-weight:600; color:var(--primary-color);"></span>
            </td>
        `;
        tbody.appendChild(groupRow);

        groupItems.forEach(item => {
            const tr = document.createElement('tr');
            tr.dataset.itemId = item.id;
            tr.dataset.qty = item.qty;
            const lineTotal = item.qty * ((item.material_rate || 0) + (item.labour_rate || 0));
            tr.innerHTML = `
                <td class="text-center"><input type="checkbox" class="rfq-item-included" ${item.is_included ? 'checked' : ''}></td>
                <td>
                    <div>${escapeHtml(item.description || '-')}</div>
                    <small style="color:var(--text-muted);">${state.currentLanguage === 'en' ? 'Brand' : 'แบรนด์'}: ${escapeHtml(item.brand || '-')}</small>
                </td>
                <td class="text-center">${formatNumber(item.qty)}</td>
                <td class="text-center">${escapeHtml(item.unit || '-')}</td>
                <td><input type="number" step="0.01" min="0" class="table-number-input rfq-item-material-rate" value="${item.material_rate || 0}"></td>
                <td><input type="number" step="0.01" min="0" class="table-number-input rfq-item-labour-rate" value="${item.labour_rate || 0}"></td>
                <td class="text-right rfq-item-line-total">${formatCurrency(lineTotal)}</td>
            `;
            tbody.appendChild(tr);

            const recalcAndRerender = () => recalculateRfqTotals();
            tr.querySelector('.rfq-item-included').addEventListener('change', recalcAndRerender);
            tr.querySelector('.rfq-item-material-rate').addEventListener('input', recalcAndRerender);
            tr.querySelector('.rfq-item-labour-rate').addEventListener('input', recalcAndRerender);
        });
    });

    recalculateRfqTotals();
}

function recalculateRfqTotals() {
    let grandTotal = 0;
    let currentGroupTotal = 0;
    let lastGroupRow = null;

    const rows = Array.from(document.getElementById('rfq-items-tbody').children);
    rows.forEach(row => {
        if (row.dataset.itemId === undefined) {
            // Group header row: flush the previous group's subtotal, then start a new one
            if (lastGroupRow) {
                lastGroupRow.querySelector('.rfq-group-subtotal').textContent = `${state.currentLanguage === 'en' ? 'Total' : 'รวม'}: ${formatCurrency(currentGroupTotal)}`;
            }
            currentGroupTotal = 0;
            lastGroupRow = row;
            return;
        }
        const included = row.querySelector('.rfq-item-included').checked;
        const qty = parseFloat(row.dataset.qty) || 0;
        const materialRate = parseFloat(row.querySelector('.rfq-item-material-rate').value) || 0;
        const labourRate = parseFloat(row.querySelector('.rfq-item-labour-rate').value) || 0;
        const lineTotal = qty * (materialRate + labourRate);

        const lineTotalEl = row.querySelector('.rfq-item-line-total');
        if (lineTotalEl) {
            lineTotalEl.textContent = formatCurrency(lineTotal);
            lineTotalEl.style.opacity = included ? '1' : '0.5';
        }

        if (included) {
            currentGroupTotal += lineTotal;
            grandTotal += lineTotal;
        }
    });
    if (lastGroupRow) {
        lastGroupRow.querySelector('.rfq-group-subtotal').textContent = `${state.currentLanguage === 'en' ? 'Total' : 'รวม'}: ${formatCurrency(currentGroupTotal)}`;
    }

    document.getElementById('rfq-detail-total-amount').textContent = `${formatCurrency(grandTotal)} ฿`;
}

function collectRfqItemsPayload() {
    const rows = Array.from(document.getElementById('rfq-items-tbody').children).filter(row => row.dataset.itemId !== undefined);
    return rows.map(row => ({
        id: parseInt(row.dataset.itemId),
        is_included: row.querySelector('.rfq-item-included').checked,
        material_rate: parseFloat(row.querySelector('.rfq-item-material-rate').value) || 0,
        labour_rate: parseFloat(row.querySelector('.rfq-item-labour-rate').value) || 0
    }));
}

async function handleSaveRfqDraft() {
    if (!currentRfqDetail) return;
    const payload = {
        status: document.getElementById('rfq-detail-status').value,
        due_date: document.getElementById('rfq-detail-due-date').value || null,
        notes: document.getElementById('rfq-detail-notes').value,
        items: collectRfqItemsPayload()
    };
    try {
        await authFetch(`${API_BASE}/contractor-rfqs/${currentRfqDetail.id}`, {
            method: 'PUT',
            body: JSON.stringify(payload)
        });
        showToast(t('toast_rfq_updated'));
        const isContractor = state.currentUser && state.currentUser.role === 'contractor';
        if (isContractor) {
            applyRoleBasedUI();
        } else {
            await fetchAndRenderRfqList();
        }
        closeRfqDetailModal();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to save RFQ' : 'ไม่สามารถบันทึก RFQ ได้', 'error');
    }
}

function handleRfqSubmit() {
    if (!currentRfqDetail) return;
    
    // Clear password input and focus it
    const pwdInput = document.getElementById('rfq-confirm-password');
    if (pwdInput) {
        pwdInput.value = '';
    }
    
    // Display custom confirm modal
    document.getElementById('modal-rfq-confirm').classList.add('active');
    if (pwdInput) {
        pwdInput.focus();
    }
}

async function submitRfqQuotationConfirmed() {
    if (!currentRfqDetail) return;
    
    const pwdInput = document.getElementById('rfq-confirm-password');
    const password = pwdInput ? pwdInput.value : '';
    
    if (!password.trim()) {
        showToast(state.currentLanguage === 'en' ? 'Password cannot be empty' : 'กรุณากรอกรหัสผ่านเพื่อยืนยัน', 'error');
        return;
    }

    const payload = {
        password: password,
        items: collectRfqItemsPayload()
    };

    // Disable button to prevent double-submit
    const confirmBtn = document.getElementById('btn-submit-rfq-confirm');
    if (confirmBtn) confirmBtn.disabled = true;

    try {
        const res = await authFetch(`${API_BASE}/contractor-rfqs/${currentRfqDetail.id}/submit`, {
            method: 'POST',
            body: JSON.stringify(payload)
        });

        if (!res.ok) {
            const errData = await res.json();
            let errMsg = errData.error || 'Failed to submit RFQ';
            if (errMsg === 'Invalid password') {
                errMsg = state.currentLanguage === 'en'
                    ? 'Incorrect password. Submission failed.'
                    : 'รหัสผ่านไม่ถูกต้อง การส่งใบเสนอราคาไม่สำเร็จ';
            }
            throw new Error(errMsg);
        }

        const data = await res.json();
        showToast(state.currentLanguage === 'en' 
            ? `Quotation submitted successfully! (Revision ${data.revision_number})` 
            : `ส่งใบเสนอราคาเสร็จสิ้นแล้ว! (ปรับปรุงครั้งที่ ${data.revision_number})`, 'success');
        
        document.getElementById('modal-rfq-confirm').classList.remove('active');
        closeRfqDetailModal();
    } catch (err) {
        showToast(err.message, 'error');
    } finally {
        if (confirmBtn) confirmBtn.disabled = false;
    }
}

function printRfqQuotation() {
    if (!currentRfqDetail) return;

    // Get project name from active project summary
    const projectName = state.activeProjectSummary 
        ? (state.activeProjectSummary.external_name || state.activeProjectSummary.name)
        : '';

    // Collect current values from table inputs
    const rows = Array.from(document.getElementById('rfq-items-tbody').children);
    
    let currentSectionName = '';
    const groupedItems = [];
    let currentGroup = null;

    rows.forEach(row => {
        if (row.dataset.itemId === undefined) {
            // Group header row
            const folderIcon = row.querySelector('.fa-folder');
            if (folderIcon) {
                currentSectionName = row.innerText.split('\n')[0].replace('รวม:', '').replace('Total:', '').trim();
                currentGroup = {
                    sectionName: currentSectionName,
                    items: []
                };
                groupedItems.push(currentGroup);
            }
        } else {
            // Item row
            const isIncluded = row.querySelector('.rfq-item-included').checked;
            if (isIncluded) {
                const descDiv = row.children[1].querySelector('div');
                const brandSmall = row.children[1].querySelector('small');
                const desc = descDiv ? descDiv.textContent : '';
                const brandText = brandSmall ? brandSmall.textContent.replace('แบรนด์: ', '').replace('Brand: ', '').trim() : '-';
                const qty = parseFloat(row.dataset.qty) || 0;
                const unit = row.children[3].textContent;
                const materialRate = parseFloat(row.querySelector('.rfq-item-material-rate').value) || 0;
                const labourRate = parseFloat(row.querySelector('.rfq-item-labour-rate').value) || 0;
                const totalRate = qty * (materialRate + labourRate);

                if (currentGroup) {
                    currentGroup.items.push({
                        description: desc,
                        brand: brandText,
                        qty: qty,
                        unit: unit,
                        material_rate: materialRate,
                        labour_rate: labourRate,
                        total: totalRate
                    });
                }
            }
        }
    });

    // Clean up empty groups
    const finalGroups = groupedItems.filter(g => g.items.length > 0);

    const win = window.open('', '_blank');
    if (!win) {
        alert(state.currentLanguage === 'en' ? 'Please allow popups to print' : 'กรุณาอนุญาตให้แสดงหน้าต่างป๊อปอัปเพื่อสั่งพิมพ์');
        return;
    }

    const title = state.currentLanguage === 'en' ? `Quotation - ${currentRfqDetail.rfq_number}` : `ใบเสนอราคา - ${currentRfqDetail.rfq_number}`;
    
    // HTML build
    let html = `
    <html>
    <head>
        <title>${title}</title>
        <style>
            body {
                font-family: 'Sarabun', 'Inter', sans-serif;
                margin: 40px;
                color: #333;
                background-color: #fff;
            }
            .header-table {
                width: 100%;
                border-collapse: collapse;
                margin-bottom: 24px;
            }
            .header-title {
                font-size: 1.6rem;
                font-weight: 700;
                color: #1e3a8a;
                margin-bottom: 4px;
            }
            .header-meta {
                font-size: 0.9rem;
                line-height: 1.6;
            }
            .data-table {
                width: 100%;
                border-collapse: collapse;
                margin-bottom: 30px;
                font-size: 0.9rem;
            }
            .data-table th {
                background-color: #f1f5f9;
                color: #334155;
                font-weight: 600;
                border: 1px solid #cbd5e1;
                padding: 8px 10px;
                text-align: left;
            }
            .data-table td {
                border: 1px solid #cbd5e1;
                padding: 8px 10px;
                vertical-align: top;
            }
            .group-header {
                background-color: #f8fafc;
                font-weight: bold;
                color: #0f172a;
            }
            .text-center { text-align: center; }
            .text-right { text-align: right; }
            .totals-section {
                width: 100%;
                margin-top: 20px;
                display: flex;
                justify-content: flex-end;
            }
            .totals-table {
                width: 320px;
                border-collapse: collapse;
                font-size: 0.95rem;
            }
            .totals-table td {
                padding: 6px 10px;
            }
            .totals-table tr.grand-total {
                font-weight: 700;
                font-size: 1.1rem;
                color: #1e3a8a;
                border-top: 2px double #1e3a8a;
                border-bottom: 2px double #1e3a8a;
            }
            .notes-section {
                margin-top: 30px;
                font-size: 0.85rem;
                border-top: 1px dashed #cbd5e1;
                padding-top: 15px;
                color: #64748b;
            }
            @media print {
                body { margin: 20px; }
                .no-print { display: none; }
            }
        </style>
    </head>
    <body>
        <table class="header-table">
            <tr>
                <td>
                    <div class="header-title">${state.currentLanguage === 'en' ? 'Contractor Quotation' : 'ใบเสนอราคาผู้รับเหมา'}</div>
                    <div class="header-meta">
                        <strong>${state.currentLanguage === 'en' ? 'Project Name' : 'ชื่อโครงการ'}:</strong> ${escapeHtml(projectName)}<br>
                        <strong>${state.currentLanguage === 'en' ? 'Contractor' : 'ผู้รับเหมา'}:</strong> ${escapeHtml(currentRfqDetail.contractor_name || '-')}<br>
                    </div>
                </td>
                <td class="text-right" style="vertical-align: top;">
                    <div class="header-meta">
                        <strong>${state.currentLanguage === 'en' ? 'RFQ No.' : 'เลขที่ใบขอราคา'}:</strong> ${escapeHtml(currentRfqDetail.rfq_number)} ${currentRfqDetail.revision_number > 0 ? '(REV ' + currentRfqDetail.revision_number + ')' : ''}<br>
                        <strong>${state.currentLanguage === 'en' ? 'Issue Date' : 'วันที่ส่งราคา'}:</strong> ${currentRfqDetail.issue_date ? parseDbDate(currentRfqDetail.issue_date).toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH') : '-'}<br>
                        <strong>${state.currentLanguage === 'en' ? 'Due Date' : 'กำหนดส่งราคา'}:</strong> ${currentRfqDetail.due_date ? parseDbDate(currentRfqDetail.due_date).toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH') : '-'}<br>
                    </div>
                </td>
            </tr>
        </table>

        <table class="data-table">
            <thead>
                <tr>
                    <th style="width: 5%;" class="text-center">#</th>
                    <th style="width: 45%;">${state.currentLanguage === 'en' ? 'Description' : 'ระบบงาน / รายละเอียดสินค้า'}</th>
                    <th style="width: 10%;" class="text-center">${state.currentLanguage === 'en' ? 'Qty' : 'จำนวน'}</th>
                    <th style="width: 10%;" class="text-center">${state.currentLanguage === 'en' ? 'Unit' : 'หน่วย'}</th>
                    <th style="width: 15%;" class="text-right">${state.currentLanguage === 'en' ? 'Material (฿)' : 'ราคาวัสดุ (฿)'}</th>
                    <th style="width: 15%;" class="text-right">${state.currentLanguage === 'en' ? 'Labour (฿)' : 'ราคาค่าแรง (฿)'}</th>
                    <th style="width: 15%;" class="text-right">${state.currentLanguage === 'en' ? 'Total (฿)' : 'ราคารวม (฿)'}</th>
                </tr>
            </thead>
            <tbody>
    `;

    let itemIndex = 1;
    let grandMaterialTotal = 0;
    let grandLabourTotal = 0;
    let grandTotal = 0;

    finalGroups.forEach(group => {
        html += `
            <tr class="group-header">
                <td colspan="7"><i class="fa-solid fa-folder"></i> ${escapeHtml(group.sectionName)}</td>
            </tr>
        `;

        group.items.forEach(item => {
            const rowTotal = item.total;
            grandMaterialTotal += item.qty * item.material_rate;
            grandLabourTotal += item.qty * item.labour_rate;
            grandTotal += rowTotal;

            html += `
                <tr>
                    <td class="text-center">${itemIndex++}</td>
                    <td>
                        <div>${escapeHtml(item.description)}</div>
                        <small style="color: #64748b; font-size: 0.8rem;">${state.currentLanguage === 'en' ? 'Brand' : 'แบรนด์'}: ${escapeHtml(item.brand)}</small>
                    </td>
                    <td class="text-center">${formatNumber(item.qty)}</td>
                    <td class="text-center">${escapeHtml(item.unit)}</td>
                    <td class="text-right">${formatCurrency(item.material_rate)}</td>
                    <td class="text-right">${formatCurrency(item.labour_rate)}</td>
                    <td class="text-right">${formatCurrency(rowTotal)}</td>
                </tr>
            `;
        });
    });

    html += `
            </tbody>
        </table>

        <div class="totals-section">
            <table class="totals-table">
                <tr>
                    <td>${state.currentLanguage === 'en' ? 'Total Material' : 'รวมค่าวัสดุ'}:</td>
                    <td class="text-right">${formatCurrency(grandMaterialTotal)} ฿</td>
                </tr>
                <tr>
                    <td>${state.currentLanguage === 'en' ? 'Total Labour' : 'รวมค่าแรง'}:</td>
                    <td class="text-right">${formatCurrency(grandLabourTotal)} ฿</td>
                </tr>
                <tr class="grand-total">
                    <td>${state.currentLanguage === 'en' ? 'Grand Total' : 'ยอดรวมทั้งสิ้น'}:</td>
                    <td class="text-right">${formatCurrency(grandTotal)} ฿</td>
                </tr>
            </table>
        </div>
    `;

    if (currentRfqDetail.notes && currentRfqDetail.notes.trim()) {
        html += `
            <div class="notes-section">
                <strong>${state.currentLanguage === 'en' ? 'Notes / Details' : 'หมายเหตุ / รายละเอียด'}:</strong><br>
                <div style="white-space: pre-wrap; margin-top: 6px;">${escapeHtml(currentRfqDetail.notes)}</div>
            </div>
        `;
    }

    html += `
    </body>
    </html>
    `;

    win.document.write(html);
    win.document.close();
    win.print();
}

async function handleRfqQuoteFileSelected(e) {
    if (!currentRfqDetail || !e.target.files.length) return;
    const formData = new FormData();
    formData.append('quote', e.target.files[0]);
    try {
        await authFetch(`${API_BASE}/contractor-rfqs/${currentRfqDetail.id}/quote-file`, {
            method: 'POST',
            body: formData
        });
        showToast(t('toast_rfq_quote_uploaded'));
        await openRfqDetailModal(currentRfqDetail.id);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to upload quote file' : 'ไม่สามารถอัปโหลดไฟล์ใบเสนอราคาได้', 'error');
    } finally {
        e.target.value = '';
    }
}

async function handleRfqRemoveQuoteFile() {
    if (!currentRfqDetail) return;
    if (!confirm(t('confirm_delete_rfq_quote_file'))) return;
    try {
        await authFetch(`${API_BASE}/contractor-rfqs/${currentRfqDetail.id}/quote-file`, { method: 'DELETE' });
        showToast(t('toast_rfq_quote_deleted'));
        await openRfqDetailModal(currentRfqDetail.id);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to remove quote file' : 'ไม่สามารถลบไฟล์ใบเสนอราคาได้', 'error');
    }
}

async function openActivityLogModal() {
    document.getElementById('activity-log-search').value = '';
    document.getElementById('activity-log-date-from').value = '';
    document.getElementById('activity-log-date-to').value = '';
    state.activityLogPage = 1;
    await fetchAndRenderActivityLog();
    document.getElementById('modal-activity-log').classList.add('active');
}

function closeActivityLogModal() {
    document.getElementById('modal-activity-log').classList.remove('active');
}

async function fetchAndRenderActivityLog() {
    const search = document.getElementById('activity-log-search').value.trim();
    const dateFrom = document.getElementById('activity-log-date-from').value;
    const dateTo = document.getElementById('activity-log-date-to').value;
    const params = new URLSearchParams({
        page: state.activityLogPage,
        limit: state.activityLogLimit
    });
    if (search) params.set('search', search);
    if (dateFrom) params.set('date_from', dateFrom);
    if (dateTo) params.set('date_to', dateTo);

    try {
        const res = await authFetch(`${API_BASE}/activity-logs?${params.toString()}`);
        const data = await res.json();
        state.activityLogTotal = data.total;
        renderActivityLogList(data.logs);
        updateActivityLogPaginationUI();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load activity log' : 'ไม่สามารถโหลดประวัติการใช้งานได้', 'error');
    }
}

function renderActivityLogList(logs) {
    const tbody = document.getElementById('activity-log-tbody');
    tbody.innerHTML = '';

    if (logs.length === 0) {
        tbody.innerHTML = `<tr><td colspan="4" style="padding:30px; text-align:center; color:var(--text-muted);">${state.currentLanguage === 'en' ? 'No activity found' : 'ไม่พบประวัติการใช้งาน'}</td></tr>`;
        return;
    }

    logs.forEach(log => {
        const tr = document.createElement('tr');
        const time = log.created_at ? parseDbDate(log.created_at).toLocaleString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH') : '-';
        tr.innerHTML = `
            <td style="font-size:0.85rem; color:var(--text-muted);">${time}</td>
            <td><b>${escapeHtml(log.username || '-')}</b></td>
            <td><span style="font-family:monospace; font-size:0.75rem; background:var(--bg-hover); padding:2px 8px; border-radius:10px;">${escapeHtml(log.action)}</span></td>
            <td>${escapeHtml(log.details || '-')}</td>
        `;
        tbody.appendChild(tr);
    });
}

function updateActivityLogPaginationUI() {
    const totalPages = Math.max(Math.ceil(state.activityLogTotal / state.activityLogLimit), 1);
    const startIndex = state.activityLogTotal === 0 ? 0 : (state.activityLogPage - 1) * state.activityLogLimit + 1;
    const endIndex = Math.min(state.activityLogPage * state.activityLogLimit, state.activityLogTotal);

    document.getElementById('activity-log-page-start').textContent = startIndex;
    document.getElementById('activity-log-page-end').textContent = endIndex;
    document.getElementById('activity-log-total-items').textContent = state.activityLogTotal;

    document.getElementById('btn-activity-log-prev-page').disabled = state.activityLogPage <= 1;
    document.getElementById('btn-activity-log-next-page').disabled = state.activityLogPage >= totalPages;
}

function filterActivityLog() {
    state.activityLogPage = 1;
    fetchAndRenderActivityLog();
}

function updateSupplierWebsiteLink(supplierId) {
    const wrapper = document.getElementById('detail-supplier-website-wrapper');
    const linkBtn = document.getElementById('detail-supplier-website');

    if (!supplierId) {
        wrapper.style.display = 'none';
        return;
    }

    const supplier = state.suppliers.find(s => s.id === parseInt(supplierId));
    if (supplier && supplier.website) {
        linkBtn.href = supplier.website;
        wrapper.style.display = 'block';
    } else {
        wrapper.style.display = 'none';
    }
}

function handleSupplierQuoteSelection(e) {
    const file = e.target.files[0];
    if (!file) return;

    state.quoteFileToUpload = file;
    document.getElementById('product-supplier-quote-status').innerHTML = `
        <span class="text-success"><i class="fa-solid fa-file-circle-check"></i> ${state.currentLanguage === 'en' ? 'Ready to upload' : 'พร้อมอัปโหลด'}: ${escapeHtml(file.name)}</span>
    `;
}

// ==========================================
// 8. ADMIN PANEL CONTROL CONTROLLER
// ==========================================

async function openAdminPanelModal() {
    const role = state.currentUser ? state.currentUser.role : 'user';
    const isAdmin = role === 'admin' || role === 'superadmin';
    const usersBtn = document.getElementById('tab-users-btn');
    const permBtn = document.getElementById('tab-permissions-btn');

    // User management and project-permission tabs stay admin/superadmin-only.
    usersBtn.style.display = isAdmin ? 'inline-block' : 'none';
    permBtn.style.display = isAdmin ? 'inline-block' : 'none';

    if (isAdmin) {
        switchAdminTab('users');
        await fetchAdminUsers();
    } else {
        switchAdminTab('permissions');
    }

    // Populate select project list
    const selectProj = document.getElementById('admin-select-project');
    selectProj.innerHTML = '';

    // Non-admin roles see only their allowed projects (pre-filtered by the API in state.projects)
    let filteredProjects = state.projects || [];
    if (role === 'supervisor' || role === 'estimate') {
        filteredProjects = filteredProjects.filter(p => p.created_by === state.currentUser.id);
    }
    filteredProjects = [...filteredProjects].sort((a, b) => (a.name || '').localeCompare(b.name || '', undefined, { sensitivity: 'base' }));

    if (filteredProjects.length > 0) {
        filteredProjects.forEach(proj => {
            const opt = document.createElement('option');
            opt.value = proj.id;
            opt.textContent = `${proj.name} (${proj.client_name || '-'})`;
            selectProj.appendChild(opt);
        });
        // Load permissions for first project
        fetchProjectPermissions(filteredProjects[0].id);
    } else {
        const opt = document.createElement('option');
        opt.value = '';
        opt.textContent = state.currentLanguage === 'en' ? '-- No projects --' : '-- ไม่มีโครงการ --';
        selectProj.appendChild(opt);

        // Clear supervisors list if no projects
        document.getElementById('admin-supervisors-list').innerHTML = `<div class="text-center text-muted">${state.currentLanguage === 'en' ? 'No projects available to manage permissions' : 'ไม่มีโครงการให้สามารถจัดการสิทธิ์ได้'}</div>`;
    }

    document.getElementById('modal-admin-panel').classList.add('active');
}

function closeAdminPanelModal() {
    document.getElementById('modal-admin-panel').classList.remove('active');
}

function switchAdminTab(tab) {
    const usersBtn = document.getElementById('tab-users-btn');
    const permBtn = document.getElementById('tab-permissions-btn');
    const usersContent = document.getElementById('tab-users-content');
    const permContent = document.getElementById('tab-permissions-content');

    usersBtn.classList.remove('active');
    permBtn.classList.remove('active');
    usersContent.style.display = 'none';
    permContent.style.display = 'none';

    usersBtn.style.borderBottomColor = 'transparent';
    permBtn.style.borderBottomColor = 'transparent';

    if (tab === 'users') {
        usersBtn.classList.add('active');
        usersBtn.style.borderBottomColor = 'var(--primary-color)';
        usersContent.style.display = 'block';
    } else {
        permBtn.classList.add('active');
        permBtn.style.borderBottomColor = 'var(--primary-color)';
        permContent.style.display = 'block';
    }
}

async function fetchAdminUsers() {
    try {
        const res = await authFetch(`${API_BASE}/users`);
        const users = await res.json();
        renderAdminUsers(users);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to fetch user accounts' : 'ไม่สามารถดึงข้อมูลบัญชีผู้ใช้งานได้', 'error');
    }
}

function renderAdminUsers(users) {
    const tbody = document.getElementById('admin-users-tbody');
    tbody.innerHTML = '';

    const sortedUsers = [...users].sort((a, b) => (a.username || '').localeCompare(b.username || '', undefined, { sensitivity: 'base' }));

    sortedUsers.forEach(user => {
        const tr = document.createElement('tr');

        // Prevent editing current admin role to avoid self lockout
        const isSelf = state.currentUser && state.currentUser.id === user.id;
        const disabledAttr = isSelf ? 'disabled' : '';

        let roleSelectHtml = '';
        if (user.role === 'superadmin') {
            roleSelectHtml = `<span class="badge bg-warning-light text-warning" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600;">${t('role_superadmin')}</span>`;
        } else {
            roleSelectHtml = `
                <select class="form-control change-role-select" data-user-id="${user.id}" ${disabledAttr} style="padding: 6px; border-radius: var(--radius-sm); border: 1px solid var(--border-color); background-color: var(--bg-panel); color: var(--text-main);">
                    <option value="admin" ${user.role === 'admin' ? 'selected' : ''}>${t('role_admin')}</option>
                    <option value="supervisor" ${user.role === 'supervisor' ? 'selected' : ''}>${t('role_supervisor')}</option>
                    <option value="estimate" ${user.role === 'estimate' ? 'selected' : ''}>${t('role_estimate')}</option>
                    <option value="user" ${user.role === 'user' ? 'selected' : ''}>${t('role_user')}</option>
                    <option value="sale" ${user.role === 'sale' ? 'selected' : ''}>${t('role_sale')}</option>
                    <option value="design" ${user.role === 'design' ? 'selected' : ''}>${t('role_design')}</option>
                    <option value="production" ${user.role === 'production' ? 'selected' : ''}>${t('role_production')}</option>
                    <option value="qc" ${user.role === 'qc' ? 'selected' : ''}>${t('role_qc')}</option>
                    <option value="qa" ${user.role === 'qa' ? 'selected' : ''}>${t('role_qa')}</option>
                    <option value="stock" ${user.role === 'stock' ? 'selected' : ''}>${t('role_stock')}</option>
                    <option value="procurment" ${user.role === 'procurment' ? 'selected' : ''}>${t('role_procurment')}</option>
                    <option value="support" ${user.role === 'support' ? 'selected' : ''}>${t('role_support')}</option>
                    <option value="excusive" ${user.role === 'excusive' ? 'selected' : ''}>${t('role_excusive')}</option>
                    <option value="draft" ${user.role === 'draft' ? 'selected' : ''}>${t('role_draft')}</option>
                    <option value="sale_manager" ${user.role === 'sale_manager' ? 'selected' : ''}>${t('role_sale_manager')}</option>
                    <option value="design_manager_mech" ${user.role === 'design_manager_mech' ? 'selected' : ''}>${t('role_design_manager_mech')}</option>
                    <option value="design_manager_elec" ${user.role === 'design_manager_elec' ? 'selected' : ''}>${t('role_design_manager_elec')}</option>
                    <option value="consultant_mech" ${user.role === 'consultant_mech' ? 'selected' : ''}>${t('role_consultant_mech')}</option>
                    <option value="consultant_elec" ${user.role === 'consultant_elec' ? 'selected' : ''}>${t('role_consultant_elec')}</option>
                    <option value="factory_manager" ${user.role === 'factory_manager' ? 'selected' : ''}>${t('role_factory_manager')}</option>
                    <option value="account_manager" ${user.role === 'account_manager' ? 'selected' : ''}>${t('role_account_manager')}</option>
                    <option value="procurement_manager" ${user.role === 'procurement_manager' ? 'selected' : ''}>${t('role_procurement_manager')}</option>
                    <option value="contractor" ${user.role === 'contractor' ? 'selected' : ''}>${t('role_contractor')}</option>
                </select>
            `;
        }

        let deleteBtnHtml = '';
        if (user.role === 'superadmin') {
            deleteBtnHtml = `<span style="color:var(--text-muted); font-size:0.85rem;">System</span>`;
        } else if (isSelf) {
            deleteBtnHtml = `
                <span style="color:var(--text-muted); font-size:0.85rem;">${state.currentLanguage === 'en' ? 'Logged In' : 'ผู้ใช้นี้เข้าใช้งานอยู่'}</span>
            `;
        } else {
            deleteBtnHtml = `
                <button class="btn-icon btn-danger-icon btn-sm btn-delete-user" data-user-id="${user.id}">
                    <i class="fa-solid fa-trash-can"></i>
                </button>
            `;
        }

        let statusHtml = '';
        if (user.role === 'superadmin') {
            statusHtml = `<span class="badge bg-success-light text-success" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600;">${state.currentLanguage === 'en' ? 'Active' : 'ใช้งานอยู่'}</span>`;
        } else if (isSelf) {
            const isActive = user.is_active !== 0;
            statusHtml = `<span class="badge ${isActive ? 'bg-success-light text-success' : 'bg-danger-light text-danger'}" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600;">${isActive ? (state.currentLanguage === 'en' ? 'Active' : 'ใช้งานอยู่') : (state.currentLanguage === 'en' ? 'Inactive' : 'ระงับใช้งาน')}</span>`;
        } else {
            const isActive = user.is_active !== 0;
            statusHtml = `
                <button class="btn-icon btn-sm btn-toggle-user-status" data-user-id="${user.id}" data-current-active="${isActive ? '1' : '0'}" title="${isActive ? (state.currentLanguage === 'en' ? 'Click to deactivate' : 'คลิกเพื่อระงับการใช้งาน') : (state.currentLanguage === 'en' ? 'Click to activate' : 'คลิกเพื่อเปิดใช้งาน')}" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600; border:1px solid; cursor:pointer; ${isActive ? 'background-color:var(--bg-success-light,#dcfce7); color:var(--success,#16a34a); border-color:var(--success,#16a34a);' : 'background-color:var(--bg-danger-light,#fee2e2); color:var(--danger,#dc2626); border-color:var(--danger,#dc2626);'}">
                    ${isActive ? (state.currentLanguage === 'en' ? 'Active' : 'ใช้งานอยู่') : (state.currentLanguage === 'en' ? 'Inactive' : 'ระงับใช้งาน')}
                </button>
            `;
        }

        let projectAccessHtml = '';
        if (user.role === 'superadmin' || user.role === 'excusive') {
            projectAccessHtml = `<span class="badge bg-success-light text-success" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600;">${state.currentLanguage === 'en' ? 'All Projects' : 'ทุกโครงการ'}</span>`;
        } else {
            if (user.projectAccess && user.projectAccess.length > 0) {
                const list = user.projectAccess.map(pName => `• ${escapeHtml(pName)}`).join('<br>');
                projectAccessHtml = `<div style="font-size:0.8rem; line-height:1.4; max-height:80px; overflow-y:auto; padding:2px;">${list}</div>`;
            } else {
                projectAccessHtml = `<span style="color:var(--text-muted); font-size:0.8rem;">-</span>`;
            }
        }

        const isSuperAdmin = user.role === 'superadmin';
        const passwordInputDisabled = (isSuperAdmin && state.currentUser?.role !== 'superadmin') ? 'disabled' : '';
        const passwordHtml = `
            <div style="display:flex; align-items:center; gap:6px;">
                <input type="text" class="form-control user-password-input" data-user-id="${user.id}" ${passwordInputDisabled} value="${escapeHtml(user.plain_password || '********')}" style="padding: 4px 8px; font-size: 0.85rem; border-radius: var(--radius-sm); border: 1px solid var(--border-color); background-color: var(--bg-panel); color: var(--text-main); width: 110px;">
                <button class="btn btn-outline btn-sm btn-update-user-password" data-user-id="${user.id}" ${(isSuperAdmin && state.currentUser?.role !== 'superadmin') ? 'disabled' : ''} title="${state.currentLanguage === 'en' ? 'Update password' : 'อัปเดตเซ็ตรหัสผ่านใหม่'}" style="padding:2px 6px; display:inline-flex; align-items:center; justify-content:center;">
                    <i class="fa-solid fa-check" style="font-size:0.75rem;"></i>
                </button>
            </div>
        `;

        let accessGroupHtml = '';
        if (user.role === 'superadmin' || user.role === 'excusive') {
            accessGroupHtml = `<span class="badge" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600; background-color:#fee2e2; color:#dc2626;">${t('access_executive')}</span>`;
        } else if (user.role === 'admin' || user.role === 'supervisor' || user.role === 'estimate') {
            accessGroupHtml = `<span class="badge" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600; background-color:#fef3c7; color:#d97706;">${t('access_confidential')}</span>`;
        } else if (user.role === 'contractor') {
            accessGroupHtml = `<span class="badge" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600; background-color:#e2e8f0; color:#475569;">${t('access_low')}</span>`;
        } else {
            accessGroupHtml = `<span class="badge" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600; background-color:#dcfce7; color:#16a34a;">${t('access_general')}</span>`;
        }

        tr.innerHTML = `
            <td class="font-bold">${escapeHtml(user.username)}</td>
            <td>${roleSelectHtml}</td>
            <td>${accessGroupHtml}</td>
            <td>${passwordHtml}</td>
            <td>${projectAccessHtml}</td>
            <td>${parseDbDate(user.created_at).toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH')}</td>
            <td class="text-center">${statusHtml}</td>
            <td class="text-center">${deleteBtnHtml}</td>
        `;

        tbody.appendChild(tr);
    });

    // Bind listeners for change-role-select
    tbody.querySelectorAll('.change-role-select').forEach(select => {
        select.addEventListener('change', async (e) => {
            const userId = e.target.dataset.userId;
            const newRole = e.target.value;
            await handleRoleChange(userId, newRole);
        });
    });

    // Bind listeners for btn-delete-user
    tbody.querySelectorAll('.btn-delete-user').forEach(btn => {
        btn.addEventListener('click', async (e) => {
            const userId = e.currentTarget.dataset.userId;
            await handleDeleteUser(userId);
        });
    });

    // Bind listeners for btn-update-user-password
    tbody.querySelectorAll('.btn-update-user-password').forEach(btn => {
        btn.addEventListener('click', async (e) => {
            const userId = e.currentTarget.dataset.userId;
            const input = tbody.querySelector(`.user-password-input[data-user-id="${userId}"]`);
            const newPassword = input ? input.value : '';
            if (!newPassword) {
                alert(state.currentLanguage === 'en' ? 'Password cannot be empty' : 'รหัสผ่านต้องไม่ว่างเปล่า');
                return;
            }
            if (!confirm(state.currentLanguage === 'en' ? `Are you sure you want to change password for this user?` : `คุณแน่ใจหรือไม่ว่าต้องการเปลี่ยนรหัสผ่านสำหรับผู้ใช้งานรายนี้?`)) return;
            try {
                const res = await authFetch(`${API_BASE}/users/${userId}/password`, {
                    method: 'PUT',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ newPassword })
                });
                if (res.ok) {
                    showToast(state.currentLanguage === 'en' ? 'Password updated successfully' : 'อัปเดตรหัสผ่านสำเร็จ');
                    await fetchAdminUsers();
                } else {
                    const err = await res.json();
                    alert(err.error || 'Failed to update password');
                }
            } catch (err) {
                console.error(err);
                alert('Connection error');
            }
        });
    });

    // Bind listeners for btn-toggle-user-status
    tbody.querySelectorAll('.btn-toggle-user-status').forEach(btn => {
        btn.addEventListener('click', async (e) => {
            const userId = e.currentTarget.dataset.userId;
            const currentlyActive = e.currentTarget.dataset.currentActive === '1';
            await handleToggleUserStatus(userId, !currentlyActive);
        });
    });
}

async function handleToggleUserStatus(userId, newIsActive) {
    const confirmMsg = newIsActive
        ? (state.currentLanguage === 'en' ? 'Reactivate this account?' : 'ต้องการเปิดใช้งานบัญชีนี้ใช่หรือไม่?')
        : (state.currentLanguage === 'en' ? 'Deactivate this account? The user will not be able to log in.' : 'ต้องการระงับการใช้งานบัญชีนี้ใช่หรือไม่? ผู้ใช้จะไม่สามารถเข้าสู่ระบบได้');
    if (!confirm(confirmMsg)) return;

    try {
        await authFetch(`${API_BASE}/users/${userId}/status`, {
            method: 'PUT',
            body: JSON.stringify({ is_active: newIsActive })
        });
        showToast(newIsActive
            ? (state.currentLanguage === 'en' ? 'Account activated' : 'เปิดใช้งานบัญชีเรียบร้อยแล้ว')
            : (state.currentLanguage === 'en' ? 'Account deactivated' : 'ระงับการใช้งานบัญชีเรียบร้อยแล้ว'));
        await fetchAdminUsers();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to update account status' : 'ไม่สามารถเปลี่ยนสถานะบัญชีได้', 'error');
    }
}

async function openAnnouncementsManagerModal() {
    document.getElementById('modal-announcements-manager').classList.add('active');
    await fetchAndRenderAnnouncements();
}

function closeAnnouncementsManagerModal() {
    document.getElementById('modal-announcements-manager').classList.remove('active');
}

async function handleAdminPanelRefresh() {
    showToast(state.currentLanguage === 'en' ? 'Refreshing...' : 'กำลังรีเฟรชข้อมูล...');
    try {
        await fetchAdminUsers();

        // Repopulate projects
        const selectProj = document.getElementById('admin-select-project');
        const currentSelectedId = selectProj ? selectProj.value : null;

        await fetchProjects();

        if (selectProj) {
            selectProj.innerHTML = '';
            let filteredProjects = state.projects || [];
            if (state.currentUser && (state.currentUser.role === 'supervisor' || state.currentUser.role === 'estimate')) {
                filteredProjects = filteredProjects.filter(p => p.created_by === state.currentUser.id);
            }
            if (filteredProjects.length > 0) {
                filteredProjects.forEach(proj => {
                    const opt = document.createElement('option');
                    opt.value = proj.id;
                    opt.textContent = `${proj.name} (${proj.client_name || '-'})`;
                    if (proj.id === currentSelectedId) opt.selected = true;
                    selectProj.appendChild(opt);
                });

                const newSelectedId = selectProj.value;
                if (newSelectedId) {
                    await fetchProjectPermissions(newSelectedId);
                }
            } else {
                const opt = document.createElement('option');
                opt.value = '';
                opt.textContent = state.currentLanguage === 'en' ? '-- No projects --' : '-- ไม่มีโครงการ --';
                selectProj.appendChild(opt);
                document.getElementById('admin-supervisors-list').innerHTML = `<div class="text-center text-muted">${state.currentLanguage === 'en' ? 'No projects available to manage permissions' : 'ไม่มีโครงการให้สามารถจัดการสิทธิ์ได้'}</div>`;
            }
        }

        showToast(state.currentLanguage === 'en' ? 'Data refreshed' : 'รีเฟรชข้อมูลเรียบร้อยแล้ว');
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to refresh' : 'ไม่สามารถรีเฟรชข้อมูลได้', 'error');
    }
}

async function fetchAndRenderAnnouncements() {
    try {
        const res = await authFetch(`${API_BASE}/announcements`);
        const announcements = await res.json();
        state.allAnnouncements = announcements;
        renderAnnouncementsList(announcements);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load announcements' : 'ไม่สามารถโหลดข้อมูลประกาศได้', 'error');
    }
}

function renderAnnouncementsList(announcements) {
    const tbody = document.getElementById('announcements-manager-tbody');
    tbody.innerHTML = '';

    if (announcements.length === 0) {
        tbody.innerHTML = `<tr><td colspan="6" style="padding:30px; text-align:center; color:var(--text-muted);">${state.currentLanguage === 'en' ? 'No announcements yet' : 'ยังไม่มีประกาศ'}</td></tr>`;
        return;
    }

    announcements.forEach(a => {
        const tr = document.createElement('tr');
        const isActive = a.is_active !== 0;
        tr.innerHTML = `
            <td><b>${escapeHtml(a.title)}</b></td>
            <td>${escapeHtml(a.created_by_name || '-')}</td>
            <td>${parseDbDate(a.created_at).toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH')}</td>
            <td class="text-center">${a.ack_count}</td>
            <td class="text-center">
                <button class="btn-icon btn-sm btn-toggle-announcement-active" data-announcement-id="${a.id}" data-current-active="${isActive ? '1' : '0'}" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600; border:1px solid; cursor:pointer; ${isActive ? 'background-color:var(--bg-success-light,#dcfce7); color:var(--success,#16a34a); border-color:var(--success,#16a34a);' : 'background-color:var(--bg-danger-light,#fee2e2); color:var(--danger,#dc2626); border-color:var(--danger,#dc2626);'}">
                    ${isActive ? (state.currentLanguage === 'en' ? 'Active' : 'เปิดใช้งาน') : (state.currentLanguage === 'en' ? 'Inactive' : 'ปิดใช้งาน')}
                </button>
            </td>
            <td class="text-center">
                <div style="display:flex; justify-content:center; gap:8px;">
                    <button class="btn btn-outline btn-sm btn-edit-announcement" data-announcement-id="${a.id}">
                        <i class="fa-solid fa-edit"></i>
                    </button>
                    <button class="btn btn-danger-outline btn-sm btn-delete-announcement" data-announcement-id="${a.id}">
                        <i class="fa-solid fa-trash"></i>
                    </button>
                </div>
            </td>
        `;

        tr.querySelector('.btn-edit-announcement').addEventListener('click', () => {
            const announcement = state.allAnnouncements.find(x => x.id === a.id);
            openAnnouncementDetailModal(announcement);
        });
        tr.querySelector('.btn-delete-announcement').addEventListener('click', () => handleDeleteAnnouncement(a.id));
        tr.querySelector('.btn-toggle-announcement-active').addEventListener('click', () => {
            const announcement = state.allAnnouncements.find(x => x.id === a.id);
            handleToggleAnnouncementActive(announcement);
        });

        tbody.appendChild(tr);
    });
}

function openAnnouncementDetailModal(announcement = null) {
    const modal = document.getElementById('modal-announcement-detail');
    const title = document.getElementById('announcement-detail-title');
    const form = document.getElementById('form-announcement-detail');
    form.reset();

    if (announcement) {
        title.textContent = state.currentLanguage === 'en' ? 'Edit Announcement' : 'แก้ไขประกาศ';
        document.getElementById('announcement-detail-id').value = announcement.id;
        document.getElementById('announcement-detail-title-input').value = announcement.title;
        document.getElementById('announcement-detail-body-input').value = announcement.body;
        document.getElementById('announcement-detail-active').checked = announcement.is_active !== 0;
    } else {
        title.textContent = state.currentLanguage === 'en' ? 'Add New Announcement' : 'เพิ่มประกาศใหม่';
        document.getElementById('announcement-detail-id').value = '';
        document.getElementById('announcement-detail-active').checked = true;
    }
    modal.classList.add('active');
}

function closeAnnouncementDetailModal() {
    document.getElementById('modal-announcement-detail').classList.remove('active');
}

async function handleAnnouncementDetailSubmit(e) {
    e.preventDefault();
    const id = document.getElementById('announcement-detail-id').value;
    const title = document.getElementById('announcement-detail-title-input').value.trim();
    const body = document.getElementById('announcement-detail-body-input').value.trim();
    const isActive = document.getElementById('announcement-detail-active').checked;

    try {
        if (id) {
            await authFetch(`${API_BASE}/announcements/${id}`, {
                method: 'PUT',
                body: JSON.stringify({ title, body, is_active: isActive })
            });
            showToast(state.currentLanguage === 'en' ? 'Announcement updated' : 'อัปเดตประกาศเรียบร้อยแล้ว');
        } else {
            await authFetch(`${API_BASE}/announcements`, {
                method: 'POST',
                body: JSON.stringify({ title, body })
            });
            showToast(state.currentLanguage === 'en' ? 'Announcement created' : 'สร้างประกาศเรียบร้อยแล้ว');
        }
        closeAnnouncementDetailModal();
        await fetchAndRenderAnnouncements();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to save announcement' : 'ไม่สามารถบันทึกประกาศได้', 'error');
    }
}

async function handleToggleAnnouncementActive(announcement) {
    try {
        await authFetch(`${API_BASE}/announcements/${announcement.id}`, {
            method: 'PUT',
            body: JSON.stringify({ title: announcement.title, body: announcement.body, is_active: announcement.is_active === 0 })
        });
        await fetchAndRenderAnnouncements();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to update announcement status' : 'ไม่สามารถเปลี่ยนสถานะประกาศได้', 'error');
    }
}

async function handleDeleteAnnouncement(id) {
    if (!confirm(state.currentLanguage === 'en' ? 'Delete this announcement?' : 'ต้องการลบประกาศนี้ใช่หรือไม่?')) return;
    try {
        await authFetch(`${API_BASE}/announcements/${id}`, { method: 'DELETE' });
        showToast(state.currentLanguage === 'en' ? 'Announcement deleted' : 'ลบประกาศเรียบร้อยแล้ว');
        await fetchAndRenderAnnouncements();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to delete announcement' : 'ไม่สามารถลบประกาศได้', 'error');
    }
}

// ==========================================
// Department Reports Module
// ==========================================

const REPORT_TABS = [
    { key: 'electrical-design', th: 'ออกแบบระบบไฟฟ้า', en: 'Electrical Design', icon: 'fa-bolt' },
    { key: 'mechanical-design', th: 'ออกแบบระบบเครื่องกล', en: 'Mechanical Design', icon: 'fa-fan' },
    { key: 'sales', th: 'ฝ่ายขาย', en: 'Sales', icon: 'fa-handshake' },
    { key: 'production', th: 'ฝ่ายผลิต', en: 'Production', icon: 'fa-industry' },
    { key: 'qc', th: 'ฝ่ายควบคุมคุณภาพ', en: 'Quality Control', icon: 'fa-clipboard-check' },
    { key: 'planning', th: 'ฝ่ายวางแผน', en: 'Planning', icon: 'fa-calendar-days' },
    { key: 'procurement', th: 'ฝ่ายจัดซื้อ', en: 'Procurement', icon: 'fa-cart-shopping' },
    { key: 'accounting', th: 'ฝ่ายบัญชี', en: 'Accounting', icon: 'fa-calculator' },
    { key: 'executive', th: 'ฝ่ายบริหาร', en: 'Executive', icon: 'fa-crown' },
];

async function checkReportsButtonVisibility() {
    const btn = document.getElementById('btn-open-reports');
    try {
        const res = await authFetch(`${API_BASE}/reports/available`);
        const data = await res.json();
        state.availableReports = data.available || [];
        btn.style.display = state.availableReports.length > 0 ? 'inline-flex' : 'none';
    } catch (err) {
        btn.style.display = 'none';
    }
}

async function openReportsModal() {
    const tabBar = document.getElementById('reports-tab-bar');
    tabBar.innerHTML = '';

    if (!state.availableReports || state.availableReports.length === 0) {
        await checkReportsButtonVisibility();
    }

    REPORT_TABS.filter(tab => state.availableReports.includes(tab.key)).forEach((tab, idx) => {
        const btn = document.createElement('button');
        btn.className = 'btn btn-outline btn-sm';
        btn.dataset.reportKey = tab.key;
        btn.innerHTML = `<i class="fa-solid ${tab.icon}"></i> ${state.currentLanguage === 'en' ? tab.en : tab.th}`;
        btn.addEventListener('click', () => switchReportTab(tab.key));
        tabBar.appendChild(btn);
        if (idx === 0) switchReportTab(tab.key);
    });

    document.getElementById('modal-reports').classList.add('active');
}

function closeReportsModal() {
    document.getElementById('modal-reports').classList.remove('active');
}

async function switchReportTab(key) {
    document.querySelectorAll('#reports-tab-bar button').forEach(btn => {
        btn.classList.toggle('btn-primary', btn.dataset.reportKey === key);
        btn.classList.toggle('btn-outline', btn.dataset.reportKey !== key);
    });

    const content = document.getElementById('reports-content-area');
    content.innerHTML = `<div style="text-align:center; padding:40px; color:var(--text-muted);"><i class="fa-solid fa-spinner fa-spin" style="font-size:2rem;"></i></div>`;

    try {
        const res = await authFetch(`${API_BASE}/reports/${key}`);
        const data = await res.json();
        content.innerHTML = renderReportContent(key, data);
    } catch (err) {
        content.innerHTML = `<div style="text-align:center; padding:40px; color:var(--danger);">${state.currentLanguage === 'en' ? 'Failed to load report' : 'ไม่สามารถโหลดรายงานได้'}</div>`;
    }
}

function renderSummaryCards(items) {
    return `
        <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap:12px; margin-bottom:20px;">
            ${items.map(item => `
                <div style="background:var(--bg-hover); border-radius:var(--radius-md); padding:14px 16px;">
                    <div style="font-size:0.78rem; color:var(--text-muted); margin-bottom:4px;">${escapeHtml(item.label)}</div>
                    <div style="font-size:1.3rem; font-weight:700; color:${item.color || 'var(--text-main)'};">${item.value}</div>
                </div>
            `).join('')}
        </div>
    `;
}

function renderDataTable(title, columns, rows) {
    if (!rows || rows.length === 0) {
        return `<div style="margin-bottom:24px;"><h4 style="margin-bottom:10px;">${escapeHtml(title)}</h4><div style="padding:20px; text-align:center; color:var(--text-muted); background:var(--bg-hover); border-radius:var(--radius-sm);">${state.currentLanguage === 'en' ? 'No data' : 'ไม่มีข้อมูล'}</div></div>`;
    }
    return `
        <div style="margin-bottom:24px;">
            <h4 style="margin-bottom:10px;">${escapeHtml(title)}</h4>
            <div class="explorer-table-wrapper">
                <table class="data-table">
                    <thead><tr>${columns.map(c => `<th>${escapeHtml(c.label)}</th>`).join('')}</tr></thead>
                    <tbody>
                        ${rows.map(row => `<tr>${columns.map(c => `<td>${c.format ? c.format(row[c.key], row) : escapeHtml(String(row[c.key] ?? '-'))}</td>`).join('')}</tr>`).join('')}
                    </tbody>
                </table>
            </div>
        </div>
    `;
}

function renderReportContent(key, data) {
    const isEn = state.currentLanguage === 'en';
    switch (key) {
        case 'electrical-design':
        case 'mechanical-design':
            return renderSummaryCards([
                { label: isEn ? 'Total Sections' : 'ระบบงานทั้งหมด', value: data.summary.total_sections },
                { label: isEn ? 'Projects Involved' : 'จำนวนโครงการ', value: data.summary.total_projects },
                { label: isEn ? 'Missing Spec Upload' : 'ยังไม่มีไฟล์สเปก', value: data.summary.sections_missing_spec, color: data.summary.sections_missing_spec > 0 ? 'var(--danger)' : 'var(--success)' },
            ]) + renderDataTable(isEn ? 'Sections' : 'รายการระบบงาน',
                [
                    { key: 'project_name', label: isEn ? 'Project' : 'โครงการ' },
                    { key: 'section_name', label: isEn ? 'Section' : 'ระบบงาน' },
                    { key: 'item_count', label: isEn ? 'Items' : 'จำนวนสินค้า' },
                    { key: 'has_spec', label: isEn ? 'Spec Uploaded' : 'มีไฟล์สเปก', format: v => v ? `<span class="text-success"><i class="fa-solid fa-check"></i></span>` : `<span class="text-danger"><i class="fa-solid fa-xmark"></i></span>` },
                ], data.sections);

        case 'sales':
            return renderSummaryCards([
                { label: isEn ? 'Total Projects' : 'โครงการทั้งหมด', value: data.summary.total_projects },
                { label: isEn ? 'Total Bid Value' : 'มูลค่าเสนอราคารวม', value: formatCurrency(data.summary.total_bid_value) },
            ]) + renderDataTable(isEn ? 'Top Clients by Value' : 'ลูกค้าตามมูลค่า',
                [{ key: 'client', label: isEn ? 'Client' : 'ลูกค้า' }, { key: 'value', label: isEn ? 'Value' : 'มูลค่า', format: formatCurrency }],
                data.summary.top_clients)
                + renderDataTable(isEn ? 'All Projects' : 'โครงการทั้งหมด',
                [
                    { key: 'name', label: isEn ? 'Project' : 'โครงการ' },
                    { key: 'client_name', label: isEn ? 'Client' : 'ลูกค้า' },
                    { key: 'status', label: isEn ? 'Status' : 'สถานะ' },
                    { key: 'price_total', label: isEn ? 'Bid Price' : 'ราคาเสนอ', format: formatCurrency },
                ], data.projects);

        case 'production':
            return renderSummaryCards([
                { label: isEn ? 'Total Updates' : 'อัปเดตทั้งหมด', value: data.summary.total_updates },
                { label: isEn ? 'Open Issues' : 'ปัญหาที่ยังเปิดอยู่', value: data.summary.open_issue_count, color: data.summary.open_issue_count > 0 ? 'var(--danger)' : 'var(--success)' },
                { label: isEn ? 'Stale Projects (14+ days)' : 'โครงการที่ไม่มีอัปเดต 14 วัน+', value: data.summary.stale_project_count, color: data.summary.stale_project_count > 0 ? 'var(--danger)' : 'var(--success)' },
            ]) + renderDataTable(isEn ? 'Open Issues' : 'ปัญหาที่ยังเปิดอยู่',
                [
                    { key: 'project_name', label: isEn ? 'Project' : 'โครงการ' },
                    { key: 'system_name', label: isEn ? 'System' : 'ระบบงาน' },
                    { key: 'issues', label: isEn ? 'Issue' : 'ปัญหา' },
                    { key: 'created_at', label: isEn ? 'Date' : 'วันที่', format: v => parseDbDate(v).toLocaleDateString(isEn ? 'en-US' : 'th-TH') },
                ], data.open_issues)
                + renderDataTable(isEn ? 'Recent Updates' : 'อัปเดตล่าสุด',
                [
                    { key: 'project_name', label: isEn ? 'Project' : 'โครงการ' },
                    { key: 'progress_desc', label: isEn ? 'Description' : 'รายละเอียด' },
                    { key: 'creator_name', label: isEn ? 'By' : 'โดย' },
                    { key: 'created_at', label: isEn ? 'Date' : 'วันที่', format: v => parseDbDate(v).toLocaleDateString(isEn ? 'en-US' : 'th-TH') },
                ], data.recent_updates.slice(0, 30));

        case 'qc':
            return renderSummaryCards([
                { label: isEn ? 'Total FAT Reports' : 'รายงาน FAT ทั้งหมด', value: data.summary.total_reports },
                { label: isEn ? 'Total Pass' : 'ผ่านทั้งหมด', value: data.summary.total_pass, color: 'var(--success)' },
                { label: isEn ? 'Total Fail' : 'ไม่ผ่านทั้งหมด', value: data.summary.total_fail, color: data.summary.total_fail > 0 ? 'var(--danger)' : 'var(--success)' },
            ]) + renderDataTable(isEn ? 'Failed Items Needing Attention' : 'รายการที่ไม่ผ่านและต้องแก้ไข',
                [
                    { key: 'project_name', label: isEn ? 'Project' : 'โครงการ' },
                    { key: 'report_type', label: isEn ? 'Report Type' : 'ประเภทรายงาน' },
                    { key: 'title', label: isEn ? 'Item' : 'รายการ' },
                    { key: 'remarks', label: isEn ? 'Remarks' : 'หมายเหตุ' },
                ], data.failed_items)
                + renderDataTable(isEn ? 'FAT Reports' : 'รายงาน FAT ทั้งหมด',
                [
                    { key: 'project_name', label: isEn ? 'Project' : 'โครงการ' },
                    { key: 'report_type', label: isEn ? 'Type' : 'ประเภท' },
                    { key: 'pass_count', label: isEn ? 'Pass' : 'ผ่าน' },
                    { key: 'fail_count', label: isEn ? 'Fail' : 'ไม่ผ่าน' },
                ], data.reports);

        case 'planning':
            return `<div style="padding:10px 14px; background:var(--bg-hover); border-radius:var(--radius-sm); font-size:0.85rem; color:var(--text-muted); margin-bottom:16px;"><i class="fa-solid fa-circle-info"></i> ${escapeHtml(data.note)}</div>`
                + renderSummaryCards([
                    { label: isEn ? 'Total Projects' : 'โครงการทั้งหมด', value: data.summary.total_projects },
                ]) + renderDataTable(isEn ? 'Upcoming RFQ Due Dates' : 'กำหนดส่ง RFQ ที่ใกล้ถึง',
                [
                    { key: 'rfq_number', label: 'RFQ' },
                    { key: 'project_name', label: isEn ? 'Project' : 'โครงการ' },
                    { key: 'contractor_name', label: isEn ? 'Contractor' : 'ผู้รับเหมา' },
                    { key: 'due_date', label: isEn ? 'Due Date' : 'กำหนดส่ง' },
                    { key: 'status', label: isEn ? 'Status' : 'สถานะ' },
                ], data.upcoming_rfqs)
                + renderDataTable(isEn ? 'All Projects' : 'โครงการทั้งหมด',
                [
                    { key: 'name', label: isEn ? 'Project' : 'โครงการ' },
                    { key: 'status', label: isEn ? 'Status' : 'สถานะ' },
                    { key: 'current_revision', label: isEn ? 'Revision' : 'เวอร์ชัน' },
                ], data.projects);

        case 'procurement':
            return renderSummaryCards([
                { label: isEn ? 'Total RFQs' : 'RFQ ทั้งหมด', value: data.summary.total_rfqs },
                { label: isEn ? 'Total Suppliers' : 'ผู้จัดจำหน่ายทั้งหมด', value: data.summary.total_suppliers },
            ]) + renderDataTable(isEn ? 'Spend by Contractor' : 'ยอดใช้จ่ายตามผู้รับเหมา',
                [{ key: 'contractor', label: isEn ? 'Contractor' : 'ผู้รับเหมา' }, { key: 'total', label: isEn ? 'Total' : 'ยอดรวม', format: formatCurrency }],
                data.summary.spend_by_contractor)
                + renderDataTable(isEn ? 'All RFQs' : 'RFQ ทั้งหมด',
                [
                    { key: 'rfq_number', label: 'RFQ' },
                    { key: 'project_name', label: isEn ? 'Project' : 'โครงการ' },
                    { key: 'contractor_name', label: isEn ? 'Contractor' : 'ผู้รับเหมา' },
                    { key: 'status', label: isEn ? 'Status' : 'สถานะ' },
                    { key: 'total_amount', label: isEn ? 'Amount' : 'ยอดเงิน', format: formatCurrency },
                ], data.rfqs);

        case 'accounting':
            return renderSummaryCards([
                { label: isEn ? 'Total Cost' : 'ต้นทุนรวม', value: formatCurrency(data.summary.total_cost) },
                { label: isEn ? 'Total Price' : 'ราคาขายรวม', value: formatCurrency(data.summary.total_price) },
                { label: isEn ? 'Total Profit' : 'กำไรรวม', value: formatCurrency(data.summary.total_profit), color: data.summary.total_profit >= 0 ? 'var(--success)' : 'var(--danger)' },
            ]) + renderDataTable(isEn ? 'Project P&L' : 'กำไร-ขาดทุนรายโครงการ',
                [
                    { key: 'name', label: isEn ? 'Project' : 'โครงการ' },
                    { key: 'client_name', label: isEn ? 'Client' : 'ลูกค้า' },
                    { key: 'cost_total', label: isEn ? 'Cost' : 'ต้นทุน', format: formatCurrency },
                    { key: 'price_total', label: isEn ? 'Price' : 'ราคาขาย', format: formatCurrency },
                    { key: 'profit', label: isEn ? 'Profit' : 'กำไร', format: formatCurrency },
                    { key: 'profit_margin_percent', label: isEn ? 'Margin %' : 'อัตรากำไร %', format: v => v.toFixed(1) + '%' },
                ], data.projects);

        case 'executive':
            return renderSummaryCards([
                { label: isEn ? 'Total Projects' : 'โครงการทั้งหมด', value: data.summary.total_projects },
                { label: isEn ? 'Portfolio Value' : 'มูลค่าพอร์ตโฟลิโอ', value: formatCurrency(data.summary.total_portfolio_value) },
                { label: isEn ? 'Total Profit' : 'กำไรรวม', value: formatCurrency(data.summary.total_profit), color: data.summary.total_profit >= 0 ? 'var(--success)' : 'var(--danger)' },
                { label: isEn ? 'Overall Margin' : 'อัตรากำไรรวม', value: data.summary.overall_margin_percent.toFixed(1) + '%' },
            ]) + renderDataTable(isEn ? 'Recent Activity' : 'กิจกรรมล่าสุด',
                [
                    { key: 'username', label: isEn ? 'User' : 'ผู้ใช้' },
                    { key: 'action', label: isEn ? 'Action' : 'การกระทำ' },
                    { key: 'details', label: isEn ? 'Details' : 'รายละเอียด' },
                    { key: 'created_at', label: isEn ? 'Time' : 'เวลา', format: v => parseDbDate(v).toLocaleString(isEn ? 'en-US' : 'th-TH') },
                ], data.recent_activity);

        default:
            return '';
    }
}

// ==========================================
// Internal Chat Module
// ==========================================

async function checkChatUnreadBadge() {
    if (state.currentUser && state.currentUser.role === 'contractor') {
        return;
    }
    try {
        const res = await authFetch(`${API_BASE}/chat/unread-count`);
        const data = await res.json();
        const badge = document.getElementById('chat-unread-badge');
        if (data.total_unread > 0) {
            badge.textContent = data.total_unread > 99 ? '99+' : data.total_unread;
            badge.style.display = 'flex';
        } else {
            badge.style.display = 'none';
        }
    } catch (err) {
        // Silent - badge polling shouldn't be noisy on failure
    }
}

function startChatUnreadPolling() {
    if (state.currentUser && state.currentUser.role === 'contractor') {
        if (state.chatUnreadPollInterval) {
            clearInterval(state.chatUnreadPollInterval);
            state.chatUnreadPollInterval = null;
        }
        return;
    }
    if (state.chatUnreadPollInterval) clearInterval(state.chatUnreadPollInterval);
    checkChatUnreadBadge();
    state.chatUnreadPollInterval = setInterval(checkChatUnreadBadge, 25000);
}

async function openChatModal() {
    document.getElementById('modal-chat').classList.add('active');
    document.getElementById('chat-thread-active').style.display = 'none';
    document.getElementById('chat-thread-empty').style.display = 'flex';
    state.activeChatConversationId = null;
    
    // Clear search values
    document.getElementById('chat-search-input').value = '';
    document.getElementById('chat-message-search-input').value = '';
    document.getElementById('chat-message-search-container').style.display = 'none';
    document.getElementById('btn-chat-message-search-clear').style.display = 'none';
    
    // Initialize emoji picker
    if (!state.emojiPickerInitialized) {
        initEmojiPicker();
        state.emojiPickerInitialized = true;
    }
    
    await fetchAndRenderConversations();
}

function closeChatModal() {
    document.getElementById('modal-chat').classList.remove('active');
    stopChatThreadPolling();
}

async function fetchAndRenderConversations() {
    try {
        const res = await authFetch(`${API_BASE}/chat/conversations`);
        const conversations = await res.json();
        state.chatConversations = conversations;
        
        // Filter conversations based on search
        const query = (document.getElementById('chat-search-input').value || '').toLowerCase().trim();
        let filtered = conversations;
        if (query) {
            filtered = conversations.filter(c => 
                (c.other_username && c.other_username.toLowerCase().includes(query)) ||
                (c.last_message && c.last_message.toLowerCase().includes(query))
            );
        }
        renderConversationsList(filtered);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load conversations' : 'ไม่สามารถโหลดรายการสนทนาได้', 'error');
    }
}

function renderConversationsList(conversations) {
    const container = document.getElementById('chat-conversations-list');
    container.innerHTML = '';

    if (conversations.length === 0) {
        container.innerHTML = `<div style="padding:20px; text-align:center; color:var(--text-muted); font-size:0.85rem;">${state.currentLanguage === 'en' ? 'No conversations found' : 'ไม่พบรายการสนทนา'}</div>`;
        return;
    }

    conversations.forEach(conv => {
        const item = document.createElement('div');
        const isActive = state.activeChatConversationId === conv.id;
        
        // Circular profile initials avatar
        const name = conv.is_group === 1 ? conv.name : (conv.other_username || '-');
        const initial = name.charAt(0).toUpperCase();
        
        // Generate a stable color index based on username string
        let charCodeSum = 0;
        for (let i = 0; i < name.length; i++) charCodeSum += name.charCodeAt(i);
        const colors = [
            'linear-gradient(135deg, #3b82f6, #1d4ed8)', // Blue
            'linear-gradient(135deg, #ec4899, #be185d)', // Pink
            'linear-gradient(135deg, #10b981, #047857)', // Green
            'linear-gradient(135deg, #f59e0b, #b45309)', // Amber
            'linear-gradient(135deg, #8b5cf6, #6d28d9)', // Purple
            'linear-gradient(135deg, #ef4444, #b91c1c)'  // Red
        ];
        const avatarBg = colors[charCodeSum % colors.length];

        let lastMsgPreview = '';
        if (conv.last_message) {
            if (conv.last_message.startsWith('[sticker:')) {
                lastMsgPreview = `[${state.currentLanguage === 'en' ? 'Sticker' : 'สติกเกอร์'}]`;
            } else if (conv.last_message.startsWith('[image:')) {
                lastMsgPreview = `[${state.currentLanguage === 'en' ? 'Image' : 'รูปภาพ'}]`;
            } else {
                lastMsgPreview = escapeHtml(conv.last_message).slice(0, 30);
            }
        } else {
            lastMsgPreview = state.currentLanguage === 'en' ? 'No messages yet' : 'ยังไม่มีข้อความ';
        }

        item.style.cssText = `
            display: flex;
            align-items: center;
            gap: 12px;
            padding: 12px 16px;
            cursor: pointer;
            border-bottom: 1px solid var(--border-color);
            transition: background-color 0.2s;
            ${isActive ? 'background-color: var(--primary-light, #dbeafe); border-left: 4px solid var(--primary-color); padding-left: 12px;' : ''}
        `;
        
        item.className = 'chat-conversations-list-item';

        const showOnlineStatus = conv.is_group !== 1 && conv.other_is_online === 1;
        item.innerHTML = `
            <div class="chat-avatar-wrapper">
                <div style="width: 40px; height: 40px; border-radius: 50%; background: ${avatarBg}; color: white; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 1.1rem; flex-shrink: 0; box-shadow: 0 2px 4px rgba(0,0,0,0.1); user-select: none;">
                    ${initial}
                </div>
                ${showOnlineStatus ? `<span class="online-status-dot"></span>` : ''}
            </div>
            <div style="flex: 1; min-width: 0;">
                <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2px;">
                    <b style="font-size: 0.92rem; color: var(--text-main); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: block; max-width: 140px;">
                        ${escapeHtml(name)}
                    </b>
                    ${conv.unread_count > 0 ? `
                        <span style="background: var(--danger, #ef4444); color: white; font-size: 0.65rem; font-weight: 700; min-width: 18px; height: 18px; border-radius: 9px; display: flex; align-items: center; justify-content: center; padding: 0 5px; flex-shrink: 0; box-shadow: 0 1px 3px rgba(239, 68, 68, 0.3);">
                            ${conv.unread_count}
                        </span>
                    ` : ''}
                </div>
                <div style="font-size: 0.78rem; color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
                    ${lastMsgPreview}
                </div>
            </div>
        `;
        
        item.addEventListener('click', () => openConversationThread(conv.id, name));
        container.appendChild(item);
    });
}

function stopChatThreadPolling() {
    if (state.chatThreadPollInterval) {
        clearInterval(state.chatThreadPollInterval);
        state.chatThreadPollInterval = null;
    }
}

async function openConversationThread(conversationId, otherUsername) {
    state.activeChatConversationId = conversationId;
    document.getElementById('chat-thread-empty').style.display = 'none';
    document.getElementById('chat-thread-active').style.display = 'flex';
    
    const activeConv = (state.chatConversations || []).find(c => c.id === conversationId);
    state.activeChatIsGroup = activeConv ? activeConv.is_group === 1 : false;
    state.activeChatCreatorId = activeConv ? activeConv.creator_id : null;
    
    const manageGroupBtn = document.getElementById('btn-manage-group');
    if (state.activeChatIsGroup) {
        manageGroupBtn.style.display = 'flex';
    } else {
        manageGroupBtn.style.display = 'none';
    }
    
    const displayName = activeConv && activeConv.is_group === 1 ? activeConv.name : otherUsername;
    document.getElementById('chat-thread-header').textContent = displayName;
    
    // Reset message search values on chat thread change
    document.getElementById('chat-message-search-input').value = '';
    document.getElementById('chat-message-search-container').style.display = 'none';
    document.getElementById('btn-chat-message-search-clear').style.display = 'none';

    renderConversationsList(state.chatConversations || []);

    await fetchAndRenderChatMessages();
    await authFetch(`${API_BASE}/chat/conversations/${conversationId}/read`, { method: 'PUT' });
    checkChatUnreadBadge();

    stopChatThreadPolling();
    state.chatThreadPollInterval = setInterval(async () => {
        await fetchAndRenderChatMessages();
        await authFetch(`${API_BASE}/chat/conversations/${conversationId}/read`, { method: 'PUT' });
        checkChatUnreadBadge();
    }, 5000);
}

async function fetchAndRenderChatMessages() {
    if (!state.activeChatConversationId) return;
    try {
        const res = await authFetch(`${API_BASE}/chat/conversations/${state.activeChatConversationId}/messages`);
        const messages = await res.json();
        renderChatMessages(messages);
    } catch (err) {
        // Silent on polling failure
    }
}

const stickerEmojis = {
    love: '❤️',
    haha: '😂',
    cry: '😭',
    thumbsup: '👍',
    party: '🎉',
    clap: '👏',
    angry: '😡',
    wow: '😮',
    ok: '👌',
    wink: '😉',
    pray: '🙏',
    sweat: '😅'
};

function renderChatMessages(messages) {
    const container = document.getElementById('chat-thread-messages');
    const wasAtBottom = container.scrollTop + container.clientHeight >= container.scrollHeight - 40;

    container.innerHTML = '';
    
    // Get active thread search term
    const searchTerm = (document.getElementById('chat-message-search-input').value || '').toLowerCase().trim();

    messages.forEach(msg => {
        const isMine = state.currentUser && msg.sender_id === state.currentUser.id;
        const isSticker = msg.body.startsWith('[sticker:') && msg.body.endsWith(']');
        const isImage = msg.body.startsWith('[image:') && msg.body.endsWith(']');
        const isAudio = msg.body.startsWith('[audio:') && msg.body.endsWith(']');
        
        let isMatch = true;
        if (searchTerm) {
            if (isSticker || isImage || isAudio) {
                isMatch = false;
            } else {
                isMatch = msg.body.toLowerCase().includes(searchTerm);
            }
        }
        
        if (!isMatch) return; // Hide message if it doesn't match the search filter

        const bubble = document.createElement('div');
        bubble.style.cssText = `max-width:70%; align-self:${isMine ? 'flex-end' : 'flex-start'}; display:flex; flex-direction:column; gap:2px;`;

        let bubbleContentHtml = '';
        if (isSticker) {
            const stickerName = msg.body.slice(9, -1);
            const emojiChar = stickerEmojis[stickerName] || '❓';
            bubbleContentHtml = `<div class="chat-sticker-bubble" style="font-size:4rem; user-select:none; animation: pop 0.3s ease;">${emojiChar}</div>`;
        } else if (isImage) {
            const imgPath = msg.body.slice(7, -1);
            bubbleContentHtml = `
                <div style="background:transparent; border-radius:12px; overflow:hidden; border:1px solid var(--border-color); cursor:pointer;" onclick="window.open('/${imgPath}', '_blank')">
                    <img class="chat-image-preview" src="/${imgPath}" style="max-width:100%; max-height:220px; display:block; object-fit:cover;">
                </div>
            `;
        } else if (isAudio) {
            const audioPath = msg.body.slice(7, -1);
            bubbleContentHtml = `
                <div style="background:${isMine ? 'var(--primary-color)' : 'var(--bg-hover)'}; padding:6px 12px; border-radius:16px; ${isMine ? 'border-bottom-right-radius:2px;' : 'border-bottom-left-radius:2px;'} box-shadow: 0 1px 2px rgba(0,0,0,0.05); display:flex; align-items:center;">
                    <audio controls src="/${audioPath}" style="max-width:240px; outline:none; filter: ${isMine ? 'invert(1)' : 'none'};"></audio>
                </div>
            `;
        } else {
            let displayText = escapeHtml(msg.body);
            if (searchTerm) {
                // Highlight matches using case-insensitive replace
                const regex = new RegExp(`(${escapeRegExp(searchTerm)})`, 'gi');
                displayText = displayText.replace(regex, '<mark class="chat-highlight">$1</mark>');
            }
            bubbleContentHtml = `<div style="background:${isMine ? 'var(--primary-color)' : 'var(--bg-hover)'}; color:${isMine ? 'white' : 'var(--text-main)'}; padding:10px 14px; border-radius:16px; ${isMine ? 'border-bottom-right-radius:2px;' : 'border-bottom-left-radius:2px;'} white-space:pre-wrap; word-break:break-word; font-size:0.9rem; box-shadow: 0 1px 2px rgba(0,0,0,0.05);">${displayText}</div>`;
        }

        // Align with timezone
        const localTime = parseDbDate(msg.created_at);
        const timeString = localTime ? localTime.toLocaleTimeString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH', { hour: '2-digit', minute: '2-digit' }) : '';

        const senderNameHtml = (!isMine && state.activeChatIsGroup) ? `<div style="font-size:0.75rem; font-weight:bold; color:var(--text-muted); margin-bottom:2px; margin-left:4px; user-select:none;">${escapeHtml(msg.sender_name)}</div>` : '';

        bubble.innerHTML = `
            ${senderNameHtml}
            ${bubbleContentHtml}
            <div style="font-size:0.68rem; color:var(--text-muted); ${isMine ? 'text-align:right;' : ''}">${timeString}</div>
        `;
        container.appendChild(bubble);
    });

    if (wasAtBottom || messages.length <= 1) {
        container.scrollTop = container.scrollHeight;
    }
}

async function handleChatSendSubmit(e) {
    e.preventDefault();
    const input = document.getElementById('chat-message-input');
    const body = input.value.trim();
    if (!body || !state.activeChatConversationId) return;

    input.value = '';
    try {
        await authFetch(`${API_BASE}/chat/conversations/${state.activeChatConversationId}/messages`, {
            method: 'POST',
            body: JSON.stringify({ body })
        });
        await fetchAndRenderChatMessages();
        await fetchAndRenderConversations();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to send message' : 'ไม่สามารถส่งข้อความได้', 'error');
        input.value = body;
    }
}

// Send Sticker helper
async function sendChatSticker(name) {
    if (!state.activeChatConversationId) return;
    const body = `[sticker:${name}]`;
    try {
        await authFetch(`${API_BASE}/chat/conversations/${state.activeChatConversationId}/messages`, {
            method: 'POST',
            body: JSON.stringify({ body })
        });
        await fetchAndRenderChatMessages();
        await fetchAndRenderConversations();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to send sticker' : 'ไม่สามารถส่งสติกเกอร์ได้', 'error');
    }
}

// Chat Image Upload handler
async function handleChatImageUpload(file) {
    if (!file || !state.activeChatConversationId) return;
    
    const input = document.getElementById('chat-message-input');
    const imageBtn = document.getElementById('btn-chat-image');
    imageBtn.disabled = true;
    input.disabled = true;
    
    const formData = new FormData();
    formData.append('image', file);

    try {
        const res = await authFetch(`${API_BASE}/chat/upload`, {
            method: 'POST',
            body: formData
        });
        
        if (!res.ok) {
            const errData = await res.json();
            throw new Error(errData.error || 'Upload failed');
        }
        
        const data = await res.json();
        const body = `[image:${data.filePath}]`;
        
        await authFetch(`${API_BASE}/chat/conversations/${state.activeChatConversationId}/messages`, {
            method: 'POST',
            body: JSON.stringify({ body })
        });
        
        await fetchAndRenderChatMessages();
        await fetchAndRenderConversations();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to upload image' : 'อัปโหลดรูปภาพล้มเหลว: ' + err.message, 'error');
    } finally {
        imageBtn.disabled = false;
        input.disabled = false;
        document.getElementById('chat-image-input').value = '';
    }
}

// Emoji and Sticker Popover Initialization
function initEmojiPicker() {
    const emojis = [
        '😀','😃','😄','😁','😆','😅','😂','🤣','😊','😇','🙂','🙃','😉','😌','😍','🥰','😘','😗','😙','😚','😋','😛','😝','😜','🤪','🤨','🧐','🤓','😎','🥸','🤩','🥳','😏','😒','😞','😔','😟','😕','🙁','☹️','😣','😖','😫','😩','🥺','😢','😭','😤','😠','😡','🤬','🤯','😳','🥵','🥶','😱','😨','😰','😥','😓','🤗','🤔','🫣','🤭','🫢','🫡','🤫','🫠','✍️','👍','👎','👊','✊','🤛','🤜','👏','🙌','👐','🤲','🤝','🙏','⚡','🔥','⭐','🎉','❤️','💔'
    ];
    const stickers = [
        { name: 'love', char: '❤️' },
        { name: 'haha', char: '😂' },
        { name: 'cry', char: '😭' },
        { name: 'thumbsup', char: '👍' },
        { name: 'party', char: '🎉' },
        { name: 'clap', char: '👏' },
        { name: 'angry', char: '😡' },
        { name: 'wow', char: '😮' },
        { name: 'ok', char: '👌' },
        { name: 'wink', char: '😉' },
        { name: 'pray', char: '🙏' },
        { name: 'sweat', char: '😅' }
    ];

    const emojiPane = document.getElementById('emoji-pane-emojis');
    const stickerPane = document.getElementById('emoji-pane-stickers');
    
    emojiPane.innerHTML = '';
    emojis.forEach(e => {
        const span = document.createElement('span');
        span.className = 'emoji-item';
        span.textContent = e;
        span.addEventListener('click', () => {
            const input = document.getElementById('chat-message-input');
            input.value += e;
            input.focus();
        });
        emojiPane.appendChild(span);
    });

    stickerPane.innerHTML = '';
    stickers.forEach(s => {
        const span = document.createElement('span');
        span.className = 'sticker-item';
        span.textContent = s.char;
        span.title = s.name;
        span.addEventListener('click', async () => {
            document.getElementById('chat-emoji-popover').style.display = 'none';
            await sendChatSticker(s.name);
        });
        stickerPane.appendChild(span);
    });

    // Tab switching
    const tabBtns = document.querySelectorAll('.emoji-tab-btn');
    tabBtns.forEach(btn => {
        btn.addEventListener('click', () => {
            tabBtns.forEach(b => {
                b.classList.remove('active');
                b.style.borderBottom = 'none';
            });
            btn.classList.add('active');
            btn.style.borderBottom = '2px solid var(--primary-color)';
            
            const tab = btn.getAttribute('data-tab');
            if (tab === 'emojis') {
                emojiPane.style.display = 'grid';
                stickerPane.style.display = 'none';
            } else {
                emojiPane.style.display = 'none';
                stickerPane.style.display = 'grid';
            }
        });
    });
}
async function openNewConversationModal() {
    document.getElementById('new-conversation-search').value = '';
    
    // Reset group chat creation states
    state.groupChatMode = false;
    state.groupChatSelectedUsers = [];
    
    document.getElementById('group-chat-name').value = '';
    document.getElementById('group-chat-name').style.display = 'none';
    document.getElementById('btn-submit-group-chat').style.display = 'none';
    
    const toggleBtn = document.getElementById('btn-toggle-group-mode');
    toggleBtn.textContent = state.currentLanguage === 'en' ? 'Create Group' : 'สร้างกลุ่มแชท';
    toggleBtn.className = 'btn btn-outline btn-sm';

    try {
        const res = await authFetch(`${API_BASE}/users/directory`);
        state.chatUserDirectory = await res.json();
        renderNewConversationUserList(state.chatUserDirectory);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load user list' : 'ไม่สามารถโหลดรายชื่อผู้ใช้ได้', 'error');
    }
    document.getElementById('modal-new-conversation').classList.add('active');
}

function closeNewConversationModal() {
    document.getElementById('modal-new-conversation').classList.remove('active');
}

function renderNewConversationUserList(users) {
    const container = document.getElementById('new-conversation-user-list');
    container.innerHTML = '';

    if (users.length === 0) {
        container.innerHTML = `<div style="padding:12px; text-align:center; color:var(--text-muted); font-size:0.85rem;">${state.currentLanguage === 'en' ? 'No users found' : 'ไม่พบผู้ใช้'}</div>`;
        return;
    }

    users.forEach(u => {
        const item = document.createElement('div');
        item.style.cssText = 'padding:10px 12px; cursor:pointer; border-radius:var(--radius-sm); display:flex; justify-content:space-between; align-items:center;';
        item.onmouseenter = () => item.style.background = 'var(--bg-hover)';
        item.onmouseleave = () => item.style.background = 'transparent';
        
        const isOnline = u.is_online === 1;
        const statusDot = `<span style="width:8px; height:8px; border-radius:50%; background-color:${isOnline ? '#10b981' : '#d1d5db'}; display:inline-block; margin-right:6px;" title="${isOnline ? 'Online' : 'Offline'}"></span>`;

        if (state.groupChatMode) {
            const isChecked = state.groupChatSelectedUsers.includes(u.id);
            item.innerHTML = `
                <div style="display:flex; align-items:center; gap:8px;">
                    <input type="checkbox" class="group-user-chk" data-user-id="${u.id}" ${isChecked ? 'checked' : ''} style="cursor:pointer;">
                    ${statusDot}
                    <b style="font-size:0.9rem;">${escapeHtml(u.username)}</b>
                </div>
                <span style="font-size:0.75rem; color:var(--text-muted);">${escapeHtml(translateRole(u.role))}</span>
            `;
            item.addEventListener('click', (e) => {
                const chk = item.querySelector('.group-user-chk');
                if (e.target !== chk) {
                    chk.checked = !chk.checked;
                }
                toggleGroupUserSelection(u.id, chk.checked);
            });
        } else {
            item.innerHTML = `
                <div style="display:flex; align-items:center;">
                    ${statusDot}
                    <b style="font-size:0.9rem;">${escapeHtml(u.username)}</b>
                </div>
                <span style="font-size:0.75rem; color:var(--text-muted);">${escapeHtml(translateRole(u.role))}</span>
            `;
            item.addEventListener('click', () => handleStartConversation(u.id, u.username));
        }
        container.appendChild(item);
    });
}

function toggleGroupUserSelection(userId, isSelected) {
    if (isSelected) {
        if (!state.groupChatSelectedUsers.includes(userId)) {
            state.groupChatSelectedUsers.push(userId);
        }
    } else {
        state.groupChatSelectedUsers = state.groupChatSelectedUsers.filter(id => id !== userId);
    }
}

function filterNewConversationUserList() {
    const query = document.getElementById('new-conversation-search').value.toLowerCase().trim();
    if (!query) {
        renderNewConversationUserList(state.chatUserDirectory);
        return;
    }
    const filtered = state.chatUserDirectory.filter(u => u.username.toLowerCase().includes(query));
    renderNewConversationUserList(filtered);
}

async function handleStartConversation(targetUserId, targetUsername) {
    try {
        const res = await authFetch(`${API_BASE}/chat/conversations`, {
            method: 'POST',
            body: JSON.stringify({ userId: targetUserId })
        });
        const data = await res.json();
        closeNewConversationModal();
        await fetchAndRenderConversations();
        await openConversationThread(data.id, targetUsername);
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to start conversation' : 'ไม่สามารถเริ่มการสนทนาได้', 'error');
    }
}

function toggleGroupChatMode() {
    state.groupChatMode = !state.groupChatMode;
    state.groupChatSelectedUsers = [];
    
    const groupNameInput = document.getElementById('group-chat-name');
    const submitBtn = document.getElementById('btn-submit-group-chat');
    const toggleBtn = document.getElementById('btn-toggle-group-mode');
    
    groupNameInput.value = '';
    
    if (state.groupChatMode) {
        groupNameInput.style.display = 'block';
        submitBtn.style.display = 'flex';
        toggleBtn.textContent = state.currentLanguage === 'en' ? 'Cancel' : 'ยกเลิกสร้างกลุ่ม';
        toggleBtn.className = 'btn btn-danger-outline btn-sm';
    } else {
        groupNameInput.style.display = 'none';
        submitBtn.style.display = 'none';
        toggleBtn.textContent = state.currentLanguage === 'en' ? 'Create Group' : 'สร้างกลุ่มแชท';
        toggleBtn.className = 'btn btn-outline btn-sm';
    }
    renderNewConversationUserList(state.chatUserDirectory);
}

async function handleSubmitGroupChat() {
    const groupNameInput = document.getElementById('group-chat-name');
    const groupName = groupNameInput.value.trim();
    if (!groupName) {
        showToast(state.currentLanguage === 'en' ? 'Please enter a group name' : 'กรุณาป้อนชื่อกลุ่มแชท', 'error');
        groupNameInput.focus();
        return;
    }
    if (state.groupChatSelectedUsers.length === 0) {
        showToast(state.currentLanguage === 'en' ? 'Please select at least one participant' : 'กรุณาเลือกสมาชิกในกลุ่มอย่างน้อย 1 คน', 'error');
        return;
    }

    try {
        const res = await authFetch(`${API_BASE}/chat/conversations/group`, {
            method: 'POST',
            body: JSON.stringify({
                name: groupName,
                userIds: state.groupChatSelectedUsers
            })
        });
        if (!res.ok) {
            const errData = await res.json();
            throw new Error(errData.error || 'Failed to create group');
        }
        const data = await res.json();
        closeNewConversationModal();
        await fetchAndRenderConversations();
        await openConversationThread(data.id, data.name);
        showToast(state.currentLanguage === 'en' ? 'Group created' : 'สร้างกลุ่มแชทสำเร็จ');
    } catch (err) {
        showToast(err.message, 'error');
    }
}

async function openGroupMembersModal() {
    const conversationId = state.activeChatConversationId;
    if (!conversationId) return;

    try {
        const res = await authFetch(`${API_BASE}/chat/conversations/${conversationId}/participants`);
        state.groupParticipants = await res.json();
        
        renderGroupParticipants();
        
        // Show/hide creator controls
        const isCreator = state.currentUser && state.activeChatCreatorId === state.currentUser.id;
        const creatorControls = document.getElementById('group-creator-controls');
        if (isCreator) {
            creatorControls.style.display = 'block';
            await populateInviteUserDropdown();
        } else {
            creatorControls.style.display = 'none';
        }
        
        document.getElementById('modal-group-members').classList.add('active');
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to load group members' : 'ไม่สามารถโหลดรายชื่อสมาชิกกลุ่มได้', 'error');
    }
}

function closeGroupMembersModal() {
    document.getElementById('modal-group-members').classList.remove('active');
}

function renderGroupParticipants() {
    const container = document.getElementById('group-members-list');
    container.innerHTML = '';

    const isCreator = state.currentUser && state.activeChatCreatorId === state.currentUser.id;

    state.groupParticipants.forEach(member => {
        const item = document.createElement('div');
        item.style.cssText = 'padding:8px 12px; display:flex; justify-content:space-between; align-items:center; border-radius:var(--radius-sm); border-bottom:1px solid var(--border-color);';
        
        const isOnline = member.is_online === 1;
        const statusDot = `<span style="width:8px; height:8px; border-radius:50%; background-color:${isOnline ? '#10b981' : '#d1d5db'}; display:inline-block; margin-right:6px;" title="${isOnline ? 'Online' : 'Offline'}"></span>`;
        
        const isCurrentMemberCreator = state.activeChatCreatorId === member.id;
        const badge = isCurrentMemberCreator ? ' <span style="background:var(--primary-color); color:white; font-size:0.65rem; padding:1px 4px; border-radius:3px; font-weight:600; margin-left:4px;">Creator</span>' : '';

        item.innerHTML = `
            <div style="display:flex; align-items:center;">
                ${statusDot}
                <b style="font-size:0.85rem; color:var(--text-main);">${escapeHtml(member.username)}</b>
                ${badge}
            </div>
        `;

        // Render Kick button if current user is creator, and member is not himself
        if (isCreator && member.id !== state.currentUser.id) {
            const kickBtn = document.createElement('button');
            kickBtn.type = 'button';
            kickBtn.className = 'btn btn-danger-outline btn-xs';
            kickBtn.style.cssText = 'padding: 2px 6px; font-size: 0.7rem; border-radius: 4px; height: auto; font-weight:600; margin-left:8px;';
            kickBtn.textContent = state.currentLanguage === 'en' ? 'Kick' : 'กีดกัน';
            kickBtn.addEventListener('click', () => handleKickMember(member.id, member.username));
            item.appendChild(kickBtn);
        }

        container.appendChild(item);
    });
}

async function populateInviteUserDropdown() {
    const select = document.getElementById('select-invite-user');
    select.innerHTML = '';

    try {
        const res = await authFetch(`${API_BASE}/users/directory`);
        const allUsers = await res.json();
        
        // Filter out users who are already in the group
        const existingUserIds = state.groupParticipants.map(p => p.id);
        const inviteable = allUsers.filter(u => !existingUserIds.includes(u.id));

        if (inviteable.length === 0) {
            select.innerHTML = `<option value="">${state.currentLanguage === 'en' ? 'No users available to invite' : 'ไม่มีรายชื่อที่จะเชิญ'}</option>`;
            document.getElementById('btn-submit-invite').disabled = true;
            return;
        }

        document.getElementById('btn-submit-invite').disabled = false;
        inviteable.forEach(u => {
            const opt = document.createElement('option');
            opt.value = u.id;
            opt.textContent = `${u.username} (${translateRole(u.role)})`;
            select.appendChild(opt);
        });
    } catch (err) {
        console.error("Failed to load invite directory:", err);
    }
}

async function handleInviteMember() {
    const select = document.getElementById('select-invite-user');
    const targetUserId = select.value;
    if (!targetUserId) return;

    const conversationId = state.activeChatConversationId;
    try {
        const res = await authFetch(`${API_BASE}/chat/conversations/${conversationId}/participants`, {
            method: 'POST',
            body: JSON.stringify({ targetUserId })
        });
        
        if (!res.ok) {
            const errData = await res.json();
            throw new Error(errData.error || 'Failed to invite user');
        }

        showToast(state.currentLanguage === 'en' ? 'User invited' : 'เชิญผู้เข้ากลุ่มเรียบร้อย');
        
        // Refresh participants
        const freshRes = await authFetch(`${API_BASE}/chat/conversations/${conversationId}/participants`);
        state.groupParticipants = await freshRes.json();
        renderGroupParticipants();
        await populateInviteUserDropdown();
    } catch (err) {
        showToast(err.message, 'error');
    }
}

async function handleKickMember(targetUserId, username) {
    const ok = confirm(state.currentLanguage === 'en' ? `Are you sure you want to kick ${username} from the group?` : `คุณแน่ใจหรือไม่ที่จะกีดกัน ${username} ออกจากกลุ่ม?`);
    if (!ok) return;

    const conversationId = state.activeChatConversationId;
    try {
        const res = await authFetch(`${API_BASE}/chat/conversations/${conversationId}/participants/${targetUserId}`, {
            method: 'DELETE'
        });
        
        if (!res.ok) {
            const errData = await res.json();
            throw new Error(errData.error || 'Failed to kick user');
        }

        showToast(state.currentLanguage === 'en' ? 'User kicked' : 'กีดกันผู้ใช้ออกจากกลุ่มแล้ว');
        
        // Refresh participants
        const freshRes = await authFetch(`${API_BASE}/chat/conversations/${conversationId}/participants`);
        state.groupParticipants = await freshRes.json();
        renderGroupParticipants();
        
        // Refresh dropdown
        const isCreator = state.currentUser && state.activeChatCreatorId === state.currentUser.id;
        if (isCreator) {
            await populateInviteUserDropdown();
        }
    } catch (err) {
        showToast(err.message, 'error');
    }
}

async function startVoiceRecording() {
    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        showToast(state.currentLanguage === 'en' ? 'Microphone is not supported in this browser' : 'เบราว์เซอร์นี้ไม่รองรับการบันทึกเสียง', 'error');
        return;
    }

    try {
        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        
        state.audioChunks = [];
        state.mediaRecorder = new MediaRecorder(stream);
        
        state.mediaRecorder.ondataavailable = (e) => {
            if (e.data && e.data.size > 0) {
                state.audioChunks.push(e.data);
            }
        };

        state.mediaRecorder.onstop = async () => {
            // Stop all tracks on the stream
            stream.getTracks().forEach(track => track.stop());

            if (state.voiceRecordingShouldSend) {
                const audioBlob = new Blob(state.audioChunks, { type: 'audio/webm' });
                await uploadAndSendAudioBlob(audioBlob);
            }
        };

        // Request data periodically (not just on stop) so the final moment of
        // audio isn't lost to MediaRecorder's end-of-recording flush timing.
        state.mediaRecorder.start(250);
        state.recordingStartTime = Date.now();
        state.voiceRecordingShouldSend = false;

        // Toggle UI
        document.getElementById('chat-message-input').style.display = 'none';
        document.getElementById('btn-chat-submit').style.display = 'none';
        document.getElementById('chat-recording-panel').style.display = 'flex';
        document.getElementById('btn-chat-mic').classList.add('recording-active');

        // Start timer
        clearInterval(state.recordingTimerInterval);
        document.getElementById('chat-recording-timer').textContent = '00:00';
        state.recordingTimerInterval = setInterval(() => {
            const seconds = Math.floor((Date.now() - state.recordingStartTime) / 1000);
            const mins = String(Math.floor(seconds / 60)).padStart(2, '0');
            const secs = String(seconds % 60).padStart(2, '0');
            document.getElementById('chat-recording-timer').textContent = `${mins}:${secs}`;
        }, 1000);

    } catch (err) {
        console.error(err);
        showToast(state.currentLanguage === 'en' ? 'Failed to access microphone' : 'ไม่สามารถเข้าถึงไมโครโฟนได้', 'error');
    }
}

function stopVoiceRecording(shouldSend) {
    if (!state.mediaRecorder || state.mediaRecorder.state === 'inactive') return;

    state.voiceRecordingShouldSend = shouldSend;

    // Request the in-flight buffer first, then wait a beat before stopping so
    // the last spoken moment has time to reach the recorder before it flushes.
    const recorder = state.mediaRecorder;
    recorder.requestData();
    setTimeout(() => {
        if (recorder.state !== 'inactive') recorder.stop();
    }, 300);

    // Reset timer
    clearInterval(state.recordingTimerInterval);
    state.recordingTimerInterval = null;

    // Restore UI
    document.getElementById('chat-message-input').style.display = 'block';
    document.getElementById('btn-chat-submit').style.display = 'flex';
    document.getElementById('chat-recording-panel').style.display = 'none';
    document.getElementById('btn-chat-mic').classList.remove('recording-active');
}

async function uploadAndSendAudioBlob(blob) {
    const conversationId = state.activeChatConversationId;
    if (!conversationId) return;

    const formData = new FormData();
    formData.append('audio', blob, 'voice_clip.webm');

    try {
        // Upload audio file
        const uploadRes = await authFetch(`${API_BASE}/chat/upload-audio`, {
            method: 'POST',
            body: formData
        });

        if (!uploadRes.ok) {
            const errData = await uploadRes.json();
            throw new Error(errData.error || 'Failed to upload audio');
        }

        const uploadData = await uploadRes.json();
        const filePath = uploadData.filePath;

        // Send chat message with the audio reference format: [audio:uploads/chat/...]
        const sendRes = await authFetch(`${API_BASE}/chat/conversations/${conversationId}/messages`, {
            method: 'POST',
            body: JSON.stringify({
                body: `[audio:${filePath}]`
            })
        });

        if (!sendRes.ok) {
            throw new Error('Failed to send voice message');
        }

        await fetchAndRenderChatMessages();
    } catch (err) {
        console.error(err);
        showToast(err.message, 'error');
    }
}
function openAddUserModal() {
    document.getElementById('form-add-user').reset();
    document.getElementById('modal-add-user').classList.add('active');
}

function closeAddUserModal() {
    document.getElementById('modal-add-user').classList.remove('active');
}

async function handleNewUserSubmit(e) {
    e.preventDefault();
    const username = document.getElementById('new-username').value;
    const password = document.getElementById('new-password').value;
    const userRole = document.getElementById('new-role').value;

    try {
        const res = await authFetch(`${API_BASE}/users`, {
            method: 'POST',
            body: JSON.stringify({ username, password, userRole })
        });
        const data = await res.json();
        if (!res.ok) {
            throw new Error(data.error || (state.currentLanguage === 'en' ? 'Username already exists or invalid data' : 'มีผู้ใช้นี้อยู่แล้วในระบบ หรือข้อมูลไม่ถูกต้อง'));
        }
        showToast(state.currentLanguage === 'en' ? 'User account created successfully' : 'สร้างบัญชีผู้ใช้งานใหม่เรียบร้อยแล้ว');
        closeAddUserModal();
        await fetchAdminUsers();
    } catch (err) {
        showToast(err.message, 'error');
    }
}

async function handleRoleChange(userId, newRole) {
    try {
        await authFetch(`${API_BASE}/users/${userId}/role`, {
            method: 'PUT',
            body: JSON.stringify({ userRole: newRole })
        });
        showToast(state.currentLanguage === 'en' ? 'Role updated successfully' : 'อัปเดตบทบาทผู้ใช้สำเร็จ');
        await fetchAdminUsers();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to update user role' : 'ไม่สามารถอัปเดตบทบาทผู้ใช้ได้', 'error');
    }
}

async function handleDeleteUser(userId) {
    if (!confirm(state.currentLanguage === 'en' ? 'Are you sure you want to delete this user?' : 'คุณแน่ใจหรือไม่ว่าต้องการลบผู้ใช้งานรายนี้?')) return;

    try {
        await authFetch(`${API_BASE}/users/${userId}`, { method: 'DELETE' });
        showToast(state.currentLanguage === 'en' ? 'User deleted successfully' : 'ลบผู้ใช้งานเรียบร้อยแล้ว');
        await fetchAdminUsers();
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to delete user account' : 'ไม่สามารถลบผู้ใช้งานได้', 'error');
    }
}

async function fetchProjectPermissions(projectId) {
    if (!projectId) return;

    try {
        // Fetch mapped supervisor user IDs
        const resPerms = await authFetch(`${API_BASE}/project-permissions/${projectId}`);
        const allowedUserIds = await resPerms.json();

        // Fetch users: admins can fetch all users, others fetch from directory
        const role = state.currentUser ? state.currentUser.role : 'user';
        const endpoint = (role === 'admin' || role === 'superadmin') ? `${API_BASE}/users` : `${API_BASE}/users/directory`;
        const resUsers = await authFetch(endpoint);
        const allUsers = await resUsers.json();

        const container = document.getElementById('admin-supervisors-list');
        container.innerHTML = '';

        const supervisors = allUsers
            .filter(u => u.role !== 'superadmin' && u.role !== 'excusive' && u.role !== 'admin')
            .sort((a, b) => (a.username || '').localeCompare(b.username || '', undefined, { sensitivity: 'base' }));

        if (supervisors.length === 0) {
            container.innerHTML = `<p style="text-align:center; color:var(--text-muted);">${state.currentLanguage === 'en' ? 'No users to assign permissions to' : 'ไม่มีผู้ใช้งานที่สามารถมอบหมายสิทธิ์ได้'}</p>`;
            return;
        }

        // Get the active project details to see who the creator is
        const project = state.projects.find(p => p.id === parseInt(projectId));
        const creatorId = project ? project.created_by : null;

        supervisors.forEach(sup => {
            const isCreator = sup.id === creatorId;
            const isChecked = isCreator || allowedUserIds.includes(sup.id);
            const disabledAttr = isCreator ? 'disabled checked' : '';

            const label = document.createElement('label');
            label.innerHTML = `
                <input type="checkbox" class="supervisor-permission-checkbox" data-user-id="${sup.id}" ${disabledAttr}>
                <span>${escapeHtml(sup.username)} (${translateRole(sup.role)}) ${isCreator ? (state.currentLanguage === 'en' ? '(Creator)' : '(ผู้สร้างโครงการ)') : ''}</span>
            `;

            if (!isCreator) {
                // Bind check toggle listener
                label.querySelector('input').addEventListener('change', async (e) => {
                    await toggleSupervisorProjectPermission(projectId, sup.id, e.target.checked);
                });
            }

            container.appendChild(label);

            // Set checked state
            if (isChecked) {
                label.querySelector('input').checked = true;
            }
        });
    } catch (err) {
        console.error(err);
        showToast(state.currentLanguage === 'en' ? 'Failed to load project permissions' : 'ไม่สามารถโหลดสิทธิ์การเข้าถึงโครงการได้', 'error');
    }
}

async function toggleSupervisorProjectPermission(projectId, supervisorId, grantAccess) {
    try {
        // Fetch current mapped supervisor IDs
        const resPerms = await authFetch(`${API_BASE}/project-permissions/${projectId}`);
        let allowedUserIds = await resPerms.json();

        if (grantAccess) {
            if (!allowedUserIds.includes(supervisorId)) {
                allowedUserIds.push(supervisorId);
            }
        } else {
            allowedUserIds = allowedUserIds.filter(id => id !== supervisorId);
        }

        // Send request to overwrite mappings
        await authFetch(`${API_BASE}/project-permissions/${projectId}`, {
            method: 'POST',
            body: JSON.stringify({ supervisorIds: allowedUserIds })
        });

        showToast(state.currentLanguage === 'en' ? 'Permissions updated' : 'อัปเดตสิทธิ์ผู้ควบคุมเรียบร้อยแล้ว');
    } catch (err) {
        showToast(state.currentLanguage === 'en' ? 'Failed to update permission mapping' : 'ไม่สามารถอัปเดตการแชร์สิทธิ์ได้', 'error');
    }
}

// ==========================================
// Revisions & Comparison Module
// ==========================================
function openRevisionsModal() {
    if (!state.activeProjectId) return;
    document.getElementById('modal-revisions').classList.add('active');
    loadRevisionsList();
}

function closeRevisionsModal() {
    document.getElementById('modal-revisions').classList.remove('active');
}

async function loadRevisionsList() {
    const listContainer = document.getElementById('revisions-list');
    listContainer.innerHTML = `<div class="text-center text-muted" style="padding: 20px;">${state.currentLanguage === 'en' ? 'Loading...' : 'กำลังโหลด...'}</div>`;

    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/revisions`);
        const revisions = await res.json();

        if (revisions.length === 0) {
            listContainer.innerHTML = `<div class="text-center text-muted" style="padding: 20px;">${state.currentLanguage === 'en' ? 'No revisions found' : 'ไม่พบประวัติการแก้ไข'}</div>`;
            return;
        }

        listContainer.innerHTML = '';

        // Populate dropdown selectors
        const selectA = document.getElementById('compare-rev-a');
        const selectB = document.getElementById('compare-rev-b');
        selectA.innerHTML = '';
        selectB.innerHTML = '';

        revisions.forEach((rev, index) => {
            // Render list item
            const item = document.createElement('div');
            item.className = 'revision-card';
            item.innerHTML = `
                <div class="revision-card-header">
                    <span class="revision-card-num">Rev ${rev.revision_number}</span>
                    <span class="revision-card-time">${parseDbDate(rev.created_at).toLocaleString()}</span>
                </div>
                <div class="revision-card-author"><i class="fa-solid fa-user-pen"></i> By: ${escapeHtml(rev.username)}</div>
                <div class="revision-card-summary">${escapeHtml(rev.change_summary || '')}</div>
            `;

            item.addEventListener('click', () => {
                document.querySelectorAll('.revision-card').forEach(i => {
                    i.classList.remove('active');
                });
                item.classList.add('active');

                // Auto-select in compare dropdowns
                selectB.value = rev.revision_number;
                if (index + 1 < revisions.length) {
                    selectA.value = revisions[index + 1].revision_number;
                } else {
                    selectA.value = rev.revision_number;
                }
                compareRevisions();
            });

            listContainer.appendChild(item);

            // Add options to dropdowns
            const optA = document.createElement('option');
            optA.value = rev.revision_number;
            optA.textContent = `Rev ${rev.revision_number} (${rev.username})`;
            selectA.appendChild(optA);

            const optB = document.createElement('option');
            optB.value = rev.revision_number;
            optB.textContent = `Rev ${rev.revision_number} (${rev.username})`;
            selectB.appendChild(optB.cloneNode(true));
        });

        // Default select: B = latest, A = second latest
        if (revisions.length > 0) {
            // Add active class to first card
            const firstCard = listContainer.querySelector('.revision-card');
            if (firstCard) firstCard.classList.add('active');

            selectB.value = revisions[0].revision_number;
            if (revisions.length > 1) {
                selectA.value = revisions[1].revision_number;
            } else {
                selectA.value = revisions[0].revision_number;
            }
            // Trigger automatic first comparison
            compareRevisions();
        }

    } catch (err) {
        console.error(err);
        listContainer.innerHTML = `<div class="text-center text-danger" style="padding: 20px;">Failed to load revisions</div>`;
    }
}

// Helper to format detailed changes with rich HTML badges
function formatDiffDetails(details, type) {
    if (!details) return '';

    const parts = details.split(', ');
    return parts.map(part => {
        if (part.includes(' -> ')) {
            const arrowIndex = part.indexOf(' -> ');
            const leftSide = part.substring(0, arrowIndex);
            const rightSide = part.substring(arrowIndex + 4);

            const colonIndex = leftSide.indexOf(': ');
            let label = '';
            let oldValue = leftSide;
            if (colonIndex !== -1) {
                label = leftSide.substring(0, colonIndex + 2);
                oldValue = leftSide.substring(colonIndex + 2);
            }

            let badgeOld = `<span class="diff-old">${escapeHtml(oldValue)}</span>`;
            let badgeNew = `<span class="diff-new">${escapeHtml(rightSide)}</span>`;

            return `<div style="margin-bottom: 6px;"><b>${escapeHtml(label)}</b> ${badgeOld} <i class="fa-solid fa-arrow-right-long" style="margin: 0 6px; color: var(--text-muted); font-size: 0.8rem;"></i> ${badgeNew}</div>`;
        } else if (part.startsWith('Added (') && part.endsWith(')')) {
            const content = part.substring(7, part.length - 1);
            const innerParts = content.split(', ');
            const badges = innerParts.map(ip => {
                const cIndex = ip.indexOf(': ');
                if (cIndex !== -1) {
                    const label = ip.substring(0, cIndex + 2);
                    const val = ip.substring(cIndex + 2);
                    return `<div style="margin-bottom: 2px;"><b>${escapeHtml(label)}</b> <span class="diff-tag-added">${escapeHtml(val)}</span></div>`;
                }
                return `<div style="margin-bottom: 2px;">${escapeHtml(ip)}</div>`;
            }).join('');
            return `<div style="display: flex; flex-direction: column; gap: 4px; padding: 4px 0;">${badges}</div>`;
        } else if (part.endsWith(' -> Removed')) {
            const leftVal = part.substring(0, part.length - 11);
            return `<div><b class="diff-removed-label">${escapeHtml(leftVal)}</b> <span class="badge bg-danger-light text-danger" style="margin-left: 6px; font-size: 0.75rem;">Removed</span></div>`;
        }
        return `<div>${escapeHtml(part)}</div>`;
    }).join('');
}

async function compareRevisions() {
    const revA = document.getElementById('compare-rev-a').value;
    const revB = document.getElementById('compare-rev-b').value;
    const tbody = document.getElementById('revisions-compare-tbody');

    if (!revA || !revB) return;

    tbody.innerHTML = `<tr><td colspan="4" class="text-center text-muted" style="padding: 30px 10px;">${state.currentLanguage === 'en' ? 'Comparing...' : 'กำลังเปรียบเทียบ...'}</td></tr>`;

    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/revisions/${revA}/compare/${revB}`);
        const data = await res.json();

        if (!data.changes || data.changes.length === 0) {
            tbody.innerHTML = `<tr><td colspan="4" class="text-center text-success" style="padding: 30px 10px; font-weight:600;"><i class="fa-solid fa-circle-check"></i> ${state.currentLanguage === 'en' ? 'No differences found between these two versions' : 'ไม่มีรายการเปลี่ยนแปลงระหว่างสองเวอร์ชันนี้'}</td></tr>`;
            return;
        }

        tbody.innerHTML = '';
        data.changes.forEach(chg => {
            const tr = document.createElement('tr');

            let badgeClass = 'bg-warning-light text-warning';
            let badgeText = state.currentLanguage === 'en' ? 'Modified' : 'แก้ไข';
            if (chg.type === 'added') {
                badgeClass = 'bg-success-light text-success';
                badgeText = state.currentLanguage === 'en' ? 'Added' : 'เพิ่ม';
            } else if (chg.type === 'removed') {
                badgeClass = 'bg-danger-light text-danger';
                badgeText = state.currentLanguage === 'en' ? 'Deleted' : 'ลบ';
            }

            tr.innerHTML = `
                <td><b>${escapeHtml(chg.section_name)}</b></td>
                <td>${escapeHtml(chg.description)}</td>
                <td class="text-center">
                    <span class="badge ${badgeClass}" style="padding:4px 8px; border-radius:12px; font-size:0.75rem; font-weight:600;">${badgeText}</span>
                </td>
                <td style="font-size:0.85rem; line-height:1.4;">${formatDiffDetails(chg.details, chg.type)}</td>
            `;
            tbody.appendChild(tr);
        });
    } catch (err) {
        console.error(err);
        tbody.innerHTML = `<tr><td colspan="4" class="text-center text-danger" style="padding: 30px 10px;">Failed to compare revisions</td></tr>`;
    }
}

// ==========================================
// Project Progress Helper Functions (NEW)
// ==========================================

function buildProgressSystemDropdown() {
    const select = document.getElementById('progress-system-select');
    if (!select) return;

    const currentValue = select.value;
    select.innerHTML = '';

    const defaultOpt = document.createElement('option');
    defaultOpt.value = 'ทั่วไป';
    defaultOpt.textContent = state.currentLanguage === 'en' ? 'General (ทั่วไป)' : 'ทั่วไป (General)';
    select.appendChild(defaultOpt);

    const systemsSet = new Set();

    // Add catalog systems
    if (state.systems && Array.isArray(state.systems)) {
        state.systems.forEach(s => {
            if (s) systemsSet.add(s.trim());
        });
    }

    // Add existing project progress systems
    if (state.projectProgressList && Array.isArray(state.projectProgressList)) {
        state.projectProgressList.forEach(item => {
            if (item.system_name) {
                systemsSet.add(item.system_name.trim());
            }
        });
    }

    systemsSet.forEach(sys => {
        if (sys && sys !== 'ทั่วไป') {
            const opt = document.createElement('option');
            opt.value = sys;
            opt.textContent = sys;
            select.appendChild(opt);
        }
    });

    const customOpt = document.createElement('option');
    customOpt.value = 'CUSTOM';
    customOpt.textContent = state.currentLanguage === 'en' ? '+ Define custom system...' : '+ กำหนดระบบใหม่...';
    select.appendChild(customOpt);

    if (Array.from(select.options).some(opt => opt.value === currentValue)) {
        select.value = currentValue;
    } else {
        select.value = 'ทั่วไป';
    }
}

function initSpeechRecognition() {
    const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
    if (!SpeechRecognition) {
        document.querySelectorAll('.btn-voice-input').forEach(btn => btn.style.display = 'none');
        return;
    }

    document.querySelectorAll('.btn-voice-input').forEach(btn => {
        const targetId = btn.dataset.target;
        const textarea = document.getElementById(targetId);
        if (!textarea) return;

        let recognition = null;
        let isRecording = false;

        btn.addEventListener('click', (e) => {
            e.preventDefault();
            e.stopPropagation();

            if (isRecording) {
                recognition.stop();
                return;
            }

            recognition = new SpeechRecognition();
            recognition.lang = state.currentLanguage === 'en' ? 'en-US' : 'th-TH';
            recognition.continuous = true;
            recognition.interimResults = false;

            recognition.onstart = () => {
                isRecording = true;
                btn.innerHTML = '<i class="fa-solid fa-microphone fa-beat-fade text-danger"></i>';
                showToast(state.currentLanguage === 'en' ? 'Listening...' : 'กำลังฟังเสียง...', 'info');
            };

            recognition.onresult = (event) => {
                const transcript = event.results[event.results.length - 1][0].transcript;
                const currentText = textarea.value;
                textarea.value = currentText ? currentText + ' ' + transcript : transcript;
                textarea.dispatchEvent(new Event('input'));
            };

            recognition.onerror = (err) => {
                console.error('Speech recognition error', err);
                isRecording = false;
                btn.innerHTML = '<i class="fa-solid fa-microphone"></i>';
                showToast(state.currentLanguage === 'en' ? 'Speech input error' : 'การป้อนข้อมูลด้วยเสียงขัดข้อง', 'danger');
            };

            recognition.onend = () => {
                isRecording = false;
                btn.innerHTML = '<i class="fa-solid fa-microphone"></i>';
            };

            recognition.start();
        });
    });
}

function addTimestampWatermark(file, timestampStr) {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = (event) => {
            const img = new Image();
            img.src = event.target.result;
            img.onload = () => {
                try {
                    const maxDim = 1280;
                    let w = img.naturalWidth || img.width;
                    let h = img.naturalHeight || img.height;

                    if (w > maxDim || h > maxDim) {
                        if (w > h) {
                            h = Math.round((h * maxDim) / w);
                            w = maxDim;
                        } else {
                            w = Math.round((w * maxDim) / h);
                            h = maxDim;
                        }
                    }

                    const canvas = document.createElement('canvas');
                    canvas.width = w;
                    canvas.height = h;
                    const ctx = canvas.getContext('2d');

                    ctx.drawImage(img, 0, 0, w, h);

                    const fontSize = Math.max(16, Math.round(canvas.width * 0.025));
                    ctx.font = `bold ${fontSize}px sans-serif`;

                    const text = timestampStr;
                    const textWidth = ctx.measureText(text).width;
                    const padding = 10;
                    const fillWidth = textWidth + padding * 2;
                    const fillHeight = fontSize + padding * 2;
                    const x = canvas.width - fillWidth - 20;
                    const y = canvas.height - fillHeight - 20;

                    ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
                    ctx.fillRect(x, y, fillWidth, fillHeight);

                    ctx.fillStyle = '#ffffff';
                    ctx.textBaseline = 'middle';
                    ctx.fillText(text, x + padding, y + fillHeight / 2);

                    canvas.toBlob((blob) => {
                        if (!blob) {
                            resolve(file);
                            return;
                        }
                        const newFile = new File([blob], file.name || 'watermarked.jpg', { type: 'image/jpeg' });
                        resolve(newFile);
                    }, 'image/jpeg', 0.85);
                } catch (err) {
                    console.error('Watermarking failed, using original image:', err);
                    resolve(file);
                }
            };
            img.onerror = () => resolve(file);
        };
        reader.onerror = () => resolve(file);
    });
}

async function processAndSetProgressImage(file) {
    if (!file) return;

    setCurrentProgressTimestamp();

    const tsInputVal = document.getElementById('progress-timestamp').value;
    const tsDate = tsInputVal ? parseDbDate(tsInputVal) : new Date();
    const tsStr = tsDate.toLocaleString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH');

    showToast(state.currentLanguage === 'en' ? 'Processing image...' : 'กำลังประมวลผลรูปภาพ...', 'info');

    try {
        const watermarkedFile = await addTimestampWatermark(file, tsStr);
        state.progressSelectedFile = watermarkedFile;
        displayProgressImagePreview(watermarkedFile);
    } catch (err) {
        console.error(err);
        state.progressSelectedFile = file;
        displayProgressImagePreview(file);
    }
}

async function triggerPrintProgressReport() {
    if (!state.activeProjectId || !state.activeProjectSummary) return;

    const container = document.getElementById('print-progress-report-container');
    if (!container) return;

    document.body.classList.remove('print-mode-quotation', 'print-mode-bom', 'print-mode-free-issue');
    document.body.classList.add('print-mode-progress');
    container.style.display = 'block';

    const grouped = {};
    const list = state.projectProgressList || [];

    list.forEach(item => {
        const sys = item.system_name || (state.currentLanguage === 'en' ? 'General' : 'ทั่วไป');
        if (!grouped[sys]) {
            grouped[sys] = [];
        }
        grouped[sys].push(item);
    });

    const systems = Object.keys(grouped).sort();

    const projectTitle = state.activeProjectSummary.name;
    const clientName = state.activeProjectSummary.client_name || '-';
    const printDate = new Date().toLocaleDateString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH');

    let html = `
        <div class="print-progress-header">
            <h1 class="print-progress-title">${state.currentLanguage === 'en' ? 'Project Progress Report' : 'รายงานความคืบหน้าโครงการ'}</h1>
            <div class="print-progress-meta">
                <div><b>${state.currentLanguage === 'en' ? 'Project' : 'โครงการ'}:</b> ${escapeHtml(projectTitle)}</div>
                <div><b>${state.currentLanguage === 'en' ? 'Client' : 'ลูกค้า'}:</b> ${escapeHtml(clientName)}</div>
                <div><b>${state.currentLanguage === 'en' ? 'Date' : 'วันที่พิมพ์'}:</b> ${printDate}</div>
            </div>
        </div>
    `;

    if (systems.length === 0) {
        html += `<p style="text-align:center; padding: 40px; color:#64748b;">${state.currentLanguage === 'en' ? 'No progress updates found.' : 'ไม่พบข้อมูลความคืบหน้าของโครงการ'}</p>`;
    } else {
        systems.forEach(sys => {
            html += `
                <div class="print-progress-system-section">
                    <div class="print-progress-system-title">${escapeHtml(sys)}</div>
            `;

            const items = grouped[sys];
            items.forEach(item => {
                const updateDate = parseDbDate(item.timestamp).toLocaleString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH');

                let imgHtml = '';
                if (item.image_name) {
                    const imageUrl = withAuthToken(`${API_BASE}/projects/${state.activeProjectId}/progress/${item.id}/image?_ts=${Date.now()}`);
                    imgHtml = `
                        <div class="print-progress-card-image">
                            <img src="${imageUrl}" class="print-progress-card-img">
                            ${item.image_title ? `<div class="print-progress-card-img-title">${escapeHtml(item.image_title)}</div>` : ''}
                        </div>
                    `;
                }

                const descHtml = `
                    <div class="print-progress-card-section">
                        <div class="print-progress-card-section-label">${state.currentLanguage === 'en' ? 'Description' : 'รายละเอียดความคืบหน้า'}</div>
                        <div class="print-progress-card-section-content">${escapeHtml(item.progress_desc || '')}</div>
                    </div>
                `;

                const issuesHtml = item.issues ? `
                    <div class="print-progress-card-section" style="margin-top:6px;">
                        <div class="print-progress-card-section-label" style="color:#ef4444;">${state.currentLanguage === 'en' ? 'Issues & Obstacles' : 'ปัญหาและอุปสรรค'}</div>
                        <div class="print-progress-card-section-content">${escapeHtml(item.issues)}</div>
                    </div>
                ` : '';

                const solutionsHtml = item.solutions ? `
                    <div class="print-progress-card-section" style="margin-top:6px;">
                        <div class="print-progress-card-section-label" style="color:#10b981;">${state.currentLanguage === 'en' ? 'Action Plan / Solutions' : 'แนวทางแก้ไข'}</div>
                        <div class="print-progress-card-section-content">${escapeHtml(item.solutions)}</div>
                    </div>
                ` : '';

                const suggestionsHtml = item.suggestions ? `
                    <div class="print-progress-card-section" style="margin-top:6px;">
                        <div class="print-progress-card-section-label" style="color:#3b82f6;">${state.currentLanguage === 'en' ? 'Suggestions' : 'ข้อเสนอแนะ'}</div>
                        <div class="print-progress-card-section-content">${escapeHtml(item.suggestions)}</div>
                    </div>
                ` : '';

                html += `
                    <div class="print-progress-card">
                        <div class="print-progress-card-meta">
                            <span><b><i class="fa-solid fa-clock"></i> ${updateDate}</b></span>
                            <span><b>${state.currentLanguage === 'en' ? 'By' : 'โดย'}:</b> ${escapeHtml(item.creator_name || 'System')}</span>
                        </div>
                        <div class="print-progress-card-body">
                            ${imgHtml}
                            <div class="print-progress-card-details">
                                ${descHtml}
                                ${issuesHtml}
                                ${solutionsHtml}
                                ${suggestionsHtml}
                            </div>
                        </div>
                    </div>
                `;
            });

            html += `</div>`;
        });
    }

    container.innerHTML = html;

    window.addEventListener('afterprint', () => {
        setTimeout(() => {
            document.body.classList.remove('print-mode-progress');
            container.style.display = 'none';
            container.innerHTML = '';
        }, 2000); // 2 seconds delay to allow mobile browsers to capture print preview
    }, { once: true });

    setTimeout(() => {
        window.print();
    }, 250);
}

// Auto-logout idle tracker logic
let idleTimer = null;
const IDLE_TIMEOUT_MS = 3 * 60 * 1000; // 3 minutes

function resetIdleTimer() {
    if (idleTimer) {
        clearTimeout(idleTimer);
    }

    if (state.currentUser) {
        idleTimer = setTimeout(async () => {
            // Log logout action on backend
            if (state.currentUser) {
                const userId = state.currentUser.id;
                const key = `modifiedProjects_${userId}`;
                let modifiedProjects = [];
                try {
                    modifiedProjects = JSON.parse(localStorage.getItem(key)) || [];
                } catch (e) {
                    modifiedProjects = [];
                }

                try {
                    await fetch(`${API_BASE}/logout`, {
                        method: 'POST',
                        headers: {
                            ...getHeaders()
                        },
                        body: JSON.stringify({ userId, modifiedProjects })
                    });
                    localStorage.removeItem(key);
                } catch (err) {
                    console.error('Failed to report logout revisions:', err);
                }
            }

            localStorage.removeItem('authToken');
            localStorage.removeItem('currentUser');
            state.currentUser = null;
            state.activeProjectId = null;
            state.activeProject = null;
            state.activeProjectSummary = null;
            checkSession();
            showToast(state.currentLanguage === 'en' ? 'Logged out due to inactivity' : 'ออกจากระบบอัตโนมัติเนื่องจากไม่มีการใช้งาน', 'error');
        }, IDLE_TIMEOUT_MS);
    }
}

function setupIdleTracker() {
    const events = ['mousemove', 'mousedown', 'keypress', 'touchstart', 'scroll', 'click'];
    events.forEach(evt => {
        document.addEventListener(evt, resetIdleTimer, { passive: true });
    });
    resetIdleTimer();
}

// Super Admin System Panel Operations
function openSystemPanel() {
    document.getElementById('modal-system-panel').classList.add('active');
    fetchBackupVersions();
    fetchBackupSchedule();
}

function closeSystemPanel() {
    document.getElementById('modal-system-panel').classList.remove('active');
}

async function fetchBackupVersions() {
    const tbody = document.getElementById('system-backups-tbody');
    tbody.innerHTML = `<tr><td colspan="4" class="text-center">${state.currentLanguage === 'en' ? 'Loading backups...' : 'กำลังโหลดรายการสำรองข้อมูล...'}</td></tr>`;

    try {
        const res = await authFetch(`${API_BASE}/system/backups`);
        if (!res.ok) throw new Error('Failed to fetch backups');
        const backups = await res.json();

        if (backups.length === 0) {
            tbody.innerHTML = `<tr><td colspan="4" class="text-center">${state.currentLanguage === 'en' ? 'No backup files found' : 'ไม่พบไฟล์สำรองข้อมูล'}</td></tr>`;
            return;
        }

        tbody.innerHTML = '';
        backups.forEach(b => {
            const tr = document.createElement('tr');

            const sizeKB = (b.size / 1024).toFixed(2);
            const dateStr = parseDbDate(b.created_at).toLocaleString(state.currentLanguage === 'en' ? 'en-US' : 'th-TH');
            const downloadUrl = `${API_BASE}/system/backups/${b.filename}/download?userId=${state.currentUser.id}&role=${state.currentUser.role}`;

            tr.innerHTML = `
                <td class="font-bold">
                    <a href="${downloadUrl}" download style="color:var(--primary-color); text-decoration:none;">
                        <i class="fa-solid fa-database"></i> ${escapeHtml(b.version || b.filename)}
                    </a>
                </td>
                <td>${sizeKB} KB</td>
                <td>${dateStr}</td>
                <td class="text-center">
                    <button class="btn btn-danger btn-sm btn-restore-backup" data-filename="${b.filename}" style="padding:4px 8px; font-size:0.75rem;">
                        <i class="fa-solid fa-rotate-left"></i> Restore
                    </button>
                </td>
            `;

            tbody.appendChild(tr);
        });

        // Bind Restore listeners
        tbody.querySelectorAll('.btn-restore-backup').forEach(btn => {
            btn.addEventListener('click', async (e) => {
                const filename = e.currentTarget.dataset.filename;
                await restoreBackupVersion(filename);
            });
        });
    } catch (err) {
        tbody.innerHTML = `<tr><td colspan="4" class="text-center text-danger">${err.message}</td></tr>`;
    }
}

async function fetchBackupSchedule() {
    try {
        const res = await authFetch(`${API_BASE}/system/backups/schedule`);
        if (!res.ok) throw new Error('Failed to fetch schedule config');
        const config = await res.json();
        document.getElementById('select-backup-schedule').value = config.schedule || 'disabled';
    } catch (err) {
        console.error(err);
    }
}

async function saveBackupScheduleConfig() {
    const schedule = document.getElementById('select-backup-schedule').value;
    try {
        const res = await authFetch(`${API_BASE}/system/backups/schedule`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ schedule })
        });
        if (!res.ok) {
            const err = await res.json();
            throw new Error(err.error || 'Failed to update schedule');
        }
        showToast(state.currentLanguage === 'en' ? 'Backup schedule updated successfully' : 'อัปเดตความถี่การสำรองข้อมูลเรียบร้อยแล้ว');
    } catch (err) {
        showToast(err.message, 'error');
    }
}

async function triggerManualBackup() {
    const btn = document.getElementById('btn-trigger-manual-backup');
    btn.disabled = true;
    const originalText = btn.innerHTML;
    btn.innerHTML = `<i class="fa-solid fa-spinner fa-spin"></i> ${state.currentLanguage === 'en' ? 'Backing up...' : 'กำลังสำรองข้อมูล...'}`;

    try {
        const res = await authFetch(`${API_BASE}/system/backups`, { method: 'POST' });
        if (!res.ok) {
            const err = await res.json();
            throw new Error(err.error || 'Backup failed');
        }
        showToast(t('toast_backup_created'));
        await fetchBackupVersions();
    } catch (err) {
        showToast(err.message, 'error');
    } finally {
        btn.disabled = false;
        btn.innerHTML = originalText;
    }
}

async function triggerDbRepair() {
    const btn = document.getElementById('btn-trigger-db-repair');
    btn.disabled = true;
    const originalText = btn.innerHTML;
    btn.innerHTML = `<i class="fa-solid fa-spinner fa-spin"></i> ${state.currentLanguage === 'en' ? 'Repairing...' : 'กำลังซ่อมแซม...'}`;

    try {
        const res = await authFetch(`${API_BASE}/system/repair`, { method: 'POST' });
        if (!res.ok) {
            const err = await res.json();
            throw new Error(err.error || 'Repair failed');
        }
        const data = await res.json();
        const msg = state.currentLanguage === 'en'
            ? `Repair Complete: Status ${data.health}. ${data.message}`
            : `ซ่อมแซมเสร็จสิ้น: สถานะสุขภาพข้อมูล ${data.health}. ${data.message}`;
        showToast(msg);
    } catch (err) {
        showToast(err.message, 'error');
    } finally {
        btn.disabled = false;
        btn.innerHTML = originalText;
    }
}

async function restoreBackupVersion(filename) {
    const confirmMsg = state.currentLanguage === 'en'
        ? `CAUTION: Restoring will overwrite the current database with this snapshot. All active changes since this backup will be lost. Are you sure you want to restore "${filename}"?`
        : `ข้อควรระวัง: การ Restore จะเขียนทับฐานข้อมูลปัจจุบันทั้งหมด ข้อมูลล่าสุดหลังจากวันที่ไฟล์นี้จะสูญหาย คุณยืนยันที่จะกู้คืนฐานข้อมูลจากไฟล์ "${filename}" ใช่หรือไม่?`;

    if (!confirm(confirmMsg)) return;

    try {
        const res = await authFetch(`${API_BASE}/system/backups/${filename}/restore`, { method: 'POST' });
        if (!res.ok) {
            const err = await res.json();
            throw new Error(err.error || 'Restore failed');
        }
        showToast(t('toast_db_restored'));
        closeSystemPanel();
        await initApp();
    } catch (err) {
        showToast(err.message, 'error');
    }
}

async function handleRestoreUpload(e) {
    e.preventDefault();
    const fileInput = document.getElementById('input-restore-file');
    if (fileInput.files.length === 0) {
        showToast(state.currentLanguage === 'en' ? 'Please select a .db file' : 'กรุณาเลือกไฟล์ .db', 'error');
        return;
    }

    const confirmMsg = state.currentLanguage === 'en'
        ? `CAUTION: Uploading and restoring this file will completely overwrite the current database. Are you sure you want to proceed?`
        : `ข้อควรระวัง: การอัปโหลดและกู้คืนไฟล์นี้จะเขียนทับฐานข้อมูลปัจจุบันทั้งหมด คุณยืนยันที่จะกู้คืนใช่หรือไม่?`;

    if (!confirm(confirmMsg)) return;

    const btn = document.getElementById('btn-submit-restore-file');
    btn.disabled = true;

    const formData = new FormData();
    formData.append('db_file', fileInput.files[0]);

    try {
        const res = await fetch(`${API_BASE}/system/restore-file`, {
            method: 'POST',
            headers: {
                ...getAuthHeader()
            },
            body: formData
        });

        if (!res.ok) {
            const err = await res.json();
            throw new Error(err.error || 'Upload restore failed');
        }

        showToast(t('toast_db_restored'));
        closeSystemPanel();
        fileInput.value = '';
        await initApp();
    } catch (err) {
        showToast(err.message, 'error');
    } finally {
        btn.disabled = false;
    }
}

// ==========================================
// Project Sourcing, Procurement, and Stock Workflows
// ==========================================

function initPrPoStockFlow() {
    // Modal Selectors
    const modalProjectBoms = document.getElementById('modal-project-boms');
    const modalProcurementPanel = document.getElementById('modal-procurement-panel');
    const modalStockPanel = document.getElementById('modal-stock-panel');
    const modalStockReportLoss = document.getElementById('modal-stock-report-loss');

    // Open Project BOM & PR Request Dialog
    const btnOpenProjectBoms = document.getElementById('btn-open-project-boms');
    if (btnOpenProjectBoms) {
        btnOpenProjectBoms.addEventListener('click', () => {
            if (!state.activeProjectId) {
                showToast('Please select a project first', 'error');
                return;
            }
            document.getElementById('bom-project-title').textContent = `BOM & PR Requests: ${state.activeProjectSummary.name}`;
            modalProjectBoms.classList.add('active');
            switchBomTab('create-pr');
        });
    }

    // Close Project BOM Modal
    const btnCloseProjectBoms = document.getElementById('btn-close-project-boms');
    if (btnCloseProjectBoms) {
        btnCloseProjectBoms.addEventListener('click', () => {
            modalProjectBoms.classList.remove('active');
        });
    }

    // Tab Switchers in BOM Dialog
    const btnTabCreatePr = document.getElementById('btn-tab-create-pr');
    const btnTabViewPrs = document.getElementById('btn-tab-view-prs');
    if (btnTabCreatePr) {
        btnTabCreatePr.addEventListener('click', () => switchBomTab('create-pr'));
    }
    if (btnTabViewPrs) {
        btnTabViewPrs.addEventListener('click', () => switchBomTab('view-prs'));
    }

    function switchBomTab(tab) {
        if (tab === 'create-pr') {
            btnTabCreatePr.className = 'btn btn-primary';
            btnTabViewPrs.className = 'btn btn-outline';
            document.getElementById('tab-content-create-pr').style.display = 'flex';
            document.getElementById('tab-content-view-prs').style.display = 'none';
            renderBomItems();
        } else {
            btnTabCreatePr.className = 'btn btn-outline';
            btnTabViewPrs.className = 'btn btn-primary';
            document.getElementById('tab-content-create-pr').style.display = 'none';
            document.getElementById('tab-content-view-prs').style.display = 'block';
            loadProjectPRs();
        }
    }

    // Render BOM items inside PR creation tab
    function renderBomItems() {
        const tbody = document.getElementById('bom-items-tbody');
        tbody.innerHTML = '';
        const items = getActiveProjectItems();
        if (items.length === 0) {
            tbody.innerHTML = '<tr><td colspan="7" class="text-center">ไม่มีสินค้าในระบบงานโครงการนี้</td></tr>';
            return;
        }

        items.forEach(item => {
            const tr = document.createElement('tr');
            tr.innerHTML = `
                <td class="text-center"><input type="checkbox" class="bom-item-select" data-id="${item.id}" data-desc="${escapeHtml(item.description)}" data-brand="${escapeHtml(item.brand)}" data-model="${escapeHtml(item.model)}" data-qty="${item.qty}" data-unit="${escapeHtml(item.unit)}"></td>
                <td>${escapeHtml(item.description)}</td>
                <td>${escapeHtml(item.brand || '-')}</td>
                <td>${escapeHtml(item.model || '-')}</td>
                <td>
                    <select class="form-control bom-item-system-type" style="width: 100px; padding: 4px;">
                        <option value="Other">ทั่วไป</option>
                        <option value="EE">EE (ไฟฟ้า)</option>
                        <option value="ME">ME (เครื่องกล)</option>
                    </select>
                </td>
                <td class="text-center"><input type="number" class="form-control bom-item-qty" style="width: 80px; text-align: center; margin: 0 auto; padding: 4px;" value="${item.qty}"></td>
                <td class="text-center">${escapeHtml(item.unit || 'ชิ้น')}</td>
            `;
            tbody.appendChild(tr);
        });
    }

    function getActiveProjectItems() {
        const items = [];
        if (state.activeProjectSummary && state.activeProjectSummary.sections) {
            state.activeProjectSummary.sections.forEach(sec => {
                if (sec.items) {
                    sec.items.forEach(it => {
                        items.push({
                            id: it.id,
                            description: it.description || '',
                            brand: it.brand || '',
                            model: it.model || '',
                            unit: it.unit || '',
                            qty: it.qty || 0,
                            system_type: it.type || 'Other'
                        });
                    });
                }
            });
        }
        return items;
    }

    // Submit PR
    const btnSubmitBomPr = document.getElementById('btn-submit-bom-pr');
    if (btnSubmitBomPr) {
        btnSubmitBomPr.addEventListener('click', async () => {
            const targetDate = document.getElementById('pr-target-delivery-date').value;
            if (!targetDate) {
                showToast('กรุณาระบุวันที่ต้องการสินค้า', 'error');
                return;
            }

            const selectedRows = document.querySelectorAll('.bom-item-select:checked');
            if (selectedRows.length === 0) {
                showToast('กรุณาเลือกสินค้าอย่างน้อย 1 รายการเพื่อสร้าง PR', 'error');
                return;
            }

            const items = [];
            selectedRows.forEach(row => {
                const tr = row.closest('tr');
                const qtyInput = tr.querySelector('.bom-item-qty');
                const systemSelect = tr.querySelector('.bom-item-system-type');
                items.push({
                    description: row.dataset.desc,
                    brand: row.dataset.brand,
                    model: row.dataset.model,
                    qty: parseFloat(qtyInput.value) || 0,
                    unit: row.dataset.unit,
                    system_type: systemSelect.value,
                    target_delivery_date: targetDate
                });
            });

            try {
                const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/prs`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ target_delivery_date: targetDate, items })
                });
                if (!res.ok) throw new Error('Failed to submit PR request');
                showToast('ส่งคำขอ PR เรียบร้อยแล้ว');
                switchBomTab('view-prs');
            } catch (err) {
                showToast(err.message, 'error');
            }
        });
    }

    // Load Project PRs list
    async function loadProjectPRs() {
        const tbody = document.getElementById('project-prs-tbody');
        tbody.innerHTML = '<tr><td colspan="7" class="text-center">กำลังโหลด...</td></tr>';
        try {
            const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/prs`);
            const prs = await res.json();
            tbody.innerHTML = '';
            if (prs.length === 0) {
                tbody.innerHTML = '<tr><td colspan="7" class="text-center">ไม่มีคำขอ PR ของโครงการนี้</td></tr>';
                return;
            }

            prs.forEach(pr => {
                const tr = document.createElement('tr');
                const dateStr = parseDbDate(pr.created_at).toLocaleDateString('th-TH');
                const targetStr = pr.target_delivery_date ? parseDbDate(pr.target_delivery_date).toLocaleDateString('th-TH') : '-';
                
                const eeApproval = pr.ee_manager_approved === 1 ? '<span class="badge badge-success">EE Approved</span>' : (pr.ee_manager_approved === -1 ? '<span class="badge badge-danger">EE Rejected</span>' : '<span class="badge badge-warning">EE Pending</span>');
                const meApproval = pr.me_manager_approved === 1 ? '<span class="badge badge-success">ME Approved</span>' : (pr.me_manager_approved === -1 ? '<span class="badge badge-danger">ME Rejected</span>' : '<span class="badge badge-warning">ME Pending</span>');
                const execApproval = pr.executive_approved === 1 ? '<span class="badge badge-success">Approved</span>' : (pr.executive_approved === -1 ? '<span class="badge badge-danger">Rejected</span>' : '<span class="badge badge-warning">Pending</span>');

                tr.innerHTML = `
                    <td class="text-center">PR-${pr.id}</td>
                    <td>${dateStr}</td>
                    <td>${targetStr}</td>
                    <td><span class="badge badge-info">${pr.status}</span></td>
                    <td><div style="display:flex; flex-direction:column; gap:4px;">${eeApproval} ${meApproval}</div></td>
                    <td>${execApproval}</td>
                    <td class="text-center"><button class="btn btn-outline btn-sm" onclick="viewPrDetailsDirectly(${pr.id})">ดูรายการ</button></td>
                `;
                tbody.appendChild(tr);
            });
        } catch (err) {
            tbody.innerHTML = '<tr><td colspan="7" class="text-center" style="color:var(--danger);">เกิดข้อผิดพลาดในการโหลด</td></tr>';
        }
    }

    // Direct helper to view details inside BOM modal
    window.viewPrDetailsDirectly = async function(prId) {
        modalProjectBoms.classList.remove('active');
        modalProcurementPanel.classList.add('active');
        document.getElementById('btn-proc-tab-pr').click();
        await loadProcurementPRs();
        showPRDetails(prId);
    };


    // ==========================================
    // Procurement & Pricing Flow
    // ==========================================

    const btnOpenProcurementPanel = document.getElementById('btn-open-procurement-panel');
    if (btnOpenProcurementPanel) {
        btnOpenProcurementPanel.addEventListener('click', () => {
            modalProcurementPanel.classList.add('active');
            document.getElementById('btn-proc-tab-pr').click();
        });
    }

    const btnCloseProcurementPanel = document.getElementById('btn-close-procurement-panel');
    if (btnCloseProcurementPanel) {
        btnCloseProcurementPanel.addEventListener('click', () => {
            modalProcurementPanel.classList.remove('active');
        });
    }

    const btnProcTabPr = document.getElementById('btn-proc-tab-pr');
    const btnProcTabPo = document.getElementById('btn-proc-tab-po');
    if (btnProcTabPr) {
        btnProcTabPr.addEventListener('click', () => {
            btnProcTabPr.className = 'btn btn-primary btn-sm';
            btnProcTabPo.className = 'btn btn-outline btn-sm';
            document.getElementById('proc-prs-list-container').style.display = 'flex';
            document.getElementById('proc-pos-list-container').style.display = 'none';
            loadProcurementPRs();
        });
    }
    if (btnProcTabPo) {
        btnProcTabPo.addEventListener('click', () => {
            btnProcTabPr.className = 'btn btn-outline btn-sm';
            btnProcTabPo.className = 'btn btn-primary btn-sm';
            document.getElementById('proc-prs-list-container').style.display = 'none';
            document.getElementById('proc-pos-list-container').style.display = 'flex';
            loadProcurementPOs();
        });
    }

    // Load global PRs list
    async function loadProcurementPRs() {
        const container = document.getElementById('proc-prs-list-container');
        container.innerHTML = '<div class="text-center">กำลังโหลด...</div>';
        try {
            const res = await authFetch(`${API_BASE}/prs`);
            const prs = await res.json();
            container.innerHTML = '';
            if (prs.length === 0) {
                container.innerHTML = '<div class="text-center" style="padding:20px;">ไม่มีรายการ PR</div>';
                return;
            }

            prs.forEach(pr => {
                const div = document.createElement('div');
                div.style = 'background:#f1f5f9; padding:12px; border-radius:6px; cursor:pointer; border:1px solid #cbd5e1;';
                div.innerHTML = `
                    <div style="font-weight:bold; display:flex; justify-content:space-between;">
                        <span>PR-${pr.id}</span>
                        <span class="badge badge-info">${pr.status}</span>
                    </div>
                    <div style="font-size:0.8rem; color:#475569; margin-top:4px;">โครงการ: ${escapeHtml(pr.project_name)}</div>
                    <div style="font-size:0.75rem; color:#64748b; margin-top:2px;">ผู้ขอ: ${escapeHtml(pr.creator_name)}</div>
                `;
                div.addEventListener('click', () => showPRDetails(pr.id));
                container.appendChild(div);
            });
        } catch (err) {
            container.innerHTML = '<div class="text-center" style="color:var(--danger);">เกิดข้อผิดพลาด</div>';
        }
    }

    // Fetch and show single PR details
    async function showPRDetails(prId) {
        const pane = document.getElementById('procurement-details-pane');
        pane.innerHTML = '<div class="text-center" style="padding:100px 0;">กำลังโหลด...</div>';
        try {
            const res = await authFetch(`${API_BASE}/prs/${prId}`);
            const data = await res.json();
            const pr = data.pr;
            const items = data.items;

            // Fetch suppliers list to select
            const resSuppliers = await authFetch(`${API_BASE}/suppliers`);
            const suppliers = await resSuppliers.json();

            let itemsRows = items.map((item, idx) => {
                const supplierOptions = suppliers.map(s => `
                    <option value="${s.id}" ${item.supplier_id === s.id ? 'selected' : ''}>${escapeHtml(s.name)}</option>
                `).join('');

                return `
                    <tr>
                        <td>${escapeHtml(item.description)}</td>
                        <td>${escapeHtml(item.brand || '-')}</td>
                        <td>${escapeHtml(item.model || '-')}</td>
                        <td class="text-center">${item.qty} ${escapeHtml(item.unit || 'ชิ้น')}</td>
                        <td><span class="badge badge-warning">${escapeHtml(item.system_type)}</span></td>
                        <td>
                            <input type="number" class="form-control item-sourced-price" data-id="${item.id}" style="width:100px; padding:4px;" value="${item.sourced_price || 0}">
                        </td>
                        <td>
                            <select class="form-control item-supplier-select" data-id="${item.id}" style="width:150px; padding:4px;">
                                <option value="">-- เลือกผู้ขาย --</option>
                                ${supplierOptions}
                            </select>
                        </td>
                    </tr>
                `;
            }).join('');

            const role = state.currentUser ? state.currentUser.role : 'user';
            
            // Managers reviews approval status
            const eeReviewMarkup = pr.ee_manager_approved === 1 ? '<span class="badge badge-success">EE Approved</span>' : (pr.ee_manager_approved === -1 ? '<span class="badge badge-danger">EE Rejected</span>' : '<span class="badge badge-warning">EE Pending</span>');
            const meReviewMarkup = pr.me_manager_approved === 1 ? '<span class="badge badge-success">ME Approved</span>' : (pr.me_manager_approved === -1 ? '<span class="badge badge-danger">ME Rejected</span>' : '<span class="badge badge-warning">ME Pending</span>');

            let actionButtons = '';
            
            // 1. Procurement pricing submission
            if (role === 'procurment' || role === 'admin' || role === 'superadmin') {
                actionButtons += `<button class="btn btn-success" id="btn-proc-submit-pricing">อัปเดตราคาและขออนุมัติเทคนิค (Sourcing Complete)</button>`;
            }

            // 2. EE Manager review action
            const hasEEItems = items.some(it => it.system_type === 'EE');
            if (hasEEItems && (role === 'ee_manager' || role === 'admin' || role === 'superadmin') && pr.status === 'pending_manager_review') {
                actionButtons += `
                    <div style="display:flex; gap:10px; align-items:center; background:#eff6ff; padding:12px; border-radius:6px; border:1px solid #bfdbfe;">
                        <span style="font-weight:bold;">EE Manager Review:</span>
                        <button class="btn btn-success btn-sm" onclick="submitPrReview(${pr.id}, true, 'EE')">อนุมัติระบบ EE</button>
                        <button class="btn btn-danger btn-sm" onclick="submitPrReview(${pr.id}, false, 'EE')">ปฏิเสธ</button>
                    </div>
                `;
            }

            // 3. ME Manager review action
            const hasMEItems = items.some(it => it.system_type === 'ME');
            if (hasMEItems && (role === 'me_manager' || role === 'admin' || role === 'superadmin') && pr.status === 'pending_manager_review') {
                actionButtons += `
                    <div style="display:flex; gap:10px; align-items:center; background:#eff6ff; padding:12px; border-radius:6px; border:1px solid #bfdbfe; margin-top:10px;">
                        <span style="font-weight:bold;">ME Manager Review:</span>
                        <button class="btn btn-success btn-sm" onclick="submitPrReview(${pr.id}, true, 'ME')">อนุมัติระบบ ME</button>
                        <button class="btn btn-danger btn-sm" onclick="submitPrReview(${pr.id}, false, 'ME')">ปฏิเสธ</button>
                    </div>
                `;
            }

            // 4. Executive final approval
            if ((role === 'excusive' || role === 'admin' || role === 'superadmin') && pr.status === 'pending_executive_approval') {
                actionButtons += `
                    <div style="display:flex; gap:10px; align-items:center; background:#fef3c7; padding:12px; border-radius:6px; border:1px solid #fde68a;">
                        <span style="font-weight:bold; color:#b45309;"><i class="fa-solid fa-stamp"></i> Executive Final Approval:</span>
                        <button class="btn btn-success btn-sm" onclick="submitPrApproval(${pr.id}, true)">อนุมัติใบสั่งซื้อ (Convert to PO)</button>
                        <button class="btn btn-danger btn-sm" onclick="submitPrApproval(${pr.id}, false)">ปฏิเสธ</button>
                    </div>
                `;
            }

            pane.innerHTML = `
                <div style="display:flex; justify-content:space-between; align-items:center; border-bottom:1px solid var(--border-color); padding-bottom:8px;">
                    <h4>ใบขอจัดซื้อ PR-${pr.id} (โครงการ ID: ${pr.project_id})</h4>
                    <span class="badge badge-info" style="font-size:1rem;">สถานะ: ${pr.status}</span>
                </div>

                <div style="display:grid; grid-template-columns:1fr 1fr 1fr; gap:10px; background:#f8fafc; padding:12px; border-radius:6px; border:1px solid var(--border-color);">
                    <div><strong>วันที่ต้องการสินค้า:</strong> ${pr.target_delivery_date ? parseDbDate(pr.target_delivery_date).toLocaleDateString('th-TH') : '-'}</div>
                    <div><strong>ตรวจสอบเทคนิค EE:</strong> ${eeReviewMarkup}</div>
                    <div><strong>ตรวจสอบเทคนิค ME:</strong> ${meReviewMarkup}</div>
                </div>

                <table class="table">
                    <thead>
                        <tr>
                            <th>รายการ</th>
                            <th>ยี่ห้อ</th>
                            <th>รุ่น</th>
                            <th class="text-center">จำนวน</th>
                            <th>ระบบ</th>
                            <th>ราคาซื้อจริงที่จัดซื้อได้</th>
                            <th>ผู้จัดจำหน่าย (Supplier)</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${itemsRows}
                    </tbody>
                </table>

                <div style="display:flex; flex-direction:column; gap:10px; margin-top:20px; align-items:flex-end;">
                    ${actionButtons}
                </div>
            `;

            // Bind click for procurement pricing submission
            const btnProcSubmitPricing = document.getElementById('btn-proc-submit-pricing');
            if (btnProcSubmitPricing) {
                btnProcSubmitPricing.addEventListener('click', async () => {
                    const priceInputs = pane.querySelectorAll('.item-sourced-price');
                    const supplierSelects = pane.querySelectorAll('.item-supplier-select');

                    const updatedItems = [];
                    for (let i = 0; i < priceInputs.length; i++) {
                        const id = priceInputs[i].dataset.id;
                        const price = parseFloat(priceInputs[i].value) || 0;
                        const supplierId = supplierSelects[i].value;

                        if (!supplierId) {
                            showToast('กรุณาระบุผู้จัดจำหน่ายให้ครบทุกรายการ', 'error');
                            return;
                        }
                        updatedItems.push({ id, sourced_price: price, supplier_id: supplierId });
                    }

                    try {
                        const res = await authFetch(`${API_BASE}/prs/${prId}/items`, {
                            method: 'PUT',
                            headers: { 'Content-Type': 'application/json' },
                            body: JSON.stringify({ items: updatedItems })
                        });
                        if (!res.ok) throw new Error('Failed to update pricing');
                        showToast('อัปเดตราคาและส่งขออนุมัติเทคนิคแล้ว');
                        showPRDetails(prId);
                    } catch (err) {
                        showToast(err.message, 'error');
                    }
                });
            }
        } catch (err) {
            pane.innerHTML = `<div class="text-center" style="color:var(--danger); padding:100px 0;">เกิดข้อผิดพลาดในการโหลดรายละเอียด</div>`;
        }
    };

    // Technical review API call helper
    window.submitPrReview = async function(prId, approve, systemType) {
        try {
            const res = await authFetch(`${API_BASE}/prs/${prId}/review`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ approve, system_type: systemType })
            });
            if (!res.ok) throw new Error('Review submission failed');
            showToast(approve ? 'อนุมัติเรียบร้อย' : 'ปฏิเสธคำขอจัดซื้อแล้ว');
            showPRDetails(prId);
        } catch (err) {
            showToast(err.message, 'error');
        }
    };

    // Executive final approval API call helper
    window.submitPrApproval = async function(prId, approve) {
        try {
            const res = await authFetch(`${API_BASE}/prs/${prId}/approve`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ approve })
            });
            if (!res.ok) throw new Error('Approval submission failed');
            showToast(approve ? 'อนุมัติคำขอจัดซื้อและออกเอกสารใบสั่งซื้อ PO แล้ว' : 'ปฏิเสธคำขอเรียบร้อยแล้ว');
            showPRDetails(prId);
        } catch (err) {
            showToast(err.message, 'error');
        }
    };

    // Load global POs list
    async function loadProcurementPOs() {
        const container = document.getElementById('proc-pos-list-container');
        container.innerHTML = '<div class="text-center">กำลังโหลด...</div>';
        try {
            const res = await authFetch(`${API_BASE}/pos`);
            const pos = await res.json();
            container.innerHTML = '';
            if (pos.length === 0) {
                container.innerHTML = '<div class="text-center" style="padding:20px;">ไม่มีรายการสั่งซื้อ PO</div>';
                return;
            }

            pos.forEach(po => {
                const div = document.createElement('div');
                div.style = 'background:#f1f5f9; padding:12px; border-radius:6px; cursor:pointer; border:1px solid #cbd5e1;';
                div.innerHTML = `
                    <div style="font-weight:bold; display:flex; justify-content:space-between;">
                        <span>PO-${po.id}</span>
                        <span class="badge badge-info">${po.status}</span>
                    </div>
                    <div style="font-size:0.8rem; color:#475569; margin-top:4px;">โครงการ: ${escapeHtml(po.project_name)}</div>
                    <div style="font-size:0.75rem; color:#64748b; margin-top:2px;">ผู้จัดจำหน่าย: ${escapeHtml(po.supplier_name)}</div>
                `;
                div.addEventListener('click', () => showPODetails(po.id));
                container.appendChild(div);
            });
        } catch (err) {
            container.innerHTML = '<div class="text-center" style="color:var(--danger);">เกิดข้อผิดพลาด</div>';
        }
    }

    // Show PO details
    async function showPODetails(poId) {
        const pane = document.getElementById('procurement-details-pane');
        pane.innerHTML = '<div class="text-center" style="padding:100px 0;">กำลังโหลด...</div>';
        try {
            const res = await authFetch(`${API_BASE}/pos/${poId}`);
            const data = await res.json();
            const po = data.po;
            const items = data.items;

            let totalVal = 0;
            let itemsRows = items.map((item, idx) => {
                const itemTotal = item.qty * item.price;
                totalVal += itemTotal;
                return `
                    <tr>
                        <td>${escapeHtml(item.description)}</td>
                        <td>${escapeHtml(item.brand || '-')}</td>
                        <td>${escapeHtml(item.model || '-')}</td>
                        <td class="text-center">${item.qty} ${escapeHtml(item.unit || 'ชิ้น')}</td>
                        <td class="text-right">${formatCurrency(item.price)}</td>
                        <td class="text-right">${formatCurrency(itemTotal)}</td>
                        <td class="text-center">${item.received_qty} / ${item.qty}</td>
                    </tr>
                `;
            }).join('');

            const role = state.currentUser ? state.currentUser.role : 'user';
            let approveActionBtn = '';
            if (po.status === 'pending_approval' && (role === 'excusive' || role === 'admin' || role === 'superadmin')) {
                approveActionBtn = `
                    <div style="display:flex; gap:10px; align-items:center; background:#fef3c7; padding:12px; border-radius:6px; border:1px solid #fde68a;">
                        <span style="font-weight:bold; color:#b45309;"><i class="fa-solid fa-signature"></i> อนุมัติเอกสารใบสั่งซื้อ PO:</span>
                        <button class="btn btn-success btn-sm" onclick="submitPoApproval(${po.id}, true)">อนุมัติสั่งซื้อ (Approve PO)</button>
                        <button class="btn btn-danger btn-sm" onclick="submitPoApproval(${po.id}, false)">ปฏิเสธ (Reject PO)</button>
                    </div>
                `;
            }

            pane.innerHTML = `
                <div style="display:flex; justify-content:space-between; align-items:center; border-bottom:1px solid var(--border-color); padding-bottom:8px;">
                    <h4>ใบสั่งซื้อ PO-${po.id} (โครงการ ID: ${po.project_id})</h4>
                    <span class="badge badge-info" style="font-size:1rem;">สถานะ: ${po.status}</span>
                </div>

                <div style="background:#f8fafc; padding:12px; border-radius:6px; border:1px solid var(--border-color); margin-bottom:16px;">
                    <div><strong>มูลค่ารวม:</strong> <span style="font-size:1.2rem; font-weight:bold; color:var(--primary-color);">${formatCurrency(totalVal)}</span></div>
                </div>

                <table class="table">
                    <thead>
                        <tr>
                            <th>รายการ</th>
                            <th>ยี่ห้อ</th>
                            <th>รุ่น</th>
                            <th class="text-center">จำนวนสั่ง</th>
                            <th class="text-right">ราคาต่อหน่วย</th>
                            <th class="text-right">ราคารวม</th>
                            <th class="text-center">จำนวนรับแล้ว</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${itemsRows}
                    </tbody>
                </table>

                <div style="display:flex; flex-direction:column; gap:10px; margin-top:20px; align-items:flex-end;">
                    ${approveActionBtn}
                </div>
            `;
        } catch (err) {
            pane.innerHTML = `<div class="text-center" style="color:var(--danger); padding:100px 0;">เกิดข้อผิดพลาดในการโหลดรายละเอียด PO</div>`;
        }
    };

    window.submitPoApproval = async function(poId, approve) {
        try {
            const res = await authFetch(`${API_BASE}/pos/${poId}/approve`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ approve })
            });
            if (!res.ok) throw new Error('PO Approval submission failed');
            showToast(approve ? 'อนุมัติใบสั่งซื้อ PO เรียบร้อยแล้ว' : 'ปฏิเสธเอกสารสั่งซื้อแล้ว');
            showPODetails(poId);
        } catch (err) {
            showToast(err.message, 'error');
        }
    };


    // ==========================================
    // Warehouse & Stock Management Flow
    // ==========================================

    const btnOpenStockPanel = document.getElementById('btn-open-stock-panel');
    if (btnOpenStockPanel) {
        btnOpenStockPanel.addEventListener('click', () => {
            modalStockPanel.classList.add('active');
            document.getElementById('btn-stock-tab-receive').click();
        });
    }

    const btnCloseStockPanel = document.getElementById('btn-close-stock-panel');
    if (btnCloseStockPanel) {
        btnCloseStockPanel.addEventListener('click', () => {
            modalStockPanel.classList.remove('active');
        });
    }

    // Subtabs switcher
    const tabs = ['receive', 'inventory', 'disburse', 'alerts'];
    tabs.forEach(tab => {
        const btn = document.getElementById(`btn-stock-tab-${tab}`);
        if (btn) {
            btn.addEventListener('click', () => {
                tabs.forEach(t => {
                    const b = document.getElementById(`btn-stock-tab-${t}`);
                    const content = document.getElementById(`stock-content-${t}`);
                    if (b) b.className = t === tab ? 'btn btn-primary' : 'btn btn-outline';
                    if (content) content.style.display = t === tab ? (t === 'receive' || t === 'disburse' || t === 'alerts' ? 'flex' : 'block') : 'none';
                });
                
                // Load tab data
                if (tab === 'receive') loadStockPOReceipts();
                if (tab === 'inventory') loadStockInventory();
                if (tab === 'disburse') loadStockDisbursements();
                if (tab === 'alerts') loadStockAlerts();
            });
        }
    });

    // Receive goods POs list
    async function loadStockPOReceipts() {
        const list = document.getElementById('stock-approved-pos-list');
        list.innerHTML = '<div>กำลังโหลด...</div>';
        try {
            const res = await authFetch(`${API_BASE}/pos`);
            const pos = await res.json();
            // Filter to approved / partially_received POs
            const approved = pos.filter(po => po.status === 'approved' || po.status === 'partially_received');
            list.innerHTML = '';
            if (approved.length === 0) {
                list.innerHTML = '<div class="text-center" style="color:#64748b;">ไม่มี PO ที่พร้อมรับสินค้า</div>';
                return;
            }

            approved.forEach(po => {
                const div = document.createElement('div');
                div.style = 'background:#f1f5f9; padding:10px; border-radius:6px; cursor:pointer; border:1px solid #cbd5e1; font-size:0.85rem;';
                div.innerHTML = `
                    <div style="font-weight:bold;">PO-${po.id}</div>
                    <div style="color:#475569;">โครงการ: ${escapeHtml(po.project_name)}</div>
                    <div style="color:#64748b; font-size:0.75rem;">ผู้ขาย: ${escapeHtml(po.supplier_name)}</div>
                `;
                div.addEventListener('click', () => showPOReceiptDetails(po.id));
                list.appendChild(div);
            });
        } catch (err) {
            list.innerHTML = '<div style="color:var(--danger);">เกิดข้อผิดพลาด</div>';
        }
    }

    async function showPOReceiptDetails(poId) {
        const pane = document.getElementById('stock-receive-po-details');
        pane.innerHTML = '<div>กำลังโหลดรายละเอียด...</div>';
        try {
            const res = await authFetch(`${API_BASE}/pos/${poId}`);
            const data = await res.json();
            const po = data.po;
            const items = data.items;

            let itemsRows = items.map((item, idx) => {
                const remaining = item.qty - item.received_qty;
                return `
                    <tr class="stock-receipt-item-row" data-po-item-id="${item.id}">
                        <td>
                            <strong>${escapeHtml(item.description)}</strong>
                            <div style="font-size:0.75rem; color:#64748b;">ยี่ห้อ: ${escapeHtml(item.brand || '-')} / รุ่น: ${escapeHtml(item.model || '-')}</div>
                        </td>
                        <td class="text-center">${item.qty} ${escapeHtml(item.unit || 'ชิ้น')}</td>
                        <td class="text-center">${item.received_qty}</td>
                        <td class="text-center">
                            <input type="number" class="form-control receipt-qty" style="width:70px; text-align:center; padding:4px;" value="${remaining}" max="${remaining}" min="0">
                        </td>
                        <td>
                            <select class="form-control receipt-type" style="padding:4px;">
                                <option value="consumable">ใช้แล้วหมดไป</option>
                                <option value="tool_machinery">เครื่องมือ/เครื่องจักร</option>
                            </select>
                        </td>
                        <td>
                            <input type="text" class="form-control receipt-location" style="width:100px; padding:4px;" placeholder="ชั้นเก็บของ A1">
                        </td>
                        <td>
                            <input type="number" class="form-control receipt-min-qty" style="width:60px; text-align:center; padding:4px;" value="0">
                        </td>
                        <td class="text-center">
                            <input type="checkbox" class="receipt-defective">
                        </td>
                    </tr>
                `;
            }).join('');

            pane.innerHTML = `
                <div style="border-bottom:1px solid var(--border-color); padding-bottom:8px; display:flex; justify-content:space-between; align-items:center;">
                    <h4>ตรวจรับสินค้าใบสั่งซื้อ PO-${po.id}</h4>
                    <button class="btn btn-primary" id="btn-submit-stock-receipt">บันทึกตรวจรับสินค้าเข้าคลัง</button>
                </div>

                <table class="table">
                    <thead>
                        <tr>
                            <th>รายการสินค้า</th>
                            <th class="text-center">จำนวนสั่ง</th>
                            <th class="text-center">รับแล้ว</th>
                            <th class="text-center">จำนวนตรวจรับครั้งนี้</th>
                            <th>ประเภทคลัง</th>
                            <th>สถานที่เก็บ</th>
                            <th>ระดับเตือนขั้นต่ำ</th>
                            <th class="text-center">เคลม/ชำรุด</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${itemsRows}
                    </tbody>
                </table>
            `;

            // Bind click to submit receipt
            document.getElementById('btn-submit-stock-receipt').addEventListener('click', async () => {
                const rows = pane.querySelectorAll('.stock-receipt-item-row');
                const receiptItems = [];

                rows.forEach(row => {
                    const poItemId = parseInt(row.dataset.poItemId);
                    const qty = parseFloat(row.querySelector('.receipt-qty').value) || 0;
                    const type = row.querySelector('.receipt-type').value;
                    const location = row.querySelector('.receipt-location').value.trim();
                    const minQty = parseFloat(row.querySelector('.receipt-min-qty').value) || 0;
                    const isDefective = row.querySelector('.receipt-defective').checked;

                    if (qty > 0) {
                        receiptItems.push({
                            po_item_id: poItemId,
                            qty,
                            type,
                            location,
                            min_qty: minQty,
                            is_defective: isDefective
                        });
                    }
                });

                if (receiptItems.length === 0) {
                    showToast('กรุณาระบุจำนวนสินค้าที่ต้องการตรวจรับอย่างน้อย 1 รายการ', 'error');
                    return;
                }

                try {
                    const res = await authFetch(`${API_BASE}/pos/${poId}/receive`, {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify({ items: receiptItems })
                    });
                    if (!res.ok) throw new Error('Failed to record stock receipt');
                    showToast('บันทึกตรวจรับสินค้าเข้าสต็อกเรียบร้อยแล้ว');
                    loadStockPOReceipts();
                    pane.innerHTML = '<div style="text-align: center; padding: 100px 0; color: #64748b;">ตรวจรับสำเร็จ เลือก PO ถัดไปเพื่อดำเนินการต่อ</div>';
                } catch (err) {
                    showToast(err.message, 'error');
                }
            });
        } catch (err) {
            pane.innerHTML = '<div style="color:var(--danger);">เกิดข้อผิดพลาดในการโหลดรายละเอียด PO</div>';
        }
    }

    // Load warehouse Inventory
    async function loadStockInventory() {
        const tbody = document.getElementById('stock-inventory-tbody');
        tbody.innerHTML = '<tr><td colspan="9" class="text-center">กำลังโหลดคลังสินค้า...</td></tr>';
        try {
            const res = await authFetch(`${API_BASE}/stock`);
            const stock = await res.json();
            tbody.innerHTML = '';
            if (stock.length === 0) {
                tbody.innerHTML = '<tr><td colspan="9" class="text-center">ไม่มีสินค้าอยู่ในคลังคลังขณะนี้</td></tr>';
                return;
            }

            // Populating options for disburse dropdown
            const disburseSelect = document.getElementById('disburse-select-item');
            const returnSelect = document.getElementById('return-select-item');
            const lossSelect = document.getElementById('loss-select-item');
            
            if (disburseSelect) disburseSelect.innerHTML = '';
            if (returnSelect) returnSelect.innerHTML = '';
            if (lossSelect) lossSelect.innerHTML = '';

            stock.forEach(item => {
                const tr = document.createElement('tr');
                const lastMove = item.last_movement_at ? parseDbDate(item.last_movement_at).toLocaleString('th-TH') : '-';
                const safetyClass = item.qty < item.min_qty ? 'style="color:var(--danger); font-weight:bold;"' : '';
                const typeText = item.type === 'consumable' ? 'ใช้แล้วหมดไป' : 'เครื่องมือ/เครื่องจักร';

                tr.innerHTML = `
                    <td><strong>${escapeHtml(item.description)}</strong></td>
                    <td>${escapeHtml(item.brand || '-')}</td>
                    <td>${escapeHtml(item.model || '-')}</td>
                    <td>${escapeHtml(item.unit || 'ชิ้น')}</td>
                    <td class="text-center" ${safetyClass}>${item.qty}</td>
                    <td>${typeText}</td>
                    <td>${escapeHtml(item.location || '-')}</td>
                    <td class="text-center">${item.min_qty}</td>
                    <td style="font-size:0.75rem; color:#64748b;">${lastMove}</td>
                `;
                tbody.appendChild(tr);

                // Add to selects
                const opt = `<option value="${item.id}">${escapeHtml(item.description)} (${item.qty} ${escapeHtml(item.unit)})</option>`;
                if (disburseSelect) disburseSelect.insertAdjacentHTML('beforeend', opt);
                if (returnSelect) returnSelect.insertAdjacentHTML('beforeend', opt);
                if (lossSelect) lossSelect.insertAdjacentHTML('beforeend', opt);
            });
        } catch (err) {
            tbody.innerHTML = '<tr><td colspan="9" class="text-center" style="color:var(--danger);">เกิดข้อผิดพลาดในการโหลดข้อมูล</td></tr>';
        }
    }

    // Load Stock Disbursement tab (select dropdowns + pending approvals table)
    async function loadStockDisbursements() {
        const projSelect = document.getElementById('disburse-select-project');
        const returnProjSelect = document.getElementById('return-select-project');
        
        if (projSelect) projSelect.innerHTML = '';
        if (returnProjSelect) returnProjSelect.innerHTML = '';

        try {
            // Populate projects
            const resProjects = await authFetch(`${API_BASE}/projects`);
            const projects = await resProjects.json();
            
            projects.forEach(p => {
                const opt = `<option value="${p.id}">${escapeHtml(p.name)}</option>`;
                if (projSelect) projSelect.insertAdjacentHTML('beforeend', opt);
                if (returnProjSelect) returnProjSelect.insertAdjacentHTML('beforeend', opt);
            });

            // Load Inventory list to select products
            await loadStockInventory();

            // Load Pending Disbursements approvals list
            await loadPendingDisbursements();
        } catch (err) {
            console.error('Failed to load disbursements data:', err);
        }
    }

    // Submit request to disburse items
    const btnStockDisburseSubmit = document.getElementById('btn-stock-disburse-submit');
    if (btnStockDisburseSubmit) {
        btnStockDisburseSubmit.addEventListener('click', async () => {
            const stockItemId = document.getElementById('disburse-select-item').value;
            const projectId = document.getElementById('disburse-select-project').value;
            const qty = parseFloat(document.getElementById('disburse-qty').value) || 0;

            if (qty <= 0) {
                showToast('กรุณาระบุจำนวนสินค้าที่ถูกต้อง', 'error');
                return;
            }

            try {
                const res = await authFetch(`${API_BASE}/stock/disburse`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ stock_item_id: stockItemId, qty, project_id: projectId })
                });
                if (!res.ok) {
                    const err = await res.json();
                    throw new Error(err.error || 'Failed to submit disbursement request');
                }
                showToast('ยื่นขอเบิกจ่ายสินค้าสำเร็จแล้ว รอผู้จัดการโครงการอนุมัติ');
                document.getElementById('disburse-qty').value = '';
                loadStockDisbursements();
            } catch (err) {
                showToast(err.message, 'error');
            }
        });
    }

    // Submit returned items to stock
    const btnStockReturnSubmit = document.getElementById('btn-stock-return-submit');
    if (btnStockReturnSubmit) {
        btnStockReturnSubmit.addEventListener('click', async () => {
            const stockItemId = document.getElementById('return-select-item').value;
            const projectId = document.getElementById('return-select-project').value;
            const qty = parseFloat(document.getElementById('return-qty').value) || 0;

            if (qty <= 0) {
                showToast('กรุณาระบุจำนวนคืนที่ถูกต้อง', 'error');
                return;
            }

            try {
                const res = await authFetch(`${API_BASE}/stock/return`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ stock_item_id: stockItemId, qty, project_id: projectId })
                });
                if (!res.ok) throw new Error('Return failed');
                showToast('รับคืนสินค้าเข้าคลังเรียบร้อยแล้ว');
                document.getElementById('return-qty').value = '';
                loadStockDisbursements();
            } catch (err) {
                showToast(err.message, 'error');
            }
        });
    }

    // Load pending disbursement requests to project
    async function loadPendingDisbursements() {
        const tbody = document.getElementById('stock-pending-disbursements-tbody');
        tbody.innerHTML = '<tr><td colspan="6" class="text-center">กำลังโหลดรายการขอเบิก...</td></tr>';
        
        try {
            const res = await authFetch(`${API_BASE}/stock/movements?status=pending_approval`);
            const movements = await res.json();
            tbody.innerHTML = '';
            if (movements.length === 0) {
                tbody.innerHTML = '<tr><td colspan="6" class="text-center">ไม่มีรายการขออนุมัติเบิกจ่ายสินค้า</td></tr>';
                return;
            }

            movements.forEach(m => {
                const tr = document.createElement('tr');
                tr.innerHTML = `
                    <td><strong>${escapeHtml(m.description)}</strong></td>
                    <td>${escapeHtml(m.project_name)}</td>
                    <td class="text-center">${m.qty} ${escapeHtml(m.unit || 'ชิ้น')}</td>
                    <td>${escapeHtml(m.requester_name || 'Stock Room')}</td>
                    <td><span class="badge badge-warning">รออนุมัติ</span></td>
                    <td class="text-center" style="display:flex; gap:6px; justify-content:center;">
                        <button class="btn btn-success btn-sm" onclick="approveDisbursement(${m.id}, true)">อนุมัติ</button>
                        <button class="btn btn-danger btn-sm" onclick="approveDisbursement(${m.id}, false)">ปฏิเสธ</button>
                    </td>
                `;
                tbody.appendChild(tr);
            });
        } catch (err) {
            tbody.innerHTML = '<tr><td colspan="6" class="text-center">โหลดรายการล้มเหลว</td></tr>';
        }
    }

    window.approveDisbursement = async function(movementId, approve) {
        try {
            const res = await authFetch(`${API_BASE}/stock/approve-disbursement`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ movement_id: movementId, approve })
            });
            if (!res.ok) {
                const err = await res.json();
                throw new Error(err.error || 'Failed to submit approval');
            }
            showToast(approve ? 'อนุมัติการเบิกจ่ายสินค้าและตัดสต็อกเรียบร้อย' : 'ปฏิเสธคำขอเบิกเรียบร้อย');
            loadStockDisbursements();
        } catch (err) {
            showToast(err.message, 'error');
        }
    };

    // Load Stock alerts (safety limits and dead stock)
    async function loadStockAlerts() {
        const safetyTbody = document.getElementById('stock-alert-safety-tbody');
        const deadTbody = document.getElementById('stock-alert-dead-tbody');

        safetyTbody.innerHTML = '<tr><td colspan="4" class="text-center">กำลังโหลด...</td></tr>';
        deadTbody.innerHTML = '<tr><td colspan="4" class="text-center">กำลังโหลด...</td></tr>';

        try {
            const res = await authFetch(`${API_BASE}/stock/alerts`);
            const data = await res.json();

            // Safety Stock
            safetyTbody.innerHTML = '';
            if (data.safety.length === 0) {
                safetyTbody.innerHTML = '<tr><td colspan="4" class="text-center" style="color:var(--success);">คลังสินค้าปกติ ไม่มีระดับต่ำกว่าเกณฑ์</td></tr>';
            } else {
                data.safety.forEach(item => {
                    const tr = document.createElement('tr');
                    tr.innerHTML = `
                        <td><strong>${escapeHtml(item.description)}</strong></td>
                        <td class="text-center" style="color:var(--danger); font-weight:bold;">${item.qty}</td>
                        <td class="text-center">${item.min_qty}</td>
                        <td>${escapeHtml(item.location || '-')}</td>
                    `;
                    safetyTbody.appendChild(tr);
                });
            }

            // Dead Stock
            deadTbody.innerHTML = '';
            if (data.dead.length === 0) {
                deadTbody.innerHTML = '<tr><td colspan="4" class="text-center" style="color:var(--success);">ไม่มีสินค้าค้างสต็อก</td></tr>';
            } else {
                data.dead.forEach(item => {
                    const tr = document.createElement('tr');
                    const text = item.alert_type === 'inactive_6m' ? 'ค้างเกิน 6 เดือน' : 'ค้างเกิน 3 เดือน';
                    const lastMove = item.last_movement_at ? parseDbDate(item.last_movement_at).toLocaleDateString('th-TH') : '-';
                    tr.innerHTML = `
                        <td><strong>${escapeHtml(item.description)}</strong></td>
                        <td class="text-center">${item.qty}</td>
                        <td style="color:var(--warning); font-weight:bold;">${text}</td>
                        <td>${lastMove}</td>
                    `;
                    deadTbody.appendChild(tr);
                });
            }
        } catch (err) {
            safetyTbody.innerHTML = '<tr><td colspan="4" class="text-center">เกิดข้อผิดพลาด</td></tr>';
            deadTbody.innerHTML = '<tr><td colspan="4" class="text-center">เกิดข้อผิดพลาด</td></tr>';
        }
    }

    // Damage & Loss Dialog Control
    const btnReportDamageLost = document.getElementById('btn-stock-report-damage-lost');
    if (btnReportDamageLost) {
        btnReportDamageLost.addEventListener('click', () => {
            modalStockReportLoss.classList.add('active');
        });
    }

    const btnCloseStockLossModal = document.getElementById('btn-close-stock-loss-modal');
    if (btnCloseStockLossModal) {
        btnCloseStockLossModal.addEventListener('click', () => {
            modalStockReportLoss.classList.remove('active');
        });
    }

    const btnCancelStockLoss = document.getElementById('btn-cancel-stock-loss');
    if (btnCancelStockLoss) {
        btnCancelStockLoss.addEventListener('click', () => {
            modalStockReportLoss.classList.remove('active');
        });
    }

    const btnSubmitStockLoss = document.getElementById('btn-submit-stock-loss');
    if (btnSubmitStockLoss) {
        btnSubmitStockLoss.addEventListener('click', async () => {
            const stockItemId = document.getElementById('loss-select-item').value;
            const type = document.getElementById('loss-report-type').value;
            const qty = parseFloat(document.getElementById('loss-qty').value) || 0;

            if (qty <= 0) {
                showToast('กรุณาระบุจำนวนสินค้าที่ถูกต้อง', 'error');
                return;
            }

            try {
                const res = await authFetch(`${API_BASE}/stock/report`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ stock_item_id: stockItemId, qty, type })
                });
                if (!res.ok) {
                    const err = await res.json();
                    throw new Error(err.error || 'Failed to submit loss report');
                }
                showToast(`บันทึกรายงานแจ้ง${type === 'damage' ? 'ชำรุด' : 'สูญหาย'}เรียบร้อยแล้ว`);
                modalStockReportLoss.classList.remove('active');
                loadStockInventory();
            } catch (err) {
                showToast(err.message, 'error');
            }
        });
    }
}

// Automatically load new flows on app load
initPrPoStockFlow();

function renderComparisonMode() {
    const tbody = document.getElementById('compare-mode-tbody');
    if (!tbody) return;

    if (!state.activeProjectSummary || !state.activeProjectSummary.sections) {
        tbody.innerHTML = `<tr><td colspan="9" style="text-align: center;" data-i18n="compare_no_data">ไม่มีข้อมูลสำหรับแสดงผล</td></tr>`;
        return;
    }

    const sections = state.activeProjectSummary.sections;
    let html = '';

    // Calculate totals for comparison footer / summary row
    let totalEstCost = 0;
    let totalProdCost = 0;
    let totalEstSale = 0;
    let totalProdSale = 0;

    sections.forEach(sec => {
        const estCost = sec.cost_total || 0;
        const prodCost = sec.production_cost_total || 0;
        const costDiff = prodCost - estCost;

        const estSale = sec.price_total || 0;
        const prodSale = sec.production_price_total || 0;
        const saleDiff = prodSale - estSale;

        const estProfit = sec.profit || 0;
        const prodProfit = sec.production_profit || 0;

        const estMargin = sec.profit_margin_percent || 0;
        const prodMargin = sec.production_profit_margin_percent || 0;

        totalEstCost += estCost;
        totalProdCost += prodCost;
        totalEstSale += estSale;
        totalProdSale += prodSale;

        const costDiffClass = costDiff > 0 ? 'text-danger font-bold' : (costDiff < 0 ? 'text-success font-bold' : '');
        const saleDiffClass = saleDiff > 0 ? 'text-success font-bold' : (saleDiff < 0 ? 'text-danger font-bold' : '');
        const prodProfitClass = prodProfit >= 0 ? 'text-success font-bold' : 'text-danger font-bold';
        const estProfitClass = estProfit >= 0 ? 'text-success font-bold' : 'text-danger font-bold';

        html += `
            <tr>
                <td class="font-bold">${escapeHtml(sec.name)}</td>
                <td class="text-right">${formatCurrency(estCost)}</td>
                <td class="text-right">${formatCurrency(prodCost)}</td>
                <td class="text-right ${costDiffClass}">${costDiff > 0 ? '+' : ''}${formatCurrency(costDiff)}</td>
                <td class="text-right">${formatCurrency(estSale)}</td>
                <td class="text-right">${formatCurrency(prodSale)}</td>
                <td class="text-right ${saleDiffClass}">${saleDiff > 0 ? '+' : ''}${formatCurrency(saleDiff)}</td>
                <td class="text-right ${estProfitClass}">${formatCurrency(estProfit)} (${estMargin.toFixed(2)}%)</td>
                <td class="text-right ${prodProfitClass}">${formatCurrency(prodProfit)} (${prodMargin.toFixed(2)}%)</td>
            </tr>
        `;
    });

    // Add a summary row at the end
    const overallCostDiff = totalProdCost - totalEstCost;
    const overallSaleDiff = totalProdSale - totalEstSale;
    const overallEstProfit = totalEstSale - totalEstCost;
    const overallProdProfit = totalProdSale - totalProdCost;
    const overallEstMargin = totalEstCost > 0 ? (overallEstProfit / totalEstCost) * 100 : 0;
    const overallProdMargin = totalProdCost > 0 ? (overallProdProfit / totalProdCost) * 100 : 0;

    const overallCostDiffClass = overallCostDiff > 0 ? 'text-danger font-bold' : (overallCostDiff < 0 ? 'text-success font-bold' : '');
    const overallSaleDiffClass = overallSaleDiff > 0 ? 'text-success font-bold' : (overallSaleDiff < 0 ? 'text-danger font-bold' : '');
    const overallEstProfitClass = overallEstProfit >= 0 ? 'text-success font-bold' : 'text-danger font-bold';
    const overallProdProfitClass = overallProdProfit >= 0 ? 'text-success font-bold' : 'text-danger font-bold';

    html += `
        <tr style="background-color: #f8fafc; border-top: 2px solid var(--border-color); font-weight: bold;">
            <td data-i18n="compare_total_sum">รวมทั้งสิ้น (Total Summary)</td>
            <td class="text-right">${formatCurrency(totalEstCost)}</td>
            <td class="text-right">${formatCurrency(totalProdCost)}</td>
            <td class="text-right ${overallCostDiffClass}">${overallCostDiff > 0 ? '+' : ''}${formatCurrency(overallCostDiff)}</td>
            <td class="text-right">${formatCurrency(totalEstSale)}</td>
            <td class="text-right">${formatCurrency(totalProdSale)}</td>
            <td class="text-right ${overallSaleDiffClass}">${overallSaleDiff > 0 ? '+' : ''}${formatCurrency(overallSaleDiff)}</td>
            <td class="text-right ${overallEstProfitClass}">${formatCurrency(overallEstProfit)} (${overallEstMargin.toFixed(2)}%)</td>
            <td class="text-right ${overallProdProfitClass}">${formatCurrency(overallProdProfit)} (${overallProdMargin.toFixed(2)}%)</td>
        </tr>
    `;

    tbody.innerHTML = html;
}

async function renderSupplierComparisonMode() {
    const tbody = document.getElementById('supplier-compare-mode-tbody');
    if (!tbody) return;

    tbody.innerHTML = `<tr><td colspan="9" style="text-align: center;"><i class="fa-solid fa-spinner fa-spin"></i> กำลังโหลดข้อมูล...</td></tr>`;

    try {
        const res = await authFetch(`${API_BASE}/projects/${state.activeProjectId}/items`);
        if (!res.ok) {
            throw new Error('Failed to fetch project items for comparison');
        }
        const items = await res.json();
        
        if (items.length === 0) {
            tbody.innerHTML = `<tr><td colspan="9" style="text-align: center;" data-i18n="compare_no_data">ไม่มีข้อมูลสำหรับแสดงผล</td></tr>`;
            return;
        }

        let html = '';
        let totalBidMat = 0;
        let totalSupplierMat = 0;

        items.forEach(item => {
            const qty = parseFloat(item.qty) || 0;
            const factor = 1 - (parseFloat(item.discount) || 0) / 100;
            const bidUnit = parseFloat(item.price_material) || 0;
            const bidTotal = bidUnit * qty * factor;
            
            const supplierUnit = parseFloat(item.supplier_price) || 0;
            const supplierTotal = supplierUnit * qty;

            const diff = bidTotal - supplierTotal;
            const marginPercent = supplierTotal > 0 ? (diff / supplierTotal) * 100 : 0;

            totalBidMat += bidTotal;
            totalSupplierMat += supplierTotal;

            html += `
                <tr style="transition: background-color 0.2s; cursor: default;" onmouseover="this.style.backgroundColor='#f8fafc'" onmouseout="this.style.backgroundColor='transparent'">
                    <td style="padding: 14px 16px; vertical-align: middle;">
                        <span style="background-color: #f1f5f9; color: #475569; padding: 4px 10px; border-radius: 4px; font-size: 0.8rem; font-weight: 600; display: inline-block;">
                            ${escapeHtml(item.section_name)}
                        </span>
                    </td>
                    <td style="padding: 14px 16px; vertical-align: middle;">
                        <div>
                            <div style="font-weight: 600; color: var(--text-main); font-size: 0.9rem;">${escapeHtml(item.description)}</div>
                            ${item.brand ? `<div style="font-size: 0.75rem; color: var(--text-muted); margin-top: 4px; display: flex; align-items: center; gap: 6px;">
                                <span style="background: #e0f2fe; color: #0369a1; padding: 1px 6px; border-radius: 3px; font-weight: 500;">${escapeHtml(item.brand)}</span> 
                                ${item.model ? `<span style="font-family: monospace; color: #64748b;">Model: ${escapeHtml(item.model)}</span>` : ''}
                            </div>` : ''}
                        </div>
                    </td>
                    <td class="text-right" style="padding: 14px 16px; vertical-align: middle; font-weight: 600;">
                        ${qty} <small style="color: var(--text-muted); font-weight: normal;">${escapeHtml(item.unit || 'ea')}</small>
                    </td>
                    <td class="text-right" style="padding: 14px 16px; vertical-align: middle; font-weight: 500; color: #64748b;">${formatCurrency(bidUnit)}</td>
                    <td class="text-right" style="padding: 14px 16px; vertical-align: middle; font-weight: 600; color: #0f172a;">${formatCurrency(bidTotal)}</td>
                    <td class="text-right" style="padding: 14px 16px; vertical-align: middle; font-weight: 500; color: #64748b;">${formatCurrency(supplierUnit)}</td>
                    <td class="text-right" style="padding: 14px 16px; vertical-align: middle; font-weight: 600; color: #1e293b;">${formatCurrency(supplierTotal)}</td>
                    <td class="text-right" style="padding: 14px 16px; vertical-align: middle;">
                        <span style="display: inline-block; padding: 4px 10px; border-radius: 9999px; font-size: 0.8rem; font-weight: 600; ${diff >= 0 ? 'background-color: #ecfdf5; color: #047857;' : 'background-color: #fef2f2; color: #b91c1c;'}">
                            ${diff >= 0 ? '+' : ''}${formatCurrency(diff)}
                        </span>
                    </td>
                    <td class="text-right" style="padding: 14px 16px; vertical-align: middle;">
                        <span style="display: inline-block; padding: 4px 10px; border-radius: 9999px; font-size: 0.8rem; font-weight: 600; ${diff >= 0 ? 'background-color: #ecfdf5; color: #047857;' : 'background-color: #fef2f2; color: #b91c1c;'}">
                            ${marginPercent.toFixed(2)}%
                        </span>
                    </td>
                </tr>
            `;
        });

        // Add summary row
        const totalDiff = totalBidMat - totalSupplierMat;
        const totalMarginPercent = totalSupplierMat > 0 ? (totalDiff / totalSupplierMat) * 100 : 0;

        // Update cards content
        const totalBidEl = document.getElementById('supplier-compare-total-bid');
        const totalSupplierEl = document.getElementById('supplier-compare-total-supplier');
        const totalProfitEl = document.getElementById('supplier-compare-total-profit');
        const profitCard = document.getElementById('supplier-compare-profit-card');
        const profitIconWrapper = document.getElementById('supplier-compare-profit-icon-wrapper');
        const profitIcon = document.getElementById('supplier-compare-profit-icon');

        if (totalBidEl) totalBidEl.innerText = formatCurrency(totalBidMat) + ' ฿';
        if (totalSupplierEl) totalSupplierEl.innerText = formatCurrency(totalSupplierMat) + ' ฿';
        if (totalProfitEl) {
            totalProfitEl.innerText = `${totalDiff >= 0 ? '+' : ''}${formatCurrency(totalDiff)} ฿ (${totalMarginPercent.toFixed(2)}%)`;
        }

        // Color coding the profit card based on performance
        if (profitCard && profitIconWrapper && profitIcon) {
            if (totalDiff >= 0) {
                profitCard.style.background = 'linear-gradient(135deg, #f0fdfa 0%, #ccfbf1 100%)';
                profitCard.style.borderColor = '#99f6e4';
                profitIconWrapper.style.backgroundColor = '#0d9488';
                profitIcon.className = 'fa-solid fa-chart-line';
            } else {
                profitCard.style.background = 'linear-gradient(135deg, #fff5f5 0%, #fed7d7 100%)';
                profitCard.style.borderColor = '#feb2b2';
                profitIconWrapper.style.backgroundColor = '#e53e3e';
                profitIcon.className = 'fa-solid fa-chart-line';
            }
        }

        html += `
            <tr style="background-color: #f8fafc; border-top: 2px solid var(--border-color); font-weight: 700; font-size: 0.95rem;">
                <td colspan="2" style="padding: 16px; color: var(--text-main);">รวมทั้งสิ้น (Total Summary)</td>
                <td class="text-right" style="padding: 16px;">-</td>
                <td class="text-right" style="padding: 16px;">-</td>
                <td class="text-right" style="padding: 16px; color: #0f172a; font-size: 1.05rem;">${formatCurrency(totalBidMat)}</td>
                <td class="text-right" style="padding: 16px;">-</td>
                <td class="text-right" style="padding: 16px; color: #1e293b; font-size: 1.05rem;">${formatCurrency(totalSupplierMat)}</td>
                <td class="text-right" style="padding: 16px;">
                    <span style="display: inline-block; padding: 6px 12px; border-radius: 9999px; font-size: 0.85rem; font-weight: 700; ${totalDiff >= 0 ? 'background-color: #ecfdf5; color: #047857;' : 'background-color: #fef2f2; color: #b91c1c;'}">
                        ${totalDiff >= 0 ? '+' : ''}${formatCurrency(totalDiff)}
                    </span>
                </td>
                <td class="text-right" style="padding: 16px;">
                    <span style="display: inline-block; padding: 6px 12px; border-radius: 9999px; font-size: 0.85rem; font-weight: 700; ${totalDiff >= 0 ? 'background-color: #ecfdf5; color: #047857;' : 'background-color: #fef2f2; color: #b91c1c;'}">
                        ${totalMarginPercent.toFixed(2)}%
                    </span>
                </td>
            </tr>
        `;

        tbody.innerHTML = html;
    } catch (err) {
        console.error(err);
        tbody.innerHTML = `<tr><td colspan="9" style="text-align: center; color: var(--danger);">เกิดข้อผิดพลาดในการโหลดข้อมูล</td></tr>`;
    }
}

function showGlobalSpinner(text = null) {
    const el = document.getElementById('global-loading-spinner');
    if (el) {
        const textEl = document.getElementById('global-spinner-text');
        if (textEl) {
            textEl.textContent = text || (state.currentLanguage === 'en' ? 'Processing...' : 'กำลังประมวลผล...');
        }
        el.style.display = 'flex';
    }
}

function hideGlobalSpinner() {
    const el = document.getElementById('global-loading-spinner');
    if (el) {
        el.style.display = 'none';
    }
}

window.showGlobalSpinner = showGlobalSpinner;
window.hideGlobalSpinner = hideGlobalSpinner;



// ==========================================
// Mobile Bottom Navigation & Responsive Tables Autolabelling
// ==========================================
document.addEventListener('DOMContentLoaded', () => {
    // 1. Mobile Bottom Navigation Event Bindings
    const mobileTabs = {
        'mobile-tab-project': 'btn-project-selector',
        'mobile-tab-catalog': 'btn-open-catalog-manager',
        'mobile-tab-supplier': 'btn-open-supplier-manager',
        'mobile-tab-template': 'btn-open-template-manager'
    };

    Object.entries(mobileTabs).forEach(([tabId, triggerId]) => {
        const tabBtn = document.getElementById(tabId);
        if (tabBtn) {
            tabBtn.addEventListener('click', (e) => {
                e.preventDefault();
                // Remove active class from all tabs
                document.querySelectorAll('.mobile-bottom-tab-bar .tab-item').forEach(btn => btn.classList.remove('active'));
                // Add active class to clicked tab
                tabBtn.classList.add('active');
                
                const triggerBtn = document.getElementById(triggerId);
                if (triggerBtn) {
                    triggerBtn.click();
                }
            });
        }
    });

    // 2. Active Tab State Synchronization based on Modal state
    const modals = [
        { id: 'modal-catalog-manager', tabId: 'mobile-tab-catalog' },
        { id: 'modal-supplier-manager', tabId: 'mobile-tab-supplier' },
        { id: 'modal-template-manager', tabId: 'mobile-tab-template' }
    ];

    const observer = new MutationObserver(() => {
        let activeTab = 'mobile-tab-project'; // fallback to project selector
        
        for (const modal of modals) {
            const el = document.getElementById(modal.id);
            if (el && el.classList.contains('active')) {
                activeTab = modal.tabId;
                break;
            }
        }
        
        document.querySelectorAll('.mobile-bottom-tab-bar .tab-item').forEach(btn => {
            if (btn.id === activeTab) {
                btn.classList.add('active');
            } else {
                btn.classList.remove('active');
            }
        });
    });

    modals.forEach(m => {
        const el = document.getElementById(m.id);
        if (el) {
            observer.observe(el, { attributes: true, attributeFilter: ['class'] });
        }
    });
});

// 3. Automatic Table Data Label Injector for Stacked Responsive Tables
const tableObserver = new MutationObserver((mutations) => {
    let shouldUpdate = false;
    for (const mutation of mutations) {
        if (mutation.addedNodes.length > 0) {
            for (const node of mutation.addedNodes) {
                if (node.nodeName === 'TABLE' || (node.querySelector && node.querySelector('table')) || node.nodeName === 'TR' || node.nodeName === 'TBODY') {
                    shouldUpdate = true;
                    break;
                }
            }
        }
        if (shouldUpdate) break;
    }
    if (shouldUpdate) {
        document.querySelectorAll('table').forEach(table => {
            const headers = Array.from(table.querySelectorAll('thead th')).map(th => th.textContent.trim());
            if (headers.length === 0) return;
            table.querySelectorAll('tbody tr').forEach(tr => {
                tr.querySelectorAll('td').forEach((td, index) => {
                    const headerText = headers[index];
                    if (headerText && !td.getAttribute('data-label')) {
                        td.setAttribute('data-label', headerText);
                    }
                });
            });
        });
    }
});
tableObserver.observe(document.body, { childList: true, subtree: true });