import inspect
from typing import Any

import click
from click_option_group import optgroup
import xnat


def xnatpy_common_options(func):
    common_options = [
        optgroup.group('Common XNATpy options', help='Options respected by (most) XNATpy commands'),
        optgroup.option('--output-format', envvar='XNATPY_OUTPUT', type=click.Choice(['raw', 'csv', 'human'], case_sensitive=False), help="Output format", default='human'),
    ]

    for option in reversed(common_options):
        func = option(func)

    return func


def xnatpy_login_options(func):
    login_options = [
        optgroup.group('Server configuration', help='The configuration of some server connection'),
        optgroup.option('--host', 'server',
                        envvar=['XNATPY_HOST', 'XNAT_HOST'],
                        required=True,
                        help="URL of the XNAT host to connect to, if not given will check XNAT_HOST or XNATPY_HOST environment variables"),
        optgroup.option('--user', '-u', envvar=['XNATPY_USER', 'XNAT_USER'], help="Username to connect to XNAT with."),
        optgroup.option('--netrc', 'netrc_file', '-n', help=".netrc file location, if not given will check NETRC environment variable or default to ~/.netrc"),
        optgroup.option('--jsession', envvar='XNATPY_JSESSION', help="JSESSION value for re-using a previously opened login session"),
        optgroup.option('--timeout', 'default_timeout', envvar="XNATPY_TIMEOUT", type=float, help="Timeout for requests made by this command in ms."),
        optgroup.option('--loglevel',
                        envvar='XNATPY_LOGLEVEL',
                        type=click.Choice(['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], case_sensitive=False),
                        help="Logging verbosity level."),
    ]

    for option in reversed(login_options):
        func = option(func)

    return func


def xnatpy_all_options(func):
    func = xnatpy_common_options(func)
    func = xnatpy_login_options(func)
    return func


def connect_cli(**options: Any):
    # Ensure that only valid connection arguments are in the options
    connect_signature = inspect.signature(xnat.connect)
    options = {k: v for k, v in options.items() if k in connect_signature.parameters}

    # The cli argument is True by default
    if 'cli' not in options:
        options['cli'] = True

    # Create the connection using the filtered arguments
    return xnat.connect(**options)


