# Copyright (c) 2025 Thomas Goirand <zigo@debian.org>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import socket
import sys

from keystonemiddleware import auth_token
from keystoneauth1 import loading as ks_loading
from oslo_config import cfg
from oslo_db import options as db_options
from oslo_log import log as logging

vmms_default_opts = [
    cfg.BoolOpt('accept_legacy_tls',
               default=False,
               help='Accept legacy TLS connecition (ie: TLS 1.0) when '
                    'connecting to source_cloud. This is useful for '
                    'connecting to old deployments.'),
]

# Worker configuration
worker_group = cfg.OptGroup(name='worker',
                            title='Worker options')

worker_opts = [
    cfg.StrOpt('coordination_url',
               default=None,
               help='Tooz coordination URL (e.g., zookeeper://host:port)'),
    cfg.BoolOpt('mistral_use_keystone_auth',
               default=True,
               help='Use keystone_authtoken section for Mistral authentication '
                    'instead of separate mistral section.'),
    cfg.StrOpt('my_hostname',
               default=None,
               sample_default='cl1-controller-1.example.com',
               help='FQDN of this worker instance. Used for coordination. '
                    'Must be unique across the worker cluster. If None, the server FQDN is used.'),
    cfg.IntOpt('parallel_jobs',
               default=3,
               help='Maximum number of parallel Mistral workflow executions'),
    cfg.IntOpt('check_interval',
               default=120,
               help='Periodic check interval in seconds'),
    cfg.StrOpt('migration_start_time',
               default='02:00',
               help='Daily start time for opportunistic migrations (HH:MM)'),
    cfg.StrOpt('migration_end_time',
               default='06:00',
               help='Daily end time for opportunistic migrations (HH:MM)'),
    cfg.StrOpt('mistral_workflow_name',
               default='migrate_vm',
               help='Name of the Mistral workflow to execute for migrations'),
]

def init_config(conf=None):
    """Initialize configuration and return CONF object"""
    
    # Use provided CONF or create new one
    if conf is not None:
        CONF = conf
    else:
        CONF = cfg.CONF
    
    # Register migration timing options
    CONF.register_group(worker_group)
    CONF.register_opts(worker_opts, group=worker_group)

    # DEFAULT group
    CONF.register_opts(vmms_default_opts)
    
    # Register oslo.log options
    logging.register_options(CONF)
    
    # Register oslo.db options (this includes [database]/connection)
    db_options.set_defaults(CONF)
    
    # Register keystone middleware options for API auth
    auth_token.CONF = CONF
    try:
        auth_token_opts = auth_token._opts
        CONF.register_opts(auth_token_opts, group='keystone_authtoken')
    except (AttributeError, TypeError):
        # Fallback if _opts doesn't work as expected
        pass
    
    # Register keystoneauth options for source cloud connection
    ks_loading.register_session_conf_options(CONF, "source_cloud")
    ks_loading.register_auth_conf_options(CONF, "source_cloud")
    ks_loading.register_adapter_conf_options(CONF, "source_cloud")

    # Register keystoneauth options for mistral connection
    ks_loading.register_session_conf_options(CONF, "mistral")
    ks_loading.register_auth_conf_options(CONF, "mistral")
    ks_loading.register_adapter_conf_options(CONF, "mistral")

    # Load configuration from file (only if no conf was provided)
    if conf is None:
        CONF(sys.argv[1:], project='vmms')

    # Set hostname if not provided
    if CONF.worker.my_hostname is None:
        CONF.worker.my_hostname = socket.getfqdn()

    # Set up logging
    logging.setup(CONF, 'vmms')
    
    return CONF

def list_opts():
    """Return a list of oslo.config options available in this module."""
    # Get keystoneauth options properly
    auth_opts = ks_loading.get_auth_common_conf_options()
    session_opts = ks_loading.get_session_conf_options()
    adapter_opts = ks_loading.get_adapter_conf_options()

    # Get auth plugin specific options (used by both source_cloud and mistral)
    auth_plugin_opts = []
    for name in ks_loading.get_available_plugin_names():
        auth_plugin_opts.extend(ks_loading.get_auth_plugin_conf_options(name))
    
    return [
        ("DEFAULT", vmms_default_opts),
        ('worker', worker_opts),
        ('source_cloud', list(auth_opts) + auth_plugin_opts + list(session_opts) + list(adapter_opts)),
        ('mistral', list(auth_opts) + auth_plugin_opts + list(session_opts) + list(adapter_opts)),
    ]
