"""CLI commands for ai-qa-sdk."""

import json
import sys
from pathlib import Path
from typing import Optional

import click
import yaml

from ai_qa import validate, list_checks, get_check
from .formatters import format_json, format_html, format_table


@click.command()
@click.option(
    "--output",
    required=True,
    help="The AI system's response (required)",
)
@click.option(
    "--input",
    default=None,
    help="The original prompt/query",
)
@click.option(
    "--checks",
    required=True,
    help="Comma-separated check names (e.g., factuality,relevance,toxicity)",
)
@click.option(
    "--threshold",
    type=float,
    default=None,
    help="Override default threshold for all checks (0.0-1.0)",
)
@click.option(
    "--ground-truth",
    default=None,
    help="Expected/correct answer for comparison",
)
@click.option(
    "--context",
    multiple=True,
    help="Retrieved context chunks for RAG validation (use multiple times)",
)
@click.option(
    "--format",
    type=click.Choice(["json", "table", "html"]),
    default="table",
    help="Output format",
)
@click.option(
    "--output-file",
    default=None,
    help="Save output to file (for JSON/HTML)",
)
@click.option(
    "--parallelism",
    type=int,
    default=None,
    help="Max concurrent LLM checks",
)
@click.option(
    "--cache/--no-cache",
    default=True,
    help="Enable/disable result caching",
)
def validate_cmd(
    output: str,
    input: Optional[str],
    checks: str,
    threshold: Optional[float],
    ground_truth: Optional[str],
    context: tuple,
    format: str,
    output_file: Optional[str],
    parallelism: Optional[int],
    cache: bool,
):
    """Validate AI outputs against a suite of checks.

    Example:
        ai-qa validate \\
            --output "Paris is the capital of France" \\
            --input "What is the capital of France?" \\
            --checks factuality,relevance
    """
    try:
        # Parse checks
        check_list = [c.strip() for c in checks.split(",")]

        # Parse context
        context_list = list(context) if context else None

        # Run validation
        result = validate(
            output=output,
            input=input,
            checks=check_list,
            threshold=threshold,
            ground_truth=ground_truth,
            context=context_list,
            parallelism=parallelism,
            cache=cache,
        )

        # Format output
        if format == "json":
            output_str = format_json(result)
        elif format == "html":
            output_str = format_html(result)
        else:  # table
            output_str = format_table(result)

        # Save or print
        if output_file:
            Path(output_file).write_text(output_str)
            click.echo(f"✅ Report saved to {output_file}", err=False)
        else:
            click.echo(output_str, err=False)

        # Exit with appropriate code
        sys.exit(0 if result.passed else 1)

    except Exception as e:
        click.echo(f"❌ Error: {str(e)}", err=True)
        sys.exit(2)


@click.command(name="checks")
@click.option("--format", type=click.Choice(["json", "table"]), default="table")
def checks_cmd(format: str):
    """List all available checks.

    Example:
        ai-qa checks
        ai-qa checks --format json
    """
    try:
        check_names = list_checks()

        # Get actual check instances
        checks = []
        for name in check_names:
            try:
                check = get_check(name)
                checks.append(check)
            except Exception:
                # Skip checks that can't be instantiated without parameters
                pass

        if format == "json":
            output = json.dumps(
                [
                    {
                        "name": check.name,
                        "description": check.description,
                        "requires_llm": check.requires_llm,
                        "version": check.version,
                        "threshold": check.threshold,
                    }
                    for check in checks
                ],
                indent=2,
            )
        else:  # table
            output = "Available Checks\n"
            output += "=" * 80 + "\n"
            output += f"{'Name':<20} {'Description':<40} {'LLM':<6} {'v':<8}\n"
            output += "-" * 80 + "\n"

            for check in checks:
                desc = (
                    check.description[:37] + "..."
                    if len(check.description) > 40
                    else check.description
                )
                llm = "Yes" if check.requires_llm else "No"
                output += f"{check.name:<20} {desc:<40} {llm:<6} {check.version:<8}\n"

            output += "-" * 80 + "\n"
            output += f"Total: {len(checks)} checks available\n"

        click.echo(output)

    except Exception as e:
        click.echo(f"❌ Error: {str(e)}", err=True)
        sys.exit(2)


