from pydantic import BaseModel, SecretStr, AnyHttpUrl, constr, HttpUrl, Field
from bson import ObjectId
from datetime import datetime
from typing import Dict, Optional, Union, Any

class OAuthConfig(BaseModel):
    client_id: str
    client_secret: SecretStr
    authorization_url: HttpUrl
    token_url: HttpUrl
    scope: Optional[str] = None
    token_exchange_method: str = "POST"  # Default to POST, can be overridden

class AppBase(BaseModel):
    name: str
    user_id: str  # Admin user ID who added the app
    category_id: str  # Foreign key reference to the category
    call_type: str  # This indicates load type - openapi or sdk or something else ?
    api_schema: Optional[str] = None  # Field to store OpenAPI spec as a string - JSON file
    auth: Optional[str] = None # Field to store Type of Authentication to use the API. 
    icon: str = ""
    status: bool = True  # 1 for active, 0 for inactive
    description: Optional[str] = ""
    account_id: Optional[str] = ""  # Specific to an account if set, otherwise a public app
    approot: Optional[str] = ""  # Unique app ID, used for identification
    integrations: int = 0  # Number of integrations
    created_date: datetime = datetime.utcnow()

class App(AppBase):
    id: str = Field(default_factory=ObjectId, alias="_id")

    class Config:
        arbitrary_types_allowed = True
        json_encoders = {ObjectId: str}
        allow_population_by_field_name = True

class AppList(App):
    app_id: str
    
class AppCategory(BaseModel):
    id: str = Field(default=None, alias="_id")
    category: str

class Category(BaseModel):
    id: str
    name: str

class AuthConfig(BaseModel):
    auth: str  # e.g., 'api_key', 'oauth', 'no_auth'
    credentials: Dict[str, Union[SecretStr, constr(), AnyHttpUrl, Any]]  # Flexible storage for various credentials
    #oauth_config: Optional[OAuthConfig] = None

class AppIntegration(BaseModel):
    integration_id: Optional[str] = ""
    title: str #Title of the integration
    app_id: str  # Reference to the App collection
    user_id: str  # User ID who created the integration
    account_id: str # Account ID
    configurations: Optional[Dict[str, str]] = {}  # Custom configuration parameters
    auth_config: AuthConfig  # Authentication configuration for the user's integration
    status: int = 1
    created_date: datetime = datetime.utcnow()

class AppIntegrationUpdate(BaseModel):
    title: str #Title of the integration
    configurations: Optional[Dict[str, str]] = {}  # Custom configuration parameters
    auth_config: Optional[AuthConfig]  # Authentication configuration for the user's integration
    status: int = 1
    created_date: datetime = datetime.utcnow()


class Integrations(AppIntegration):
    id: str = Field(default_factory=ObjectId, alias="_id")

    class Config:
        arbitrary_types_allowed = True
        json_encoders = {ObjectId: str}
        allow_population_by_field_name = True

class AppLogBase(BaseModel):
    app_id: str
    user_app_id: str  # Reference to the UserAppIntegration
    request: Dict[str, str]
    response: Dict[str, str]
    created_date: datetime = datetime.utcnow()

class AppLog(AppLogBase):
    id: str = Field(default_factory=ObjectId, alias="_id")

    class Config:
        arbitrary_types_allowed = True
        json_encoders = {ObjectId: str}
        allow_population_by_field_name = True
