# src/fmatch/algorithm_selection/cli.py
"""
CLI tool for testing and debugging algorithm selection rules.
"""

import click
import pandas as pd
import json
from pathlib import Path
from typing import Optional

from fmatch.engine import ExoticDataDetector, _get_semantic_type
from fmatch.algorithm_selection.rule_engine import get_algorithm_selection_engine
from fmatch.engine_algorithm_integration import (
    create_column_profile_for_algorithm_selection,
)


@click.group()
def cli():
    """Algorithm selection rule testing tool."""
    pass


@cli.command()
@click.argument("csv_file", type=click.Path(exists=True))
@click.option("--column", "-c", help="Specific column to analyze")
@click.option("--sample-size", "-s", default=1000, help="Sample size for analysis")
def analyze(csv_file: str, column: Optional[str], sample_size: int):
    """Analyze a CSV file and show algorithm recommendations."""
    # Load data
    df = pd.read_csv(csv_file, nrows=sample_size)

    click.echo(f"Loaded {len(df)} rows from {csv_file}")
    click.echo(f"Columns: {', '.join(df.columns)}")
    click.echo()

    # Determine which columns to analyze
    columns_to_analyze = [column] if column else df.columns.tolist()

    engine = get_algorithm_selection_engine()

    for col_name in columns_to_analyze:
        if col_name not in df.columns:
            click.echo(f"Column '{col_name}' not found in file")
            continue

        click.echo(f"=== Analyzing column: {col_name} ===")

        # Get basic stats
        series = df[col_name]

        # Basic metrics
        metrics = {
            "unique_ratio": series.nunique() / len(series),
            "null_ratio": series.isnull().sum() / len(series),
            "avg_length": series.astype(str).str.len().mean()
            if series.dtype == "object"
            else 0,
        }

        # Semantic type
        semantic_type = _get_semantic_type(col_name, series)
        if semantic_type:
            metrics["semantic_type"] = semantic_type

        # Exotic data detection
        exotic_profile = None
        if ExoticDataDetector:
            exotic_profile = ExoticDataDetector.detect_characteristics(series)

        # Create unified profile
        profile = create_column_profile_for_algorithm_selection(metrics, exotic_profile)

        # Show profile
        click.echo("Column Profile:")
        for key, value in profile.items():
            if value is not None and value != 0 and value != False:
                click.echo(f"  {key}: {value}")

        # Get algorithm recommendations
        recommendations = engine.select_algorithms(profile)

        click.echo("\nAlgorithm Recommendations:")
        for algo, score in recommendations[:5]:
            bar = "█" * int(score * 20)
            click.echo(f"  {algo:15} {score:.3f} {bar}")

        click.echo()


@cli.command()
@click.argument("rules_dir", type=click.Path(exists=True))
def validate(rules_dir: str):
    """Validate YAML rule files."""
    import yaml

    rules_path = Path(rules_dir)
    errors = []

    for yaml_file in rules_path.glob("*.yaml"):
        click.echo(f"Validating {yaml_file.name}...")

        try:
            with open(yaml_file, "r", encoding="utf-8") as f:
                data = yaml.safe_load(f)

            if "rules" not in data:
                errors.append(f"{yaml_file.name}: Missing 'rules' key")
                continue

            for i, rule in enumerate(data["rules"]):
                # Check required fields
                if "name" not in rule:
                    errors.append(f"{yaml_file.name}: Rule {i} missing 'name'")
                if "preferred_algorithms" not in rule:
                    errors.append(
                        f"{yaml_file.name}: Rule {i} missing 'preferred_algorithms'"
                    )

                # Validate algorithm names
                if "preferred_algorithms" in rule:
                    from fmatch.engine import ALGORITHM_MAP

                    for algo in rule["preferred_algorithms"]:
                        if algo not in ALGORITHM_MAP:
                            errors.append(
                                f"{yaml_file.name}: Rule '{rule.get('name', i)}' "
                                f"references unknown algorithm '{algo}'"
                            )

            click.echo(f"  ✓ {len(data.get('rules', []))} rules")

        except Exception as e:
            errors.append(f"{yaml_file.name}: {str(e)}")

    if errors:
        click.echo("\nErrors found:")
        for error in errors:
            click.echo(f"  ✗ {error}")
        raise click.ClickException("Validation failed")
    else:
        click.echo("\n✓ All rules valid")


@cli.command()
def list_rules():
    """List all loaded rules."""
    engine = get_algorithm_selection_engine()

    click.echo(f"Total rules loaded: {len(engine.rules)}")
    click.echo()

    for rule in engine.rules:
        click.echo(f"Rule: {rule.name}")
        click.echo(f"  Priority: {rule.priority}")
        click.echo(f"  Description: {rule.description}")
        click.echo(f"  Conditions: {json.dumps(rule.conditions, indent=4)}")
        click.echo(f"  Algorithms: {', '.join(rule.preferred_algorithms)}")
        click.echo()


if __name__ == "__main__":
    cli()
