#!/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 OnlyOffice Document Server statistics and license usage via the HTTP API.
Reports active connections, document editing sessions, and license consumption.
Alerts when license usage exceeds the configured thresholds."""

DEFAULT_INSECURE = False
DEFAULT_NO_PROXY = False
DEFAULT_TIMEOUT = 3
DEFAULT_URL = 'http://localhost'


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(
        '--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,
    )

    parser.add_argument(
        '--url',
        help='OnlyOffice API URL. Default: %(default)s',
        dest='URL',
        default=DEFAULT_URL,
    )

    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(
                args.URL + '/info/info.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)
        try:
            result = json.loads(stdout)
        except Exception:
            lib.base.cu('ValueError: No JSON object could be decoded')

    # init some vars
    msg = ''
    state = STATE_OK
    perfdata = ''

    # get thresholds automatically
    max_conn = result['licenseInfo']['connections']
    max_conn_warn = max_conn * 0.9
    max_conn_crit = max_conn * 0.95

    # build the message and perfdata
    msg += f'Max {max_conn} {lib.txt.pluralize("connection", max_conn)}, '

    # license; expired?
    now = lib.time.now(as_type='iso')
    msg += 'licensed' if result['licenseInfo']['hasLicense'] else 'no license'
    if result['licenseInfo']['endDate']:
        if result['licenseInfo']['endDate'][0:10] <= now[0:10]:
            msg += ' (expired) [WARNING]'
            state = lib.base.get_worst(STATE_WARN, state)
        expires_in = lib.time.timestrdiff(
            result['licenseInfo']['endDate'][0:10],
            now[0:10],
            pattern1='%Y-%m-%d',
            pattern2='%Y-%m-%d',
        )
        if expires_in <= 10 * 24 * 60 * 60:
            msg += f' (expires in {lib.human.seconds2human(expires_in)}) [WARNING]'
            state = lib.base.get_worst(STATE_WARN, state)
    msg += ', '

    hour_view = result['connectionsStat']['hour']['view']
    view_state = lib.base.get_state(
        hour_view['max'], max_conn_warn, max_conn_crit, _operator='ge'
    )
    state = lib.base.get_worst(view_state, state)
    msg += (
        f'last hour:'
        f' {hour_view["min"]}/{hour_view["avr"]}/{hour_view["max"]}'
        f' views{lib.base.state2str(view_state, prefix=" ")} '
    )
    perfdata += lib.base.get_perfdata(
        'conn_hour_view_min',
        hour_view['min'],
        warn=max_conn_warn,
        crit=max_conn_crit,
        _min=0,
        _max=result['licenseInfo']['connections'],
    )
    perfdata += lib.base.get_perfdata(
        'conn_hour_view_avr',
        hour_view['avr'],
        warn=max_conn_warn,
        crit=max_conn_crit,
        _min=0,
        _max=result['licenseInfo']['connections'],
    )
    perfdata += lib.base.get_perfdata(
        'conn_hour_view_max',
        hour_view['max'],
        warn=max_conn_warn,
        crit=max_conn_crit,
        _min=0,
        _max=result['licenseInfo']['connections'],
    )

    hour_edit = result['connectionsStat']['hour']['edit']
    edit_state = lib.base.get_state(
        hour_edit['max'], max_conn_warn, max_conn_crit, _operator='ge'
    )
    state = lib.base.get_worst(edit_state, state)
    msg += (
        f'and'
        f' {hour_edit["min"]}/{hour_edit["avr"]}/{hour_edit["max"]}'
        f' edits{lib.base.state2str(edit_state, prefix=" ")}'
        f' (min/avr/max), '
    )
    perfdata += lib.base.get_perfdata(
        'conn_hour_edit_min',
        hour_edit['min'],
        warn=max_conn_warn,
        crit=max_conn_crit,
        _min=0,
        _max=result['licenseInfo']['connections'],
    )
    perfdata += lib.base.get_perfdata(
        'conn_hour_edit_avr',
        hour_edit['avr'],
        warn=max_conn_warn,
        crit=max_conn_crit,
        _min=0,
        _max=result['licenseInfo']['connections'],
    )
    perfdata += lib.base.get_perfdata(
        'conn_hour_edit_max',
        hour_edit['max'],
        warn=max_conn_warn,
        crit=max_conn_crit,
        _min=0,
        _max=result['licenseInfo']['connections'],
    )

    if 'usersInfo' in result:
        msg += f'{result["usersInfo"]["uniqueUserCount"]} unique {lib.txt.pluralize("user", result["usersInfo"]["uniqueUserCount"])}, '
        perfdata += lib.base.get_perfdata(
            'unique_users',
            result['usersInfo']['uniqueUserCount'],
            _min=0,
        )

    msg += f'v{result["serverInfo"]["buildVersion"]}, '

    # over and out
    lib.base.oao(msg[:-2], state, perfdata)


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