"""CLI entry point for yaml-doctor."""

from __future__ import annotations

import json
import sys
from pathlib import Path

import click
from rich.console import Console

from . import __version__
from .demo import DEMOS
from .models import LintResult, ScanResult
from .output.console import render_file_result, render_rules, render_scan_result
from .output.html_report import export_file_html, export_scan_html
from .rules import all_rules
from .scanner import scan_content, scan_directory, scan_file

console = Console()


def _result_to_dict(r: LintResult) -> dict:
    return {
        "file": r.file_path,
        "valid_yaml": r.valid_yaml,
        "file_type": r.file_type.value,
        "documents": r.documents,
        "score": r.score,
        "grade": r.grade.value,
        "findings": [
            {
                "rule": f.rule.rule_id,
                "severity": f.rule.severity.value,
                "message": f.message,
                "line": f.line,
                "fix": f.rule.fix,
            }
            for f in r.findings
        ],
    }


def _scan_to_dict(s: ScanResult) -> dict:
    return {
        "total_files": s.total_files,
        "total_findings": s.total_findings,
        "overall_score": s.overall_score,
        "overall_grade": s.overall_grade.value,
        "passed_files": s.passed_files,
        "failed_files": s.failed_files,
        "files": [_result_to_dict(r) for r in s.files],
    }


@click.group()
@click.version_option(__version__, prog_name="yaml-doctor")
def cli():
    """🩺 yaml-doctor — YAML Linter & Security Scanner.

    Lint Kubernetes, Docker Compose, GitHub Actions, GitLab CI, and generic
    YAML files with 60+ built-in rules covering security, best practices,
    and code quality.
    """


@cli.command()
@click.argument("file", type=click.Path(exists=True))
@click.option("--json-output", "-j", "json_out", type=click.Path(), help="Export JSON report")
@click.option("--html", type=click.Path(), help="Export HTML report")
@click.option("--type", "file_type", type=click.Choice(["kubernetes", "compose", "github-actions", "gitlab-ci", "yaml", "auto"], case_sensitive=False), default="auto", help="Force file type detection")
def lint(file: str, json_out: str | None, html: str | None, file_type: str):
    """Lint a single YAML file.

    Examples:

        yaml-doctor lint deployment.yaml

        yaml-doctor lint docker-compose.yml --html report.html
    """
    result = scan_file(file)
    render_file_result(result)

    if json_out:
        Path(json_out).write_text(json.dumps(_result_to_dict(result), indent=2), encoding="utf-8")
        console.print(f"[green]JSON report → {json_out}[/]")

    if html:
        export_file_html(result, html)
        console.print(f"[green]HTML report → {html}[/]")

    if result.score < 50:
        sys.exit(1)


@cli.command()
@click.argument("directory", type=click.Path(exists=True))
@click.option("--json-output", "-j", "json_out", type=click.Path(), help="Export JSON report")
@click.option("--html", type=click.Path(), help="Export HTML dashboard")
@click.option("--no-recursive", is_flag=True, help="Don't scan subdirectories")
def scan(directory: str, json_out: str | None, html: str | None, no_recursive: bool):
    """Scan a directory for YAML files.

    Examples:

        yaml-doctor scan ./k8s/

        yaml-doctor scan . --html report.html
    """
    scan_result = scan_directory(directory, recursive=not no_recursive)
    render_scan_result(scan_result)

    if json_out:
        Path(json_out).write_text(json.dumps(_scan_to_dict(scan_result), indent=2), encoding="utf-8")
        console.print(f"[green]JSON report → {json_out}[/]")

    if html:
        export_scan_html(scan_result, html)
        console.print(f"[green]HTML dashboard → {html}[/]")

    if scan_result.overall_score < 50:
        sys.exit(1)


@cli.command()
def rules():
    """Show all available lint rules (60 rules)."""
    render_rules(all_rules())


@cli.command()
@click.option("--type", "demo_type", type=click.Choice(["all", "kubernetes", "compose", "github-actions", "gitlab-ci", "yaml"], case_sensitive=False), default="all", help="Demo type")
@click.option("--html", type=click.Path(), help="Export HTML report")
@click.option("--json-output", "-j", "json_out", type=click.Path(), help="Export JSON report")
def demo(demo_type: str, html: str | None, json_out: str | None):
    """Run a demo scan with sample YAML files.

    Examples:

        yaml-doctor demo

        yaml-doctor demo --type kubernetes

        yaml-doctor demo --html demo-report.html
    """
    console.print()
    console.print("[bold blue]🩺 yaml-doctor — Demo Mode[/]")
    console.print("[dim]Scanning sample YAML files with intentional issues...[/]\n")

    if demo_type == "all":
        demos = list(DEMOS.items())
    else:
        demos = [(demo_type, DEMOS[demo_type])]

    results: list[LintResult] = []
    for name, (filename, content) in demos:
        result = scan_content(content, filename)
        results.append(result)
        render_file_result(result)

    # Build scan result
    scan_result = ScanResult()
    scan_result.files = results
    scan_result.total_files = len(results)
    scan_result.total_findings = sum(len(r.findings) for r in results)
    if results:
        scan_result.overall_score = sum(r.score for r in results) // len(results)
    from .models import grade_from_score
    scan_result.overall_grade = grade_from_score(scan_result.overall_score)

    from .output.console import _render_summary
    _render_summary(scan_result)

    if json_out:
        Path(json_out).write_text(json.dumps(_scan_to_dict(scan_result), indent=2), encoding="utf-8")
        console.print(f"[green]JSON report → {json_out}[/]")

    if html:
        export_scan_html(scan_result, html)
        console.print(f"[green]HTML demo report → {html}[/]")


@cli.command()
@click.argument("file", type=click.Path(exists=True))
def fix(file: str):
    """Show auto-fix suggestions for a YAML file.

    Examples:

        yaml-doctor fix deployment.yaml
    """
    result = scan_file(file)
    if not result.findings:
        console.print(f"[green]✓ {file} — no issues to fix![/]")
        return

    console.print(f"\n[bold]🔧 Fix suggestions for {file}[/]\n")
    for i, f in enumerate(result.findings, 1):
        if f.rule.fix:
            console.print(f"  [bold]{i}.[/] [{f.rule.severity.value}]{f.rule.rule_id}[/] — {f.message}")
            console.print(f"     [green]→ {f.rule.fix}[/]\n")
        else:
            console.print(f"  [bold]{i}.[/] [{f.rule.severity.value}]{f.rule.rule_id}[/] — {f.message}")
            console.print("     [dim]No auto-fix available[/]\n")
