function beforeTaskSave(colleagueId, nextSequenceId, userList) {
    var FORCE_EMAIL_DESTINATION = "";
    var currentState = parseInt(getValue("WKCurrentState"), 10);
    var nextState = parseInt(nextSequenceId, 10);

    try {
        // Roteamento para loja na entrada da atividade "Validar Planograma" (task5).
        // Usa prioridade: destinoLojaId (colleagueId) -> destinoLoja (login).
        if (nextState === 5) {
            atribuiResponsavelLoja(userList);
        }
    } catch (eAssign) {
        log.error("[checklist][atribuicao] Falha ao atribuir responsavel da loja: " + eAssign);
        throw eAssign;
    }

    // Notificacao por email so quando sai da atividade de analise (task5).
    if (currentState !== 5) {
        return;
    }

    try {
        var saidaAnalise = (hAPI.getCardValue("saidaAnalise") || "").trim();
        var usuarioRetorno = (hAPI.getCardValue("usuarioRetorno") || "").trim();
        var destino = String(FORCE_EMAIL_DESTINATION || "").trim();
        var usuarioDestino = "";
        if (!destino) {
            usuarioDestino = usuarioRetorno || String(colleagueId || getValue("WKUser") || "").trim();
            destino = resolveEmailByColleagueId(usuarioDestino);
        }

        log.info("[checklist][notificacao] saidaAnalise=" + saidaAnalise
            + ", usuarioRetorno=" + usuarioRetorno
            + ", colleagueId=" + colleagueId
            + ", usuarioDestino=" + usuarioDestino
            + ", destinoFinal=" + destino
            + ", nextState=" + nextState);

        if (!destino) {
            log.warn("[checklist][notificacao] Usuario destino nao informado.");
            return;
        }

        if (!isValidEmail(destino)) {
            log.warn("[checklist][notificacao] Email de destino invalido: " + destino);
            return;
        }

        if (nextState === 9 || saidaAnalise === "NAO_CONFORME") {
            notificaPorTemplate("CHECKLIST_NAO_CONFORME", destino);
            return;
        }

        if (nextState === 11 || saidaAnalise === "CONFORME") {
            notificaPorTemplate("CHECKLIST_CONFORME", destino);
        }
    } catch (e) {
        log.error("[checklist][notificacao] Falha ao disparar notificacao: " + e);
    }
}

function atribuiResponsavelLoja(userList) {
    var destinoLojaId = String(hAPI.getCardValue("destinoLojaId") || "").trim();
    var destinoLojaLogin = String(hAPI.getCardValue("destinoLoja") || "").trim();
    var colleagueId = "";

    if (destinoLojaId && existsActiveUserByColleagueId(destinoLojaId)) {
        colleagueId = destinoLojaId;
    }

    if (!colleagueId && destinoLojaLogin) {
        colleagueId = resolveColleagueIdByLogin(destinoLojaLogin);
    }

    if (!colleagueId) {
        throw "Preencha uma loja valida. destinoLojaId/destinoLoja nao encontrado no colleague ativo.";
    }

    userList.clear();
    userList.add(colleagueId);
    hAPI.setCardValue("destinoLojaId", colleagueId);

    log.info("[checklist][atribuicao] Responsavel definido. destinoLojaId=" + destinoLojaId
        + ", destinoLoja=" + destinoLojaLogin
        + ", colleagueIdFinal=" + colleagueId);
}

function notificaPorTemplate(templateCode, destinatario) {
    var NOTIFIER_SENDER_USER = "admin";
    var recipients = new java.util.ArrayList();
    recipients.add(destinatario);

    var parametros = new java.util.HashMap();
    parametros.put("numeroSolicitacao", String(getValue("WKNumProces") || ""));
    parametros.put("qtdNaoConforme", String(hAPI.getCardValue("qtdNaoConforme") || "0"));
    parametros.put("listaNaoConforme", String(hAPI.getCardValue("listaNaoConforme") || ""));
    parametros.put("loja", String(hAPI.getCardValue("loja") || ""));
    parametros.put("linkSolicitacao", montaLinkSolicitacao());

    notifier.notify(
        NOTIFIER_SENDER_USER,
        templateCode,
        parametros,
        recipients,
        "text/html"
    );

    log.info("[checklist][notificacao] Template " + templateCode + " enviado para " + destinatario);
}

