var PROBUM = {
    API_BASE: '',
    MAX_FILE_SIZE: 20 * 1024 * 1024,
    MAX_TOTAL_FILE_SIZE: 20 * 1024 * 1024,

    isFileTooLarge: function(file) {
        return !!file && Number(file.size) > this.MAX_FILE_SIZE;
    },

    getTotalUploadSize: function(files) {
        var total = 0;
        var items = files || [];
        for (var i = 0; i < items.length; i++) {
            var item = items[i] || {};
            var size = item.size !== undefined ? item.size : item.tamanho_bytes;
            total += Number(size) || 0;
        }
        return total;
    },

    validateUploadFiles: function(files, allowedExtensions, currentTotalSize) {
        var result = { validos: [], invalidos: [], grandes: [], excedentes: [] };
        var totalSize = Number(currentTotalSize) || 0;
        var items = files || [];

        for (var i = 0; i < items.length; i++) {
            var file = items[i];
            var name = file && file.name ? file.name : '';
            if (this.isFileTooLarge(file)) {
                result.grandes.push(name);
                continue;
            }

            var dot = name.lastIndexOf('.');
            var extension = dot > -1 ? name.substring(dot + 1).toLowerCase() : '';
            if (allowedExtensions.indexOf(extension) === -1) {
                result.invalidos.push(name);
                continue;
            }

            var size = Number(file && file.size) || 0;
            if (totalSize + size > this.MAX_TOTAL_FILE_SIZE) {
                result.excedentes.push(name);
                continue;
            }

            result.validos.push(file);
            totalSize += size;
        }
        return result;
    },

    getUploadValidationMessage: function(result, allowedLabel) {
        if (!result) return '';
        var avisos = [];
        if (result.grandes.length > 0) {
            avisos.push((result.grandes.length > 1 ? 'Arquivos acima de 20 MB: ' : 'Arquivo acima de 20 MB: ') + result.grandes.join(', ') + '.');
        }
        if (result.excedentes.length > 0) {
            avisos.push((result.excedentes.length > 1 ? 'Arquivos que excedem o limite total de 20 MB: ' : 'Arquivo que excede o limite total de 20 MB: ') + result.excedentes.join(', ') + '.');
        }
        if (result.invalidos.length > 0) {
            avisos.push((result.invalidos.length > 1 ? 'Formatos não permitidos: ' : 'Formato não permitido: ') + result.invalidos.join(', ') + '. Aceitos: ' + allowedLabel + '.');
        }
        return avisos.join(' ');
    },

    tableSkeletonRows: function(columns, count) {
        var rows = '';
        var widths = ['82%', '64%', '74%', '48%', '68%', '56%'];
        var totalColumns = Number(columns) || 1;
        var totalRows = Number(count) || 4;
        var i;
        var j;
        for (i = 0; i < totalRows; i++) {
            rows += '<tr aria-hidden="true">';
            for (j = 0; j < totalColumns; j++) rows += '<td class="table-skeleton-cell"><span class="table-skeleton-line skeleton-shimmer" style="width:' + widths[j % widths.length] + '"></span></td>';
            rows += '</tr>';
        }
        return rows;
    },

    _isAuthUrl: function(url) {
        return url.indexOf('/api/auth/login') === 0
            || url.indexOf('/api/auth/logout') === 0
            || url.indexOf('/api/profiles/me') === 0;
    },

    _handleAuth: function(url, xhr) {
        if (xhr.status === 401 && !this._isAuthUrl(url)) {
            window.location.href = '/login';
            return true;
        }
        return false;
    },

    _request: function(method, url, body, callback) {
        var xhr = new XMLHttpRequest();
        xhr.open(method, this.API_BASE + url, true);
        if (body !== null) {
            xhr.setRequestHeader('Content-Type', 'application/json');
        }
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (PROBUM._handleAuth(url, xhr)) return;
                callback(xhr);
            }
        };
        xhr.send(body !== null ? JSON.stringify(body) : null);
    },

    checkAuth: function(callback) {
        this._request('GET', '/api/profiles/me', null, function(xhr) {
            if (xhr.status === 200) {
                try {
                    var user = JSON.parse(xhr.responseText);
                    if (callback) callback(null, user);
                } catch (e) {
                    if (callback) callback(e, null);
                }
            } else {
                if (callback) callback(new Error('Nao autenticado'), null);
            }
        });
    },

    login: function(email, password, callback) {
        this._request('POST', '/api/auth/login', { email: email, password: password }, function(xhr) {
            try {
                var data = JSON.parse(xhr.responseText);
                if (callback) callback(data);
            } catch (e) {
                if (callback) callback({ success: false, error: 'Erro de conexao' });
            }
        });
    },

    logout: function() {
        this._request('POST', '/api/auth/logout', null, function() {
            window.location.href = '/login';
        });
    },

    showLoading: function(btn) {
        btn.disabled = true;
        btn._originalText = btn.textContent;
        btn.textContent = 'Carregando...';
    },

    hideLoading: function(btn) {
        btn.disabled = false;
        if (btn._originalText) btn.textContent = btn._originalText;
    },

    showError: function(element, message) {
        element.textContent = message;
        element.className = element.className + ' show';
    },

    hideError: function(element) {
        element.className = element.className.replace(/\bshow\b/g, '').trim();
    },

    getRoleLabel: function(papel) {
        var roles = {
            'admin_sistema': 'Admin do Sistema',
            'manager': 'Gestor da Organização',
            'auditor': 'Auditor'
        };
        return roles[papel] || papel;
    },

    createPedido: function(fields, files, callback) {
        var fd = new FormData();
        for (var key in fields) {
            if (fields.hasOwnProperty(key) && fields[key] !== null && fields[key] !== undefined) {
                fd.append(key, fields[key]);
            }
        }
        for (var i = 0; i < files.length; i++) {
            fd.append('files', files[i]);
        }
        var xhr = new XMLHttpRequest();
        xhr.open('POST', this.API_BASE + '/api/pedidos/create', true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (PROBUM._handleAuth('/api/pedidos/create', xhr)) return;
                try {
                    var result = JSON.parse(xhr.responseText);
                    if (xhr.status === 201 && result.success) {
                        if (callback) callback(null, result);
                    } else {
                        if (callback) callback(new Error(result.error || 'Erro ao criar pedido'), null);
                    }
                } catch (e) {
                    if (callback) callback(e, null);
                }
            }
        };
        xhr.send(fd);
    },

    listPedidos: function(produto, filtros, callback) {
        if (typeof filtros === 'function' && !callback) {
            callback = filtros;
            filtros = {};
        }
        filtros = filtros || {};
        var qs = 'produto=' + encodeURIComponent(produto);
        if (filtros.status !== undefined && filtros.status !== null && filtros.status !== '') {
            var status = Object.prototype.toString.call(filtros.status) === '[object Array]' ? filtros.status.join(',') : filtros.status;
            qs += '&status=' + encodeURIComponent(status);
        }
        if (filtros.periodo_de) qs += '&periodo_de=' + encodeURIComponent(filtros.periodo_de);
        if (filtros.periodo_ate) qs += '&periodo_ate=' + encodeURIComponent(filtros.periodo_ate);
        if (filtros.q) qs += '&q=' + encodeURIComponent(filtros.q);
        if (filtros.sort) qs += '&sort=' + encodeURIComponent(filtros.sort);
        if (filtros.dir) qs += '&dir=' + encodeURIComponent(filtros.dir);
        if (filtros.page !== undefined && filtros.page !== null && filtros.page !== '') qs += '&page=' + encodeURIComponent(filtros.page);
        if (filtros.page_size !== undefined && filtros.page_size !== null && filtros.page_size !== '') qs += '&page_size=' + encodeURIComponent(filtros.page_size);
        this._request('GET', '/api/pedidos/list?' + qs, null, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao listar pedidos'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    getPedidoStats: function(produto, callback) {
        var qs = produto ? '?produto=' + encodeURIComponent(produto) : '';
        this._request('GET', '/api/pedidos/stats' + qs, null, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao carregar estatisticas'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    createPaginatedSections: function(produto, config) {
        var api = this;
        var states = config.states || {};
        var controller = {};

        function renderSortHeaders(which) {
            var state = states[which];
            var heads = document.querySelectorAll('[data-table="' + which + '"].th-sort');
            for (var i = 0; i < heads.length; i++) {
                heads[i].classList.remove('active');
                var arrow = heads[i].querySelector('.arrow');
                if (arrow) arrow.parentNode.removeChild(arrow);
            }
            if (state.sortKey) {
                for (var j = 0; j < heads.length; j++) {
                    if (heads[j].getAttribute('data-sort-key') === state.sortKey) {
                        heads[j].classList.add('active');
                        var s = document.createElement('span');
                        s.className = 'arrow';
                        s.textContent = (state.sortDir === 1) ? '▲' : '▼';
                        heads[j].appendChild(s);
                        break;
                    }
                }
            }
        }

        function renderPagination(which) {
            var state = states[which];
            var el = document.getElementById(state.pagination);
            if (!el) return;
            var inicio = state.total > 0 ? ((state.page - 1) * state.pageSize) + 1 : 0;
            var fim = Math.min(state.page * state.pageSize, state.total);
            var anteriorDisabled = state.page <= 1 ? ' disabled' : '';
            var proximaDisabled = state.page >= state.pages ? ' disabled' : '';
            var vazio = state.buscaAtual ? 'Nenhum resultado encontrado.' : state.vazio;
            el.innerHTML = '<span>' + (state.total > 0 ? ('Exibindo ' + inicio + '&ndash;' + fim + ' de ' + state.total) : vazio) + '</span>' +
                '<span style="display:flex;align-items:center;gap:8px;flex-wrap:wrap">' +
                '<label>Por pagina <select onchange="alterarTamanhoPagina(\'' + which + '\', this.value)" style="padding:5px 7px;border:1px solid var(--borda);border-radius:5px;font-size:12px">' +
                '<option value="25"' + (state.pageSize === 25 ? ' selected' : '') + '>25</option>' +
                '<option value="50"' + (state.pageSize === 50 ? ' selected' : '') + '>50</option>' +
                '<option value="100"' + (state.pageSize === 100 ? ' selected' : '') + '>100</option>' +
                '</select></label>' +
                '<button class="btn btn-outline" style="font-size:11px;padding:5px 9px" onclick="irPagina(\'' + which + '\',' + (state.page - 1) + ')"' + anteriorDisabled + '>&lsaquo; Anterior</button>' +
                '<span>Pagina ' + (state.pages > 0 ? state.page : 0) + ' de ' + state.pages + '</span>' +
                '<button class="btn btn-outline" style="font-size:11px;padding:5px 9px" onclick="irPagina(\'' + which + '\',' + (state.page + 1) + ')"' + proximaDisabled + '>Proxima &rsaquo;</button>' +
                '</span>';
        }

        function renderSection(which) {
            var state = states[which];
            if (!state) return;
            var input = document.getElementById(state.busca);
            var termo = input ? input.value.trim() : '';
            state.buscaAtual = termo;
            var requestId = ++state.requestId;
            var colspan = config.colspan(which);
            var tbody = document.getElementById(state.tbody);
            if (tbody) tbody.innerHTML = api.tableSkeletonRows(colspan, 4);
            var filtros = {
                status: state.status,
                page: state.page,
                page_size: state.pageSize,
                q: termo,
                sort: state.sortKey,
                dir: state.sortDir === 1 ? 'asc' : 'desc'
            };

            api.listPedidos(produto, filtros, function(err, data) {
                if (requestId !== state.requestId) return;
                if (err) {
                    if (tbody) tbody.innerHTML = '<tr><td colspan="' + colspan + '" class="empty-cell">Não foi possível carregar os dados.</td></tr>';
                    if (config.onError) config.onError(err, which);
                    return;
                }
                state.pedidos = (data && data.pedidos) ? data.pedidos : [];
                state.total = Number(data && data.total) || 0;
                state.pages = Number(data && data.pages) || 0;
                if (state.pages > 0 && state.page > state.pages) {
                    state.page = state.pages;
                    renderSection(which);
                    return;
                }
                if (state.pages === 0) state.page = 1;
                var rows = config.renderRows(which, state.pedidos, state);
                var vazio = state.buscaAtual ? 'Nenhum resultado encontrado.' : state.vazio;
                if (tbody) tbody.innerHTML = rows || '<tr><td colspan="' + colspan + '" style="text-align:center;color:var(--cinza);padding:18px">' + vazio + '</td></tr>';
                renderSortHeaders(which);
                renderPagination(which);
            });
        }

        controller.render = function() {
            for (var which in states) {
                if (states.hasOwnProperty(which)) renderSection(which);
            }
        };

        controller.buscar = function(which) {
            var state = states[which];
            if (!state) return;
            if (state.timer) clearTimeout(state.timer);
            state.timer = setTimeout(function() {
                state.timer = null;
                state.page = 1;
                renderSection(which);
            }, 300);
        };

        controller.sort = function(which, key) {
            var state = states[which];
            if (!state) return;
            if (state.sortKey === key) state.sortDir = -state.sortDir;
            else { state.sortKey = key; state.sortDir = 1; }
            state.page = 1;
            renderSection(which);
        };

        controller.pagina = function(which, page) {
            var state = states[which];
            var destino = parseInt(page, 10);
            if (!state || isNaN(destino) || destino < 1 || destino > state.pages || destino === state.page) return;
            state.page = destino;
            renderSection(which);
        };

        controller.tamanho = function(which, pageSize) {
            var state = states[which];
            var tamanho = parseInt(pageSize, 10);
            if (!state) return;
            if (tamanho !== 25 && tamanho !== 50 && tamanho !== 100) tamanho = 25;
            state.pageSize = tamanho;
            state.page = 1;
            renderSection(which);
        };

        return controller;
    },

    requestPendencia: function(id, observacao, callback) {
        this._request('POST', '/api/pedidos/' + encodeURIComponent(id) + '/pendencia', { observacao: observacao }, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao solicitar pendencia'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    resolvePendencia: function(id, resposta, files, callback) {
        var fd = new FormData();
        fd.append('resposta', resposta || '');
        for (var i = 0; i < files.length; i++) {
            fd.append('new_files', files[i]);
        }
        var xhr = new XMLHttpRequest();
        xhr.open('POST', this.API_BASE + '/api/pedidos/' + encodeURIComponent(id) + '/pendencia/resolver', true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (PROBUM._handleAuth('/api/pedidos/' + id + '/pendencia/resolver', xhr)) return;
                try {
                    var result = JSON.parse(xhr.responseText);
                    if (xhr.status === 200 && result.success) {
                        if (callback) callback(null, result);
                    } else {
                        if (callback) callback(new Error(result.error || 'Erro ao resolver pendencia'), null);
                    }
                } catch (e) {
                    if (callback) callback(e, null);
                }
            }
        };
        xhr.send(fd);
    },


    getPedido: function(id, callback) {
        this._request('GET', '/api/pedidos/' + encodeURIComponent(id), null, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao buscar pedido'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    updatePedido: function(id, fields, callback) {
        this._request('PUT', '/api/pedidos/' + encodeURIComponent(id), fields, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao atualizar pedido'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    deletePedido: function(id, callback) {
        this._request('DELETE', '/api/pedidos/' + encodeURIComponent(id), null, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao excluir pedido'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    advanceStatus: function(id, callback) {
        this._request('POST', '/api/pedidos/' + encodeURIComponent(id) + '/status', { action: 'advance' }, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao avancar status'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    denyPedido: function(id, motivo, callback) {
        if (typeof motivo === 'function') { callback = motivo; motivo = null; }
        var payload = { action: 'deny' };
        if (motivo) payload.motivo = motivo;
        this._request('POST', '/api/pedidos/' + encodeURIComponent(id) + '/status', payload, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao negar pedido'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    setConteudo: function(id, conteudo, callback) {
        this._request('POST', '/api/pedidos/' + encodeURIComponent(id) + '/conteudo', { conteudo_entrega: conteudo }, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao salvar conteudo'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    uploadAnexos: function(pedidoId, files, tipo, callback) {
        if (typeof tipo === 'function') { callback = tipo; tipo = 'pedido'; }
        var fd = new FormData();
        fd.append('pedido_id', pedidoId);
        if (tipo) fd.append('tipo', tipo);
        for (var i = 0; i < files.length; i++) {
            fd.append('files', files[i]);
        }
        var xhr = new XMLHttpRequest();
        xhr.open('POST', this.API_BASE + '/api/pedidos/' + encodeURIComponent(pedidoId) + '/anexos', true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (PROBUM._handleAuth('/api/pedidos/' + pedidoId + '/anexos', xhr)) return;
                try {
                    var result = JSON.parse(xhr.responseText);
                    if (callback) callback(null, result);
                } catch (e) {
                    if (callback) callback(e, null);
                }
            }
        };
        xhr.send(fd);
    },

    listAnexos: function(pedidoId, callback) {
        this._request('GET', '/api/pedidos/' + encodeURIComponent(pedidoId) + '/anexos', null, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao listar anexos'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    downloadAnexo: function(pedidoId, anexoId) {
        window.open(this.API_BASE + '/api/pedidos/' + encodeURIComponent(pedidoId) + '/anexos/' + encodeURIComponent(anexoId), '_blank');
    },

    deleteAnexo: function(pedidoId, anexoId, callback) {
        this._request('DELETE', '/api/pedidos/' + encodeURIComponent(pedidoId) + '/anexos/' + encodeURIComponent(anexoId), null, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao remover anexo'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    formatMoney: function(value) {
        if (value === null || value === undefined || value === '') return 'R$ 0,00';
        var num = Number(value);
        if (isNaN(num)) return 'R$ 0,00';
        var neg = num < 0;
        var abs = Math.abs(num);
        var intPart = Math.floor(abs);
        var cents = Math.round((abs - intPart) * 100);
        if (cents === 100) { intPart += 1; cents = 0; }
        var intStr = String(intPart).replace(/\B(?=(\d{3})+(?!\d))/g, '.');
        var centStr = (cents < 10 ? '0' : '') + cents;
        return (neg ? '-R$ ' : 'R$ ') + intStr + ',' + centStr;
    },

    formatCnpj: function(value) {
        var digits = String(value || '').replace(/\D/g, '');
        if (digits.length !== 14) return value || '';
        return digits.replace(/^(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})$/, '$1.$2.$3/$4-$5');
    },

    maskCnpjInput: function(el) {
        var digits = el.value.replace(/\D/g, '').slice(0, 14);
        var out = digits;
        if (digits.length > 12) out = digits.replace(/^(\d{2})(\d{3})(\d{3})(\d{4})(\d{0,2})$/, '$1.$2.$3/$4-$5');
        else if (digits.length > 8) out = digits.replace(/^(\d{2})(\d{3})(\d{3})(\d{0,4})$/, '$1.$2.$3/$4');
        else if (digits.length > 5) out = digits.replace(/^(\d{2})(\d{3})(\d{0,3})$/, '$1.$2.$3');
        else if (digits.length > 2) out = digits.replace(/^(\d{2})(\d{0,3})$/, '$1.$2');
        el.value = out;
    },

    parseMoney: function(str) {
        if (str === null || str === undefined) return 0;
        var s = String(str).replace(/[^\d.,\-]/g, '');
        if (s === '') return 0;
        var neg = false;
        if (s.charAt(0) === '-') { neg = true; s = s.substring(1); }
        var lastDot = s.lastIndexOf('.');
        var lastComma = s.lastIndexOf(',');
        var sep = '';
        var hasDecimal = false;
        if (lastDot > -1 && lastComma > -1) {
            sep = (lastDot > lastComma) ? ',' : '.';
            hasDecimal = true;
        } else if (lastDot > -1) {
            sep = '.';
            hasDecimal = true;
        } else if (lastComma > -1) {
            sep = ',';
            hasDecimal = true;
        }
        var intPart = s;
        var decPart = '';
        if (hasDecimal && sep) {
            var idx = Math.max(lastDot, lastComma);
            intPart = s.substring(0, idx);
            decPart = s.substring(idx + 1);
        }
        intPart = intPart.replace(/[.,]/g, '');
        var full = intPart + (decPart.length === 1 ? decPart + '0' : decPart);
        if (full === '') full = '0';
        var num = parseFloat(full) / 100;
        return neg ? -num : num;
    },

    getCategoriaTree: function(produto, callback) {
        this._request('GET', '/api/categorias/tree?produto=' + encodeURIComponent(produto), null, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao carregar categorias'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    createCategoria: function(data, callback) {
        this._request('POST', '/api/categorias/create', data, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 201 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao criar categoria'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    editCategoria: function(id, data, callback) {
        var payload = { action: 'edit' };
        for (var k in data) {
            if (data.hasOwnProperty(k)) payload[k] = data[k];
        }
        this._request('POST', '/api/categorias/' + encodeURIComponent(id), payload, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao editar categoria'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    deleteCategoria: function(id, callback) {
        this._request('POST', '/api/categorias/' + encodeURIComponent(id), { action: 'delete' }, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao desativar categoria'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    excluirCategoria: function(id, callback) {
        this._request('POST', '/api/categorias/' + encodeURIComponent(id), { action: 'excluir' }, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao excluir categoria'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    getPedidoCategorias: function(id, callback) {
        this._request('GET', '/api/pedidos/' + encodeURIComponent(id) + '/categorias', null, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao carregar categorias do pedido'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    setPedidoCategorias: function(id, categoria_ids, callback) {
        this._request('PUT', '/api/pedidos/' + encodeURIComponent(id) + '/categorias', { categoria_ids: categoria_ids }, function(xhr) {
            try {
                var result = JSON.parse(xhr.responseText);
                if (xhr.status === 200 && result.success) {
                    if (callback) callback(null, result);
                } else {
                    if (callback) callback(new Error(result.error || 'Erro ao salvar categorias'), null);
                }
            } catch (e) {
                if (callback) callback(e, null);
            }
        });
    },

    maskMoney: function(str) {
        if (!str) return '';
        var digits = String(str).replace(/\D/g, '');
        digits = digits.replace(/^0+(?=\d)/, '');
        while (digits.length < 3) digits = '0' + digits;
        var intPart = digits.substring(0, digits.length - 2);
        var cents = digits.substring(digits.length - 2);
        intPart = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, '.');
        return intPart + ',' + cents;
    },

    escapeHtml: function(value) {
        if (value === null || value === undefined) return '';
        return String(value).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
    },

    _triagemQuery: function(filters) {
        var parts = [];
        var source = filters || {};
        for (var key in source) {
            if (source.hasOwnProperty(key) && source[key] !== null && source[key] !== undefined && source[key] !== '') parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(source[key]));
        }
        return parts.length ? '?' + parts.join('&') : '';
    },

    _triagemRequest: function(method, url, body, callback, formData) {
        var xhr = new XMLHttpRequest();
        var finished = false;
        xhr.open(method, this.API_BASE + url, true);
        if (!formData && body !== null && body !== undefined) xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.onreadystatechange = function() {
            if (xhr.readyState !== 4 || finished) return;
            finished = true;
            if (PROBUM._handleAuth(url, xhr)) return;
            var data = null;
            if (xhr.responseText) {
                try { data = JSON.parse(xhr.responseText); } catch (e) { data = null; }
            }
            if (xhr.status >= 200 && xhr.status < 300 && (!data || data.success !== false)) {
                if (callback) callback(null, data || {}, xhr.status);
            } else {
                var error = new Error((data && data.error) || 'Erro ao comunicar com a Triagem.');
                error.status = xhr.status;
                error.data = data;
                if (callback) callback(error, data, xhr.status);
            }
        };
        xhr.onerror = function() {
            if (finished) return;
            finished = true;
            var error = new Error('Falha de conexão. Tente novamente.');
            error.status = 0;
            if (callback) callback(error, null, 0);
        };
        xhr.send(formData ? body : (body === null || body === undefined ? null : JSON.stringify(body)));
    },

    listOrganizacoes: function(filters, callback) { this._triagemRequest('GET','/api/organizacoes'+this._triagemQuery(filters),null,callback); },
    criarOrganizacao: function(payload, callback) { this._triagemRequest('POST','/api/organizacoes',payload,callback); },
    editarOrganizacao: function(id,payload,callback) { this._triagemRequest('PUT','/api/organizacoes/'+encodeURIComponent(id),payload,callback); },
    alterarStatusOrganizacao: function(id,payload,callback) { this._triagemRequest('POST','/api/organizacoes/'+encodeURIComponent(id)+'/status',payload,callback); },
    getOrganizacao: function(id, callback) { this._triagemRequest('GET', '/api/organizacoes/' + encodeURIComponent(id), null, callback); },
    listUsuariosOrganizacao: function(id, callback) { this._triagemRequest('GET', '/api/organizacoes/' + encodeURIComponent(id) + '/usuarios', null, callback); },
    editarUsuarioOrganizacao: function(orgId, userId, payload, callback) {
        this._triagemRequest('PUT', '/api/organizacoes/' + encodeURIComponent(orgId) + '/usuarios/' + encodeURIComponent(userId), payload, callback);
    },
    listUsuarios: function(filters,callback) { this._triagemRequest('GET','/api/usuarios'+this._triagemQuery(filters),null,callback); },
    criarUsuario: function(payload,callback) { this._triagemRequest('POST','/api/usuarios',payload,callback); },
    editarUsuario: function(id,payload,callback) { this._triagemRequest('PUT','/api/usuarios/'+encodeURIComponent(id),payload,callback); },
    alterarStatusUsuario: function(id,payload,callback) { this._triagemRequest('POST','/api/usuarios/'+encodeURIComponent(id)+'/status',payload,callback); },
    gerarSenhaTemporaria: function(id,callback) { this._triagemRequest('POST','/api/usuarios/'+encodeURIComponent(id)+'/generate-temporary-password',{},callback); },
    alterarSenha: function(payload,callback) { this._triagemRequest('POST','/api/auth/alterar-senha',payload,callback); },
    validarTrocaSenha: function(atual, nova, confirmacao) {
        if (!atual) return 'Informe a senha atual.';
        if (!nova) return 'Informe a nova senha.';
        if (nova.length < 12) return 'A nova senha deve ter pelo menos 12 caracteres.';
        if (!/[A-Z]/.test(nova) || !/[a-z]/.test(nova) || !/[0-9]/.test(nova) || !/[^A-Za-z0-9]/.test(nova)) return 'A nova senha deve ter ao menos 1 letra maiúscula, 1 minúscula, 1 número e 1 caractere especial.';
        if (nova !== confirmacao) return 'A confirmação não corresponde à nova senha.';
        if (nova === atual) return 'A nova senha deve ser diferente da senha atual.';
        return '';
    },

    getGestorDashboard: function(callback) { this._triagemRequest('GET', '/api/gestor/dashboard', null, callback); },

    getTriagemDashboard: function(callback) { this._triagemRequest('GET', '/api/triagem/dashboard', null, callback); },
    listTriagemProtocolos: function(filters, callback) {
        if (typeof filters === 'function') { callback = filters; filters = {}; }
        this._triagemRequest('GET', '/api/triagem/protocolos' + this._triagemQuery(filters), null, callback);
    },
    getTriagemProtocolo: function(id, callback) { this._triagemRequest('GET', '/api/triagem/protocolos/' + encodeURIComponent(id), null, callback); },
    editAdminProtocolContent: function(protocolId, payload, callback) {
        this._triagemRequest('POST', '/api/protocolos/' + encodeURIComponent(protocolId) + '/editar', payload, callback);
    },
    createTriagemAnalysis: function(payload, callback) { this._triagemRequest('POST', '/api/triagem/analises', payload, callback); },
    listTriagemAnalises: function(filters, callback) {
        if (typeof filters === 'function') { callback = filters; filters = {}; }
        this._triagemRequest('GET', '/api/triagem/analises' + this._triagemQuery(filters), null, callback);
    },
    getTriagemAnalysis: function(id, callback) { this._triagemRequest('GET', '/api/triagem/analises/' + encodeURIComponent(id), null, callback); },
    saveTriagemAnswer: function(id, payload, callback) { this._triagemRequest('POST', '/api/triagem/analises/' + encodeURIComponent(id) + '/respostas', payload, callback); },
    finalizeTriagemAnalysis: function(id, payload, callback) { this._triagemRequest('POST', '/api/triagem/analises/' + encodeURIComponent(id) + '/respostas', { finalizar: true, estado_versao: payload.estado_versao }, callback); },
    chooseTriagemOutput: function(id, payload, callback) { this._triagemRequest('POST', '/api/triagem/analises/' + encodeURIComponent(id) + '/saida', payload, callback); },
    cancelTriagemAnalysis: function(id, callback) { this._triagemRequest('POST', '/api/triagem/analises/' + encodeURIComponent(id) + '/cancelar', {}, callback); },
    restartTriagemAnalysis: function(id, callback) { this._triagemRequest('POST', '/api/triagem/analises/' + encodeURIComponent(id) + '/reiniciar', {}, callback); },
    selectTriagemIndicacao: function(id, payload, callback) {
        this._triagemRequest('POST', '/api/triagem/analises/' + encodeURIComponent(id) + '/indicacao', payload, callback);
    },
    listTriagemTemplates: function(filters, callback) {
        if (typeof filters === 'function') { callback = filters; filters = {}; }
        this._triagemRequest('GET', '/api/triagem/templates-genericos' + this._triagemQuery(filters), null, callback);
    },
    createTriagemTemplate: function(payload, callback) { this._triagemRequest('POST', '/api/triagem/templates-genericos', payload, callback); },
    updateTriagemTemplate: function(id, payload, callback) {
        var body = payload || {};
        body.id = id;
        this._triagemRequest('PUT', '/api/triagem/templates-genericos', body, callback);
    },
    publishTriagemTemplate: function(id, callback) { this._triagemRequest('POST', '/api/triagem/templates-genericos/' + encodeURIComponent(id) + '/publicar', {}, callback); },
    retractTriagemTemplate: function(id, callback) { this._triagemRequest('POST', '/api/triagem/templates-genericos/' + encodeURIComponent(id) + '/retirar', {}, callback); },
    deleteTriagemTemplate: function(id, callback) { this._triagemRequest('POST', '/api/triagem/templates-genericos/' + encodeURIComponent(id) + '/excluir', {}, callback); },
    listTriagemDocuments: function(filters, callback) {
        if (typeof filters === 'function') { callback = filters; filters = {}; }
        this._triagemRequest('GET', '/api/triagem/documentos' + this._triagemQuery(filters), null, callback);
    },
    getTriagemDocument: function(id, callback) { this._triagemRequest('GET', '/api/triagem/documentos/' + encodeURIComponent(id), null, callback); },
    listAdminProtocolos: function(filters, callback) {
        if (typeof filters === 'function') { callback = filters; filters = {}; }
        this._triagemRequest('GET', '/api/protocolos' + this._triagemQuery(filters), null, callback);
    },
    importAdminProtocolo: function(payload, callback) { this._triagemRequest('POST', '/api/protocolos/import', payload, callback); },
    previewTriagemParecer: function(id, payload, callback) { this._triagemRequest('POST', '/api/protocolos/' + encodeURIComponent(id) + '/preview-parecer', payload, callback); },
    publishAdminProtocolo: function(id, callback) { this._triagemRequest('POST', '/api/protocolos/' + encodeURIComponent(id) + '/publicar', {}, callback); },
    cancelAdminProtocoloPublication: function(id, callback) { this._triagemRequest('POST', '/api/protocolos/' + encodeURIComponent(id) + '/cancelar-publicacao', {}, callback); },
    listAdminDocuments: function(filters, callback) {
        if (typeof filters === 'function') { callback = filters; filters = {}; }
        this._triagemRequest('GET', '/api/triagem/documentos' + this._triagemQuery(filters), null, callback);
    },
    uploadAdminDocument: function(fields, file, callback) {
        var form = new FormData();
        var key;
        for (key in fields) if (fields.hasOwnProperty(key) && fields[key] !== null && fields[key] !== undefined) form.append(key, fields[key]);
        if (file) form.append('file', file);
        this._triagemRequest('POST', '/api/documentos', form, callback, true);
    },
    publishAdminDocument: function(id, callback) { this._triagemRequest('POST', '/api/documentos/' + encodeURIComponent(id) + '/publicar', {}, callback); },
    updateAdminDocument: function(id, payload, callback) {
        this._triagemRequest('PUT', '/api/documentos/' + encodeURIComponent(id), payload, callback);
    },
    uploadAdminDocumentVersion: function(id, fields, file, callback) {
        var form = new FormData();
        var key;
        for (key in fields) if (fields.hasOwnProperty(key) && fields[key] !== null && fields[key] !== undefined) form.append(key, fields[key]);
        if (file) form.append('file', file);
        this._triagemRequest('POST', '/api/documentos/' + encodeURIComponent(id) + '/versao', form, callback, true);
    },
    deleteAdminDocument: function(id, callback) { this._triagemRequest('POST', '/api/documentos/' + encodeURIComponent(id) + '/excluir', {}, callback); },
    listEventos: function(filters, callback) { this._triagemRequest('GET', '/api/eventos' + this._triagemQuery(filters), null, callback); }
};

