"""Table name and type resolution.

Resolves the physical name and type for a Table from the ``tables:`` section
of the config. Called from ``Model.Table()`` after the Table instance is
created, populating ``table.info``.

Resolution rules:

Physical name (priority order):
1. ``fqn`` in per-table config entry
2. ``default_schema`` prefix for unqualified names (no dots)
3. Logical name as-is

Table type (priority order):
1. Explicit ``type=`` kwarg on ``model.Table()``
2. ``type`` in per-table config entry
3. ``default_type`` from ``TablesConfig`` (defaults to ``"native"``)

Volume (priority order, only relevant for Iceberg):
1. ``Iceberg(external_volume=...)`` kwarg
2. ``volume`` in per-table config entry
3. ``default_volume`` from ``TablesConfig``
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from relationalai.config.tables import Iceberg, Native, TableInfo

if TYPE_CHECKING:
    from relationalai.config.config_tables_fields import TablesConfig
    from relationalai.semantics.frontend.base import Table


def resolve_table_info(table: "Table", tables_config: "TablesConfig | None") -> TableInfo:
    """Resolve the full config for a Table and return a ``TableInfo``.

    Parameters
    ----------
    table : Table
        The table reference created via ``model.Table()``.
    tables_config : TablesConfig or None
        The ``tables:`` section from config, or ``None`` if not set.

    Returns
    -------
    TableInfo
        Fully resolved table configuration.
    """
    name = table._name
    explicit_type = table._explicit_type

    # Look up per-table config entry (case-insensitive)
    entry = _find_entry(name, tables_config)

    # --- Resolve physical name ---
    if entry is not None and entry.fqn is not None:
        physical_name = entry.fqn
    elif tables_config is not None and tables_config.default_schema and "." not in name:
        physical_name = f"{tables_config.default_schema}.{name}"
    else:
        physical_name = name

    # --- Resolve table type ---
    if explicit_type is not None:
        resolved_type: Iceberg | Native = explicit_type
    elif entry is not None and entry.type == "iceberg":
        resolved_type = Iceberg()
    elif entry is not None and entry.type == "native":
        resolved_type = Native()
    elif tables_config is not None and tables_config.default_type == "iceberg":
        resolved_type = Iceberg()
    else:
        resolved_type = Native()

    # --- Resolve volume (only meaningful for Iceberg) ---
    volume: str | None = None
    if isinstance(explicit_type, Iceberg) and explicit_type.external_volume is not None:
        volume = explicit_type.external_volume
    elif entry is not None and entry.volume is not None:
        volume = entry.volume
    elif tables_config is not None:
        volume = tables_config.default_volume

    return TableInfo(
        type=resolved_type,
        volume=volume,
        fqn=entry.fqn if entry is not None else None,
        physical_name=physical_name,
    )


def _find_entry(name: str, tables_config: "TablesConfig | None"):
    """Look up a per-table entry by name, case-insensitively."""
    if tables_config is None or not tables_config.tables:
        return None
    name_lower = name.lower()
    for key, entry in tables_config.tables.items():
        if key.lower() == name_lower:
            return entry
    return None
