"""SQL dialect abstractions for cross-database compatibility."""

from __future__ import annotations

from abc import ABC, abstractmethod


class Dialect(ABC):
    """Abstract SQL dialect defining database-specific syntax."""

    @abstractmethod
    def param(self, index: int) -> str:
        """Return a parameter placeholder for the given 1-based index."""

    @abstractmethod
    def quote(self, name: str) -> str:
        """Quote a SQL identifier."""

    @abstractmethod
    def cast(self, expr: str, type_name: str) -> str:
        """Cast an expression to a type."""


class PostgresDialect(Dialect):
    def param(self, index: int) -> str:
        return f"${index}"

    def quote(self, name: str) -> str:
        return '"' + name.replace('"', '""') + '"'

    def cast(self, expr: str, type_name: str) -> str:
        return f"{expr}::{type_name}"


class BigQueryDialect(Dialect):
    _TYPE_MAP = {"numeric": "FLOAT64", "text": "STRING"}

    def param(self, index: int) -> str:
        return f"@p{index}"

    def quote(self, name: str) -> str:
        return "`" + name.replace("`", r"\`") + "`"

    def cast(self, expr: str, type_name: str) -> str:
        bq_type = self._TYPE_MAP.get(type_name.lower(), type_name.upper())
        return f"CAST({expr} AS {bq_type})"
