from dataclasses import (
    dataclass,
)
from fa_purity.frozen import (
    FrozenDict,
)
from psycopg2.sql import (
    Identifier,
    SQL,
)
from typing import (
    cast,
    Optional,
)


def _purifier(
    statement: str, identifiers: FrozenDict[str, Optional[str]]
) -> SQL:
    raw_sql = SQL(statement)
    safe_args = FrozenDict(
        {key: Identifier(value) for key, value in identifiers.items()}
    )
    return cast(SQL, raw_sql.format(**safe_args))  # type: ignore[no-untyped-call]


@dataclass(frozen=True)
class _Query:
    statement: SQL


@dataclass(frozen=True)
class Query:
    _inner: _Query


def _pretty(raw: str) -> str:
    return " ".join(raw.strip(" \n\t").split())


def new_query(stm: str) -> Query:
    draft = _Query(SQL(_pretty(stm)))
    return Query(draft)


def dynamic_query(
    stm: str, identifiers: FrozenDict[str, Optional[str]]
) -> Query:
    draft = _Query(_purifier(_pretty(stm), identifiers))
    return Query(draft)
