#!/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 re
import sys

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

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

DESCRIPTION = """Monitors the Infomaniak status page for open events and incidents. Alerts when active
events are reported."""

DEFAULT_INSECURE = False
DEFAULT_NO_PROXY = False
DEFAULT_TIMEOUT = 28


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(
        '--ignore-regex',
        help='Any English event title matching this Python regex will be ignored. '
        'Can be specified multiple times. '
        'Example: `--ignore-regex "(?i)linuxfabrik"`.',
        action='append',
        default=None,
        dest='IGNORE_REGEX',
    )

    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(
        '--service',
        help='Only report events for this service category. '
        'Can be specified multiple times. '
        'If not specified, all categories are reported. '
        'Example: `--service swiss_backup --service public_cloud`.',
        dest='SERVICE',
        action='append',
        default=None,
    )

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

    parser.add_argument(
        '--token',
        help='Infomaniak API token.',
        dest='TOKEN',
        required=True,
    )

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

    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)

    # set default values for append parameters that were not specified
    if args.IGNORE_REGEX is None:
        args.IGNORE_REGEX = []

    # fetch data
    if args.TEST is None:
        result = lib.base.coe(
            lib.infomaniak.get_events(
                args.TOKEN,
                insecure=args.INSECURE,
                no_proxy=args.NO_PROXY,
                timeout=args.TIMEOUT,
            )
        )
    else:
        # do not call the command, put in test data
        stdout, _, _ = lib.lftest.test(args.TEST)
        result = json.loads(stdout)

    # init some vars
    msg = ''
    state = STATE_OK
    perfdata = lib.base.get_perfdata(
        'event',
        0,
        _min=0,
    )
    try:
        compiled_ignore_regex = [re.compile(item) for item in args.IGNORE_REGEX]
    except Exception:
        lib.base.cu('Unable to compile regex.')

    table_data = []

    # analyze data
    for event in result.get('data', {}):
        services = [tr['name'] for tr in event.get('services')]
        # just get the english title of the event message
        title = next(
            (
                tr['title']
                for tr in event.get('description').get('translations')
                if tr['language'] == 'en'
            ),
            event.get('description').get('title'),
        )

        # a filter for ``--service`` is applied before the ``--ignore-regex`` parameter
        if args.SERVICE and not services:
            # we got a filter for a service category, but an uncategorized event message - skip
            continue
        if args.SERVICE and not set(services).intersection(args.SERVICE):
            # is there any intersection (services wanted)? if not, continue
            continue
        if any(item.search(title) for item in compiled_ignore_regex):
            continue

        services = ', '.join(services)
        if event.get('status') != 'terminated':
            msg += f'{event.get("type")}: {title} ({services}), '
            if event.get('type').lower() == 'critical':
                state = STATE_CRIT
            else:
                state = STATE_WARN
            perfdata = perfdata.replace('=0', '=1')

        table_data.append(
            {
                'type': event.get('type'),
                'status': event.get('status'),
                'title': title,
                'services': services,
                'started_at': f'{lib.time.epoch2iso(int(event.get("started_at")))}',
                # in case of an ongoing event, `ended_at` is "None"
                'ended_at': (
                    f'{lib.time.epoch2iso(int(event.get("ended_at")))}'
                    f' ({lib.human.seconds2human(lib.time.now(as_type="epoch") - int(event.get("ended_at")))} ago)'
                )
                if event.get('ended_at') is not None
                else 'in progress',
                'duration': lib.human.seconds2human(
                    event.get('ended_at') - event.get('started_at')
                )
                if event.get('ended_at') is not None
                else '',
            }
        )

    # build the message
    if state == STATE_OK:
        msg = 'Everything is ok.\n\n' + msg
    else:
        msg = msg[:-2] + ' - see https://infomaniakstatus.com/en/\n\n'
    if table_data:
        keys = [
            'type',
            'title',
            'services',
            'started_at',
            'ended_at',
            'duration',
        ]
        headers = [
            'Type',
            'Title',
            'Services',
            'Start',
            'End',
            'Duration',
        ]
        msg += lib.base.get_table(table_data, keys, header=headers)

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


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