import yaml
import os
from pathlib import Path
from enum import Enum


class SegmentDetectionMethod(Enum):
    ALIGN = "align"
    MINIMIZER = "minimizer"


with open("config/defaults.yaml") as f:
    defaults = yaml.safe_load(f)

# Merge configs, using defaults only as fallback
# Write to results/config.yaml
for key, value in defaults.items():
    if not key in config:
        config[key] = value

config["slack_hook"] = os.getenv("SLACK_HOOK")
# Infer whether nucleotide sequences are segmented
config["segmented"] = len(config["nucleotide_sequences"]) > 1

Path("results").mkdir(parents=True, exist_ok=True)
with open("results/config.yaml", "w") as f:
    f.write(yaml.dump(config))

TAXON_ID = config["taxon_id"]
SEGMENTED = config["segmented"]
segment_detection_method: SegmentDetectionMethod | None = (
    None  # align uses nextclade align to determine segments it is slower but more precise, minimizer uses nextclade sort and requires a minimizer index
)
LOG_LEVEL = config.get("log_level", "INFO")
NCBI_API_KEY = os.getenv("NCBI_API_KEY")
NCBI_GATEWAY_URL = config.get("ncbi_gateway_url")
MIRROR_BUCKET = config.get("mirror_bucket", "")
CHECK_ENA_DEPOSITION = config.get("check_ena_deposition", False)
FILTER = config.get("metadata_filter", None)
CALCULATE_GROUPS_OVERRIDE_JSON = config.get(
    "calculate_groups_override_json", False
)  # Calculate the groups override JSON based on assembly report data.
GROUPING_OVERRIDE_URL = config.get("grouping_override_url", False)
GROUPS_OVERRIDE_JSON = CALCULATE_GROUPS_OVERRIDE_JSON or GROUPING_OVERRIDE_URL
DOWNLOADED_GROUPS_JSON = (
    "results/downloaded_groups.json"
    if CALCULATE_GROUPS_OVERRIDE_JSON
    else "results/groups.json"
)
CALCULATED_GROUPS_JSON = (
    "results/calculated_groups.json" if GROUPING_OVERRIDE_URL else "results/groups.json"
)
MUTED_HASHES_URL = config.get("muted_hashes_url", False)


if SEGMENTED:
    dataset_server_map = {}
    dataset_name_map = {}

    try:
        segment_identification = config.get("segment_identification", None)
        segment_detection_method = SegmentDetectionMethod(
            segment_identification.get("method")
        )
    except:
        raise ValueError(
            "Segmented sequences require segment_identification and method"
        )
    if segment_detection_method == SegmentDetectionMethod.ALIGN:
        for segment in config["nucleotide_sequences"]:
            dataset_server_map[segment] = segment_identification.get(
                "nextclade_dataset_server_map", {}
            ).get(
                segment,
                segment_identification.get(
                    "nextclade_dataset_server", config.get("nextclade_dataset_server")
                ),
            )
            dataset_name_map[segment] = segment_identification.get(
                "nextclade_dataset_name_map", {}
            ).get(
                segment,
                segment_identification.get("nextclade_dataset_name") + "/" + segment,
            )

APPLY_MINIMIZER = (
    SEGMENTED and segment_detection_method == SegmentDetectionMethod.MINIMIZER
) or (config.get("minimizer_url") and config.get("minimizer_parser"))

print(segment_detection_method)

if os.uname().sysname == "Darwin":
    # Don't use conda-forge unzip on macOS
    # Due to https://github.com/conda-forge/unzip-feedstock/issues/16
    unzip = "/usr/bin/unzip"
else:
    unzip = "unzip"


def prepped_metadata():
    if FILTER:
        return "results/metadata_filtered.ndjson"
    if SEGMENTED:
        return "results/metadata_post_group.ndjson"
    return "results/metadata_post_prepare.ndjson"


