import overseer
from overseer.api import open_websockets
from flask import Blueprint, request
from flask_socketio import SocketIO

# Setup blueprint & websocket
bp = Blueprint("v1", __name__, url_prefix="/api/v1")
socketio = SocketIO(overseer.app, path="/api/v1/socket.io")
open_websockets.append(socketio)


@bp.route("/status", methods=["GET"])
def get_status():
    """Get server version and all active scans."""
    return {
        "version": overseer.__version__,
        "active_scans": overseer.scan_manager.get_status(),
    }


@bp.route("/scans", methods=["POST"])
def post_scans():
    """
    POST:
        REQUEST: /api/v1/scans
        DATA: { target: 'www.google.com' }

        RESPONSE: { status: "started" }
    """
    data = request.get_json()
    if data is None or "target" not in data:
        return {"error": "Missing target"}, 422

    if data["target"].strip() == "":
        return {"error": "Invalid target"}, 422

    scan_history = overseer.scan_manager.perform_scan(data["target"])
    if scan_history is None:
        return {"error": "Unable to resolve hostname"}, 422

    return __normalize_scan_results([scan_history], data["target"])[0]


@bp.route("/scans/<string:target>", methods=["GET"])
def get_scans_by_target(target):
    """
    GET:
        REQUEST: /api/v1/scans/www.google.com
                 /api/v1/scans/1.1.1.1
        RESPONSE: { "data": [ <ARRAY_OF_SCAN_HISTORY> ] }
    """
    page = 1  # TODO: Pagination

    if overseer.scan_manager.is_ip(target):
        scan_results = overseer.database.get_scan_results_by_target(
            page, ip_addr=target
        )
    else:
        scan_results = overseer.database.get_scan_results_by_target(
            page, hostname=target
        )

    return {"data": __normalize_scan_results(scan_results, target)}


@bp.route("/search", methods=["GET"])
def get_scans(search):
    """Not Implemented
    GET:
        REQUEST: /api/v1/search?query=1.1.1.1
                 /api/v1/search?query=192.168.0.0/24
                 /api/v1/search?query=www.google.com&page=2
        RESPONSE: { data: [ <ARRAY_OF_TARGETS> ] }
    """
    return "SEARCH PLACEHOLDER"


def __normalize_scan_results(scan_results, target):
    """Returns a normalized list of objects for ScanHistory items"""
    return list(
        map(
            lambda x: {
                "id": x.id,
                "target": target,
                "status": x.status,
                "results": x.results.split(",") if x.results != "" else [],
                "created_at": x.created_at.isoformat(),
                "error": x.error,
            },
            scan_results,
        )
    )
