"""MMseqs2 sequence clustering tool for the Amina CLI."""

from pathlib import Path
from typing import List, Optional

import typer
from rich.console import Console

METADATA = {
    "name": "mmseqs2-cluster",
    "display_name": "MMseqs2 Cluster",
    "category": "analysis",
    "description": "Cluster protein sequences using MMseqs2 at a specified identity threshold",
    "modal_function_name": "mmseqs2_cluster_worker",
    "modal_app_name": "mmseqs2-cluster-api",
    "status": "available",
    "outputs": {
        "clusters_csv_filepath": "CSV with full cluster assignments",
        "representatives_fasta_filepath": "FASTA with one representative per cluster",
        "summary_json_filepath": "JSON summary with statistics",
        "cluster_sizes_png": "Bar chart of all cluster sizes",
        "cluster_sizes_html": "Interactive bar chart of cluster sizes",
    },
}

console = Console()


def register(app: typer.Typer):
    """Register this tool's command with the app."""
    from amina_cli.commands.tools import run_tool_with_progress

    @app.command("mmseqs2-cluster")
    def run_mmseqs2_cluster(
        fasta: List[Path] = typer.Option(
            ...,
            "--fasta",
            "-f",
            help="Path to FASTA file(s). Can be specified multiple times for multiple files.",
            exists=True,
        ),
        identity: float = typer.Option(
            0.5,
            "--identity",
            "-i",
            help="Sequence identity threshold (0.0-1.0). Common values: 0.3 (30%), 0.5 (50%), 0.7 (70%)",
            min=0.0,
            max=1.0,
        ),
        coverage: float = typer.Option(
            0.8,
            "--coverage",
            "-c",
            help="Coverage threshold (0.0-1.0). Default 0.8 means 80% of shorter sequence must align",
            min=0.0,
            max=1.0,
        ),
        output: Optional[Path] = typer.Option(
            None,
            "--output",
            "-o",
            help="Output directory for results (required unless --background)",
        ),
        job_name: Optional[str] = typer.Option(
            None,
            "--job-name",
            "-j",
            help="Custom job name for tracking (default: random 4-letter code)",
        ),
        background: bool = typer.Option(
            False,
            "--background",
            "-b",
            help="Submit job and return immediately without waiting for completion",
        ),
    ):
        """
        Cluster protein sequences using MMseqs2 at a specified identity threshold.

        This tool clusters protein sequences and returns cluster assignments with
        visualizations. It's useful for ensuring experimental diversity when
        selecting designs from hundreds or thousands of candidate sequences.

        Features:
        - Accepts multiple FASTA files with source tracking
        - Removes exact duplicates before clustering
        - Generates cluster size distribution visualizations
        - Outputs representative sequences FASTA

        Common identity thresholds:
        - 0.30 (30%): Very broad clusters, useful for distant homologs
        - 0.50 (50%): Moderate clustering, good for reducing redundancy
        - 0.70 (70%): Tight clusters, closely related sequences
        - 0.90 (90%): Very tight, near-identical sequences only

        Examples:
            # Cluster sequences at 50% identity
            amina run mmseqs2-cluster -f designs.fasta --identity 0.5 -o ./results/

            # Cluster multiple files at 70% identity
            amina run mmseqs2-cluster -f mpnn.fasta -f rfdiff.fasta -i 0.7 -o ./results/

            # Cluster with custom coverage threshold
            amina run mmseqs2-cluster -f designs.fasta -i 0.5 -c 0.6 -o ./results/

            # Run in background (returns job ID immediately)
            amina run mmseqs2-cluster -f designs.fasta -i 0.5 --background
        """
        # Validate output
        if output is None and not background:
            console.print("[red]Error:[/red] --output / -o is required (unless using --background)")
            raise typer.Exit(1)

        # Validate at least one FASTA file
        if not fasta or len(fasta) == 0:
            console.print("[red]Error:[/red] At least one --fasta / -f file is required")
            raise typer.Exit(1)

        # Read file contents and track filenames
        fasta_contents = []
        fasta_filenames = []

        for fasta_path in fasta:
            try:
                content = fasta_path.read_text()
                fasta_contents.append(content)
                fasta_filenames.append(fasta_path.name)
                console.print(f"Read FASTA from {fasta_path}")
            except Exception as e:
                console.print(f"[red]Error:[/red] Failed to read {fasta_path}: {e}")
                raise typer.Exit(1)

        # Count sequences
        total_seqs = sum(content.count(">") for content in fasta_contents)
        console.print(f"Total sequences: {total_seqs} from {len(fasta)} file(s)")
        console.print(f"Clustering at {identity * 100:.0f}% identity, {coverage * 100:.0f}% coverage")

        # Build params
        params = {
            "fasta_contents": fasta_contents,
            "fasta_filenames": fasta_filenames,
            "seq_identity": identity,
            "coverage": coverage,
        }

        if job_name:
            params["job_name"] = job_name

        run_tool_with_progress("mmseqs2-cluster", params, output, background=background)
