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

import lib.args
import lib.base
import lib.lftest
import lib.version
from lib.globals import STATE_UNKNOWN

try:
    import psutil
except ImportError:
    print('Python module "psutil" is not installed.')
    sys.exit(STATE_UNKNOWN)


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

DESCRIPTION = """Reports the average system load per CPU over the last 1, 5, and 15 minutes. Load
represents the average number of processes waiting in the run queue plus those
currently executing. The values are normalized by dividing by the number of CPUs.
Alerts when the load average exceeds the configured thresholds."""

DEFAULT_WARN = 1.15  # load divided by all cpus
DEFAULT_CRIT = 5.00  # load divided by all cpus


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(
        '-c',
        '--critical',
        help='CRIT threshold for load15 per CPU. Default: %(default)s',
        dest='CRIT',
        type=float,
        default=DEFAULT_CRIT,
    )

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

    parser.add_argument(
        '-w',
        '--warning',
        help='WARN threshold for load15 per CPU. Default: %(default)s',
        dest='WARN',
        type=float,
        default=DEFAULT_WARN,
    )

    args, _ = parser.parse_known_args()
    return args


def _load_load_fixture(raw_json):
    """Convert a test fixture into the shape the plugin expects from
    `psutil.getloadavg()` and `psutil.cpu_count()`. Returns a tuple of
    `([load1, load5, load15], cpu_count)`.
    """
    data = json.loads(raw_json)
    return data['loadavg'], int(data['cpu_count'])


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:
        if lib.version.version(psutil.__version__) < lib.version.version('5.6.2'):
            # Linux only
            loadavg = os.getloadavg()
        else:
            # OS-independent
            loadavg = psutil.getloadavg()
        cpu_count = psutil.cpu_count()
    else:
        stdout, _, _ = lib.lftest.test(args.TEST)
        loadavg, cpu_count = _load_load_fixture(stdout)
    load1, load5, load15 = [x / cpu_count for x in loadavg]

    # init some vars
    msg = ''
    state = lib.base.get_state(
        load15, float(args.WARN), float(args.CRIT), _operator='ge'
    )
    perfdata = ''

    # build the message
    msg += f'Avg per CPU: {load1:0.2f} {load5:0.2f} {load15:0.2f}'
    perfdata += lib.base.get_perfdata(
        'load1',
        load1,
        warn=args.WARN,
        crit=args.CRIT,
        _min=0,
    )
    perfdata += lib.base.get_perfdata(
        'load5',
        load5,
        warn=args.WARN,
        crit=args.CRIT,
        _min=0,
    )
    perfdata += lib.base.get_perfdata(
        'load15',
        load15,
        warn=args.WARN,
        crit=args.CRIT,
        _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()
