#!/usr/bin/env python3
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
"""ASF Infrastructure Reporting Dashboard - Uptime Statistics Tasks"""
import asyncio

from ..lib import config
from .. import plugins
import aiohttp
import datetime
import dateutil.relativedelta
import functools

DEFAULT_TIMESPAN_MONTHS = 13  # Show last 12 months, plus current one

_stats: dict = {}


def get_stats():
    return _stats


async def uptime_scan(months=DEFAULT_TIMESPAN_MONTHS):
    """Performs a full uptime scan from NodePing"""
    nodeping_summary_url = config.reporting.uptime["summary_url"]
    now = datetime.datetime.now()
    cutoff_date = (now - dateutil.relativedelta.relativedelta(months=months)).strftime("%Y-%m")
    async with aiohttp.ClientSession() as hc:
        async with hc.get(nodeping_summary_url) as req:
            if req.status == 200:
                hosts_json = await req.json()
                tmpstats = {}
                for host_entry in hosts_json.values():
                    uuid = host_entry["uuid"]
                    host_stats = {
                        "uuid": uuid,
                        "label": host_entry["label"],
                        "uptime_monthly": {},
                        "uptime_average": 100.0,
                        "uptime_past_week": 100.0,
                    }
                    # Monthly stats per host
                    host_url = config.reporting.uptime["host_url"].format(uuid=uuid)
                    async with hc.get(host_url, params={"format": "json"}) as hreq:
                        if req.status == 200:
                            host_data = await hreq.json()
                            uptimes = []
                            for month in host_data:
                                mid = month["id"]
                                if mid > cutoff_date and mid != "total":
                                    uptime_val = month["uptime"]
                                    if uptime_val != "-":
                                        host_stats["uptime_monthly"][mid] = uptime_val
                                        uptimes.append(uptime_val)
                            host_stats["uptime_average"] = (
                                functools.reduce(lambda x, y: x + y, uptimes) / float(len(uptimes))
                                if uptimes
                                else 100.0
                            )
                    # Last week's stats per host
                    weekly_url = config.reporting.uptime["results_url"].format(uuid=uuid)
                    async with hc.get(weekly_url, params={"format": "json", "span": 168, "limit": 20000}) as wreq:
                        if wreq.status == 200:
                            weekly_json = await wreq.json()
                            checks_done = len(weekly_json)
                            checks_failed = len([x for x in weekly_json if x["su"] is False])
                            weekly_uptime = 100.0
                            if checks_done:
                                weekly_uptime -= float((checks_failed / checks_done) * 100)
                            host_stats["uptime_past_week"] = weekly_uptime
                    tmpstats[uuid] = host_stats
                    _stats.update(tmpstats)
                _stats.clear()
                _stats.update(tmpstats)


async def scan_loop():
    while True:
        await uptime_scan()
        await asyncio.sleep(3600)


plugins.root.register(scan_loop, slug="uptime", title="Uptime Statistics", icon="bi-router-fill")