rule all:
    input:
        "results/submitted",
        "results/revised",
    params:
        config=lambda wildcards: str(config),


rule clean:
    # Useful for testing, when debugging
    shell:
        "rm -rf results/*"


rule fetch_inflate_ncbi_dataset_package:
    output:
        dataset_report="results/ncbi_dataset/data/data_report.jsonl",
        dataset_sequences="results/ncbi_dataset/data/genomic.fna",
    params:
        taxon_id=TAXON_ID,
        api_key=f"--api-key {NCBI_API_KEY}" if NCBI_API_KEY else "",
        gateway=f"--gateway-url {NCBI_GATEWAY_URL}" if NCBI_GATEWAY_URL else "",
        use_mirror=bool(MIRROR_BUCKET),
        mirror_url=f"{MIRROR_BUCKET.strip('/')}/{TAXON_ID}.tar.zst",
        unzip=unzip,
        dataset_package=directory("results/ncbi_dataset"),
        compressed_package_tzst="results/dataset.tar.zst",
        compressed_package_zip="results/dataset.zip",
    shell:
        """
        if [[ "{params.use_mirror}" == "True" ]]; then
            curl {params.mirror_url} -o {params.compressed_package_tzst}
            tar xvf {params.compressed_package_tzst} -C results
        else
            datasets download virus genome taxon {params.taxon_id} \
                --no-progressbar \
                --filename {params.compressed_package_zip} \
                {params.api_key} \
                {params.gateway} \
                && {params.unzip} \
                    -o {params.compressed_package_zip} \
                    -d results
        fi
        """


rule format_ncbi_dataset_report:
    input:
        script="scripts/format_ncbi_metadata.py",
        dataset_report="results/ncbi_dataset/data/data_report.jsonl",
        config="results/config.yaml",
    output:
        ncbi_dataset_tsv="results/metadata_post_rename.tsv",
    shell:
        """
        python {input.script} \
            --config-file {input.config} \
            --input {input.dataset_report} \
            --output {output.ncbi_dataset_tsv}
        echo "Processed metadata file lines: $(wc -l <{output.ncbi_dataset_tsv})"
        echo "Hash of output: $(md5sum {output.ncbi_dataset_tsv})"
        echo "Hash of sorted output: $(md5sum <(sort {output.ncbi_dataset_tsv}))"
        """


rule format_ncbi_dataset_sequences:
    input:
        dataset_sequences="results/ncbi_dataset/data/genomic.fna",
    output:
        ncbi_dataset_sequences="results/sequences.fasta",
    shell:
        """
        seqkit seq -w0 -i \
            {input.dataset_sequences} \
            >{output.ncbi_dataset_sequences}
        echo "Stats of NCBI dataset sequences: $(seqkit stats {output.ncbi_dataset_sequences})"
        echo "seqkit hash of NCBI dataset sequences: $(seqkit sum -a -s {output.ncbi_dataset_sequences})"
        echo "Plain hash of NCBI dataset sequences: $(md5sum {output.ncbi_dataset_sequences})"
        """


if CHECK_ENA_DEPOSITION:

    rule get_loculus_depositions:
        input:
            script="scripts/get_loculus_depositions.py",
            config="results/config.yaml",
        output:
            exclude_insdc_accessions="results/accessions_to_exclude.json",
        params:
            log_level=LOG_LEVEL,
        shell:
            """
            python {input.script} \
                --output-insdc-accessions {output.exclude_insdc_accessions} \
                --log-level {params.log_level} \
                --config-file {input.config}
            """

    rule filter_out_loculus_depositions:
        input:
            ncbi_dataset_tsv="results/metadata_post_rename.tsv",
            exclude_insdc_accessions="results/accessions_to_exclude.json",
            script="scripts/filter_out_depositions.py",
            config="results/config.yaml",
        output:
            metadata_tsv="results/filtered_metadata.tsv",
        params:
            log_level=LOG_LEVEL,
        shell:
            """
            python {input.script} \
                --input-metadata-tsv {input.ncbi_dataset_tsv} \
                --exclude-insdc-accessions {input.exclude_insdc_accessions} \
                --log-level {params.log_level} \
                --config-file {input.config} \
                --output-metadata-tsv {output.metadata_tsv}
            """


