"""abreka exp prune — delete an experiment and all downstream descendants."""

from __future__ import annotations

import shutil

import click

from abreka.branch import get_subtree_ids
from abreka.config import find_abreka_dir, load_index, save_index
from abreka.persistence import (
    delete_backlog_item,
    experiment_dir,
    load_backlog_index,
    normalize_exp_id,
)


@click.command("prune")
@click.argument("exp_id")
@click.option(
    "--exclusive",
    is_flag=True,
    help="Keep the target node; delete only its descendants.",
)
@click.option("--yes", "-y", is_flag=True, help="Skip confirmation.")
def prune_cmd(exp_id: str, exclusive: bool, yes: bool):
    """Delete an experiment and all downstream descendants.

    DESTRUCTIVE: removes experiment directories, index entries, and any
    backlog items whose source_exp falls within the pruned subtree.
    Use --exclusive to keep the target node itself.
    """
    abreka_dir = find_abreka_dir()
    exp_id = normalize_exp_id(exp_id)
    index = load_index(abreka_dir)

    if exp_id not in index:
        raise click.ClickException(f"Experiment {exp_id} not found in index.")

    subtree = get_subtree_ids(index, exp_id)
    if exclusive:
        subtree.discard(exp_id)
    if not subtree:
        click.echo("Nothing to prune.")
        return

    backlog_index = load_backlog_index(abreka_dir)
    backlog_hits = sorted(
        bid for bid, entry in backlog_index.items()
        if entry.get("source_exp") in subtree
    )

    scope = "exclusive" if exclusive else "inclusive"
    click.echo(
        f"About to delete {len(subtree)} experiment(s) downstream of "
        f"{exp_id} ({scope}):"
    )
    for eid in sorted(subtree):
        click.echo(f"  - {eid}")
    if backlog_hits:
        click.echo(f"And {len(backlog_hits)} backlog item(s):")
        for bid in backlog_hits:
            click.echo(f"  - {bid}")

    if not yes:
        click.confirm("Proceed?", abort=True)

    for eid in subtree:
        path = experiment_dir(abreka_dir, eid)
        if path.exists():
            shutil.rmtree(path)
        index.pop(eid, None)
    save_index(index, abreka_dir)

    for bid in backlog_hits:
        delete_backlog_item(abreka_dir, bid)

    msg = f"Pruned {len(subtree)} experiment(s)"
    if backlog_hits:
        msg += f" and {len(backlog_hits)} backlog item(s)"
    click.echo(msg + ".")