@click.command()
@click.argument("suite_file", type=click.Path(exists=True))
@click.option(
    "--format",
    type=click.Choice(["json", "html", "table"]),
    default="table",
    help="Output format",
)
@click.option(
    "--output",
    default=None,
    help="Save report to file",
)
@click.option(
    "--parallelism",
    type=int,
    default=None,
    help="Max concurrent LLM checks",
)
@click.option(
    "--cache/--no-cache",
    default=True,
    help="Enable/disable result caching",
)
def suite_cmd(
    suite_file: str,
    format: str,
    output: Optional[str],
    parallelism: Optional[int],
    cache: bool,
):
    """Run a test suite from JSON or YAML file.

    Example:
        ai-qa suite run tests.json --format html --output report.html
        ai-qa suite run tests.yaml --format table
    """
    try:
        suite_path = Path(suite_file)

        # Load test cases
        if suite_path.suffix == ".json":
            with open(suite_path) as f:
                test_cases = json.load(f)
        elif suite_path.suffix in [".yaml", ".yml"]:
            with open(suite_path) as f:
                test_cases = yaml.safe_load(f)
        else:
            click.echo(
                "❌ Error: File must be .json or .yaml/.yml",
                err=True,
            )
            sys.exit(2)

        # Handle different file structures
        if isinstance(test_cases, dict):
            if "test_cases" in test_cases:
                test_cases = test_cases["test_cases"]
            elif "test_suites" in test_cases:
                # Flatten test suites
                flattened = []
                for suite in test_cases["test_suites"]:
                    flattened.extend(suite.get("test_cases", []))
                test_cases = flattened

        if not isinstance(test_cases, list):
            click.echo(
                "❌ Error: File must contain list of test cases or test suites",
                err=True,
            )
            sys.exit(2)

        # Run all test cases
        all_results = []
        passed = 0
        failed = 0

        with click.progressbar(
            test_cases,
            label="Running tests",
            show_pos=True,
        ) as bar:
            for i, test_case in enumerate(bar):
                try:
                    result = validate(
                        output=test_case["output"],
                        input=test_case.get("input"),
                        checks=test_case.get("checks", []),
                        ground_truth=test_case.get("ground_truth"),
                        context=test_case.get("context"),
                        threshold=test_case.get("threshold"),
                        parallelism=parallelism,
                        cache=cache,
                    )

                    test_id = test_case.get("test_id", f"test_{i+1}")
                    category = test_case.get("category", "uncategorized")

                    if result.passed:
                        passed += 1
                        status = "PASS"
                    else:
                        failed += 1
                        status = "FAIL"

                    # Calculate pass rate
                    passed_count = sum(1 for c in result.checks if c.passed)
                    total_checks = len(result.checks)
                    passed_rate = passed_count / total_checks if total_checks > 0 else 0

                    all_results.append({
                        "test_id": test_id,
                        "category": category,
                        "status": status,
                        "passed_rate": passed_rate,
                        "checks": [
                            {
                                "name": c.name,
                                "score": c.score,
                                "passed": c.passed,
                                "threshold": c.threshold,
                                "evidence": c.evidence,
                                "cost_usd": c.cost_usd,
                            }
                            for c in result.checks
                        ],
                        "cost_usd": result.total_cost,
                    })

                except Exception as e:
                    test_id = test_case.get("test_id", f"test_{i+1}")
                    category = test_case.get("category", "uncategorized")
                    failed += 1

                    all_results.append({
                        "test_id": test_id,
                        "category": category,
                        "status": "ERROR",
                        "error": str(e),
                    })

        # Format output
        if format == "json":
            output_str = json.dumps(
                {
                    "total": len(test_cases),
                    "passed": passed,
                    "failed": failed,
                    "pass_rate": passed / len(test_cases) * 100 if test_cases else 0,
                    "results": all_results,
                },
                indent=2,
            )
        elif format == "html":
            output_str = _format_suite_html(all_results, passed, failed, len(test_cases))
        else:  # table
            output_str = _format_suite_table(all_results, passed, failed, len(test_cases))

        # Save or print
        if output:
            Path(output).write_text(output_str)
            click.echo(f"\n✅ Report saved to {output}", err=False)
        else:
            click.echo(f"\n{output_str}", err=False)

        click.echo(f"\n📊 Results: {passed}/{len(test_cases)} passed ({passed/len(test_cases)*100:.1f}%)")

    except Exception as e:
        click.echo(f"❌ Error: {str(e)}", err=True)
        sys.exit(2)


