#!/usr/bin/env python3
"""
Donjon Platform -- CLI Entry Point

Installed as the ``donjon`` console script via pip install.
"""
from __future__ import annotations

import os
import sys
import webbrowser
from pathlib import Path

# Ensure the project root is on sys.path so lib/scanners/web imports work
# regardless of how the package was installed.
_PROJECT_ROOT = Path(__file__).resolve().parent.parent
if str(_PROJECT_ROOT) not in sys.path:
    sys.path.insert(0, str(_PROJECT_ROOT))
os.environ.setdefault("DONJON_HOME", str(_PROJECT_ROOT))

VERSION_TAG = "7.5.0"

HELP_TEXT = f"""\
Donjon Platform v{VERSION_TAG} -- Security Intelligence CLI

Usage:
  donjon <command> [options]

Commands:
  quickstart       First-scan wizard: detect network, scan, generate report
  scan [options]   Run a security assessment
  demo             Run the automated demo
  dashboard        Launch the web dashboard
  report           Generate an HTML report from the last session
  version          Print version and exit
  help             Show this help

Scan options:
  --quick          Quick scan (host + network, ~5 min)
  --standard       Standard scan (all applicable scanners, 1-2 hrs)
  --deep           Deep scan (all scanners + AI analysis, 2-4 hrs)
  --targets CIDR   Target network(s), comma-separated (default: auto-detect)

Examples:
  donjon quickstart
  donjon scan --quick
  donjon scan --targets 192.168.1.0/24,10.0.0.0/24
  donjon dashboard
"""


def main(argv: list[str] | None = None) -> int:
    args = argv if argv is not None else sys.argv[1:]

    if not args or args[0] in ("help", "--help", "-h"):
        print(HELP_TEXT)
        return 0

    cmd = args[0]

    if cmd == "version":
        return _cmd_version()
    elif cmd == "demo":
        return _cmd_demo()
    elif cmd == "scan":
        return _cmd_scan(args[1:])
    elif cmd == "dashboard":
        return _cmd_dashboard(args[1:])
    elif cmd == "report":
        return _cmd_report(args[1:])
    elif cmd == "quickstart":
        return _cmd_quickstart(args[1:])
    else:
        print(f"Unknown command: {cmd}")
        print("Run 'donjon help' for usage.")
        return 1


# ── Commands ────────────────────────────────────────────────────────


def _cmd_version() -> int:
    from lib.config import Config
    cfg = Config()
    print(f"Donjon Platform v{cfg.DEFAULTS.get('version', VERSION_TAG)}")
    return 0


def _cmd_demo() -> int:
    """Run demo mode with simulated findings."""
    try:
        from lib.demo import run_demo
        run_demo()
        return 0
    except ImportError:
        # Fallback to tools/demo.py
        demo_path = _PROJECT_ROOT / "tools" / "demo.py"
        if not demo_path.exists():
            print("Error: demo module not found.")
            return 1
        import subprocess
        result = subprocess.run([sys.executable, str(demo_path)], cwd=str(_PROJECT_ROOT))
        return result.returncode


def _cmd_scan(args: list[str]) -> int:
    """Run a security assessment via the orchestrator."""
    scan_type = "standard"
    targets = None

    i = 0
    while i < len(args):
        if args[i] == "--quick":
            scan_type = "quick"
        elif args[i] == "--standard":
            scan_type = "standard"
        elif args[i] == "--deep":
            scan_type = "deep"
        elif args[i] == "--targets" and i + 1 < len(args):
            i += 1
            targets = [t.strip() for t in args[i].split(",") if t.strip()]
        else:
            print(f"Unknown scan option: {args[i]}")
            return 1
        i += 1

    from lib.orchestrator import AssessmentOrchestrator
    orch = AssessmentOrchestrator()
    result = orch.run_full_assessment(
        assessment_type=scan_type,
        targets=targets,
    )
    session_id = result.get("session_id", "unknown")
    findings = result.get("findings", [])
    print(f"\nAssessment complete. Session: {session_id}")
    print(f"  Findings: {len(findings)}")
    severity_counts = {}
    for f in findings:
        sev = (f.get("severity") or "INFO").upper()
        severity_counts[sev] = severity_counts.get(sev, 0) + 1
    for sev in ("CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"):
        if severity_counts.get(sev):
            print(f"  {sev}: {severity_counts[sev]}")
    return 0


