"""Console script for stile."""

import subprocess
import sys
from pathlib import Path

import scanpy as sc
import typer
from rich.console import Console

from stile.nodes import (
    assign_cells_hdbscan,
    assign_cells_to_cores,
    compute_median_nn_distance,
    find_connected_components,
    merge_clusters_by_component,
    plot_cores,
    reassign_unassigned_to_nearest_center,
)

app = typer.Typer()
console = Console()


@app.command()
def identify_tissue_cores(
    adata_path: str,
    min_cluster_size: int = 20,
    min_samples: int = 7,
    min_cells_per_center: int = 10,
    num_rows: int = 7,
    num_cols: int = 7,
    buffer_distance: float = 0.0,
    x_col: str = "x_centroid",
    y_col: str = "y_centroid",
    peak_prominence: int = 50,
    peak_distance: int = 50,
    density_bins: int = 1000,
    preliminary_cluster_col: str = "hdbscan_cluster",
    core_label_col: str = "path_block_core",
    save_intermediate: bool = False,
):
    adata_path = Path(adata_path)
    if not adata_path.exists():
        console.print(f"[red]Error:[/red] The specified adata file does not exist: {adata_path}")
        raise typer.Exit(code=1)
    adata = sc.read_h5ad(adata_path)
    # Step 1: Compute median NN distance
    compute_median_nn_distance(adata, x_col=x_col, y_col=y_col)
    # Step 2: Find connected components
    buf = buffer_distance if buffer_distance > 0 else None
    adata = find_connected_components(adata, buffer_distance=buf, x_col=x_col, y_col=y_col)
    # Step 3: HDBSCAN clustering
    adata = assign_cells_hdbscan(
        adata,
        x_col=x_col,
        y_col=y_col,
        cluster_label_col=preliminary_cluster_col,
        min_cluster_size=min_cluster_size,
        min_samples=min_samples,
    )
    # Step 4: Merge clusters by connected component
    adata = merge_clusters_by_component(adata, cluster_label_col=preliminary_cluster_col)
    if save_intermediate:
        fig = plot_cores(adata, x_col=x_col, y_col=y_col, core_label_col="merged_cluster")
        output_path = adata_path.parent / f"{adata_path.stem}_temp_assignments.png"
        fig.savefig(output_path, dpi=300)
    # Step 5: Grid detection and core assignment
    adata = assign_cells_to_cores(
        adata,
        max_x_peaks=num_cols,
        max_y_peaks=num_rows,
        x_col=x_col,
        y_col=y_col,
        peak_prominence=peak_prominence,
        peak_distance=peak_distance,
        core_label_col=core_label_col,
        density_bins=density_bins,
        min_cells_per_center=min_cells_per_center,
        preliminary_cluster_col="merged_cluster",
    )
    # Step 6: Reassign unassigned cells to nearest center
    adata, count = reassign_unassigned_to_nearest_center(adata, core_label_col=core_label_col, x_col=x_col, y_col=y_col)
    fig = plot_cores(adata, x_col=x_col, y_col=y_col, core_label_col=core_label_col)
    output_path = adata_path.parent / f"{adata_path.stem}_cores.png"
    fig.savefig(output_path, dpi=300)
    console.print(f"[green]Tissue core plot saved to:[/green] {output_path}")
    return adata


@app.command()
def run():
    """Launch the Streamlit UI (same workflow as identify_tissue_cores)."""
    app_path = Path(__file__).with_name("app.py")
    cmd = [sys.executable, "-m", "streamlit", "run", str(app_path)]
    result = subprocess.run(cmd)
    if result.returncode != 0:  # pragma: no cover - CLI passthrough
        raise typer.Exit(code=result.returncode)


if __name__ == "__main__":
    app()
