from typing import Optional, cast

from litestar.contrib.repository import FilterTypes
from litestar.contrib.sqlalchemy.repository import ModelT, SQLAlchemyAsyncRepository
from litestar.contrib.sqlalchemy.repository.types import SelectT
from sqlalchemy import true, Column

from app.lib.filters import ExactFilter


class FilterRepository(SQLAlchemyAsyncRepository[ModelT]):
    alive_flag: Optional[str] = None

    def _get_column_by_name(self, name: str) -> Column | None:
        return cast(Column, getattr(self.model_type, name, None))

    def _apply_filters(
        self, *filters: FilterTypes, apply_pagination: bool = True, statement: SelectT
    ) -> SelectT:
        standard_filters = []
        for filter_ in filters:
            if isinstance(filter_, ExactFilter):
                statement = statement.where(
                    self._get_column_by_name(filter_.field_name) == filter_.value
                )
            else:
                standard_filters.append(filter_)

        statement = super()._apply_filters(
            *standard_filters, apply_pagination=apply_pagination, statement=statement
        )

        if self.alive_flag:
            statement = statement.where(
                self._get_column_by_name(self.alive_flag) == true()
            )

        return statement
