"""When/Then/Otherwise conditional expressions."""
from __future__ import annotations

from typing import TYPE_CHECKING

from cqla.exprs import base as exprs_base

if TYPE_CHECKING:
    from cqla.exprs.base import Expr


class WhenBuilder:
    """Builder for when().then() chains."""

    def __init__(self, condition) -> None:
        self._condition = condition

    def then(self, value) -> ThenBuilder:
        """Specify value when condition is true."""
        return ThenBuilder([(self._condition, value)])


class ThenBuilder:
    """Builder after when().then(), allows chaining or otherwise()."""

    def __init__(self, cases: list[tuple]) -> None:
        self._cases = cases

    def when(self, condition) -> ChainedWhenBuilder:
        """Add another condition to the chain."""
        return ChainedWhenBuilder(self._cases, condition)

    def otherwise(self, value) -> 'Expr':
        """Specify the default value and return the final Expr."""
        cases = self._cases
        default = value

        def evaluate(record):
            for cond, val in cases:
                cond_result = cond(record) if callable(cond) else cond
                if cond_result:
                    return val(record) if callable(val) else val
            return default(record) if callable(default) else default

        # Build repr
        repr_parts = []
        for cond, val in cases:
            cond_repr = repr(cond) if hasattr(cond, '__repr__') else str(cond)
            val_repr = repr(val) if hasattr(val, '__repr__') else str(val)
            repr_parts.append(f"when({cond_repr}).then({val_repr})")

        default_repr = repr(default) if hasattr(default, '__repr__') else str(default)
        repr_str = ".".join(repr_parts) + f".otherwise({default_repr})"

        return exprs_base.Expr(evaluate, repr_str)


class ChainedWhenBuilder:
    """Builder for chained when conditions after initial when().then()."""

    def __init__(self, cases: list[tuple], condition) -> None:
        self._cases = cases
        self._condition = condition

    def then(self, value) -> ThenBuilder:
        """Specify value for this chained condition."""
        new_cases = self._cases + [(self._condition, value)]
        return ThenBuilder(new_cases)


def when(condition) -> WhenBuilder:
    """
    Start a conditional expression chain.

    Usage:
        when(field('age') > 18).then('adult').otherwise('minor')

        when(field('score') >= 90).then('A')
        .when(field('score') >= 80).then('B')
        .when(field('score') >= 70).then('C')
        .otherwise('F')

    Args:
        condition: An expression or callable that returns a boolean.

    Returns:
        WhenBuilder to continue the chain with .then()
    """
    return WhenBuilder(condition)
