"""
Main CLI entry point for cybersec-scanner.

Provides command-line interface with YAML configuration support
and individual scanner commands.
"""

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

from ..__version__ import __version__
from ..exceptions import CyberSecScannerError
from .config import load_config, create_default_config, validate_config


def cmd_scan(args):
    """Execute full scan with all enabled scanners."""
    from .. import scan_all
    
    try:
        if args.config:
            config = load_config(args.config)
            validate_config(config)
            results = scan_all(config_file=args.config)
        else:
            # Use command-line arguments
            config = {
                "enable_git": args.git,
                "enable_web": args.web,
                "enable_mitm": args.mitm,
                "enable_runtime": args.runtime,
                "root": args.root,
                "target": args.target,
                "max_commits": args.max_commits,
                "mitm_traffic": args.mitm_traffic,
            }
            results = scan_all(**config)
        
        # Save results
        output_file = args.output or "audit_report.json"
        all_findings = []
        for scanner_type, findings in results.items():
            all_findings.extend(findings)
        
        report = {"findings": all_findings}
        with open(output_file, "w", encoding="utf-8") as f:
            json.dump(report, f, indent=2)
        
        print(f"✓ Scan complete. Found {len(all_findings)} findings.")
        print(f"✓ Report saved to: {output_file}")
        
        # Build RAG if enabled
        if args.enable_rag or (args.config and config.get("rag", {}).get("enabled")):
            from ..rag import KnowledgeGraph
            kg = KnowledgeGraph()
            kg.build_from_audit(Path(output_file))
            kg.save()
            print("✓ Knowledge graph built successfully")
        
        return 0
    except CyberSecScannerError as e:
        print(f"✗ Error: {e}", file=sys.stderr)
        return 1


def cmd_scan_git(args):
    """Execute git-only scan."""
    from .. import scan_git
    
    try:
        findings = scan_git(args.root, max_commits=args.max_commits)
        
        output_file = args.output or "git_findings.json"
        with open(output_file, "w", encoding="utf-8") as f:
            json.dump({"findings": findings}, f, indent=2)
        
        print(f"✓ Git scan complete. Found {len(findings)} findings.")
        print(f"✓ Report saved to: {output_file}")
        return 0
    except Exception as e:
        print(f"✗ Git scan failed: {e}", file=sys.stderr)
        return 1


def cmd_scan_web(args):
    """Execute web-only scan."""
    from .. import scan_web
    
    try:
        findings = scan_web(args.url, max_pages=args.max_pages)
        
        output_file = args.output or "web_findings.json"
        with open(output_file, "w", encoding="utf-8") as f:
            json.dump({"findings": findings}, f, indent=2)
        
        print(f"✓ Web scan complete. Found {len(findings)} findings.")
        print(f"✓ Report saved to: {output_file}")
        return 0
    except Exception as e:
        print(f"✗ Web scan failed: {e}", file=sys.stderr)
        return 1


def cmd_query(args):
    """Query findings using RAG system."""
    from ..rag import query_graph_and_llm, KnowledgeGraph, Retriever
    
    try:
        # Load or build graph
        graph_path = Path(args.graph or "rag/graph.gpickle")
        if not graph_path.exists():
            if not args.audit:
                print("✗ No graph found. Provide --audit to build graph first.", file=sys.stderr)
                return 1
            
            print(f"Building knowledge graph from {args.audit}...")
            kg = KnowledgeGraph()
            kg.build_from_audit(Path(args.audit))
            kg.save(graph_path)
            print("✓ Graph built successfully")
        
        # Query
        print(f"Querying: {args.question}")
        answer = query_graph_and_llm(
            args.question,
            graph_path=str(graph_path),
            model=args.model,
            k=args.top_k,
        )
        
        print("\n" + "="*60)
        print(answer)
        print("="*60)
        return 0
    except Exception as e:
        print(f"✗ Query failed: {e}", file=sys.stderr)
        return 1


def cmd_build_graph(args):
    """Build knowledge graph from audit report."""
    from ..rag import KnowledgeGraph
    
    try:
        audit_path = Path(args.audit)
        if not audit_path.exists():
            print(f"✗ Audit report not found: {audit_path}", file=sys.stderr)
            return 1
        
        print(f"Building knowledge graph from {audit_path}...")
        kg = KnowledgeGraph()
        kg.build_from_audit(audit_path)
        
        output_path = Path(args.output) if args.output else Path("rag/graph.gpickle")
        kg.save(output_path)
        
        stats = kg.stats()
        print("✓ Knowledge graph built successfully")
        print(f"  Findings: {stats['findings']}")
        print(f"  CWE nodes: {stats['cwes']}")
        print(f"  OWASP nodes: {stats['owasps']}")
        print(f"  Saved to: {output_path}")
        return 0
    except Exception as e:
        print(f"✗ Graph building failed: {e}", file=sys.stderr)
        return 1