rule calculate_sequence_hashes:
    """Output JSON: {insdc_accession: md5_sequence_hash, ...}"""
    input:
        script="scripts/calculate_sequence_hashes.py",
        sequences="results/sequences.fasta",
    output:
        sequence_hashes="results/sequence_hashes.ndjson",
        sequence_json="results/sequences.ndjson",
    params:
        log_level=LOG_LEVEL,
    shell:
        """
        python {input.script} \
            --input {input.sequences} \
            --output-hashes {output.sequence_hashes} \
            --output-sequences {output.sequence_json} \
            --log-level {params.log_level}
        """


if SEGMENTED and segment_detection_method == SegmentDetectionMethod.ALIGN:

    rule align:
        input:
            sequences="results/sequences.fasta",
        output:
            results="results/nextclade_{segment}.tsv",
        params:
            dataset_server=lambda w: dataset_server_map[w.segment],
            dataset_name=lambda w: dataset_name_map[w.segment],
        shell:
            """
            nextclade run \
                {input.sequences} \
                --output-tsv {output.results} \
                --server {params.dataset_server} \
                --dataset-name {params.dataset_name}
            """

    rule process_alignments:
        input:
            results=expand(
                "results/nextclade_{segment}.tsv",
                segment=config["nucleotide_sequences"],
            ),
            script="scripts/parse_alignment_output.py",
        output:
            merged="results/nextclade_merged.tsv",
        params:
            segment_paths=" ".join(
                [
                    f" --alignment-results results/nextclade_{segment}.tsv"
                    for segment in config["nucleotide_sequences"]
                ]
            ),
        shell:
            """
            python {input.script} \
                {params.segment_paths} \
                --output {output.merged}
            """


if APPLY_MINIMIZER:

    rule download_minimizer:
        output:
            results="results/minimizer.json",
        params:
            minimizer=(
                config.get("segment_identification").get("minimizer_url")
                if config.get("segment_identification")
                else config.get("minimizer_url")
            ),
        shell:
            """
            curl -L -o {output.results} {params.minimizer}
            """

    rule nextclade_sort:
        input:
            sequences="results/sequences.fasta",
            minimizer="results/minimizer.json",
        output:
            results="results/sort_results.tsv",
        shell:
            """
            nextclade sort -m {input.minimizer} \
                -r {output.results} {input.sequences} \
                --max-score-gap 0.3 --min-score 0.05 --min-hits 2 --all-matches
            """

    rule parse_sort:
        input:
            sorted="results/sort_results.tsv",
            config="results/config.yaml",
            script="scripts/parse_nextclade_sort_output.py",
        output:
            merged="results/nextclade_merged.tsv",
        params:
            log_level=LOG_LEVEL,
        shell:
            """
            python {input.script} \
                --config-file {input.config} \
                --sort-results {input.sorted} \
                --output {output.merged} \
                --log-level {params.log_level}
            """


rule prepare_metadata:
    # Transform Genbank metadata keys and values to Loculus format
    input:
        script="scripts/prepare_metadata.py",
        metadata=(
            "results/filtered_metadata.tsv"
            if CHECK_ENA_DEPOSITION
            else "results/metadata_post_rename.tsv"
        ),
        sequence_hashes="results/sequence_hashes.ndjson",
        config="results/config.yaml",
        # else is just a dummy
        segments=(
            "results/nextclade_merged.tsv"
            if (SEGMENTED or APPLY_MINIMIZER)
            else "results/config.yaml"
        ),
    output:
        metadata="results/metadata_post_prepare.ndjson",
    params:
        log_level=LOG_LEVEL,
        segments=(
            f"--segments results/nextclade_merged.tsv"
            if (SEGMENTED or APPLY_MINIMIZER)
            else ""
        ),
    shell:
        """
        python {input.script} \
            --config-file {input.config} \
            --input {input.metadata} \
            --sequence-hashes-file {input.sequence_hashes} \
            {params.segments} \
            --output {output.metadata} \
            --log-level {params.log_level}
        """


