# patchworks Snakemake workflow.
#
#   convert ──▶ prepare (checkpoint) ──▶ segment {tile}  ──▶ merge
#                                        one GPU job per tile
#
# Run locally:
#   snakemake --cores 8 --configfile config/config.yaml
# Run on SLURM (one GPU job per tile, many GPUs in parallel):
#   snakemake --workflow-profile profile/slurm --configfile config/config.yaml

import json
from pathlib import Path

configfile: "config/config.yaml"

include: "rules/common.smk"
include: "rules/convert.smk"
include: "rules/segment.smk"
include: "rules/merge.smk"


# Runs on the submit host (has network) — never submitted to an offline GPU node.
localrules:
    fetch_model,


rule all:
    input:
        f"{RUN}/labels.done",


# Workflow-level notifications, covering what SLURM's per-job mail cannot:
# a local run with no scheduler, and a failure where the useful content is
# the step's traceback rather than the job's exit code.
onerror:
    from patchworks._notify import failing_step, log_tail, send

    # Snakemake's own log names the failing rule and the log it used. Picking
    # the most recently written step log instead gets this wrong in the most
    # common case: a `segment` failure leaves prepare.log newest among the
    # sequential steps, so the mail quoted a log that had succeeded.
    _rule, _log = failing_step(log)
    if _log is None:
        _cands = [p for p in (CONVERTLOG, OCCUPANCYLOG, PREPARELOG, MERGELOG)
                  if Path(p).exists()]
        _cands += [str(p) for p in Path(LOGS).glob("segment/*.log")]
        _log = max(_cands, key=lambda p: Path(p).stat().st_mtime, default=None)
    _what = f"rule {_rule}" if _rule else "the workflow"
    send(
        NOTIFY_EMAIL,
        f"[patchworks] FAILED: {_rule or 'workflow'} - {LABEL_NAME}",
        f"The patchworks workflow failed in {_what}.\n\n"
        f"  work_dir      : {WORK}\n"
        f"  config        : {LABEL_NAME}\n"
        f"  failing step  : {_rule or 'unknown'}\n"
        f"  step log      : {_log}\n"
        f"  snakemake log : {log}\n\n"
        + (f"Last lines of {_log}:\n\n{log_tail(_log)}\n"
           if _log else "No step log was written.\n"),
    )


onsuccess:
    if "finish" in NOTIFY_EVENTS:
        from patchworks._notify import send

        send(
            NOTIFY_EMAIL,
            f"[patchworks] done: {LABEL_NAME} in {WORK}",
            f"The patchworks workflow finished successfully.\n\n"
            f"  work_dir : {WORK}\n"
            f"  config   : {LABEL_NAME}\n"
            f"  labels   : {IMAGE}/labels/{LABEL_NAME}\n",
        )
