#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (C) 2019 tribe29 GmbH - License: GNU General Public License v2
# This file is part of Checkmk (https://checkmk.com). It is subject to the terms and
# conditions defined in the file COPYING, which is part of this source code package.
"""
<<<prism_alerts:sep(0)>>>
["timestamp", "severity", "message", "context"]
[1594904735396095, "kWarning", "Disk space usage for root on Controller VM 10.19.34.121 has exceeded 80%.", {}]
[1594857282558164, "kCritical", "File Server space usage for tk2sydafs1 is at 100%.", {}]
[1594776768272094, "kWarning", "The CVM is not synchronizing time with any external servers. [check_cvm_ntp_sync][3026]NTP leader is not synchronizing to an external NTP server", {"vm_type": "CVM"}]
"""
import json
from datetime import datetime
from typing import Any, Dict, Mapping, Sequence, Tuple

Section = Sequence[Dict[Any, Any]]
StringMap = Mapping[str, str]


def parse_prism_alerts(info: Sequence[Sequence[str]]) -> Section:
    """Every line is a JSON string, first line is a header row used for keys in a dict
    >>> for line in parse_prism_alerts([
    ...     ['["name", "version", "context"]'],
    ...     ['["Unnamed", "5.16.1.3", {}]'],
    ...     ['["Named", "6.16.1.3", {"vm_type": "Prism Central VM"}]']]):
    ...   print(line)
    {'name': 'Unnamed', 'version': '5.16.1.3', 'context': {}}
    {'name': 'Named', 'version': '6.16.1.3', 'context': {'vm_type': 'Prism Central VM'}}
    """
    return [
        dict(zip(header, row))  #
        for header, *data in ((json.loads(line[0]) for line in info),)
        for row in data
    ]


def severity(name: str) -> Tuple[int, int]:
    # first value is for sorting second is the nagios status codes
    return {
        "kInfo": (0, 0),
        "kWarning": (1, 1),
        "kCritical": (3, 2),
    }.get(name, (2, 3))


def inventory_prism_alerts(parsed: Section) -> Any:
    """We cannot guess items from alerts, since an empty list of alerts does not mean there are
    no items to monitor"""
    yield None, {}


def to_string(timestamp: str) -> str:
    """Turn a textual timestamp in microseconds into a readable format"""
    return datetime.fromtimestamp(int(timestamp) // 1000000).strftime("%c")


def check_prism_alerts(_no_item: str, params: StringMap, parsed: Section) -> Any:
    valid_alerts = (
        [e for e in parsed if e.get("context", {}).get("vm_type") == "Prism Central VM"]  #
        if params.get("prism_central_only")
        else parsed
    )

    if not valid_alerts:
        yield 0, "No alerts"
        return

    # find the newest alert among those with the highest severity
    immediate_alert = max(valid_alerts, key=lambda x: (severity(x["severity"])[0], x["timestamp"]))

    yield severity(immediate_alert["severity"])[1], "%d alerts" % len(valid_alerts)

    message = immediate_alert["message"]
    state = 1 if "has the following problems" in message else 0  # see werk #7203
    yield state, "Last worst on %s: %r" % (to_string(immediate_alert["timestamp"]), message)


check_info["prism_alerts"] = {
    "check_function": check_prism_alerts,
    "inventory_function": inventory_prism_alerts,
    "parse_function": parse_prism_alerts,
    "group": "prism_alerts",
    "has_perfdata": True,
    "service_description": "Prism Alerts",
}