if GROUPING_OVERRIDE_URL:

    rule download_groups:
        output:
            results=DOWNLOADED_GROUPS_JSON,
        params:
            grouping=GROUPING_OVERRIDE_URL,
        shell:
            """
            curl -L -o {output.results} {params.grouping}
            """


if CALCULATE_GROUPS_OVERRIDE_JSON:

    rule download_ignore_list:
        output:
            ignore_list="results/grouping_ignore_list.txt",
        params:
            grouping_ignore_list_url=config.get("grouping_ignore_list_url", ""),
        shell:
            """
            if [[ -n "{params.grouping_ignore_list_url}" ]]; then
                curl -L -o {output.ignore_list} {params.grouping_ignore_list_url}
            else
                touch {output.ignore_list}
            fi
            """

    rule fetch_inflate_assemblies:
        output:
            marker="results/{source}_assembly/.fetch_inflate_complete",
        params:
            taxon_id=TAXON_ID,
            api_key=f"--api-key {NCBI_API_KEY}" if NCBI_API_KEY else "",
            gateway=f"--gateway-url {NCBI_GATEWAY_URL}" if NCBI_GATEWAY_URL else "",
            use_mirror=bool(MIRROR_BUCKET),
            mirror_url=lambda wc: f"{MIRROR_BUCKET.strip('/')}/{TAXON_ID}-assembly-{wc.source}.tar.zst",
            unzip=unzip,
            compressed_package_tzst="results/{source}_assembly.tar.zst",
            compressed_package_zip="results/{source}_assembly.zip",
            package=directory("results/{source}_assembly"),
        shell:
            """
            if [[ "{params.use_mirror}" == "True" ]]; then
                curl {params.mirror_url} -o {params.compressed_package_tzst} \
                    && mkdir -p {params.package} \
                    && tar xf {params.compressed_package_tzst} -C {params.package}
            else
                datasets download genome taxon {params.taxon_id} \
                    --assembly-source {wildcards.source} \
                    --no-progressbar --dehydrated \
                    --filename {params.compressed_package_zip} \
                    {params.api_key} \
                    {params.gateway} \
                    && {params.unzip} \
                        -o {params.compressed_package_zip} \
                        -d {params.package} \
                    && datasets rehydrate \
                        --directory {params.package} \
                        --no-progressbar
            fi
            touch {output.marker}
            """

    rule get_assembly_groups:
        input:
            script="scripts/calculate_assembly_groups.py",
            fetch_genbank="results/genbank_assembly/.fetch_inflate_complete",
            fetch_refseq="results/refseq_assembly/.fetch_inflate_complete",
            ignore_list="results/grouping_ignore_list.txt",
            config_file="results/config.yaml",
        output:
            groups_json=CALCULATED_GROUPS_JSON,
        params:
            genbank_dir="results/genbank_assembly/ncbi_dataset/data",
            refseq_dir="results/refseq_assembly/ncbi_dataset/data",
        shell:
            """
            python {input.script} \
                --dataset-dir {params.genbank_dir} \
                --dataset-dir {params.refseq_dir} \
                --output-file {output.groups_json} \
                --ignore-list {input.ignore_list} \
                --config-file {input.config_file}
            """


