"""Field proxies that support Python comparison operators for queries."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Any


# ── Sentinel types for special fields ────────────────────────────────────

class _DateType:
    """Sentinel for date fields. Usage: zuzu.date"""
    def __repr__(self) -> str:
        return "zuzu.date"

class _ImageType:
    """Sentinel for image URL fields. Usage: zuzu.image"""
    def __repr__(self) -> str:
        return "zuzu.image"

date = _DateType()
image = _ImageType()


# ── Choice field with optional color mapping ─────────────────────────────

class Choice:
    """A choice field with an explicit list of options and optional colors.

    Usage:
        status=zuzu.Choice(["lead", "active", "churned"], colors={
            "lead": "yellow",
            "active": "green",
            "churned": "red",
        })
    """

    def __init__(self, options: list[str], colors: dict[str, str] | None = None) -> None:
        self.options = options
        self.colors = colors or {}

    def __repr__(self) -> str:
        return f"Choice({self.options!r})"


# ── Number formatting types ──────────────────────────────────────────────

class Currency:
    """A monetary value with a currency symbol.

    Usage:
        price=zuzu.Currency(0.0, symbol="$")
    """

    def __init__(self, default: float = 0.0, symbol: str = "$") -> None:
        self.default = default
        self.symbol = symbol

    def __repr__(self) -> str:
        return f"Currency({self.default!r}, symbol={self.symbol!r})"


class Percent:
    """A percentage value (stored as a plain number, formatted with %).

    Usage:
        tax_rate=zuzu.Percent(0.0)
    """

    def __init__(self, default: float = 0.0) -> None:
        self.default = default

    def __repr__(self) -> str:
        return f"Percent({self.default!r})"


class Rating:
    """A rating value (integer, with a configurable max).

    Usage:
        stars=zuzu.Rating(0, max=5)
    """

    def __init__(self, default: int = 0, max: int = 5) -> None:
        self.default = default
        self.max = max

    def __repr__(self) -> str:
        return f"Rating({self.default!r}, max={self.max!r})"


# ── Condition (result of a comparison) ───────────────────────────────────

@dataclass(frozen=True)
class Condition:
    """A single filter condition, produced by Field comparisons."""
    field: str
    op: str
    value: Any

    def __and__(self, other: Condition) -> CompoundCondition:
        return CompoundCondition("AND", [self, other])

    def __or__(self, other: Condition) -> CompoundCondition:
        return CompoundCondition("OR", [self, other])


@dataclass(frozen=True)
class CompoundCondition:
    """Multiple conditions joined by AND/OR."""
    join: str  # "AND" or "OR"
    conditions: list[Condition | CompoundCondition]

    def __and__(self, other: Condition | CompoundCondition) -> CompoundCondition:
        if self.join == "AND":
            return CompoundCondition("AND", [*self.conditions, other])
        return CompoundCondition("AND", [self, other])

    def __or__(self, other: Condition | CompoundCondition) -> CompoundCondition:
        if self.join == "OR":
            return CompoundCondition("OR", [*self.conditions, other])
        return CompoundCondition("OR", [self, other])


# ── Field proxy (returned by Record.field_name access) ───────────────────

class FieldProxy:
    """Proxy object that supports comparison operators.

    Usage:
        clients.where(clients.revenue > 100)
        clients.where(clients.name.contains("tech"))
    """

    def __init__(self, name: str) -> None:
        self._name = name

    # Comparison operators
    def __gt__(self, value: Any) -> Condition:
        return Condition(self._name, ">", value)

    def __ge__(self, value: Any) -> Condition:
        return Condition(self._name, ">=", value)

    def __lt__(self, value: Any) -> Condition:
        return Condition(self._name, "<", value)

    def __le__(self, value: Any) -> Condition:
        return Condition(self._name, "<=", value)

    def __eq__(self, value: Any) -> Condition:  # type: ignore[override]
        return Condition(self._name, "=", value)

    def __ne__(self, value: Any) -> Condition:  # type: ignore[override]
        return Condition(self._name, "!=", value)

    # String operators
    def contains(self, value: str) -> Condition:
        return Condition(self._name, "LIKE", f"%{value}%")

    def starts_with(self, value: str) -> Condition:
        return Condition(self._name, "LIKE", f"{value}%")

    def ends_with(self, value: str) -> Condition:
        return Condition(self._name, "LIKE", f"%{value}")

    # List membership
    def is_in(self, values: list[Any]) -> Condition:
        return Condition(self._name, "IN", values)

    def __repr__(self) -> str:
        return f"Field({self._name!r})"
