"""String accessor for string operations."""
from __future__ import annotations

import re
from typing import TYPE_CHECKING

from cqla.exprs import base as exprs_base
from cqla.accessors.base import Accessor

if TYPE_CHECKING:
    from cqla.exprs.base import Expr


class String(Accessor):
    """Accessor for string operations."""

    def _expr_repr(self) -> str:
        return f"{self._expr!r}.str"

    def contains(self, pattern: str, *, literal: bool = False) -> Expr:
        repr_str = f"{self._expr_repr()}.contains({pattern!r})"
        if literal:
            fn = lambda r: pattern in self._expr(r)
        else:
            fn = lambda r: re.search(pattern, self._expr(r)) is not None
        return exprs_base.Expr(fn, repr_str)

    def contains_any(self, patterns: list[str]) -> Expr:
        return exprs_base.Expr(
            lambda r: any(s in self._expr(r) for s in patterns),
            f"{self._expr_repr()}.contains_any({', '.join(repr(s) for s in patterns)})"
        )

    def starts_with(self, prefix: str) -> Expr:
        return exprs_base.Expr(
            lambda r: self._expr(r).startswith(prefix),
            f"{self._expr_repr()}.starts_with({prefix!r})"
        )

    def ends_with(self, suffix: str) -> Expr:
        return exprs_base.Expr(
            lambda r: self._expr(r).endswith(suffix),
            f"{self._expr_repr()}.ends_with({suffix!r})"
        )

    def len_chars(self) -> Expr:
        return exprs_base.Expr(
            lambda r: len(self._expr(r)),
            f"{self._expr_repr()}.len_chars()"
        )

    def to_lowercase(self) -> Expr:
        return exprs_base.Expr(
            lambda r: self._expr(r).lower(),
            f"{self._expr_repr()}.to_lowercase()"
        )

    def to_uppercase(self) -> Expr:
        return exprs_base.Expr(
            lambda r: self._expr(r).upper(),
            f"{self._expr_repr()}.to_uppercase()"
        )