if GROUPING_OVERRIDE_URL and CALCULATE_GROUPS_OVERRIDE_JSON:

    rule merge_groups:
        input:
            script="scripts/merge_group_overrides.py",
            downloaded=DOWNLOADED_GROUPS_JSON,
            calculated=CALCULATED_GROUPS_JSON,
            config="results/config.yaml",
        output:
            groups_json="results/groups.json",
        shell:
            """
            python {input.script} \
                --groups {input.calculated} \
                --groups {input.downloaded} \
                --config-file {input.config} \
                --output-file {output.groups_json}
            """


if GROUPS_OVERRIDE_JSON:

    rule override_group_segments:
        """Group segments based on JSON map"""
        input:
            script="scripts/override_group_segments.py",
            metadata="results/metadata_post_prepare.ndjson",
            sequences="results/sequences.ndjson",
            config="results/config.yaml",
            groups="results/groups.json",
        output:
            metadata="results/metadata_grouped.ndjson",
            sequences="results/sequences_grouped.ndjson",
            ungrouped_metadata="results/metadata_ungrouped.ndjson",
            ungrouped_sequences="results/sequences_ungrouped.ndjson",
        params:
            log_level=LOG_LEVEL,
            match_prev_flag=lambda w: (
                "--match-previous-accession-versions"
                if config.get("match_previous_accession_versions", False)
                else ""
            ),
        shell:
            """
            python {input.script} \
                --config-file {input.config} \
                --groups {input.groups} \
                --input-metadata {input.metadata} \
                --input-seq {input.sequences} \
                --output-metadata {output.metadata} \
                --output-ungrouped-metadata {output.ungrouped_metadata} \
                --output-ungrouped-seq {output.ungrouped_sequences} \
                --output-seq {output.sequences} \
                --log-level {params.log_level} \
                {params.match_prev_flag}
            """


if MUTED_HASHES_URL:

    rule download_muted_hashes:
        """Download the tsv file of hashes that should not trigger a revision"""
        output:
            results="results/muted_hashes.tsv",
        params:
            url=MUTED_HASHES_URL,
        shell:
            """
            curl --fail --silent --show-error --retry 3 -L -o {output.results} "{params.url}"
            """


rule heuristic_group_segments:
    """Group segments based on heuristic, join with previous groups if available"""
    input:
        script="scripts/heuristic_group_segments.py",
        metadata=(
            "results/metadata_ungrouped.ndjson"
            if GROUPS_OVERRIDE_JSON
            else "results/metadata_post_prepare.ndjson"
        ),
        sequences=(
            "results/sequences_ungrouped.ndjson"
            if GROUPS_OVERRIDE_JSON
            else "results/sequences.ndjson"
        ),
        metadata_grouped=(
            "results/metadata_grouped.ndjson"
            if GROUPS_OVERRIDE_JSON
            else "results/metadata_post_prepare.ndjson"
        ),
        sequences_grouped=(
            "results/sequences_grouped.ndjson"
            if GROUPS_OVERRIDE_JSON
            else "results/sequences.ndjson"
        ),
        config="results/config.yaml",
    output:
        metadata="results/metadata_post_group.ndjson",
        sequences="results/sequences_post_group.ndjson",
    params:
        log_level=LOG_LEVEL,
        GROUPS_OVERRIDE_JSON="true" if GROUPS_OVERRIDE_JSON else "false",
    shell:
        """
        python {input.script} \
            --config-file {input.config} \
            --input-metadata {input.metadata} \
            --input-seq {input.sequences} \
            --output-metadata {output.metadata} \
            --output-seq {output.sequences} \
            --log-level {params.log_level}
        if [ "{params.GROUPS_OVERRIDE_JSON}" = "true" ]; then
            cat {input.metadata_grouped} >>{output.metadata}
            cat {input.sequences_grouped} >>{output.sequences}
        fi
        """