def cmd_init_config(args):
    """Create default configuration file."""
    output = args.output or "cybersec-config.yaml"
    try:
        create_default_config(output)
        print(f"✓ Created configuration file: {output}")
        print("  Edit this file and use: cybersec-scanner scan --config " + output)
        return 0
    except Exception as e:
        print(f"✗ Failed to create config: {e}", file=sys.stderr)
        return 1


def cmd_version(args):
    """Show version information."""
    from ..__version__ import __title__, __description__
    print(f"{__title__} v{__version__}")
    print(__description__)
    return 0


def main():
    """Main CLI entry point."""
    parser = argparse.ArgumentParser(
        prog="cybersec-scanner",
        description="Comprehensive security scanner and vulnerability analyzer",
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    
    parser.add_argument(
        "--version",
        action="version",
        version=f"%(prog)s {__version__}",
    )
    
    subparsers = parser.add_subparsers(dest="command", help="Available commands")
    
    # Scan command (full scan with config)
    scan_parser = subparsers.add_parser("scan", help="Run security scan")
    scan_parser.add_argument("--config", "-c", help="YAML configuration file")
    scan_parser.add_argument("--output", "-o", help="Output file for audit report")
    scan_parser.add_argument("--git", action="store_true", help="Enable git scanner")
    scan_parser.add_argument("--web", action="store_true", help="Enable web scanner")
    scan_parser.add_argument("--mitm", action="store_true", help="Enable MITM scanner")
    scan_parser.add_argument("--runtime", action="store_true", help="Enable runtime scanner")
    scan_parser.add_argument("--root", default=".", help="Root directory for git scan")
    scan_parser.add_argument("--target", help="Target URL for web scan")
    scan_parser.add_argument("--max-commits", type=int, default=50, help="Max git commits to scan")
    scan_parser.add_argument("--mitm-traffic", help="MITM traffic file path")
    scan_parser.add_argument("--enable-rag", action="store_true", help="Build knowledge graph after scan")
    scan_parser.set_defaults(func=cmd_scan)
    
    # Scan-git command (git only)
    git_parser = subparsers.add_parser("scan-git", help="Scan git repository only")
    git_parser.add_argument("root", nargs="?", default=".", help="Git repository path")
    git_parser.add_argument("--max-commits", type=int, default=50, help="Max commits to scan")
    git_parser.add_argument("--output", "-o", help="Output file")
    git_parser.set_defaults(func=cmd_scan_git)
    
    # Scan-web command (web only)
    web_parser = subparsers.add_parser("scan-web", help="Scan web application only")
    web_parser.add_argument("url", help="Target URL to scan")
    web_parser.add_argument("--max-pages", type=int, default=50, help="Max pages to crawl")
    web_parser.add_argument("--output", "-o", help="Output file")
    web_parser.set_defaults(func=cmd_scan_web)
    
    # Query command
    query_parser = subparsers.add_parser("query", help="Query findings using RAG")
    query_parser.add_argument("question", help="Question to ask")
    query_parser.add_argument("--audit", help="Audit report (if graph doesn't exist)")
    query_parser.add_argument("--graph", help="Knowledge graph file")
    query_parser.add_argument("--model", default="gemma3:1b", help="LLM model to use")
    query_parser.add_argument("--top-k", type=int, default=5, help="Number of findings to retrieve")
    query_parser.set_defaults(func=cmd_query)
    
    # Build-graph command
    graph_parser = subparsers.add_parser("build-graph", help="Build knowledge graph from audit report")
    graph_parser.add_argument("audit", help="Audit report JSON file")
    graph_parser.add_argument("--output", "-o", help="Output graph file")
    graph_parser.set_defaults(func=cmd_build_graph)
    
    # Init-config command
    config_parser = subparsers.add_parser("init-config", help="Create default configuration file")
    config_parser.add_argument("--output", "-o", help="Output config file path")
    config_parser.set_defaults(func=cmd_init_config)
    
    # Version command
    version_parser = subparsers.add_parser("version", help="Show version information")
    version_parser.set_defaults(func=cmd_version)
    
    args = parser.parse_args()
    
    if not args.command:
        parser.print_help()
        return 1
    
    return args.func(args)


if __name__ == "__main__":
    sys.exit(main())
