function defineStructure() {
    addColumn("B1_COD");
    addColumn("B1_DESC");
    addColumn("B1_UM");
    addColumn("B1_TIPO");
    addColumn("B1_LOCPAD");
    addColumn("B1_LOCALIZ");
    addColumn("B1_CONTRAT");
    addColumn("B1_PICM");
    addColumn("B1_IPI");
    addColumn("B1_RASTRO");
    addColumn("B1_MSBLQL");
    addColumn("TOTAL");
    addColumn("HORA_CONSULTA");
    addColumn("CODIGO_DESCRICAO");

    setKey(["B1_COD"]);
    addIndex(["B1_COD"]);
    addIndex(["B1_DESC"]);
}

function onSync(lastSyncDate) {
    var dataset = DatasetBuilder.newDataset();
    addDatasetColumns(dataset);

    var payload = fetchProdutos();
    var produtos = payload.produtos || [];

    log.info("[dsComprasProdutos.onSync] lastSyncDate=" + lastSyncDate + ", totalRecebido=" + produtos.length);

    for (var i = 0; i < produtos.length; i++) {
        var row = mapProdutoToRow(produtos[i], payload.total, payload.horaConsulta);
        if (typeof dataset.addOrUpdateRow === "function") {
            dataset.addOrUpdateRow(row);
        } else {
            dataset.addRow(row);
        }
    }

    return dataset;
}

function createDataset(fields, constraints, sorts) {
    var dataset = DatasetBuilder.newDataset();
    addDatasetColumns(dataset);

    var payload = fetchProdutos();
    var produtos = payload.produtos || [];
    var filtro = parseConstraints(constraints);
    var count = 0;

    log.info("[dsComprasProdutos.createDataset] totalRecebido=" + produtos.length + ", search=[" + filtro.search + "], maxRows=" + filtro.maxRows);

    for (var i = 0; i < produtos.length; i++) {
        var item = produtos[i] || {};
        if (!matchProduto(item, filtro)) {
            continue;
        }

        dataset.addRow(mapProdutoToRow(item, payload.total, payload.horaConsulta));
        count++;

        if (filtro.maxRows > 0 && count >= filtro.maxRows) {
            break;
        }
    }

    log.info("[dsComprasProdutos.createDataset] totalRetornado=" + count);
    return dataset;
}

function onMobileSync(user) {
    var sortFields = ["B1_COD"];
    var constraints = [];
    var fields = [
        "B1_COD",
        "B1_DESC",
        "B1_UM",
        "B1_TIPO",
        "B1_LOCPAD",
        "B1_LOCALIZ",
        "B1_CONTRAT",
        "B1_PICM",
        "B1_IPI",
        "B1_RASTRO",
        "B1_MSBLQL",
        "TOTAL",
        "HORA_CONSULTA",
        "CODIGO_DESCRICAO"
    ];

    return {
        fields: fields,
        constraints: constraints,
        sortFields: sortFields
    };
}

function addDatasetColumns(dataset) {
    dataset.addColumn("B1_COD");
    dataset.addColumn("B1_DESC");
    dataset.addColumn("B1_UM");
    dataset.addColumn("B1_TIPO");
    dataset.addColumn("B1_LOCPAD");
    dataset.addColumn("B1_LOCALIZ");
    dataset.addColumn("B1_CONTRAT");
    dataset.addColumn("B1_PICM");
    dataset.addColumn("B1_IPI");
    dataset.addColumn("B1_RASTRO");
    dataset.addColumn("B1_MSBLQL");
    dataset.addColumn("TOTAL");
    dataset.addColumn("HORA_CONSULTA");
    dataset.addColumn("CODIGO_DESCRICAO");
}

function mapProdutoToRow(item, total, horaConsulta) {
    var codigo = trim(item["B1_COD"]);
    var descricao = trim(item["B1_DESC"]);

    return [
        codigo,
        descricao,
        trim(item["B1_UM"]),
        trim(item["B1_TIPO"]),
        trim(item["B1_LOCPAD"]),
        trim(item["B1_LOCALIZ"]),
        trim(item["B1_CONTRAT"]),
        trim(item["B1_PICM"]),
        trim(item["B1_IPI"]),
        trim(item["B1_RASTRO"]),
        trim(item["B1_MSBLQL"]),
        trim(total),
        trim(horaConsulta),
        codigo + " - " + descricao
    ];
}