if FILTER:

    rule metadata_filter:
        """
        FILTER allows you to throw out sequences you don't want to ingest based on metadata
        E.g. only H5N1, when the genbank download contains all influenza
        """
        input:
            metadata=(
                "results/metadata_post_group.ndjson"
                if SEGMENTED
                else "results/metadata_post_prepare.ndjson"
            ),
            sequences=(
                "results/sequences_post_group.ndjson"
                if SEGMENTED
                else "results/sequences.ndjson"
            ),
            script="scripts/metadata_filter.py",
            config="results/config.yaml",
        output:
            sequences="results/sequences_filtered.ndjson",
            metadata="results/metadata_filtered.ndjson",
        params:
            log_level=LOG_LEVEL,
        shell:
            """
            python {input.script} \
                --input-seq {input.sequences} \
                --output-seq {output.sequences} \
                --input-metadata {input.metadata} \
                --output-metadata {output.metadata} \
                --log-level {params.log_level} \
                --config-file {input.config}
            """


rule get_previous_submissions:
    """Download metadata and sequence hashes of all previously submitted sequences
    Produces mapping from INSDC accession to loculus id/version/hash
    insdc_accession:
        loculus_accession: abcd
        jointAccession: xx.seg1/xy.seg2
        versions:
        -   version: 1
            hash: abcd
            status: APPROVED_FOR_RELEASE
        -   version: 2
            hash: efg
            status: HAS_ERRORS
        ...
    """
    input:
        # Reduce likelihood of race condition of multi-submission
        # By delaying the start of the script
        script="scripts/call_loculus.py",
        prepped_metadata=prepped_metadata(),
        config="results/config.yaml",
    output:
        hashes="results/previous_submissions.ndjson",
    params:
        log_level=LOG_LEVEL,
        sleep=config["post_start_sleep"],
    shell:
        """
        sleep {params.sleep}
        python {input.script} \
            --mode get-submitted \
            --config-file {input.config} \
            --log-level {params.log_level} \
            --output {output.hashes}
        """


compare_hashes_input = {
    "script": "scripts/compare_hashes.py",
    "config": "results/config.yaml",
    "old_hashes": "results/previous_submissions.ndjson",
    "metadata": prepped_metadata(),
}

if MUTED_HASHES_URL:
    compare_hashes_input["muted_hashes"] = "results/muted_hashes.tsv"


rule compare_hashes:
    input:
        **compare_hashes_input,
    output:
        to_submit="results/to_submit.json",
        to_revise="results/to_revise.json",
        to_revoke="results/to_revoke.json",
        unchanged="results/unchanged.json",
        blocked="results/blocked.json",
        sampled_out="results/sampled_out.json",
    params:
        log_level=LOG_LEVEL,
        subsample_fraction=config.get("subsample_fraction", 1.0),
        muted_hashes=(
            "--muted-hashes results/muted_hashes.tsv" if MUTED_HASHES_URL else ""
        ),
    shell:
        """
        python {input.script} \
            --config-file {input.config} \
            --old-hashes {input.old_hashes} \
            {params.muted_hashes} \
            --metadata {input.metadata} \
            --to-submit {output.to_submit} \
            --to-revise {output.to_revise} \
            --to-revoke {output.to_revoke} \
            --unchanged {output.unchanged} \
            --output-blocked {output.blocked} \
            --sampled-out-file {output.sampled_out} \
            --log-level {params.log_level} \
            --subsample-fraction {params.subsample_fraction}
        """


