"""
Read named connections generated by the SCAI CLI.

The SCAI CLI writes source-database connection details into TOML files
under ``~/.snowflake/snowct/``::

    # ~/.snowflake/snowct/sqlserver.toml
    default_connection_name = "default"

    [connections.default]
    host = "127.0.0.1"
    port = 1433
    database = "testdb"
    username = "sa"
    password = "secret"
    trust_server_certificate = "yes"
    encrypt = "no"

Snowflake (target) connections live in ``~/.snowflake/config.toml``::

    default_connection_name = "default"

    [connections.default]
    account = "myaccount"
    user = "myuser"
    ...

Resolution order for dialect TOML files:

1. ``<project_root>/.snowflake/snowct/<dialect>.toml``  (project-level)
2. ``~/.snowflake/snowct/<dialect>.toml``                (user-level)
"""

from __future__ import annotations

import logging
import sys
from pathlib import Path
from typing import Any

if sys.version_info >= (3, 11):
    import tomllib
else:
    try:
        import tomllib  # type: ignore[import-not-found]
    except ModuleNotFoundError:
        import tomli as tomllib  # type: ignore[no-redef]

LOGGER = logging.getLogger(__name__)

SNOWFLAKE_DIR = ".snowflake"
SNOWCT_DIR = "snowct"
SNOWFLAKE_CONFIG_TOML = "config.toml"


def _toml_path(base: Path, dialect_file: str) -> Path:
    return base / SNOWFLAKE_DIR / SNOWCT_DIR / dialect_file


def _candidate_paths(dialect_file: str, project_root: Path | None) -> list[Path]:
    """Return TOML file paths to try, in priority order."""
    paths: list[Path] = []
    if project_root is not None:
        paths.append(_toml_path(project_root.resolve(), dialect_file))
    paths.append(_toml_path(Path.home(), dialect_file))
    return paths


def load_connections_toml(
    dialect_file: str,
    project_root: Path | str | None = None,
) -> dict[str, dict[str, Any]]:
    """Load the ``[connections]`` table from the first matching TOML file.

    Returns an empty dict when no file is found or the file has no
    ``[connections]`` section.
    """
    root = Path(project_root) if project_root else None
    for path in _candidate_paths(dialect_file, root):
        if path.is_file():
            LOGGER.debug("Loading connections from %s", path)
            with open(path, "rb") as fh:
                data = tomllib.load(fh)
            return data.get("connections", {})
    return {}


def resolve_named_connection(
    name: str,
    dialect_file: str = "sqlserver.toml",
    project_root: Path | str | None = None,
) -> dict[str, Any]:
    """Resolve a named connection from ``~/.snowflake/snowct/<dialect>.toml``.

    Raises ``KeyError`` when the connection name is not found.
    """
    all_connections = load_connections_toml(dialect_file, project_root)
    if name not in all_connections:
        candidates = ", ".join(sorted(all_connections)) or "(none)"
        root = Path(project_root) if project_root else None
        searched = [str(p) for p in _candidate_paths(dialect_file, root)]
        raise KeyError(
            f"Connection '{name}' not found in {SNOWFLAKE_DIR}/{SNOWCT_DIR}/{dialect_file}.\n"
            f"  Available connections: {candidates}\n"
            f"  Searched: {searched}"
        )
    return dict(all_connections[name])


def _load_toml(path: Path) -> dict[str, Any]:
    """Load a TOML file and return its contents."""
    with open(path, "rb") as fh:
        return tomllib.load(fh)


def _resolve_default_name(toml_path: Path) -> str | None:
    """Read ``default_connection_name`` from *toml_path*, or ``None``."""
    if not toml_path.is_file():
        return None
    data = _load_toml(toml_path)
    return data.get("default_connection_name")


def resolve_default_source_connection(
    dialect_file: str,
    project_root: Path | str | None = None,
) -> dict[str, Any]:
    """Resolve the *default* source connection from ``~/.snowflake/snowct/<dialect>.toml``.

    Looks for ``default_connection_name`` in the TOML, then resolves
    that connection.  Raises ``FileNotFoundError`` when no TOML file
    exists, and ``ValueError`` when no ``default_connection_name`` is set.
    """
    root = Path(project_root) if project_root else None
    for path in _candidate_paths(dialect_file, root):
        name = _resolve_default_name(path)
        if name is not None:
            return resolve_named_connection(name, dialect_file, project_root)

    searched = [str(p) for p in _candidate_paths(dialect_file, root)]
    raise FileNotFoundError(
        f"No source connection TOML found for dialect '{dialect_file}'.\n"
        f"  Searched: {searched}\n"
        "Create the file with a [connections.<name>] section and "
        "default_connection_name, or pass --source-connection."
    )


def _snowflake_config_candidates(project_root: Path | None) -> list[Path]:
    """Return paths for ``~/.snowflake/config.toml`` (and project-level)."""
    paths: list[Path] = []
    if project_root is not None:
        paths.append(project_root.resolve() / SNOWFLAKE_DIR / SNOWFLAKE_CONFIG_TOML)
    paths.append(Path.home() / SNOWFLAKE_DIR / SNOWFLAKE_CONFIG_TOML)
    return paths


def resolve_default_target_connection(
    project_root: Path | str | None = None,
) -> dict[str, Any]:
    """Resolve the *default* Snowflake target connection from ``~/.snowflake/config.toml``.

    Returns the raw connection dict.  Raises ``FileNotFoundError`` when
    no config.toml exists, and ``ValueError`` when no
    ``default_connection_name`` is set.
    """
    root = Path(project_root) if project_root else None
    for path in _snowflake_config_candidates(root):
        if not path.is_file():
            continue
        data = _load_toml(path)
        name = data.get("default_connection_name")
        if name is None:
            continue
        connections = data.get("connections", {})
        if name not in connections:
            candidates = ", ".join(sorted(connections)) or "(none)"
            raise KeyError(
                f"Default connection '{name}' not found in {path}.\n"
                f"  Available connections: {candidates}"
            )
        LOGGER.debug("Resolved default target connection '%s' from %s", name, path)
        result = dict(connections[name])
        result.setdefault("name", name)
        return result

    searched = [str(p) for p in _snowflake_config_candidates(root)]
    raise FileNotFoundError(
        f"No Snowflake config.toml found.\n"
        f"  Searched: {searched}\n"
        "Create ~/.snowflake/config.toml with a [connections.<name>] section "
        "and default_connection_name, or pass --connection."
    )
