"""catpath reaction-pathway pipeline, orchestrated by Snakemake.

The DAG fans out over seeds (one job per seed -> a partial JSON), then a single
aggregate job combines them into the reaction graph + energy map.  This gives us
restart-from-failure, parallel seed execution, and a provenance record for free.

Run:
    snakemake -c4                       # all seeds + aggregate
    snakemake -c4 --dag | dot -Tpng ... # visualise the DAG
    snakemake -n                        # dry run
"""

import yaml

configfile: "workflow/config.yaml"

RUN_CFG = config["run_config"]
SEEDS = config["seeds"]
PARTIALS = config.get("partials_dir", "runs/partials")

# read name/outdir from the catpath run config (plain load; we only touch strings)
_c = yaml.safe_load(open(RUN_CFG)) or {}
NAME = _c.get("name", "run")
OUTDIR = _c.get("outdir", "runs")
SEEDS_CSV = ",".join(str(s) for s in SEEDS)


rule all:
    input:
        f"{OUTDIR}/{NAME}/results.json",
        f"{OUTDIR}/{NAME}/energy_map.png",
        f"{OUTDIR}/{NAME}/graph.png",


rule seed:
    """One seed -> one partial JSON (the fan-out unit)."""
    output:
        f"{PARTIALS}/{NAME}.seed{{seed}}.json",
    shell:
        "catpath seed {RUN_CFG} --seed {wildcards.seed} --out {output}"


rule aggregate:
    """Combine all seed partials -> graph, energy map, results."""
    input:
        expand(f"{PARTIALS}/{NAME}.seed{{seed}}.json", seed=SEEDS),
    output:
        f"{OUTDIR}/{NAME}/results.json",
        f"{OUTDIR}/{NAME}/energy_map.png",
        f"{OUTDIR}/{NAME}/graph.png",
    shell:
        "catpath aggregate {RUN_CFG} --seeds {SEEDS_CSV} --partials {input}"