function fetchProdutos() {
    var response = {
        total: "",
        horaConsulta: "",
        produtos: []
    };

    try {
        var clientService = fluigAPI.getAuthorizeClientService();
        var endpoints = [
            "/rest/uf_mata010/",
            "/rest/uf_mata010",
            "https://rest.grupoginseng.com.br/rest/uf_mata010/",
            "https://rest.grupoginseng.com.br/rest/uf_mata010",
            "/",
            ""
        ];

        var lastStatus = "";
        var lastRetorno = "";

        for (var i = 0; i < endpoints.length; i++) {
            var endpoint = endpoints[i];
            var apiResp = invokePostprod(clientService, endpoint);
            var statusHttp = apiResp.status;
            var retorno = apiResp.body;

            lastStatus = statusHttp;
            lastRetorno = retorno;

            log.info("[dsComprasProdutos] endpoint=[" + endpoint + "], HTTP status=" + statusHttp);

            if (!retorno) {
                continue;
            }

            var obj = parseApiResponseObject(retorno);
            if (!obj || !(obj.produtos instanceof Array)) {
                continue;
            }

            response.total = obj.total != null ? String(obj.total) : "";
            response.horaConsulta = obj.hora_consulta != null ? String(obj.hora_consulta) : "";
            response.produtos = obj.produtos;

            log.info("[dsComprasProdutos] endpointOK=[" + endpoint + "], total=" + response.total + ", produtos=" + response.produtos.length + ", hora_consulta=" + response.horaConsulta);
            return response;
        }

        var preview = trim(lastRetorno);
        if (preview.length > 220) {
            preview = preview.substring(0, 220) + "...";
        }
        log.error("[dsComprasProdutos] Nenhum endpoint retornou JSON válido. UltimoStatus=" + lastStatus + ", ultimoRetornoPreview=[" + preview + "]");
    } catch (e) {
        log.error("[dsComprasProdutos] Erro ao consultar API Postprod: " + e);
    }

    return response;
}

function invokePostprod(clientService, endpoint) {
    var data = {
        companyId: String(getValue("WKCompany") || "1"),
        serviceCode: "Postprod",
        endpoint: endpoint,
        method: "get",
        timeoutService: "60000",
        params: {}
    };

    try {
        var vo = clientService.invoke(JSON.stringify(data));
        return {
            status: vo ? String(vo.getHttpStatusResult() || "") : "",
            body: vo ? String(vo.getResult() || "") : ""
        };
    } catch (e) {
        return {
            status: "EXCEPTION",
            body: String(e)
        };
    }
}

function parseConstraints(constraints) {
    var out = {
        codigo: "",
        descricao: "",
        bloqueado: "",
        search: "",
        maxRows: 0
    };

    if (!constraints) return out;

    for (var i = 0; i < constraints.length; i++) {
        var c = constraints[i];
        if (!c || !c.fieldName) continue;

        var name = String(c.fieldName || "").toUpperCase();
        var value = trim(c.initialValue);

        if (name === "B1_COD" && value) {
            out.codigo = cleanSearchValue(value);
            continue;
        }
        if (name === "B1_DESC" && value) {
            out.descricao = cleanSearchValue(value);
            continue;
        }
        if (name === "B1_MSBLQL" && value) {
            out.bloqueado = cleanSearchValue(value);
            continue;
        }
        if ((name === "SEARCH" || name === "TERMO" || name === "FILTRO") && value) {
            out.search = cleanSearchValue(value);
            continue;
        }
        if (name === "SQLLIMIT" || name === "RESULTLIMIT") {
            var n = parseInt(value, 10);
            if (!isNaN(n) && n > 0) out.maxRows = n;
            continue;
        }
    }

    return out;
}

function matchProduto(item, filtro) {
    var codigo = trim(item["B1_COD"]);
    var descricao = trim(item["B1_DESC"]);
    var um = trim(item["B1_UM"]);
    var bloqueado = trim(item["B1_MSBLQL"]);

    if (filtro.codigo && codigo !== filtro.codigo) {
        return false;
    }
    if (filtro.descricao && normalize(descricao).indexOf(normalize(filtro.descricao)) === -1) {
        return false;
    }
    if (filtro.bloqueado && bloqueado !== filtro.bloqueado) {
        return false;
    }

    if (filtro.search) {
        var blob = normalize([codigo, descricao, um, bloqueado].join(" "));
        if (blob.indexOf(normalize(filtro.search)) === -1) {
            return false;
        }
    }

    return true;
}

function parseJsonSafe(text) {
    try {
        return JSON.parse(text);
    } catch (e) {
        return null;
    }
}

function parseApiResponseObject(rawText) {
    var root = parseJsonSafe(rawText);
    if (!root) return null;

    if (root.produtos instanceof Array) {
        return root;
    }

    if (typeof root.content === "string") {
        var inner = parseJsonSafe(root.content);
        if (inner && inner.produtos instanceof Array) {
            return inner;
        }
    }

    if (root.content && root.content.produtos instanceof Array) {
        return root.content;
    }

    if (typeof root.result === "string") {
        var parsedResult = parseJsonSafe(root.result);
        if (parsedResult && parsedResult.produtos instanceof Array) {
            return parsedResult;
        }
    }

    return null;
}

function cleanSearchValue(v) {
    var s = trim(v);
    s = s.replace(/[%*_]/g, "");
    if (s === "true" || s === "false" || s === "on" || s === "off" || s === "1") {
        return "";
    }
    return trim(s);
}

function normalize(v) {
    return trim(v).toLowerCase();
}

function trim(v) {
    return String(v == null ? "" : v).trim();
}
