"""RMSD Analysis tool for the Amina CLI.

Full-featured RMSD analysis with support for:
- Active site-specific RMSD
- Per-chain breakdown
- Chain mapping for different chain IDs
"""

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

METADATA = {
    "name": "rmsd-analysis",
    "display_name": "RMSD Analysis",
    "category": "analysis",
    "description": "Calculate RMSD between two protein structures with active site support",
    "modal_function_name": "rmsd_analysis_worker",
    "modal_app_name": "rmsd-analysis-api",
    "status": "available",
    "outputs": {
        "csv_filepath": "CSV file with per-residue RMSD data",
        "plot_filepath": "RMSD histogram plot (PNG)",
    },
    "output_display": {
        "sections": [
            {
                "title": "RMSD Results",
                "fields": [
                    {"key": "rmsd_backbone_only", "label": "Backbone RMSD", "format": "{:.4f} \u00c5"},
                    {"key": "rmsd_active_site_only", "label": "Active Site RMSD", "format": "{:.4f} \u00c5"},
                    {"key": "rmsd_active_plus_backbone", "label": "Active + Backbone RMSD", "format": "{:.4f} \u00c5"},
                ],
            },
        ],
    },
}

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("rmsd-analysis")
    def run_rmsd(
        main: Path = typer.Option(
            ...,
            "--main",
            "-m",
            help="Path to main/query structure (PDB file)",
            exists=True,
        ),
        reference: Path = typer.Option(
            ...,
            "--reference",
            "-r",
            help="Path to reference structure (PDB file)",
            exists=True,
        ),
        active_main: Optional[str] = typer.Option(
            None,
            "--active-main",
            "--active-residues-main",
            help="Active site residues in main structure (e.g., 'A:30,A:105,B:42')",
        ),
        active_ref: Optional[str] = typer.Option(
            None,
            "--active-ref",
            "--active-residues-reference",
            help="Active site residues in reference structure (if numbering differs)",
        ),
        chain_mapping: Optional[str] = typer.Option(
            None,
            "--chain-mapping",
            help='Map reference chains to main chains as JSON (e.g., \'{"A": "C", "B": "D"}\')',
        ),
        save_plot: bool = typer.Option(
            True,
            "--save-plot/--no-plot",
            help="Generate RMSD histogram plots",
        ),
        save_csv: bool = typer.Option(
            True,
            "--save-csv/--no-csv",
            help="Save CSV with per-residue RMSD",
        ),
        verbose: bool = typer.Option(
            False,
            "--verbose/--quiet",
            help="Print detailed calculation info",
        ),
        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)",
        ),
    ):
        """
        Calculate RMSD between two protein structures with optional active site analysis.

        RMSD (Root Mean Square Deviation) measures structural similarity between two
        protein conformations. This tool supports:

        - Backbone RMSD: Overall structural similarity
        - Active site RMSD: Focused analysis of specific residues
        - Per-chain breakdown: RMSD for each chain separately
        - Chain mapping: Handle structures with different chain naming

        Typical RMSD interpretations:
        - < 1.0 \u00c5: Very similar (same fold, minor differences)
        - 1.0-2.0 \u00c5: Similar (same fold, some loop variations)
        - 2.0-4.0 \u00c5: Moderately similar
        - > 4.0 \u00c5: Significantly different structures

        Examples:
            # Basic RMSD between two structures
            amina run rmsd -m designed.pdb -r native.pdb -o ./results/

            # With active site analysis
            amina run rmsd -m model.pdb -r reference.pdb --active-main "A:30,A:105" -o ./results/

            # Different active site numbering in reference
            amina run rmsd -m mutant.pdb -r wildtype.pdb \\
                --active-main "A:30,A:105" --active-ref "A:32,A:107" -o ./results/

            # With chain mapping (reference A->main C)
            amina run rmsd -m complex.pdb -r reference.pdb \\
                --chain-mapping '{"A": "C", "B": "D"}' -o ./results/
        """
        # Validate required options
        if output is None:
            console.print("[red]Error:[/red] --output / -o is required")
            raise typer.Exit(1)

        # Read file contents
        main_content = main.read_text()
        reference_content = reference.read_text()
        console.print(f"Read main structure from {main}")
        console.print(f"Read reference structure from {reference}")

        # Build params matching the worker's expected fields
        params = {
            "main_pdb_content": main_content,
            "main_filename": main.name,
            "reference_pdb_content": reference_content,
            "reference_filename": reference.name,
            "save_plot": save_plot,
            "save_csv": save_csv,
            "verbose": verbose,
        }

        # Add active site residues if provided
        if active_main:
            params["active_residues_main"] = active_main
            console.print(f"Active site residues (main): {active_main}")

        if active_ref:
            params["active_residues_reference"] = active_ref
            console.print(f"Active site residues (reference): {active_ref}")

        # Parse and validate chain mapping
        if chain_mapping:
            try:
                mapping = json.loads(chain_mapping)
                if not isinstance(mapping, dict):
                    console.print("[red]Error:[/red] --chain-mapping must be a JSON object")
                    raise typer.Exit(1)
                params["chain_mapping"] = mapping
                console.print(f"Chain mapping: {mapping}")
            except json.JSONDecodeError as e:
                console.print(f"[red]Error:[/red] Invalid JSON in --chain-mapping: {e}")
                raise typer.Exit(1)

        if job_name:
            params["job_name"] = job_name

        run_tool_with_progress("rmsd-analysis", params, output)
