#!/usr/bin/env python3

"""
Nagios plugin to check that our MIT users' Zephyr mirrors are running.

It must be run on a machine that is using the live database for the
Django ORM.
"""

import os
import sys
from datetime import timedelta

sys.path.append("/home/zulip/deployments/current")
from scripts.lib.setup_path import setup_path
from scripts.lib.zulip_tools import atomic_nagios_write

setup_path()

import django
from django.utils.timezone import now as timezone_now

os.environ["DJANGO_SETTINGS_MODULE"] = "zproject.settings"
sys.path.append("/home/zulip/deployments/current")
sys.path.append("/home/zulip/deployments/current/zerver")

django.setup()


from zerver.models import UserActivity
from zerver.models.clients import get_client

now = timezone_now()


zephyr_client = get_client("zephyr_mirror")
all_users = UserActivity.objects.filter(
    # We need to use the client_id so we can use the partial index we
    # have created, which builds in both the query and the client_id.
    # The partial index is:
    # CREATE INDEX CONCURRENTLY zerver_useractivity_zehpyr_liveness
    #     ON zerver_useractivity(last_visit)
    #  WHERE client_id = 1005
    #    AND query IN ('get_events', '/api/v1/events');
    query__in=["get_events", "/api/v1/events"],
    client_id=zephyr_client.id,
)
new_inactive_user_count = (
    all_users.filter(last_visit__lt=now - timedelta(minutes=10))
    .values("user_profile_id")
    .distinct("user_profile_id")
    .count()
)

old_inactive_user_count = (
    all_users.filter(last_visit__lt=now - timedelta(minutes=60))
    .values("user_profile_id")
    .distinct("user_profile_id")
    .count()
)

recently_inactive_user_count = new_inactive_user_count - old_inactive_user_count

if recently_inactive_user_count / float(old_inactive_user_count) > 0.25:
    recently_inactive_users = (
        all_users.filter(last_visit__lt=now - timedelta(minutes=10))
        .distinct("user_profile_id")
        .difference(
            all_users.filter(last_visit__lt=now - timedelta(minutes=60)).distinct("user_profile_id")
        )
    )
    too_old_data = (
        "Many mirrors recently became inactive\n"
        "Last call to get_message for recently out of date mirrors:\n"
        + "\n".join(
            "{:>16}: {}".format(
                user.user_profile.email,
                user.last_visit.strftime("%Y-%m-%d %H:%M %Z"),
            )
            for user in recently_inactive_users
        )
    )

    sys.exit(
        atomic_nagios_write(
            "check_user_zephyr_mirror_liveness", "critical", too_old_data, int(now.timestamp())
        )
    )
else:
    atomic_nagios_write(
        "check_user_zephyr_mirror_liveness",
        "ok",
        "Most mirrors that were recently active continue to be active",
        int(now.timestamp()),
    )
