#!/usr/bin/env python3
"""
Manager that schedules runs (sync + background) and writes results to DB.

This manager contains a small built-in adapter for "nmap" that uses your existing
souleyez.scanner.run_nmap function. Later plugins can be added by implementing
ScannerPlugin in their own modules and registering them here.
"""

import importlib
import threading
from typing import Optional

from ..storage.db import init_db, insert_scan, update_scan
from ..utils import timestamp_str

# lazy import existing run_nmap (your project has souleyez/scanner.py)


def _run_nmap_adapter(target, args, label, save_xml=False):
    from .. import scanner as scanner_module

    # scanner.run_nmap should return (logpath, rc, xmlpath, summary)
    return scanner_module.run_nmap(target, args, label, save_xml=save_xml)


def run_scan_sync(
    tool: str,
    target: str,
    args: list,
    label: Optional[str] = None,
    save_xml: bool = False,
) -> int:
    """
    Run a scan synchronously and return the DB scan id.
    Currently supports 'nmap' as a built-in. Creates a DB record, runs, updates DB.
    """
    init_db()
    ts = timestamp_str()
    entry = {
        "ts": ts,
        "tool": tool,
        "target": target,
        "label": label,
        "args": args,
        "log": None,
        "xml": None,
        "summary": {},
        "per_host": [],
        "status": "pending",
        "rc": None,
    }
    scan_id = insert_scan(entry)

    try:
        if tool.lower() == "nmap":
            logpath, rc, xmlpath, summary = _run_nmap_adapter(
                target, args, label, save_xml=save_xml
            )
            # ensure per_host in summary (some parsers provide it)
            per_host = summary.get("per_host") if isinstance(summary, dict) else []
            update_scan(
                scan_id,
                status="done",
                rc=rc,
                log=logpath,
                xml=xmlpath,
                summary=summary,
                per_host=per_host,
            )
        else:
            # try to import a plugin module by convention souleyez.plugins.<tool>
            try:
                mod = importlib.import_module(f"souleyez.plugins.{tool}")
                PluginClass = getattr(mod, "Plugin", None)
                if PluginClass:
                    plugin = PluginClass()
                    prepared = plugin.prepare(target, args, label)
                    result = plugin.run(prepared)
                    update_scan(
                        scan_id,
                        status=result.get("status", "done"),
                        rc=result.get("rc"),
                        log=result.get("log"),
                        xml=result.get("xml"),
                        summary=result.get("summary"),
                        per_host=result.get("per_host"),
                    )
                else:
                    update_scan(scan_id, status="failed")
            except Exception:
                update_scan(scan_id, status="failed")
    except Exception:
        update_scan(scan_id, status="failed")
    return scan_id


def run_scan_background(
    tool: str,
    target: str,
    args: list,
    label: Optional[str] = None,
    save_xml: bool = False,
) -> int:
    """
    Run the scan in a background thread and return the DB id immediately.
    """
    init_db()
    ts = timestamp_str()
    entry = {
        "ts": ts,
        "tool": tool,
        "target": target,
        "label": label,
        "args": args,
        "log": None,
        "xml": None,
        "summary": {},
        "per_host": [],
        "status": "pending",
        "rc": None,
    }
    scan_id = insert_scan(entry)

    def worker(sid):
        try:
            # reuse sync runner to keep logic centralized
            run_scan_sync(tool, target, args, label, save_xml=save_xml)
        except Exception:
            update_scan(sid, status="failed")

    t = threading.Thread(target=worker, args=(scan_id,), daemon=True)
    t.start()
    return scan_id
