"""AutoDock Vina molecular docking tool for the Amina CLI."""

import typer
from pathlib import Path
from typing import Optional
from rich.console import Console

METADATA = {
    "name": "autodock-vina",
    "display_name": "AutoDock Vina",
    "category": "interactions",
    "description": "Molecular docking to predict ligand binding poses and affinities",
    "modal_function_name": "vina_worker",
    "modal_app_name": "vina-docking-api",
    "status": "available",
    "outputs": {
        "summary_filepath": "JSON summary with docking results and file paths",
        "pose_*": "SDF files with docked ligand poses",
    },
}

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("autodock-vina")
    def run_autodock_vina(
        receptor: Path = typer.Option(
            ...,
            "--receptor",
            "-r",
            help="Path to receptor PDB or PDBQT file",
            exists=True,
        ),
        ligand: Optional[Path] = typer.Option(
            None,
            "--ligand",
            "-l",
            help="Path to ligand SDF, MOL2, or PDBQT file",
            exists=True,
        ),
        smiles: Optional[str] = typer.Option(
            None,
            "--smiles",
            "-s",
            help="SMILES string for ligand (alternative to --ligand)",
        ),
        center_x: float = typer.Option(
            ...,
            "--center-x",
            "-cx",
            help="X coordinate of docking box center",
        ),
        center_y: float = typer.Option(
            ...,
            "--center-y",
            "-cy",
            help="Y coordinate of docking box center",
        ),
        center_z: float = typer.Option(
            ...,
            "--center-z",
            "-cz",
            help="Z coordinate of docking box center",
        ),
        size_x: float = typer.Option(
            20.0,
            "--size-x",
            "-sx",
            help="X dimension of docking box (Angstroms)",
        ),
        size_y: float = typer.Option(
            20.0,
            "--size-y",
            "-sy",
            help="Y dimension of docking box (Angstroms)",
        ),
        size_z: float = typer.Option(
            20.0,
            "--size-z",
            "-sz",
            help="Z dimension of docking box (Angstroms)",
        ),
        flex_residues: Optional[str] = typer.Option(
            None,
            "--flex",
            "-f",
            help="Flexible residues, format: 'A:123,A:456,B:10'",
        ),
        forcefield: str = typer.Option(
            "vina",
            "--forcefield",
            "--ff",
            help="Scoring function: 'vina' or 'vinardo'",
        ),
        exhaustiveness: int = typer.Option(
            8,
            "--exhaustiveness",
            "-e",
            help="Search exhaustiveness (1-1024, higher = more thorough)",
        ),
        num_modes: int = typer.Option(
            9,
            "--num-modes",
            "-n",
            help="Maximum number of binding poses to generate (1-100)",
        ),
        output: Path = typer.Option(
            ...,
            "--output",
            "-o",
            help="Output directory for results",
        ),
        job_name: Optional[str] = typer.Option(
            None,
            "--job-name",
            "-j",
            help="Custom job name for output files (default: random 4-letter code)",
        ),
    ):
        """
        Perform molecular docking using AutoDock Vina.

        Predict how a small molecule (ligand) binds to a protein (receptor).
        Supports both rigid and flexible receptor docking.

        Examples:
            amina run autodock-vina -r receptor.pdb -l ligand.sdf -cx 10 -cy 20 -cz 30 -o ./results/
            amina run autodock-vina -r receptor.pdb -s "CCO" -cx 10 -cy 20 -cz 30 -o ./results/
            amina run autodock-vina -r receptor.pdb -l ligand.sdf -cx 10 -cy 20 -cz 30 --flex A:123,A:456 -o ./results/
        """
        # Validate required options
        if output is None:
            console.print("[red]Error:[/red] --output / -o is required")
            raise typer.Exit(1)

        # Validate ligand input (exactly one of --ligand or --smiles)
        if not ligand and not smiles:
            console.print("[red]Error:[/red] Provide either --ligand or --smiles")
            raise typer.Exit(1)

        if ligand and smiles:
            console.print("[red]Error:[/red] Provide only one of --ligand or --smiles, not both")
            raise typer.Exit(1)

        # Validate forcefield
        if forcefield not in ("vina", "vinardo"):
            console.print(f"[red]Error:[/red] Invalid forcefield '{forcefield}'. Use 'vina' or 'vinardo'")
            raise typer.Exit(1)

        # Read receptor file content
        receptor_content = receptor.read_text()
        console.print(f"Read receptor from {receptor}")

        # Build params
        params = {
            "receptor_content": receptor_content,
            "receptor_filename": receptor.stem,
            "center": [center_x, center_y, center_z],
            "size": [size_x, size_y, size_z],
            "forcefield": forcefield,
            "exhaustiveness": exhaustiveness,
            "num_modes": num_modes,
        }

        # Add ligand input
        if ligand:
            ligand_content = ligand.read_text()
            params["ligand_content"] = ligand_content
            params["ligand_filename"] = ligand.stem
            console.print(f"Read ligand from {ligand}")
        elif smiles:
            params["ligand_smiles"] = smiles
            console.print(f"Using SMILES: {smiles[:50]}{'...' if len(smiles) > 50 else ''}")

        # Parse flexible residues: "A:123,A:456,B:10" -> ["A:123", "A:456", "B:10"]
        if flex_residues:
            flex_list = [r.strip() for r in flex_residues.split(",") if r.strip()]
            # Validate format
            for res in flex_list:
                if ":" not in res:
                    console.print(
                        f"[red]Error:[/red] Invalid flex residue format '{res}'. Use 'CHAIN:RESNUM' (e.g., 'A:123')"
                    )
                    raise typer.Exit(1)
            params["flex_residues"] = flex_list

        if job_name:
            params["job_name"] = job_name

        run_tool_with_progress("autodock-vina", params, output)
