from datetime import datetime
from pydantic import BaseModel, Field
from typing import Optional, List, TypeVar, Generic
from pydantic.generics import GenericModel
from .basemodel import CommonBase
from .saas.subscriptions import SaaSInvoices


# Base model for Features.
class FeatureBase(CommonBase):
    name: str = Field(..., description="Name of the feature")
    display: bool = Field(True, description="Flag to indicate if the feature should be visible")
    url: str = Field(..., description="URL for the feature")
    apiurl: Optional[str] = Field(None, description="API URL for the feature (if applicable)")
    icon: str = Field(..., description="Icon identifier for the feature")
    category: str = Field(..., description="Category of the feature (e.g. 'saas' or 'platform')")
    description: Optional[str] = Field(None, description="Description of the feature")


# Domain-specific model for Portfolio Holdings
class Portfolio(CommonBase):
    symbol: str                                     # e.g., "RELIANCE"
    quantity: float                                 # Number of shares held
    average_price: float                            # Average buy price
    current_price: Optional[float] = None           # Optional: can be null if real-time fetched
    notes: Optional[str] = None                     # Optional short note
    strategy: Optional[str] = None                  # e.g., "Momentum", "RSI", etc.
    source: Optional[str] = Field(default="manual") # "manual" or "signal" or "auto"
    executed_at: Optional[datetime] = None          # Actual execution time if it's a trade

# Zerodha Settings Model (One per user)
class ZerodhaSettings(CommonBase):
    api_key: str = Field(..., description="Zerodha Kite API key")
    api_secret: str = Field(..., description="Zerodha Kite API secret")
    redirect_url: str = Field(..., description="OAuth Redirect URL")
    
    broker_user_id: Optional[str] = Field(None, description="Zerodha user ID")
    access_token: Optional[str] = Field(None, description="Access token after login")
    public_token: Optional[str] = Field(None, description="Public token")
    login_time: Optional[datetime] = Field(None, description="Login timestamp")
    
    status: Optional[str] = Field("inactive", description="Connection status: active/inactive/expired")
    notes: Optional[str] = Field(None, description="Optional admin notes")

# Domain-specific model for Cities.
class DummyCities(CommonBase):
    name: str
    state: Optional[str] = None
    country: str

# Domain-specific model for Cities.
class DVehicleCategory(CommonBase):
    name: str
    rate: Optional[float] = None
    unit: Optional[str] = None
    base_rate: Optional[float] = None

# Domain-specific model for Cities.
class DummyPriceType(CommonBase):
    name: str
    status: Optional[str] = None
    currency: str
    city: Optional[int] = None         # Field to store the associated city (e.g., city ID or name)
    pricing_file: Optional[str] = None   # Field to store file information (e.g., URL or file path)


# Domain-specific model for Locations.
class LocationsBase(CommonBase):
    name: str
    address: str
    latitude: Optional[float] = None
    longitude: Optional[float] = None  # Corrected spelling from "langitude"
    type: Optional[str] = None

# Generic model for update operations.
class CommonUpdate(BaseModel):
    user_id: Optional[str] = None       # User performing the update
    updated_date: Optional[datetime] = Field(default_factory=datetime.utcnow)

# Generic model for list responses using Pydantic generics.
ModelType = TypeVar("ModelType", bound=BaseModel)


class CommonList(GenericModel, Generic[ModelType]):
    total_count: int
    items: List[ModelType]

# Mapping of collection names to models defined in this module.
MODEL_MAPPING = {
    "features": FeatureBase,
    "dummycities": DummyCities,
    "dummypricetype": DummyPriceType,
    "dummyvehiclecategory": DVehicleCategory,
    "saasinvoices": SaaSInvoices,
    "portfolio": Portfolio,
    "zerodha": ZerodhaSettings,  
    # Add more mappings here if needed.
}

def get_model_for_collection(collection_name: str):
    """
    Resolve the collection name to a Pydantic model using the mapping.
    This function is called by your routers.
    """
    model_class = MODEL_MAPPING.get(collection_name.lower())
    if model_class is None:
        raise ValueError(f"Model for collection '{collection_name}' not found.")
    return model_class