rule prepare_files:
    input:
        script="scripts/prepare_files.py",
        config="results/config.yaml",
        metadata=prepped_metadata(),
        sequences=(
            "results/sequences_filtered.ndjson"
            if FILTER
            else (
                "results/sequences_post_group.ndjson"
                if SEGMENTED
                else "results/sequences.ndjson"
            )
        ),
        to_submit="results/to_submit.json",
        to_revise="results/to_revise.json",
        to_revoke="results/to_revoke.json",
    output:
        sequences_submit="results/submit_sequences.fasta",
        sequences_revise="results/revise_sequences.fasta",
        sequences_revoke="results/sequences_to_submit_prior_to_revoke.fasta",
        metadata_submit="results/submit_metadata.tsv",
        metadata_revise="results/revise_metadata.tsv",
        metadata_revoke="results/metadata_to_submit_prior_to_revoke.tsv",
    shell:
        """
        python {input.script} \
            --config-file {input.config} \
            --metadata-path {input.metadata} \
            --sequences-path {input.sequences} \
            --to-submit-path {input.to_submit} \
            --to-revise-path {input.to_revise} \
            --to-revoke-path {input.to_revoke} \
            --metadata-submit-path {output.metadata_submit} \
            --metadata-revise-path {output.metadata_revise} \
            --metadata-submit-prior-to-revoke-path {output.metadata_revoke} \
            --sequences-submit-path {output.sequences_submit} \
            --sequences-revise-path {output.sequences_revise} \
            --sequences-submit-prior-to-revoke-path {output.sequences_revoke}
        """


rule sort_fasta:
    """Sort FASTA sequences by id using two-pass to avoid memory issues"""
    input:
        sequences="results/{basename}.fasta",
    output:
        sorted="results/{basename}_sorted.fasta",
    shell:
        """
        seqkit sort -N --two-pass {input.sequences} | seqkit seq -w 0 >{output.sorted}
        """


rule sort_metadata:
    """Sort metadata by id, keep header at top of file. If file is empty or id column is missing, do nothing."""
    input:
        metadata="results/{basename}.tsv",
    output:
        sorted="results/{basename}_sorted.tsv",
    shell:
        """
        columnNumber=$(awk -F'\\t' '{{for(i=1;i<=NF;i++) if($i=="id") print i}}' {input.metadata})
        if [ ${{columnNumber}} ]; then
            (head -n 1 {input.metadata} && tail -n +2 {input.metadata} | sort -t$'\t' -k${{columnNumber}},${{columnNumber}}) >{output.sorted}
        else
            cat {input.metadata} >{output.sorted}
        fi
        """


rule submit:
    input:
        script="scripts/call_loculus.py",
        metadata="results/submit_metadata_sorted.tsv",
        sequences="results/submit_sequences_sorted.fasta",
        config="results/config.yaml",
    output:
        submitted=touch("results/submitted"),
    params:
        log_level=LOG_LEVEL,
    shell:
        """
        if [ -s {input.metadata} ]; then
            python {input.script} \
                --mode submit \
                --metadata {input.metadata} \
                --sequences {input.sequences} \
                --config-file {input.config} \
                --log-level {params.log_level}
        fi
        """


rule revise:
    input:
        script="scripts/call_loculus.py",
        metadata="results/revise_metadata_sorted.tsv",
        sequences="results/revise_sequences_sorted.fasta",
        config="results/config.yaml",
    output:
        revised=touch("results/revised"),
    params:
        log_level=LOG_LEVEL,
    shell:
        """
        if [ -s {input.metadata} ]; then
            python {input.script} \
                --mode revise \
                --metadata {input.metadata} \
                --sequences {input.sequences} \
                --config-file {input.config} \
                --log-level {params.log_level}
        fi
        """


rule regroup_and_revoke:
    input:
        script="scripts/call_loculus.py",
        metadata="results/metadata_to_submit_prior_to_revoke_sorted.tsv",
        sequences="results/sequences_to_submit_prior_to_revoke_sorted.fasta",
        map="results/to_revoke.json",
        config="results/config.yaml",
    output:
        revoked=touch("results/revoked"),
    params:
        log_level=LOG_LEVEL,
    shell:
        """
        if [ -s {input.metadata} ]; then
            python {input.script} \
                --mode regroup-and-revoke \
                --metadata {input.metadata} \
                --sequences {input.sequences} \
                --revoke-map {input.map} \
                --config-file {input.config} \
                --log-level {params.log_level}
        fi
        """
