"""Teradata ODBC connection configuration."""

from pydantic import Field

from data_exchange_agent.config.sections.connections.odbc.base import (
    BaseODBCConnectionConfig,
)


# Default Teradata gateway / ODBC port
DEFAULT_TERADATA_PORT = 1025

# Common install name; override with driver_name to match pyodbc.drivers() on your host
DEFAULT_TERADATA_ODBC_DRIVER = "Teradata Database ODBC Driver 17.20"


class TeradataConnectionConfig(BaseODBCConnectionConfig):
    """
    Configuration for Teradata Database via ODBC.

    Builds a connection string using DBCName, PortNumber, Database, UID, and PWD
    as documented for the Teradata ODBC driver.

    References:
        - https://docs.teradata.com/ (ODBC Driver for Teradata connection parameters)

    """

    driver_name: str = Field(
        default=DEFAULT_TERADATA_ODBC_DRIVER,
        description="ODBC driver name as reported by pyodbc.drivers()",
    )
    host: str = Field(
        ...,
        description="Hostname or IP of the Teradata system (used as DBCName when dbc_name is unset)",
    )
    port: int = Field(
        default=DEFAULT_TERADATA_PORT,
        ge=1,
        le=65535,
        description="Teradata gateway port (default 1025)",
    )
    database: str = Field(
        ..., description="Default database (e.g. TPC-DS database name)"
    )
    username: str = Field(default="", description="Database username")
    password: str = Field(default="", description="Database password")
    dbc_name: str | None = Field(
        default=None,
        description="Teradata DBCName / COP alias; defaults to host when omitted",
    )

    def build_connection_string(self) -> str:
        """Build the ODBC connection string for Teradata."""
        dbc = self.dbc_name if self.dbc_name is not None else self.host
        parts = [
            f"DRIVER={{{self.driver_name}}}",
            f"DBCName={dbc}",
            f"UID={self.username}",
            f"PWD={self.password}",
            f"Database={self.database}",
            f"PortNumber={self.port}",
        ]
        connection_string = ";".join(parts)

        for key, value in self.extra_options.items():
            stripped_key = str(key).strip()
            stripped_value = str(value).strip()
            connection_string += f";{stripped_key}={stripped_value}"

        return connection_string

    @classmethod
    def from_config_dict(
        cls,
        database: str,
        username: str,
        host: str,
        password: str = "",
        port: int = DEFAULT_TERADATA_PORT,
        driver_name: str = DEFAULT_TERADATA_ODBC_DRIVER,
        dbc_name: str | None = None,
        extra_options: dict | None = None,
        **kwargs: str | int | float | bool,
    ) -> "TeradataConnectionConfig":
        """
        Build config from TOML-loaded flat dict (and optional nested extra_options).

        Unknown top-level keys are merged into extra_options.
        """
        merged: dict[str, str | int | float | bool] = {}
        if extra_options:
            for k, v in extra_options.items():
                merged[str(k)] = v  # type: ignore[assignment]
        merged.update(kwargs)

        return cls(
            driver_name=driver_name,
            username=username,
            password=password,
            database=database,
            host=host,
            port=port,
            dbc_name=dbc_name,
            extra_options=merged,
        )

    def _repr_fields(self) -> str:
        base = super()._repr_fields()
        dbc = self.dbc_name if self.dbc_name is not None else self.host
        return f"dbc_name={dbc!r}, {base}"
