from datetime import datetime, timezone, date, time
from typing import Literal, TypeVar, Any, Optional, get_args
from sqlmodel import SQLModel

ModelType = TypeVar("ModelType", bound=SQLModel)
Operation = Literal["create", "update", "delete", "soft_delete", "restore"]


def utcnow() -> datetime:
    return datetime.now(timezone.utc)


def to_primitive(value: Any) -> Any:
    """
    Convert Python values to CSV/JSON-friendly scalars.
    Datetime/date/time -> ISO 8601 strings; others unchanged.
    """
    if isinstance(value, (datetime, date, time)):
        return value.isoformat()
    return value


def parse_audit_operation(operation: Optional[str]) -> Optional[Operation]:
    """
    Parse and validate an operation string for audit queries.
    """
    if operation is None:
        return None

    if operation not in get_args(Operation):
        raise ValueError(
            f"Invalid operation: {operation}. Must be one of {get_args(Operation)}"
        )

    return operation  # type: ignore


def parse_audit_datetime(dt_str: Optional[str]) -> Optional[datetime]:
    """
    Parse an ISO 8601 datetime string for audit queries.
    Handles both 'Z' and '+00:00' timezone formats.
    """
    if dt_str is None:
        return None
    return datetime.fromisoformat(dt_str.replace("Z", "+00:00"))
