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

import lib.args
import lib.base
import lib.cache
import lib.lftest
import lib.shell
import lib.time
import lib.url
import lib.version
from lib.globals import STATE_OK, STATE_UNKNOWN, STATE_WARN

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

DESCRIPTION = """Checks if a newer version of mydumper is available by querying the GitHub releases API.
Alerts when the installed version is outdated."""

DEFAULT_CACHE_EXPIRE = 24  # hours


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(
        '--cache-expire',
        help=lib.args.help('--cache-expire') + ' Default: %(default)s',
        dest='CACHE_EXPIRE',
        type=int,
        default=DEFAULT_CACHE_EXPIRE,
    )

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

    args, _ = parser.parse_known_args()
    return args


def get_installed_version(test_arg=None):
    if test_arg is None:
        success, result = lib.shell.shell_exec('mydumper --version')
        if not success:
            return ''
        stdout, _, _ = result
        stdout = stdout.strip()
    else:
        stdout, _, _ = lib.lftest.test(test_arg)
        stdout = stdout.strip()
    # where to find the version number in output?
    version_regex = r'mydumper(.*?),'
    try:
        stdout = re.search(version_regex, stdout)
        return stdout.group(1).strip()
    except Exception:
        return ''


def get_latest_version(expire):
    # get version online, but first from cache
    latest_version = lib.cache.get('mydumper-version')
    if latest_version:
        return (True, latest_version)

    # nothing found in cache, get the latest version from github
    success, latest_version = lib.url.get_latest_version_from_github(
        'mydumper', 'mydumper'
    )
    if not success:
        return (success, latest_version)

    lib.cache.set('mydumper-version', latest_version, lib.time.now() + expire)
    return (True, latest_version)


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)

    installed_version = get_installed_version(args.TEST)
    if not installed_version:
        lib.base.cu('mydumper/myloader not found.')

    if args.TEST is not None:
        # In test mode, the second --test slot (the "stderr" slot of
        # lib.lftest.test) carries the pinned upstream latest version
        # so the test does not depend on a live GitHub fetch.
        _, stderr, _ = lib.lftest.test(args.TEST)
        latest_version = stderr.strip()
    else:
        latest_version = lib.base.coe(get_latest_version(args.CACHE_EXPIRE * 60 * 60))
    perfdata = lib.base.get_perfdata(
        'mydumper-version',
        lib.version.version2float(installed_version),
        _min=0,
    )

    if lib.version.version(installed_version) >= lib.version.version(latest_version):
        lib.base.oao(
            f'mydumper/myloader {installed_version} is up to date',
            STATE_OK,
            perfdata,
        )

    # over and out
    lib.base.oao(
        (
            f'mydumper/myloader {installed_version}'
            f' installed, mydumper/myloader'
            f' {latest_version} available'
        ),
        STATE_WARN,
        perfdata,
        always_ok=args.ALWAYS_OK,
    )


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