from typing import Optional, List, Dict, Any, Union, AsyncGenerator
from datetime import datetime
from pydantic import BaseModel, Field
from uuid import UUID, uuid4
from enum import Enum
from ..core.streaming import StreamFormat, StreamChunk, StreamMetrics, StreamContext, StreamState


class ModelType(Enum):
    """Model type enumeration"""
    TEXT = "text"
    TEXT_GENERATION = "text_generation"
    CHAT = "chat"
    EMBEDDING = "embedding"
    EMBED = "embed"


class ProviderType(Enum):
    """Provider type enumeration"""
    OPENAI = "openai"
    ANTHROPIC = "anthropic"
    COHERE = "cohere"
    LOCAL = "local"
    HUGGINGFACE = "huggingface"


class ProviderConfig(BaseModel):
    """Provider configuration"""
    api_key: Optional[str] = None
    base_url: Optional[str] = None
    timeout: float = 30.0
    max_retries: int = 3
    headers: Optional[Dict[str, str]] = None


class ModelConfig(BaseModel):
    """Model configuration"""
    model_name: str
    provider_type: ProviderType
    provider_config: ProviderConfig
    temperature: float = 0.7
    max_tokens: int = 1024
    top_p: float = 1.0
    frequency_penalty: float = 0.0
    presence_penalty: float = 0.0
    cache_config: Optional["CacheConfig"] = None


class BatchRequest(BaseModel):
    """Batch request data structure"""
    requests: List["Request"]
    batch_size: int = 1
    max_concurrency: int = 1
    retry_attempts: int = 3


class BatchResponse(BaseModel):
    """Batch response data structure"""
    results: List["Response"]
    failed_requests: List[Dict[str, Any]]
    total_requests: int
    successful_requests: int
    failed_requests_count: int


class Request(BaseModel):
    """Request data structure"""
    id: UUID = Field(default_factory=uuid4)
    prompt: str
    model: str
    type: ModelType = ModelType.TEXT
    temperature: float = 0.7
    max_tokens: int = 1024
    created_at: datetime = Field(default_factory=datetime.utcnow)


class Response(BaseModel):
    """Response data structure"""
    id: UUID = Field(default_factory=uuid4)
    content: str
    usage: Dict[str, int]
    created_at: datetime = Field(default_factory=datetime.utcnow)


class CacheEntry(BaseModel):
    """Cache entry data structure"""
    request: Request
    response: Response
    similarity_score: float
    cached_at: datetime


class CacheConfig(BaseModel):
    """Cache configuration"""
    enabled: bool = True
    max_size: int = 1000
    similarity_threshold: float = 0.8
    ttl_seconds: Optional[int] = 3600


class SimilarityResult(BaseModel):
    """Similarity search result"""
    request_id: UUID
    similar_entries: List[CacheEntry]
    scores: List[float]
    best_match: Optional[CacheEntry] = None
    best_score: Optional[float] = None