function montaLinkSolicitacao() {
    var server = String(getValue("WKServerURL") || "");
    var companyId = String(getValue("WKCompany") || "");
    var processId = String(getValue("WKNumProces") || "");
    if (!server || !companyId || !processId) {
        return "";
    }
    return server
        + "/portal/p/"
        + companyId
        + "/pageworkflowview?app_ecm_workflowview_detailsProcessInstanceID="
        + processId;
}

function usuarioPossuiEmailValido(colleagueId) {
    try {
        var c1 = DatasetFactory.createConstraint("colleaguePK.colleagueId", colleagueId, colleagueId, ConstraintType.MUST);
        var c2 = DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST);
        var ds = DatasetFactory.getDataset("colleague", null, [c1, c2], null);
        if (!ds || ds.rowsCount < 1) {
            log.warn("[checklist][notificacao] Usuario nao encontrado/inativo no colleague: " + colleagueId);
            return false;
        }
        var email = String(ds.getValue(0, "mail") || "").trim();
        log.info("[checklist][notificacao] Email encontrado para " + colleagueId + ": " + email);
        return email.indexOf("@") > 0;
    } catch (e) {
        log.error("[checklist][notificacao] Erro ao validar email do usuario " + colleagueId + ": " + e);
        return false;
    }
}

function resolveEmailByColleagueId(colleagueId) {
    try {
        if (!colleagueId) {
            return "";
        }
        var ds = findColleagueByIdOrLogin(colleagueId);
        if (!ds || ds.rowsCount < 1) {
            log.warn("[checklist][notificacao] Usuario nao encontrado/inativo no colleague: " + colleagueId);
            return "";
        }
        var email = String(ds.getValue(0, "mail") || "").trim();
        log.info("[checklist][notificacao] Email encontrado para " + colleagueId + ": " + email);
        return email;
    } catch (e) {
        log.error("[checklist][notificacao] Erro ao buscar email do usuario " + colleagueId + ": " + e);
        return "";
    }
}

function isValidEmail(email) {
    var v = String(email || "").trim();
    return v.indexOf("@") > 0 && v.indexOf(".") > v.indexOf("@") + 1;
}

function existsActiveUserByColleagueId(colleagueId) {
    var ds = null;
    try {
        var c1 = DatasetFactory.createConstraint("colleaguePK.colleagueId", colleagueId, colleagueId, ConstraintType.MUST);
        var c2 = DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST);
        ds = DatasetFactory.getDataset("colleague", null, [c1, c2], null);
        return ds && ds.rowsCount > 0;
    } catch (e) {
        log.error("[checklist][atribuicao] Erro ao validar colleagueId=" + colleagueId + ": " + e);
        return false;
    }
}

function resolveColleagueIdByLogin(login) {
    try {
        var c1 = DatasetFactory.createConstraint("login", login, login, ConstraintType.MUST);
        var c2 = DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST);
        var ds = DatasetFactory.getDataset("colleague", null, [c1, c2], null);
        if (ds && ds.rowsCount > 0) {
            return String(ds.getValue(0, "colleaguePK.colleagueId") || "").trim();
        }
    } catch (e) {
        log.error("[checklist][atribuicao] Erro ao resolver colleagueId por login=" + login + ": " + e);
    }
    return "";
}

function findColleagueByIdOrLogin(value) {
    var v = String(value || "").trim();
    if (!v) return null;
    var c2 = DatasetFactory.createConstraint("active", "true", "true", ConstraintType.MUST);

    var cId = DatasetFactory.createConstraint("colleaguePK.colleagueId", v, v, ConstraintType.MUST);
    var byId = DatasetFactory.getDataset("colleague", null, [cId, c2], null);
    if (byId && byId.rowsCount > 0) return byId;

    var cLogin = DatasetFactory.createConstraint("login", v, v, ConstraintType.MUST);
    var byLogin = DatasetFactory.getDataset("colleague", null, [cLogin, c2], null);
    if (byLogin && byLogin.rowsCount > 0) return byLogin;

    return null;
}
