from beanie import Document, Indexed
from pydantic import Field
from typing import Optional, Dict, Any, List
from datetime import datetime
from enum import Enum
from bson import ObjectId

class ThemeMode(str, Enum):
    LIGHT = "light"
    DARK = "dark"
    AUTO = "auto"

class Language(str, Enum):
    ENGLISH = "en"
    SPANISH = "es"
    FRENCH = "fr"
    GERMAN = "de"
    PORTUGUESE = "pt"
    CHINESE = "zh"
    JAPANESE = "ja"

class NotificationFrequency(str, Enum):
    IMMEDIATE = "immediate"
    DAILY = "daily"
    WEEKLY = "weekly"
    NEVER = "never"

class UserPreference(Document):
    # User Reference
    user_id: Indexed(ObjectId, unique=True)  # References User from auth service
    
    # UI/UX Preferences
    theme: ThemeMode = ThemeMode.AUTO
    language: Language = Language.ENGLISH
    timezone: str = "UTC"
    date_format: str = "YYYY-MM-DD"  # ISO format, US format, etc.
    time_format: str = "24"  # "12" or "24" hour
    
    # Notification Preferences
    email_notifications: bool = True
    push_notifications: bool = True
    sms_notifications: bool = False
    
    # Notification Types
    notification_preferences: Dict[str, bool] = Field(default_factory=lambda: {
        "security_alerts": True,
        "account_updates": True,
        "marketing_emails": False,
        "product_updates": True,
        "friend_requests": True,
        "messages": True,
        "mentions": True,
        "comments": True,
        "likes": False,
        "followers": True
    })
    
    # Notification Frequency
    email_frequency: NotificationFrequency = NotificationFrequency.IMMEDIATE
    digest_frequency: NotificationFrequency = NotificationFrequency.DAILY
    
    # Privacy Preferences
    privacy_settings: Dict[str, Any] = Field(default_factory=lambda: {
        "profile_visibility": "public",
        "search_visibility": True,
        "show_online_status": True,
        "show_last_seen": True,
        "allow_friend_requests": True,
        "allow_messages_from_strangers": False,
        "show_email": False,
        "show_phone": False,
        "data_collection_consent": False,
        "analytics_tracking": True
    })
    
    # Security Preferences
    security_settings: Dict[str, Any] = Field(default_factory=lambda: {
        "two_factor_enabled": False,
        "login_notifications": True,
        "unusual_activity_alerts": True,
        "password_expiry_reminder": True,
        "session_timeout": 30,  # minutes
        "require_password_for_sensitive_actions": True
    })
    
    # Content Preferences
    content_preferences: Dict[str, Any] = Field(default_factory=lambda: {
        "content_language": "en",
        "mature_content": False,
        "auto_play_videos": True,
        "high_contrast_mode": False,
        "reduce_motion": False,
        "font_size": "medium",
        "posts_per_page": 20
    })
    
    # Communication Preferences
    communication_settings: Dict[str, Any] = Field(default_factory=lambda: {
        "preferred_contact_method": "email",
        "marketing_consent": False,
        "newsletter_subscription": False,
        "survey_participation": False,
        "beta_program": False
    })
    
    # App-Specific Settings
    app_settings: Dict[str, Any] = Field(default_factory=dict)
    
    # Custom Preferences (extensible)
    custom_preferences: Dict[str, Any] = Field(default_factory=dict)
    
    # Metadata
    created_at: datetime = Field(default_factory=datetime.utcnow)
    updated_at: datetime = Field(default_factory=datetime.utcnow)
    
    class Config:
        arbitrary_types_allowed = True

    class Settings:
        name = "user_preferences"
        indexes = [
            "user_id",
            "language",
            "theme",
            "updated_at"
        ]

    @classmethod
    async def create_default_preferences(cls, user_id: ObjectId) -> "UserPreference":
        """Create default preferences for a new user"""
        preferences = cls(user_id=user_id)
        await preferences.save()
        return preferences

    async def update_notification_preference(self, notification_type: str, enabled: bool):
        """Update a specific notification preference"""
        self.notification_preferences[notification_type] = enabled
        self.updated_at = datetime.utcnow()
        await self.save()

    async def update_privacy_setting(self, setting_name: str, value: Any):
        """Update a privacy setting"""
        self.privacy_settings[setting_name] = value
        self.updated_at = datetime.utcnow()
        await self.save()

    async def update_security_setting(self, setting_name: str, value: Any):
        """Update a security setting"""
        self.security_settings[setting_name] = value
        self.updated_at = datetime.utcnow()
        await self.save()

    async def update_content_preference(self, preference_name: str, value: Any):
        """Update a content preference"""
        self.content_preferences[preference_name] = value
        self.updated_at = datetime.utcnow()
        await self.save()

    async def bulk_update_preferences(self, updates: Dict[str, Any]):
        """Bulk update multiple preferences"""
        for category, settings in updates.items():
            if category == "notification_preferences":
                self.notification_preferences.update(settings)
            elif category == "privacy_settings":
                self.privacy_settings.update(settings)
            elif category == "security_settings":
                self.security_settings.update(settings)
            elif category == "content_preferences":
                self.content_preferences.update(settings)
            elif category == "communication_settings":
                self.communication_settings.update(settings)
            elif category == "app_settings":
                self.app_settings.update(settings)
            elif category == "custom_preferences":
                self.custom_preferences.update(settings)
            elif hasattr(self, category):
                setattr(self, category, settings)
        
        self.updated_at = datetime.utcnow()
        await self.save()

    def get_notification_preference(self, notification_type: str) -> bool:
        """Get a specific notification preference"""
        return self.notification_preferences.get(notification_type, False)

    def get_privacy_setting(self, setting_name: str) -> Any:
        """Get a privacy setting"""
        return self.privacy_settings.get(setting_name)

    def get_security_setting(self, setting_name: str) -> Any:
        """Get a security setting"""
        return self.security_settings.get(setting_name)

    def is_notification_enabled(self, notification_type: str) -> bool:
        """Check if a specific notification type is enabled"""
        # Check global notification settings first
        if notification_type in ["email", "push", "sms"]:
            if notification_type == "email" and not self.email_notifications:
                return False
            elif notification_type == "push" and not self.push_notifications:
                return False
            elif notification_type == "sms" and not self.sms_notifications:
                return False
        
        # Check specific notification preference
        return self.get_notification_preference(notification_type)

    async def export_preferences(self) -> Dict[str, Any]:
        """Export all preferences as a dictionary"""
        return {
            "user_id": str(self.user_id),
            "theme": self.theme,
            "language": self.language,
            "timezone": self.timezone,
            "date_format": self.date_format,
            "time_format": self.time_format,
            "email_notifications": self.email_notifications,
            "push_notifications": self.push_notifications,
            "sms_notifications": self.sms_notifications,
            "notification_preferences": self.notification_preferences,
            "email_frequency": self.email_frequency,
            "digest_frequency": self.digest_frequency,
            "privacy_settings": self.privacy_settings,
            "security_settings": self.security_settings,
            "content_preferences": self.content_preferences,
            "communication_settings": self.communication_settings,
            "app_settings": self.app_settings,
            "custom_preferences": self.custom_preferences,
            "created_at": self.created_at,
            "updated_at": self.updated_at
        }

    @classmethod
    async def import_preferences(cls, user_id: ObjectId, preferences_data: Dict[str, Any]) -> "UserPreference":
        """Import preferences from a dictionary"""
        # Remove metadata fields
        preferences_data.pop("user_id", None)
        preferences_data.pop("created_at", None)
        preferences_data.pop("updated_at", None)
        
        # Get or create user preferences
        user_prefs = await cls.find_one(cls.user_id == user_id)
        if not user_prefs:
            user_prefs = await cls.create_default_preferences(user_id)
        
        # Update preferences
        await user_prefs.bulk_update_preferences(preferences_data)
        return user_prefs