def _cmd_dashboard(args: list[str]) -> int:
    """Start the web dashboard."""
    host = "0.0.0.0"
    port = 8443
    # Parse optional --port / --host
    i = 0
    while i < len(args):
        if args[i] == "--port" and i + 1 < len(args):
            i += 1
            port = int(args[i])
        elif args[i] == "--host" and i + 1 < len(args):
            i += 1
            host = args[i]
        i += 1

    print(f"Starting Donjon dashboard on http://{host}:{port}")
    from web.api import start_server
    start_server(host=host, port=port)
    return 0


def _cmd_report(args: list[str]) -> int:
    """Generate HTML report from the most recent (or specified) session."""
    session_id = args[0] if args else None

    if session_id is None:
        # Find the most recent session
        from lib.evidence import get_evidence_manager
        em = get_evidence_manager()
        sessions = em.get_sessions() if hasattr(em, "get_sessions") else []
        if not sessions:
            print("No scan sessions found. Run 'donjon scan' first.")
            return 1
        session_id = sessions[-1].get("session_id", sessions[-1].get("id"))

    from lib.interactive_report import generate
    html = generate(session_id)

    from lib.paths import paths
    report_dir = paths.results / session_id
    report_dir.mkdir(parents=True, exist_ok=True)
    report_path = report_dir / "report.html"
    report_path.write_text(html, encoding="utf-8")
    print(f"Report written to {report_path}")
    return 0


def _cmd_quickstart(args: list[str]) -> int:
    """First-scan wizard: detect network, confirm, scan, report, open browser."""
    print("=" * 60)
    print("  Donjon Platform -- Quick Start Wizard")
    print("=" * 60)
    print()

    # Step 1: Auto-detect local network
    from lib.network import NetworkDiscovery
    nd = NetworkDiscovery()
    networks = nd.get_private_networks()

    if not networks:
        print("Could not auto-detect a private network.")
        manual = input("Enter target network (e.g. 192.168.1.0/24): ").strip()
        if not manual:
            print("No target specified. Aborting.")
            return 1
        networks = [manual]

    target = networks[0]
    print(f"Detected network: {target}")
    confirm = input(f"Ready to scan [{target}]? (Y/n) ").strip().lower()
    if confirm in ("n", "no"):
        manual = input("Enter target network: ").strip()
        if not manual:
            print("No target specified. Aborting.")
            return 1
        target = manual

    # Step 2: Run a quick scan
    print()
    print(f"Scanning {target} (quick mode)...")
    print()

    from lib.orchestrator import AssessmentOrchestrator
    orch = AssessmentOrchestrator()
    result = orch.run_full_assessment(
        assessment_type="quick",
        targets=[target],
    )

    session_id = result.get("session_id", "unknown")
    findings = result.get("findings", [])
    print()
    print(f"Scan complete. {len(findings)} findings in session {session_id}.")

    # Step 3: Generate HTML report
    from lib.interactive_report import generate
    html = generate(session_id)

    from lib.paths import paths as donjon_paths
    report_dir = donjon_paths.results / session_id
    report_dir.mkdir(parents=True, exist_ok=True)
    report_path = report_dir / "report.html"
    report_path.write_text(html, encoding="utf-8")
    print(f"Report saved to {report_path}")

    # Step 4: Open in browser
    try:
        url = report_path.resolve().as_uri()
        webbrowser.open(url)
        print(f"Opened in browser: {url}")
    except Exception:
        print(f"Open manually: {report_path.resolve()}")

    print()
    print("Next steps:")
    print("  donjon scan --standard   # Full assessment")
    print("  donjon dashboard         # Web UI at http://localhost:8443")
    print("  donjon report            # Regenerate report")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
