"""CLI configuration management."""

import logging
import os
from dataclasses import dataclass
from functools import cache
from typing import TypeVar

from slices_clientlib_core.base.config import config_dir_location
from slices_clientlib_core.base.exceptions import ConfigurationError
from tomlkit import TOMLDocument, comment, nl, table
from tomlkit.exceptions import TOMLKitError
from tomlkit.toml_file import TOMLFile

logger = logging.getLogger(__name__)


@dataclass
class BISettings:
    """SSH settings for BI CLI."""

    extra_ssh_options: list[str]
    extra_sftp_options: list[str]
    extra_scp_options: list[str]
    ssh_exe: str
    sftp_exe: str
    scp_exe: str


bi_settings_file = config_dir_location / "bi_settings.toml"


def _get_bi_ssh_settings_toml():
    try:
        # If there is no SSH settings file, write it.
        # This file with default settings serves as a template for users to customize.
        if not bi_settings_file.exists():
            write_default_bi_settings()
    except TOMLKitError:
        # ignore not being able to write this file
        pass

    try:
        if bi_settings_file.exists():
            settings_file = TOMLFile(bi_settings_file)
            return settings_file.read()
    except TOMLKitError as e:
        raise ConfigurationError(f"Could not read settings file {bi_settings_file}") from e

    return TOMLDocument()


T = TypeVar("T")


def _env_or_toml(env_key: str, toml_section: str, toml_key: str, toml: TOMLDocument, default: T) -> T:
    """Get a value from the environment or TOML file."""
    if env_key in os.environ:
        return os.environ[env_key] if not isinstance(default, list) else os.environ[env_key].split()  # pyright: ignore[reportReturnType]
    if toml_section in toml and toml_key in toml[toml_section]:  # pyright: ignore[reportOperatorIssue]
        return toml[toml_section][toml_key]  # pyright: ignore[reportIndexIssue,reportReturnType]
    return default


@cache
def get_bi_settings() -> BISettings:
    """Get BI SSH settings."""
    toml = _get_bi_ssh_settings_toml()
    return BISettings(
        extra_ssh_options=_env_or_toml("SLICES_BI_EXTRA_SSH_OPTIONS", "ssh", "extra_options", toml, []),
        extra_scp_options=_env_or_toml("SLICES_BI_EXTRA_SCP_OPTIONS", "scp", "extra_options", toml, []),
        extra_sftp_options=_env_or_toml("SLICES_BI_EXTRA_SFTP_OPTIONS", "sftp", "extra_options", toml, []),
        ssh_exe=_env_or_toml("SLICES_BI_SSH_EXE", "ssh", "exe", toml, "ssh"),
        scp_exe=_env_or_toml("SLICES_BI_SCP_EXE", "scp", "exe", toml, "scp"),
        sftp_exe=_env_or_toml("SLICES_BI_SFTP_EXE", "sftp", "exe", toml, "sftp"),
    )


def write_default_bi_settings():
    """Write the settings file with default BI SSH settings."""
    toml = TOMLDocument()
    toml.add(comment("This file can be used to customize the Slices BI CLI."))
    # toml.add(nl())
    toml.add(comment("Each of the settings can be overridden with a specific SLICES_BI_* environment variables."))
    toml.add(nl())

    ssh_section = table()
    ssh_section.add(comment("These options control the command: slices bi ssh"))
    ssh_section.add(comment(""))
    ssh_section.add(comment("extra_options:"))
    ssh_section.add(comment("    Extra options to pass to the ssh command, before any other options."))
    ssh_section.add(comment("    Env var: SLICES_BI_EXTRA_SSH_OPTIONS"))
    ssh_section.add(comment(""))
    toml.add("ssh", ssh_section)
    ssh_section["extra_options"] = []
    ssh_section.add(comment("Example:"))
    ssh_section.add(comment('extra_options = ["-A", "-X", "-oPasswordAuthentication=no"]'))
    # ssh_section["exe"] = "ssh"  # not documented at the moment
    # ssh_section["exe"].comment("SLICES_BI_SFTP_EXE")  # not documented at the moment

    scp_section = table()
    scp_section.add(comment("These options control the command: slices bi scp"))
    scp_section.add(comment(""))
    scp_section.add(comment("extra_options:"))
    scp_section.add(comment("    Extra options to pass to the scp command, before any other options."))
    scp_section.add(comment("    Env var: SLICES_BI_EXTRA_SCP_OPTIONS"))
    scp_section.add(comment(""))
    toml.add("scp", scp_section)
    scp_section["extra_options"] = []
    # scp_section["exe"] = "scp"  # not documented at the moment
    # scp_section["exe"].comment("SLICES_BI_SCP_EXE")  # not documented at the moment

    sftp_section = table()
    sftp_section.add(comment("These options control the command: slices bi sftp"))
    sftp_section.add(comment(""))
    sftp_section.add(comment("extra_options:"))
    sftp_section.add(comment("    Extra options to pass to the sftp command, before any other options."))
    sftp_section.add(comment("    Env var: SLICES_BI_EXTRA_SFTP_OPTIONS"))
    sftp_section.add(comment(""))
    toml.add("sftp", sftp_section)
    sftp_section["extra_options"] = []
    # sftp_section["exe"] = "sftp"  # not documented at the moment
    # sftp_section["exe"].comment("SLICES_BI_SFTP_EXE")  # not documented at the moment

    config_dir_location.mkdir(exist_ok=True)
    settings_file = TOMLFile(bi_settings_file)
    settings_file.write(toml)
