#!/usr/lib64/linuxfabrik-monitoring-plugins/venv/bin/python
# -*- 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.lftest
import lib.txt
import lib.url
from lib.globals import STATE_OK, STATE_UNKNOWN, STATE_WARN

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

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,
        epilog=lib.args.epilog(__file__),
        formatter_class=lib.args.HelpFormatter,
    )

    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-perfdata',
        help=lib.args.help('--no-perfdata'),
        dest='NO_PERFDATA',
        action='store_true',
        default=False,
    )

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

    parser.add_argument(
        '--proxy',
        help=lib.args.help('--proxy'),
        dest='PROXY',
        default=None,
    )

    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,
                proxy=args.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("incident", 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, no_perfdata=args.NO_PERFDATA
    )


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