#!/usr/bin/env python3

import argparse
# import pprint
import re
import sys
from pathlib import Path

from cmk_addons.plugins.linet_truenas_api.lib.truenas_api_client import Client
from cmk_addons.plugins.linet_truenas_api.lib.truenas_api_client import ejson as json
from cmk.utils import password_store

debug = False
query_default = sorted([
    "pool.query",
    "pool.dataset.query",
    "disk.query",
    "disk.temperatures",
])

def dbg(msg):
    global debug
    if debug:
        print(f"DEBUG: {msg}")

def parse_arguments(argv):
    global query_default

    """argument parser"""
    parser = argparse.ArgumentParser(description=__doc__)

    parser.add_argument(
        "--debug",
        action="store_true",
        help="Debug mode: output more information about the calls being made",
    )

    parser.add_argument("host", help="TrueNAS host name or IP address, optionally with ws:// or wss:// prefix")
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument(
        "-p", "--password-store", help="TrueNAS API key (read from CheckMK password store)"
    )
    group.add_argument(
        "-a",
        "--api-key",
        help="TrueNAS API key (given directly as CLI argument)",
    )
    parser.add_argument(
        "--verify-cert",
        action="store_true",
        help="Verify TLS certificates (default: no verification)",
    )
    parser.add_argument(
        "-t", "--timeout",
        help="Timeout for calls in seconds (default: 5)",
        default=5,
    )

    query_default_str = ':'.join(query_default)
    parser.add_argument(
        "--query",
        help=f"Only query the the given list of things, a colon-separated list (default: {query_default_str})",
        default=query_default_str,
    )

    parser.add_argument(
        "--call-and-dump",
        help="Debug helper function for calling a specific API function & dumping its output as JSON",
    )

    args = parser.parse_args(argv)
    return args

def fetch_data(api_key, args):
    url = re.sub(r'^http(s)://', 'ws\1://', args.host)

    if '://' not in url:
        url = f'wss://{url}'

    url = f'{url}/api/current'

    dbg(f"connecting to {url}")

    global query_default

    if args.query is not None:
        to_query = [ arg for arg in args.query.split(':') if arg in query_default ]
    else:
        to_query = query_default

    with Client(url, verify_ssl=args.verify_cert, call_timeout=int(args.timeout)) as c:
        try:
            dbg(f"logging in with API key {api_key[0:5]}…")
            c.call("auth.login_with_api_key", api_key)
            dbg("logged in successfully")
        except:
            print(f"ERROR: login with API key {api_key} failed", file=sys.stderr)
            sys.exit(1)

        if (args.call_and_dump is not None) and (args.call_and_dump != ''):
            try:
                res = c.call(args.call_and_dump)
                print(json.dumps(res))
                sys.exit(0)

            except Exception as ex:
                print(f"ERROR: exception while calling {args.call_and_dump}: {ex}")
                sys.exit(1)

        data = {}

        for method in to_query:
            dbg(f"executing method {method}")
            try:
                data[method] = c.call(method)
            except:
                print(f"ERROR: executing method {method} failed", file=sys.stderr)
                sys.exit(1)

        # res = c.call("zfs.resource.query")
        # res = c.call("tunable.query")

        dbg("all data retrieved successfully")

        return data

def main(argv=None):
    global debug

    args = parse_arguments(argv or sys.argv[1:])

    debug = args.debug

    if args.password_store:
        pw_id, pw_path = args.password_store.split(":")
        api_key = password_store.lookup(Path(pw_path), pw_id)
    else:
        api_key = args.api_key

    data = fetch_data(api_key=api_key, args=args)

    if data is not None:
        print("<<<linet_truenas_api:sep(0)>>>")
        print(json.dumps(data))

    return 0

if __name__ == "__main__":
    sys.exit(main())
