"""
Anonymous Apex code templates for CloudSense operations.

Each template is a Python string constant with placeholders (e.g. {TEMPLATE_NAME})
that get substituted at runtime before being piped to `sf apex run --file -`.

Output convention: use System.debug(LoggingLevel.ERROR, '###MARKER###data')
so the Python-side ApexResult parser can extract structured output from the log.
"""

EXPORT_SINGLE_TEMPLATE = """\
String templateName = '{TEMPLATE_NAME}';
try {
    List<CSPOFA.ProcessTemplateExportRequest> reqs = new List<CSPOFA.ProcessTemplateExportRequest>{
        new CSPOFA.ProcessTemplateExportRequest()
            .templateName(templateName)
            .format(CSPOFA.SerializationFormat.JSON)
    };
    List<CSPOFA.ApiResult> results = CSPOFA.API_V1.processTemplates.export(reqs);
    for (CSPOFA.ApiResult result : results) {
        if (result.isSuccess()) {
            String jsonStr = (String) result.getResource();
            Integer chunkSize = 1500;
            Integer chunkIdx = 0;
            for (Integer i = 0; i < jsonStr.length(); i += chunkSize) {
                Integer endIdx = Math.min(i + chunkSize, jsonStr.length());
                System.debug(LoggingLevel.ERROR, '###CHUNK_' + chunkIdx + '###' + jsonStr.substring(i, endIdx));
                chunkIdx++;
            }
        } else {
            System.debug(LoggingLevel.ERROR, '###ERROR###' + result.getErrors());
        }
    }
} catch (Exception ex) {
    System.debug(LoggingLevel.ERROR, '###ERROR###' + ex.getMessage() + ' | ' + ex.getStackTraceString());
}
"""


def build_export_apex(template_name: str) -> str:
    """Build Apex code to export a single orchestration template."""
    safe_name = template_name.replace("'", "\\'")
    return EXPORT_SINGLE_TEMPLATE.replace("{TEMPLATE_NAME}", safe_name)


SAVEPOINT_WRAPPER = """\
Savepoint sp = Database.setSavepoint();
try {
{APEX_BODY}
} finally {
    Database.rollbackToSavepoint(sp);
}
"""

NO_SAVEPOINT_WRAPPER = """\
{APEX_BODY}
"""


def wrap_with_savepoint(apex_code: str, allow_dml: bool = False) -> str:
    """Wrap Apex code in a savepoint for read-only safety, unless allow_dml is True."""
    indented = "\n".join("    " + line for line in apex_code.splitlines())
    if allow_dml:
        return NO_SAVEPOINT_WRAPPER.replace("{APEX_BODY}", apex_code)
    return SAVEPOINT_WRAPPER.replace("{APEX_BODY}", indented)
