#!/usr/bin/python3
#
# Univention Management Console
#
# SPDX-FileCopyrightText: 2024-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only

import argparse
import json
import sys
from typing import Any

from univention.config_registry import ucr
from univention.udm import UDM
from univention.udm.binary_props import Base64Bzip2BinaryProperty
from univention.udm.exceptions import NoObject


settings_position = f"cn=umc,cn=data,cn=univention,{ucr.get('ldap/base')}"


class StoreInDict(argparse.Action):
    def __call__(self, parser, namespace, values, option_string) -> None:
        if not hasattr(namespace, 'options'):
            namespace.options = {}

        options = namespace.options
        options[self.dest] = values
        namespace.options = options


class UMCSettings:
    def __init__(self, position: str = settings_position):

        self.udm = UDM.machine().version(3)
        if ucr.get("server/role") in ["domaincontroller_master", "domaincontroller_backup"]:
            self.udm = UDM.admin().version(3)

        self.module = self.udm.get('settings/data')
        try:
            settings_obj = self.module.get(settings_position)
        except NoObject:
            settings_obj = self.module.new()
            settings_obj.props.name = 'umc'
            settings_obj.props.data_type = 'string'
        self.obj = settings_obj
        self._tmp_settings = {}

    def get_settings(self) -> dict[str, Any]:
        if self.obj.props.data:
            return json.loads(self.obj.props.data.raw.decode('utf-8'))
        return {}

    def print_settings(self, as_json: bool):
        if as_json:
            print(json.dumps(self.get_settings()))
        else:
            print(self.get_settings())

    def set_setting(self, key, value):
        self._tmp_settings[key] = value

    def save(self):
        new_settings = {**self.get_settings(), **self._tmp_settings}
        self.obj.props.data = Base64Bzip2BinaryProperty('data', raw_value=json.dumps(new_settings).encode('utf-8'))
        self.obj.save()


def parse_args():
    parser = argparse.ArgumentParser(
        prog='univention-management-console-settings',
    )

    parser.add_argument('-j', '--json', action='store_true')

    subparser = parser.add_subparsers(title='commands', required=True, dest='command', help='print the current configuration or set options')
    get_subparser = subparser.add_parser('get')
    get_subparser.set_defaults(func=get_options)

    set_subparser = subparser.add_parser('set')
    set_subparser.add_argument('-u', '--sqlURI', nargs='?', const=None, help='The SQL connection URI', action=StoreInDict)
    set_subparser.add_argument('-s', '--sqlPoolSize', nargs='?', const=None, help='The SQL connection pool size', action=StoreInDict)
    set_subparser.add_argument('-o', '--sqlMaxOverflow', nargs='?', const=None, help='The SQL connection max overflow', action=StoreInDict)
    set_subparser.add_argument('-t', '--sqlPoolTimeout', nargs='?', const=None, help='The SQL connection pool timeout', action=StoreInDict)
    set_subparser.add_argument('-r', '--sqlPoolRecycle', nargs='?', const=None, help='The SQL connection pool recycle', action=StoreInDict)
    set_subparser.set_defaults(func=set_options)

    args = parser.parse_args()
    if 'options' not in args and args.command == 'set':
        set_subparser.print_help()
        sys.exit(1)
    return args


def main():
    args = parse_args()
    settings = UMCSettings()

    args.func(args, settings)


def get_options(args, settings: UMCSettings):
    settings.print_settings(args.json)


def set_options(args, settings: UMCSettings):
    for key, value in args.options.items():
        settings.set_setting(key, value)
    settings.save()
    settings.print_settings(args.json)


if __name__ == '__main__':
    main()