def _format_suite_table(results, passed, failed, total):
    """Format suite results as table."""
    output = "\nTest Suite Results\n"
    output += "=" * 100 + "\n"
    output += f"{'Test ID':<20} {'Category':<20} {'Status':<10} {'Pass Rate':<12}\n"
    output += "-" * 100 + "\n"

    for result in results:
        status = result["status"]
        test_id = result["test_id"]
        category = result["category"]
        pass_rate = f"{result.get('passed_rate', 0)*100:.1f}%" if "passed_rate" in result else "N/A"

        output += f"{test_id:<20} {category:<20} {status:<10} {pass_rate:<12}\n"

    output += "-" * 100 + "\n"
    output += f"Total: {total} | Passed: {passed} | Failed: {failed} | Pass Rate: {passed/total*100:.1f}%\n"

    return output


def _format_suite_html(results, passed, failed, total):
    """Format suite results as HTML."""
    html = f"""<!DOCTYPE html>
<html>
<head>
    <title>AI-QA Test Suite Report</title>
    <style>
        body {{ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; margin: 0; background: #f5f5f5; }}
        .container {{ max-width: 1200px; margin: 0 auto; padding: 20px; }}
        .header {{ background: #2c3e50; color: white; padding: 30px; border-radius: 8px; margin-bottom: 30px; }}
        .header h1 {{ margin: 0; font-size: 28px; }}
        .summary {{ display: grid; grid-template-columns: repeat(4, 1fr); gap: 15px; margin-bottom: 30px; }}
        .stat {{ background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }}
        .stat-value {{ font-size: 32px; font-weight: bold; margin: 0; }}
        .stat-label {{ color: #7f8c8d; margin-top: 5px; }}
        .passed {{ color: #27ae60; }}
        .failed {{ color: #e74c3c; }}
        table {{ width: 100%; border-collapse: collapse; background: white; margin-top: 20px; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }}
        th {{ background: #34495e; color: white; padding: 12px; text-align: left; font-weight: 600; }}
        td {{ padding: 12px; border-bottom: 1px solid #ecf0f1; }}
        tr:hover {{ background: #f9f9f9; }}
        .pass {{ background: #d4edda; color: #155724; }}
        .fail {{ background: #f8d7da; color: #721c24; }}
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🧪 AI-QA Test Suite Report</h1>
            <p style="margin: 10px 0 0 0; opacity: 0.9;">Test Results & Validation</p>
        </div>

        <div class="summary">
            <div class="stat">
                <div class="stat-value">{total}</div>
                <div class="stat-label">Total Tests</div>
            </div>
            <div class="stat">
                <div class="stat-value passed">{passed}</div>
                <div class="stat-label">Passed ✓</div>
            </div>
            <div class="stat">
                <div class="stat-value failed">{failed}</div>
                <div class="stat-label">Failed ✗</div>
            </div>
            <div class="stat">
                <div class="stat-value">{passed/total*100:.1f}%</div>
                <div class="stat-label">Pass Rate</div>
            </div>
        </div>

        <table>
            <thead>
                <tr>
                    <th>Test ID</th>
                    <th>Category</th>
                    <th>Status</th>
                    <th>Pass Rate</th>
                </tr>
            </thead>
            <tbody>
"""

    for result in results:
        status = result["status"]
        test_id = result["test_id"]
        category = result["category"]
        pass_rate = f"{result.get('passed_rate', 0)*100:.1f}%" if "passed_rate" in result else "N/A"

        status_class = "pass" if status == "PASS" else "fail"
        html += f'                <tr><td>{test_id}</td><td>{category}</td><td><span class="{status_class}">{status}</span></td><td>{pass_rate}</td></tr>\n'

    html += """            </tbody>
        </table>
    </div>
</body>
</html>
"""

    return html
