"""lst-tools clean — remove generated files from parsing, tracking, or spectra setup."""


# --------------------------------------------------
# load necessary modules
# --------------------------------------------------
from __future__ import annotations

import logging
import shutil
from pathlib import Path
from typing import Annotated

import typer


# --------------------------------------------------
# set up logger
# --------------------------------------------------
logger = logging.getLogger(__name__)


# --------------------------------------------------
# LST solver artifact patterns
# --------------------------------------------------
# files produced by the solver that live alongside the input deck
_SOLVER_ARTIFACTS: list[str] = [
    "BaseflowTecFormat.dat",
    "Baseflow_For_Eigenfunctions_LocalFortran.dat",
    "Baseflow_For_Eigenfunctions_LocalFortran_Dimensional.dat",
    "Frequency*",
    "fort.*",
    "SpectralGrid.dat",
    "Initial2D.dat",
    "yl_array.dat",
    "meanflow.ascii",
    "NumberOfMins_forEachFrequency.dat",
    "*.o*",
    "log_proc*",
    "run.log",
    "slurm-*.out",
]


# --------------------------------------------------
# helpers
# --------------------------------------------------
def _collect_targets(
    directory: Path,
    patterns: list[str],
) -> list[Path]:
    """Glob *directory* for each pattern and return a sorted, deduplicated list."""
    hits: dict[Path, None] = {}
    for pat in patterns:
        for p in sorted(directory.glob(pat)):
            hits[p] = None
    return list(hits)


def _remove(targets: list[Path]) -> int:
    """Delete every path in *targets* (files or directories). Return count."""
    removed = 0
    for p in targets:
        if p.is_dir():
            shutil.rmtree(p)
            logger.info("removed directory %s", p)
        else:
            p.unlink()
            logger.info("removed file %s", p)
        removed += 1
    return removed


def _confirm_and_remove(targets: list[Path], force: bool) -> None:
    """Print what will be removed, prompt unless *force*, then delete."""
    if not targets:
        typer.echo("nothing to clean")
        raise typer.Exit()

    typer.echo("the following will be removed:")
    for p in targets:
        label = "dir " if p.is_dir() else "    "
        typer.echo(f"  {label}{p}")

    if not force:
        typer.confirm("proceed?", abort=True)

    n = _remove(targets)
    typer.echo(f"removed {n} item(s)")


# --------------------------------------------------
# parsing clean
# --------------------------------------------------
def cmd_clean_parsing(
    directory: Annotated[
        Path,
        typer.Option("--dir", "-d", help="Directory to clean (default: current directory)."),
    ] = Path("."),
    name: Annotated[
        str,
        typer.Option("--name", "-n", help="Input-deck filename to remove."),
    ] = "lst_input.dat",
    force: Annotated[
        bool,
        typer.Option("--force", "-f", help="Skip confirmation prompt."),
    ] = False,
) -> None:
    """Remove files generated by ``lst-tools setup parsing``.

    Removes the LST input deck, HPC run scripts (``run.*.*``), and
    solver artifacts from the target directory.
    """
    directory = directory.resolve()

    # collect targets: input deck + HPC run scripts + solver artifacts
    targets: list[Path] = []

    input_deck = directory / name
    if input_deck.exists():
        targets.append(input_deck)

    # HPC scripts follow the pattern run.<scheduler>.<hostname>
    targets.extend(_collect_targets(directory, ["run.*.*"]))

    # solver output artifacts
    targets.extend(_collect_targets(directory, _SOLVER_ARTIFACTS))

    _confirm_and_remove(targets, force)


# --------------------------------------------------
# tracking clean
# --------------------------------------------------
def cmd_clean_tracking(
    directory: Annotated[
        list[Path],
        typer.Option("--dir", "-d", help="Case directory to clean (e.g. kc_0000pt00). Repeat for multiple. If omitted, cleans all kc_* directories."),
    ] = None,
    force: Annotated[
        bool,
        typer.Option("--force", "-f", help="Skip confirmation prompt."),
    ] = False,
) -> None:
    """Remove solver artifacts from tracking case directories.

    Removes LST solver output files (BaseflowTecFormat.dat, fort.*,
    Frequency*, etc.) from ``kc_*/`` case directories.

    By default cleans all ``kc_*/`` directories in the current directory.
    Use ``--dir`` to target specific directories instead.
    """

    # build the list of directories to clean
    if directory:
        # user specified explicit directories
        dir_list = [d.resolve() for d in directory if d.resolve().is_dir()]
    else:
        # default: all kc_* directories in the current directory
        cwd = Path(".").resolve()
        dir_list = sorted(d for d in cwd.glob("kc_*") if d.is_dir())

    # collect solver artifacts from each tracking directory
    targets: list[Path] = []
    for d in dir_list:
        targets.extend(_collect_targets(d, _SOLVER_ARTIFACTS))

    _confirm_and_remove(targets, force)


# --------------------------------------------------
# spectra clean
# --------------------------------------------------
def cmd_clean_spectra(
    directory: Annotated[
        Path,
        typer.Option("--dir", "-d", help="Directory to clean (default: current directory)."),
    ] = Path("."),
    force: Annotated[
        bool,
        typer.Option("--force", "-f", help="Skip confirmation prompt."),
    ] = False,
) -> None:
    """Remove files generated by ``lst-tools setup spectra``.

    Removes all ``x_*/`` case directories and the ``run_cases.sh``
    launcher script.
    """
    directory = directory.resolve()

    # collect targets: x_* dirs, launcher script
    targets = _collect_targets(directory, ["x_*"])

    launcher = directory / "run_cases.sh"
    if launcher.exists():
        targets.append(launcher)

    _confirm_and_remove(targets, force)
