# AptaSelect - multi-process aptamer candidate selection
configfile: "config.yaml"

import os

OUT = config.get("output_dir", "/output").rstrip("/") or "/output"
SCRIPT = os.path.join(workflow.basedir, "scripts", "aptaselect.py")

# ---- fail early on must-fill values -----------------------------------------
_REQUIRED = ["r1", "r2", "lcr", "rcr", "max_errors", "left_marker", "right_marker",
             "left_stem", "right_stem", "random_region_length"]
_missing = [k for k in _REQUIRED if config.get(k) in (None, "")]
if _missing:
    raise ValueError("AptaSelect: please fill these config values: " + ", ".join(_missing))

FINAL = [
    f"{OUT}/stage0_raw.ranked.tsv",
    f"{OUT}/stage1_matching.ranked.tsv",
    f"{OUT}/stage2_flanking.ranked.tsv",
    f"{OUT}/stage3_random_region.ranked.tsv",
    f"{OUT}/survival_summary.tsv",
]

_WORKERS = int(config.get("workers", 0) or 0)


rule all:
    input:
        FINAL


rule aptaselect:
    """Stage 0-3 filtering and per-stage ranking. Reads are processed by a pool
    of worker processes in batches; results are merged in original read order.
    Progress is logged to logs/aptaselect.log (separate from the result files)."""
    input:
        r1=config["r1"],
        r2=config["r2"],
    output:
        FINAL,
    params:
        script=SCRIPT,
        outdir=OUT,
        lcr=config["lcr"],
        rcr=config["rcr"],
        max_errors=config["max_errors"],
        left_marker=config["left_marker"],
        right_marker=config["right_marker"],
        left_stem=config["left_stem"],
        right_stem=config["right_stem"],
        random_length=config["random_region_length"],
        progress=config.get("progress_every", 100000),
        progress_seconds=config.get("progress_seconds", 60),
        workers=_WORKERS,
        batch_size=config.get("batch_size", 2000),
    # auto mode may use up to all cores given to Snakemake; an explicit value reserves that many
    threads: _WORKERS if _WORKERS > 0 else workflow.cores
    log:
        f"{OUT}/logs/aptaselect.log",
    shell:
        "python3 {params.script} "
        "--reads {input.r1:q} {input.r2:q} "
        "--outdir {params.outdir:q} "
        "--lcr {params.lcr} --rcr {params.rcr} "
        "--max-errors {params.max_errors} "
        "--left-marker {params.left_marker} --right-marker {params.right_marker} "
        "--left-stem {params.left_stem} --right-stem {params.right_stem} "
        "--random-length {params.random_length} "
        "--progress-every {params.progress} --progress-seconds {params.progress_seconds} "
        "--workers {params.workers} --max-workers {threads} "
        "--batch-size {params.batch_size} "
        "2> {log:q}"