#!/usr/bin/env python3
# -*- coding: utf-8; py-indent-offset: 4 -*-
#
# Author:  Linuxfabrik GmbH, Zurich, Switzerland
# Contact: info (at) linuxfabrik (dot) ch
#          https://www.linuxfabrik.ch/
# License: The Unlicense, see LICENSE file.

# https://github.com/Linuxfabrik/monitoring-plugins/blob/main/CONTRIBUTING.md

"""See the check's README for more details."""

import argparse
import json
import sys

import lib.args
import lib.base
import lib.human
import lib.lftest
import lib.time
import lib.txt
import lib.url
from lib.globals import STATE_OK, STATE_UNKNOWN, STATE_WARN

__author__ = 'Linuxfabrik GmbH, Zurich/Switzerland'
__version__ = '2026040801'

DESCRIPTION = """Monitors the GitHub status page for service disruptions. Reports the overall status
indicator, individual component states, and any unresolved incidents.
Alerts on active incidents or degraded components."""

DEFAULT_INSECURE = False
DEFAULT_NO_PROXY = False
DEFAULT_TIMEOUT = 8


def parse_args():
    """Parse command line arguments using argparse."""
    parser = argparse.ArgumentParser(description=DESCRIPTION)

    parser.add_argument(
        '-V',
        '--version',
        action='version',
        version=f'%(prog)s: v{__version__} by {__author__}',
    )

    parser.add_argument(
        '--always-ok',
        help=lib.args.help('--always-ok'),
        dest='ALWAYS_OK',
        action='store_true',
        default=False,
    )

    parser.add_argument(
        '--insecure',
        help=lib.args.help('--insecure'),
        dest='INSECURE',
        action='store_true',
        default=DEFAULT_INSECURE,
    )

    parser.add_argument(
        '--no-proxy',
        help=lib.args.help('--no-proxy'),
        dest='NO_PROXY',
        action='store_true',
        default=DEFAULT_NO_PROXY,
    )

    parser.add_argument(
        '--test',
        help=lib.args.help('--test'),
        dest='TEST',
        type=lib.args.csv,
    )

    parser.add_argument(
        '--timeout',
        help=lib.args.help('--timeout') + ' Default: %(default)s (seconds)',
        dest='TIMEOUT',
        type=int,
        default=DEFAULT_TIMEOUT,
    )

    args, _ = parser.parse_known_args()
    return args


def main():
    """The main function. This is where the magic happens."""

    # parse the command line
    try:
        args = parse_args()
    except SystemExit:
        sys.exit(STATE_UNKNOWN)

    # fetch data
    if args.TEST is None:
        result = lib.base.coe(
            lib.url.fetch_json(
                'https://www.githubstatus.com/api/v2/summary.json',
                insecure=args.INSECURE,
                no_proxy=args.NO_PROXY,
                timeout=args.TIMEOUT,
            ),
        )
    else:
        # do not call the command, put in test data
        stdout, _stderr, _retc = lib.lftest.test(args.TEST)
        result = json.loads(stdout)

    # init some vars
    msg = ''
    state = STATE_OK
    perfdata = ''
    components, incidents = 0, 0
    table_data = []

    # analyze data
    for incident in result.get('incidents', {}):
        incident['updated_at'] = incident.get('updated_at').replace('T', ' ')[:19]
        msg += (
            f'{incident.get("updated_at")}'
            f', {incident.get("impact")} impact'
            f', {incident.get("status")}'
            f': {incident.get("name")}. '
            f'{incident.get("incident_updates", [])[0].get("body", "")} '
        )
        state = STATE_WARN
        incidents += 1

    for component in result.get('components', {}):
        if component.get('name', '').startswith('Visit '):
            # "Visit www.githubstatus.com for more information"
            continue
        component['updated_at'] = component.get('updated_at').replace('T', ' ')[:19]
        if component.get('status') != 'operational':
            state = STATE_WARN
            components += 1

        table_data.append(
            {
                'name': component.get('name'),
                'status': component.get('status'),
                'updated_at': component.get('updated_at'),
            }
        )

    if not result.get('incidents', {}) and not result.get('components', {}):
        if result.get('status', {}).get('indicator', 'none') != 'none':
            state = STATE_WARN
            msg = (
                f'{result.get("status", {}).get("description", "none")}'
                f' ({result.get("status", {}).get("indicator", "none")})'
            )

    # build the message
    if state == STATE_OK:
        msg = 'Everything is ok.'
    else:
        msg = (
            f'{incidents}'
            f' {lib.txt.pluralize("incindent", incidents)}'
            f', {components}'
            f' {lib.txt.pluralize("component", components)}'
            f' affected. {msg}'
        )
    if table_data:
        keys = [
            'name',
            'status',
            'updated_at',
        ]
        headers = [
            'Component',
            'Status',
            f'Updated ({result["page"].get("time_zone", "TZ n/a")})',
        ]
        msg += '\n\n' + lib.base.get_table(table_data, keys, header=headers)
    perfdata += lib.base.get_perfdata(
        'components',
        components,
        _min=0,
    )
    perfdata += lib.base.get_perfdata(
        'incidents',
        incidents,
        _min=0,
    )

    # over and out
    lib.base.oao(msg, state, perfdata, always_ok=args.ALWAYS_OK)


if __name__ == '__main__':
    try:
        main()
    except Exception:
        lib.base.cu()
