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

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

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

DESCRIPTION = """Lists all clients currently connected to an OpenVPN server by parsing the status log file. Reports client name, remote address, bytes received and sent, and connection time.\nRequires root or sudo."""

DEFAULT_FILENAME = '/var/log/openvpn-status.log'

DEFAULT_WARN = None
DEFAULT_CRIT = None


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(
        '-c',
        '--critical',
        help='CRIT threshold for the number of connected clients. Default: %(default)s',
        dest='CRIT',
        type=int,
        default=DEFAULT_CRIT,
    )

    parser.add_argument(
        '--filename',
        help='Path to the OpenVPN status log file. Default: %(default)s',
        dest='FILENAME',
        type=str,
        default=DEFAULT_FILENAME,
    )

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

    parser.add_argument(
        '-w',
        '--warning',
        help='WARN threshold for the number of connected clients. Default: %(default)s',
        dest='WARN',
        type=int,
        default=DEFAULT_WARN,
    )

    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:
        try:
            with open(args.FILENAME, 'r') as file:
                lines = file.readlines()
        except OSError:
            lib.base.cu(f'Failed to read file {args.FILENAME}.')
    else:
        stdout, _, _ = lib.lftest.test(args.TEST)
        lines = stdout.splitlines(keepends=True)

    counter = 0
    table = []
    for line in lines:
        if line.startswith('CLIENT_LIST'):
            counter += 1
            line = line.split(',')
            table.append(
                {
                    'name': line[1],
                    'ext_ip': line[2].split(':')[0],
                    'int_ip': line[3],
                    'connection_time': line[7],
                }
            )

    state = lib.base.get_state(counter, args.WARN, args.CRIT)
    perfdata = lib.base.get_perfdata(
        'clients',
        counter,
        warn=args.WARN,
        crit=args.CRIT,
        _min=0,
    )

    # build the message
    msg = f'{counter} {lib.txt.pluralize("user", counter)} connected to OpenVPN Server.\n\n'

    msg += lib.base.get_table(
        table,
        ['name', 'ext_ip', 'int_ip', 'connection_time'],
        header=['Common Name', 'External IP', 'Internal IP', 'Connected since'],
    )

    # over and out
    lib.base.oao(msg, state, perfdata)


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