"""Multi-tenant fair queuing background tasks.

This module provides a fair task queue implementation that ensures fair distribution
of tasks across different groups (e.g., users, tenants).

Optional Dependencies:
    - redis: Required for RedisFairQueueStorage and RedisDistributedLock
    - taskiq: Required for TaskIQAdapter
    - observability: Optional, enables MetricsHook and TracingHook with OpenTelemetry
    - sqlalchemy: Required for DatabaseFairQueueStorage
    - config: Optional, enables FairQueueConfig for configuration management

Example:
    ```python
    from redis.asyncio import Redis
    from taskiq import AsyncBroker
    from haolib.background.fair import create_fair_task_queue_quick

    redis = Redis()
    broker = AsyncBroker()

    # Quick start - simplest usage
    queue = create_fair_task_queue_quick(redis, broker)

    async with queue:
        # Simple enqueue with kwargs
        task_id = await queue.enqueue(my_task, group_id="user_123", priority=10)
        result = await queue.wait_for_result(task_id, "user_123", timeout_seconds=30.0)
    ```

    Or use the builder for more control:
    ```python
    from haolib.background.fair import FairTaskQueueBuilder

    # With Redis storage
    queue = (
        FairTaskQueueBuilder()
        .with_redis_storage(redis)
        .with_taskiq_adapter(broker)
        .with_user_id_extractor()
        .build()
    )

    # With database storage
    from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
    from sqlalchemy.orm import sessionmaker

    engine = create_async_engine("postgresql+asyncpg://...")
    async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

    queue = (
        FairTaskQueueBuilder()
        .with_database_storage(async_session())
        .with_taskiq_adapter(broker)
        .with_user_id_extractor()
        .build()
    )
    ```

Multi-Instance Deployment:
    For multi-instance deployments, configure distributed locks:

    ```python
    from haolib.background.fair import FairTaskQueueBuilder, RedisDistributedLock

    redis = Redis()
    broker = AsyncBroker()

    # Distributed lock is automatically configured when using with_redis_storage
    queue = (
        FairTaskQueueBuilder()
        .with_redis_storage(redis, enable_distributed_lock=True)
        .with_taskiq_adapter(broker)
        .with_user_id_extractor()
        .build()
    )

    # Or configure manually
    lock = RedisDistributedLock(redis, key_prefix="fair_queue:lock")
    queue = (
        FairTaskQueueBuilder()
        .with_redis_storage(redis, enable_distributed_lock=False)
        .with_taskiq_adapter(broker)
        .with_distributed_lock(lock)
        .with_user_id_extractor()
        .build()
    )
    ```

Features:
    - Fair task distribution across groups
    - Rate limiting per group
    - Task result retrieval from TaskIQ result backends
    - Automatic result storage via result handlers
    - Task result streaming
    - Distributed tracing support
    - Middleware system
    - Dead letter queue
    - Idempotency support
    - Distributed coordination for multi-instance deployments
    - Automatic recovery of stuck tasks
    - Task dependencies/chaining support
    - Structured logging with JSON format
    - Prometheus metrics export
    - Redis connection retry with exponential backoff

"""

from haolib.background.fair.abstract import (
    ComponentHealthStatus,
    EnqueueOptions,
    FairTask,
    GroupMetrics,
    GroupQueueState,
    OverallHealthStatus,
    QueueMetrics,
    QueueStats,
    RateLimit,
    SchedulerMetrics,
    SerializationStrategy,
    TaskInfo,
    TaskInvocation,
    TaskRegistration,
    TaskResultUpdate,
    TaskStatus,
)
from haolib.background.fair.adapters import (
    DefaultInvocationSerializer,
    TaskIQAdapter,
)
from haolib.background.fair.customization import (
    DefaultDependencyResolver,
    DefaultGroupWeightCalculator,
    DefaultTaskPrioritizer,
    DependencyResolver,
    GroupWeightCalculator,
    TaskPrioritizer,
)
from haolib.background.fair.distributed_lock import DistributedLock, DistributedLockContext
from haolib.background.fair.extractors import (
    TaskInvocationGroupKeyExtractor,
    compose_extractors,
    extract_from_args,
    extract_from_kwargs,
    extract_with_default,
)
from haolib.background.fair.factory import (
    FairTaskQueueBuilder,
    create_fair_task_queue,
    create_fair_task_queue_quick,
)
from haolib.background.fair.observability import (
    StructuredLoggingHook,
    TracingHook,
    export_prometheus_metrics,
    export_prometheus_metrics_async,
)
from haolib.background.fair.queue import FairTaskQueue
from haolib.background.fair.results import (
    NoOpResultHandler,
    StorageResultHandler,
    TaskResultHandler,
)
from haolib.background.fair.storages.memory import InMemoryFairQueueStorage
from haolib.background.fair.storages.redis import RedisDistributedLock
from haolib.configs.fair import FairQueueConfig

__all__ = [
    "ComponentHealthStatus",
    "DefaultDependencyResolver",
    "DefaultGroupWeightCalculator",
    "DefaultInvocationSerializer",
    "DefaultTaskPrioritizer",
    "DependencyResolver",
    "DistributedLock",
    "DistributedLockContext",
    "EnqueueOptions",
    "FairQueueConfig",
    "FairTask",
    "FairTaskQueue",
    "FairTaskQueueBuilder",
    "GroupMetrics",
    "GroupQueueState",
    "GroupWeightCalculator",
    "InMemoryFairQueueStorage",
    "NoOpResultHandler",
    "OverallHealthStatus",
    "QueueMetrics",
    "QueueStats",
    "RateLimit",
    "RedisDistributedLock",
    "SchedulerMetrics",
    "SerializationStrategy",
    "StorageResultHandler",
    "StructuredLoggingHook",
    "TaskIQAdapter",
    "TaskInfo",
    "TaskInvocation",
    "TaskInvocationGroupKeyExtractor",
    "TaskPrioritizer",
    "TaskRegistration",
    "TaskResultHandler",
    "TaskResultUpdate",
    "TaskStatus",
    "TracingHook",
    "compose_extractors",
    "create_fair_task_queue",
    "create_fair_task_queue_quick",
    "export_prometheus_metrics",
    "export_prometheus_metrics_async",
    "extract_from_args",
    "extract_from_kwargs",
    "extract_with_default",
]
