problemhardooduml-design-for-facebookuml design for facebookumldesignforfacebookobject-oriented-design-for-facebookobject oriented design for facebookobjectorienteddesignforfacebook

OOD - Facebook

HardUpdated: Jan 1, 2026

Problem Statement

You are tasked with designing the architecture for a large-scale social networking platform that connects billions of users worldwide. The platform must enable rich social interactions including profile management, bidirectional and asymmetric relationships (friends vs. followers), multimedia content sharing, real-time messaging, community building through groups and pages, and intelligent content distribution through personalized news feeds.

The system serves as the digital town square where individuals share life moments, businesses build audiences, communities organize around shared interests, and global conversations unfold. It must handle massive concurrent activity: millions of posts per hour, billions of feed impressions daily, real-time message delivery across continents, and instantaneous notifications for social interactions. The platform needs sophisticated content visibility controls through privacy settings and audience targeting, intelligent friend suggestions through graph analysis, and comprehensive search capabilities across people, content, and communities.

Critical architectural challenges include designing a scalable news feed algorithm that ranks and personalizes billions of content items, implementing efficient graph traversal for relationship queries (mutual friends, connection paths, community detection), maintaining low-latency message delivery in a distributed environment, ensuring content privacy while enabling viral distribution, and providing real-time notifications without overwhelming users. The system must also support moderation workflows, handle spam and abuse detection, manage multimedia storage and delivery, and provide analytics for user engagement patterns.

Requirements Analysis

Functional Requirements

  1. User Identity and Profile Management:

    • Register accounts with email/phone verification
    • Create rich profiles with biographical information, work history, education, interests
    • Upload and manage profile photos, cover photos, and multimedia albums
    • Control profile visibility with granular privacy settings
    • Manage account settings, security preferences, and session management
  2. Social Graph and Relationships:

    • Send, accept, reject, and cancel friend requests
    • Maintain bidirectional friend connections
    • Follow users asymmetrically (without mutual friendship)
    • Unfriend or block users
    • View mutual friends and connection paths
    • Get intelligent friend suggestions based on network proximity
  3. Content Creation and Sharing:

    • Create text posts with rich formatting
    • Attach photos, videos, and files to posts
    • Tag friends and locations in posts
    • Share external links with preview cards
    • Define post visibility (Public, Friends, Custom lists, Only Me)
    • Schedule posts for future publishing
    • Edit and delete posts with version history
  4. Social Interactions:

    • Like, love, or react to posts and comments
    • Comment on posts with nested replies (threading)
    • Share posts to own timeline or via messaging
    • Save posts for later viewing
    • Report inappropriate content
    • Hide posts from feed
  5. Groups and Communities:

    • Create public, closed, or secret groups
    • Join groups with admin approval for closed groups
    • Post content within groups
    • Assign member roles (Admin, Moderator, Member)
    • Manage group settings, rules, and membership
    • Discover groups through recommendations
  6. Pages and Public Figures:

    • Create pages for businesses, celebrities, organizations
    • Publish content as a page
    • Gain followers (asymmetric relationship)
    • Review and respond to page recommendations
    • Manage page roles and permissions
    • Access page analytics and insights
  7. Messaging System:

    • Send one-on-one messages
    • Create group conversations
    • Send multimedia messages (photos, videos, voice notes)
    • Real-time delivery with read receipts
    • Message search and archival
    • Mute or delete conversations
  8. News Feed and Content Discovery:

    • Personalized feed ranking based on relevance and engagement
    • Filter feed by content type (posts, photos, videos)
    • "See First" priority for specific friends or pages
    • Chronological vs. algorithmic feed options
    • Trending topics and hashtags
  9. Notifications:

    • Real-time notifications for social interactions (likes, comments, shares, tags)
    • Friend request and acceptance notifications
    • New message alerts
    • Group activity notifications
    • Birthday reminders
    • Notification preferences and muting
  10. Search and Discovery:

    • Search users by name, email, or phone
    • Search posts by keywords or hashtags
    • Find groups by name or topic
    • Discover pages by category
    • Search within conversations
    • People You May Know suggestions
  11. Privacy and Security:

    • Create custom privacy lists (Close Friends, Acquaintances, Restricted)
    • Control who sees posts, photos, friend list, and profile details
    • Review tags before they appear on timeline
    • Control who can send friend requests or messages
    • Two-factor authentication
    • Active session management
  12. Moderation and Safety:

    • Report content for violating community standards
    • Admin tools to review reported content
    • Suspend or ban accounts
    • Content takedown workflows
    • Appeal processes

Non-Functional Requirements

  • Performance: News feed load time < 1 second; message delivery latency < 100ms; notification delivery < 500ms
  • Scalability: Support 3 billion+ users; handle 500,000+ posts/second; deliver 10 billion+ feed impressions/day
  • Availability: 99.99% uptime; graceful degradation during peak traffic
  • Consistency: Strong consistency for friend relationships and messages; eventual consistency acceptable for feed updates
  • Security: End-to-end encryption for messages; secure authentication; protection against CSRF, XSS, SQL injection
  • Privacy: Compliance with GDPR, CCPA; user data export and deletion; transparency in data usage
  • Reliability: Zero data loss for messages and posts; durable storage with replication
  • Observability: Real-time metrics, logging, and alerting for system health

Use Case Diagram

graph TB
    subgraph Actors
        A1[👤 User]
        A2[👥 Group Admin]
        A3[📄 Page Manager]
        A4[👮 Content Moderator]
        A5[🖥️ System]
    end
    
    subgraph "Profile & Identity"
        UC1[📝 Create Profile]
        UC2[✏️ Edit Profile]
        UC3[🔐 Manage Privacy]
        UC4[📸 Upload Photos]
    end
    
    subgraph "Social Connections"
        UC5[🤝 Send Friend Request]
        UC6[✅ Accept/Reject Request]
        UC7[👁️ Follow User]
        UC8[🚫 Block User]
        UC9[💡 View Friend Suggestions]
    end
    
    subgraph "Content Creation"
        UC10[📰 Create Post]
        UC11[💬 Add Comment]
        UC12[❤️ React to Content]
        UC13[🔄 Share Post]
        UC14[🏷️ Tag Friends]
    end
    
    subgraph "Groups & Communities"
        UC15[➕ Create Group]
        UC16[🚪 Join Group]
        UC17[📢 Post in Group]
        UC18[⚙️ Manage Group Settings]
    end
    
    subgraph "Pages"
        UC19[📄 Create Page]
        UC20[📣 Publish as Page]
        UC21[⭐ Follow Page]
        UC22[💭 Add Page Review]
    end
    
    subgraph "Messaging"
        UC23[✉️ Send Message]
        UC24[👥 Create Group Chat]
        UC25[📎 Send Media]
        UC26[🔍 Search Messages]
    end
    
    subgraph "Feed & Discovery"
        UC27[📱 View News Feed]
        UC28[🔍 Search Content]
        UC29[🎯 Discover Pages/Groups]
    end
    
    subgraph "Notifications"
        UC30[🔔 Send Notification]
        UC31[🔕 Manage Preferences]
    end
    
    subgraph "Moderation"
        UC32[🚩 Report Content]
        UC33[🛡️ Review Reports]
        UC34[⛔ Suspend Account]
    end
    
    A1 --> UC1
    A1 --> UC2
    A1 --> UC3
    A1 --> UC4
    A1 --> UC5
    A1 --> UC6
    A1 --> UC7
    A1 --> UC8
    A1 --> UC9
    A1 --> UC10
    A1 --> UC11
    A1 --> UC12
    A1 --> UC13
    A1 --> UC14
    A1 --> UC27
    A1 --> UC28
    A1 --> UC29
    A1 --> UC23
    A1 --> UC32
    
    A2 --> UC15
    A2 --> UC16
    A2 --> UC17
    A2 --> UC18
    
    A3 --> UC19
    A3 --> UC20
    A3 --> UC21
    A3 --> UC22
    
    A4 --> UC33
    A4 --> UC34
    
    A5 --> UC30
    
    UC10 --> A5
    UC11 --> A5
    UC5 --> A5
    UC23 --> A5
    
    style UC1 fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
    style UC2 fill:#e1f5fe,stroke:#0288d1,stroke-width:2px
    style UC3 fill:#b3e5fc,stroke:#0277bd,stroke-width:2px
    style UC4 fill:#81d4fa,stroke:#01579b,stroke-width:2px
    style UC5 fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px
    style UC6 fill:#a5d6a7,stroke:#388e3c,stroke-width:2px
    style UC7 fill:#81c784,stroke:#43a047,stroke-width:2px
    style UC8 fill:#ffcdd2,stroke:#c62828,stroke-width:2px
    style UC9 fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style UC10 fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
    style UC11 fill:#e1bee7,stroke:#8e24aa,stroke-width:2px
    style UC12 fill:#ce93d8,stroke:#6a1b9a,stroke-width:2px
    style UC13 fill:#ba68c8,stroke:#4a148c,stroke-width:2px
    style UC14 fill:#ab47bc,stroke:#4a148c,stroke-width:2px
    style UC15 fill:#fff3e0,stroke:#ef6c00,stroke-width:2px
    style UC16 fill:#ffe0b2,stroke:#e65100,stroke-width:2px
    style UC17 fill:#ffcc80,stroke:#ef6c00,stroke-width:2px
    style UC18 fill:#ffb74d,stroke:#e65100,stroke-width:2px
    style UC19 fill:#e0f2f1,stroke:#00695c,stroke-width:2px
    style UC20 fill:#b2dfdb,stroke:#00796b,stroke-width:2px
    style UC21 fill:#80cbc4,stroke:#00897b,stroke-width:2px
    style UC22 fill:#4db6ac,stroke:#00695c,stroke-width:2px
    style UC23 fill:#f1f8e9,stroke:#558b2f,stroke-width:2px
    style UC24 fill:#dcedc8,stroke:#689f38,stroke-width:2px
    style UC25 fill:#c5e1a5,stroke:#7cb342,stroke-width:2px
    style UC26 fill:#aed581,stroke:#558b2f,stroke-width:2px
    style UC27 fill:#fce4ec,stroke:#c2185b,stroke-width:2px
    style UC28 fill:#f8bbd0,stroke:#ad1457,stroke-width:2px
    style UC29 fill:#f48fb1,stroke:#880e4f,stroke-width:2px
    style UC30 fill:#fff8e1,stroke:#f57f17,stroke-width:2px
    style UC31 fill:#ffecb3,stroke:#ff6f00,stroke-width:2px
    style UC32 fill:#ffebee,stroke:#b71c1c,stroke-width:2px
    style UC33 fill:#ef9a9a,stroke:#c62828,stroke-width:2px
    style UC34 fill:#e57373,stroke:#b71c1c,stroke-width:2px

Class Diagram

The design incorporates several key patterns:

  • Strategy Pattern: Different feed ranking algorithms (Chronological, EdgeRank, Engagement-based)
  • Observer Pattern: Real-time notifications for user activities
  • State Pattern: Account states (Active, Suspended, Deactivated, Deleted)
  • Factory Pattern: Creating different content types (TextPost, PhotoPost, VideoPost, LinkPost)
  • Composite Pattern: Nested comment threads
  • Facade Pattern: Unified search interface across multiple indexes
classDiagram
    %% Core Identity
    class UserAccount {
        <<abstract>>
        -UUID accountId
        -String email
        -String passwordHash
        -DateTime createdAt
        -AccountState state
        -SecuritySettings security
        +authenticate(password)
        +deactivate()
        +reactivate()
        +changePassword()
    }
    
    class AccountState {
        <<interface>>
        +handleLogin()
        +allowPosting()
        +transitionTo(AccountState)
    }
    
    class ActiveState {
        +handleLogin()
        +allowPosting()
    }
    
    class SuspendedState {
        +handleLogin()
        +allowPosting()
    }
    
    class DeactivatedState {
        +handleLogin()
        +allowPosting()
    }
    
    class DeletedState {
        +handleLogin()
        +allowPosting()
    }
    
    class RegularUser {
        -UserProfile profile
        -SocialGraph connections
        -List~Post~ timeline
        -List~Conversation~ messages
        -NotificationCenter notifications
        +createPost(content)
        +sendFriendRequest(user)
        +sendMessage(recipient, text)
    }
    
    class Administrator {
        -List~Permission~ permissions
        +reviewReport(reportId)
        +suspendAccount(userId)
        +deleteContent(contentId)
    }
    
    %% Profile
    class UserProfile {
        -PersonalInfo info
        -List~WorkExperience~ workHistory
        -List~Education~ educationHistory
        -List~MediaItem~ photos
        -PrivacySettings privacy
        -DateTime lastUpdated
        +updateBio(text)
        +addWorkExperience(work)
        +addEducation(edu)
        +setProfilePicture(photo)
    }
    
    class PersonalInfo {
        -String fullName
        -Date birthDate
        -Gender gender
        -String hometown
        -String currentCity
        -RelationshipStatus status
    }
    
    class WorkExperience {
        -String company
        -String position
        -String location
        -Date startDate
        -Date endDate
        -String description
    }
    
    class Education {
        -String institution
        -String degree
        -String fieldOfStudy
        -int graduationYear
    }
    
    class PrivacySettings {
        -VisibilityLevel profileVisibility
        -VisibilityLevel postsVisibility
        -VisibilityLevel friendListVisibility
        -List~PrivacyList~ customLists
        +updateSetting(key, value)
        +canView(viewer, resource)
    }
    
    class PrivacyList {
        -UUID listId
        -String name
        -List~RegularUser~ members
        +addMember(user)
        +removeMember(user)
    }
    
    %% Social Graph
    class SocialGraph {
        -List~Friendship~ friends
        -List~Following~ followings
        -List~FriendRequest~ pendingRequests
        -List~RegularUser~ blockedUsers
        +sendFriendRequest(user)
        +acceptRequest(requestId)
        +rejectRequest(requestId)
        +unfriend(user)
        +follow(user)
        +unfollow(user)
        +getMutualFriends(user)
        +getSuggestions()
    }
    
    class Friendship {
        -RegularUser user1
        -RegularUser user2
        -DateTime establishedAt
        -FriendshipStrength strength
        +calculateStrength()
    }
    
    class Following {
        -RegularUser follower
        -RegularUser followee
        -DateTime since
        -boolean notificationsEnabled
    }
    
    class FriendRequest {
        -UUID requestId
        -RegularUser sender
        -RegularUser recipient
        -RequestStatus status
        -DateTime sentAt
        +accept()
        +reject()
        +cancel()
    }
    
    class RequestStatus {
        <<enumeration>>
        PENDING
        ACCEPTED
        REJECTED
        CANCELLED
    }
    
    %% Content - Factory Pattern
    class ContentFactory {
        <<interface>>
        +createPost(type, data)
    }
    
    class PostFactory {
        +createPost(type, data)
        -createTextPost()
        -createPhotoPost()
        -createVideoPost()
        -createLinkPost()
    }
    
    class Post {
        <<abstract>>
        -UUID postId
        -RegularUser author
        -String content
        -DateTime createdAt
        -DateTime editedAt
        -VisibilityLevel visibility
        -List~Comment~ comments
        -List~Reaction~ reactions
        -int shareCount
        -List~RegularUser~ taggedUsers
        +edit(newContent)
        +delete()
        +addComment(comment)
        +react(user, reactionType)
        +share(user)
    }
    
    class TextPost {
        -String text
        -String formattedText
    }
    
    class PhotoPost {
        -List~Photo~ photos
        -String caption
    }
    
    class VideoPost {
        -Video video
        -String caption
        -String thumbnail
    }
    
    class LinkPost {
        -String url
        -LinkPreview preview
    }
    
    class Comment {
        -UUID commentId
        -RegularUser author
        -String text
        -DateTime createdAt
        -List~Comment~ replies
        -List~Reaction~ reactions
        +addReply(comment)
        +react(user, reactionType)
        +delete()
    }
    
    class Reaction {
        -RegularUser user
        -ReactionType type
        -DateTime timestamp
    }
    
    class ReactionType {
        <<enumeration>>
        LIKE
        LOVE
        HAHA
        WOW
        SAD
        ANGRY
    }
    
    %% Groups
    class Group {
        -UUID groupId
        -String name
        -String description
        -GroupType type
        -RegularUser creator
        -List~GroupMember~ members
        -List~Post~ posts
        -GroupSettings settings
        -DateTime createdAt
        +addMember(user, role)
        +removeMember(user)
        +createPost(post)
        +updateSettings(settings)
    }
    
    class GroupType {
        <<enumeration>>
        PUBLIC
        CLOSED
        SECRET
    }
    
    class GroupMember {
        -RegularUser user
        -GroupRole role
        -DateTime joinedAt
        +promoteToAdmin()
        +demote()
    }
    
    class GroupRole {
        <<enumeration>>
        MEMBER
        MODERATOR
        ADMIN
    }
    
    %% Pages
    class Page {
        -UUID pageId
        -String name
        -String description
        -PageCategory category
        -List~RegularUser~ admins
        -List~RegularUser~ followers
        -List~Post~ posts
        -List~PageReview~ reviews
        -PageAnalytics analytics
        +publishPost(post)
        +addFollower(user)
        +respondToReview(reviewId, response)
    }
    
    class PageReview {
        -UUID reviewId
        -RegularUser author
        -int rating
        -String text
        -DateTime createdAt
        -String adminResponse
    }
    
    class PageAnalytics {
        -int totalReach
        -int engagement
        -int newFollowers
        -Map~Date, Metrics~ dailyMetrics
        +getInsights(dateRange)
    }
    
    %% Messaging
    class Conversation {
        -UUID conversationId
        -List~RegularUser~ participants
        -List~Message~ messages
        -DateTime createdAt
        -DateTime lastActivity
        +sendMessage(message)
        +addParticipant(user)
        +removeParticipant(user)
        +markAsRead(user)
    }
    
    class Message {
        -UUID messageId
        -RegularUser sender
        -String content
        -DateTime sentAt
        -Map~RegularUser, DateTime~ readReceipts
        -List~MediaAttachment~ attachments
        +markAsRead(user)
        +delete()
    }
    
    class MediaAttachment {
        -UUID attachmentId
        -MediaType type
        -String url
        -int size
    }
    
    %% News Feed - Strategy Pattern
    class NewsFeed {
        -RegularUser user
        -FeedRankingStrategy rankingStrategy
        -List~Post~ cachedFeed
        -DateTime lastUpdated
        +refreshFeed()
        +setRankingStrategy(strategy)
        +getNextPage()
    }
    
    class FeedRankingStrategy {
        <<interface>>
        +rankPosts(posts, user)
    }
    
    class ChronologicalRanking {
        +rankPosts(posts, user)
    }
    
    class EdgeRankAlgorithm {
        +rankPosts(posts, user)
        -calculateAffinity(user, author)
        -calculateWeight(postType)
        -calculateTimeDecay(postAge)
    }
    
    class EngagementBasedRanking {
        +rankPosts(posts, user)
        -predictEngagement(post, user)
    }
    
    %% Notifications - Observer Pattern
    class NotificationCenter {
        -RegularUser user
        -List~Notification~ notifications
        -NotificationSettings settings
        +subscribe(eventType, handler)
        +unsubscribe(eventType)
        +sendNotification(notification)
        +markAsRead(notificationId)
    }
    
    class Notification {
        -UUID notificationId
        -NotificationType type
        -RegularUser recipient
        -RegularUser actor
        -NotificationContent content
        -DateTime createdAt
        -boolean read
        +markAsRead()
    }
    
    class NotificationType {
        <<enumeration>>
        FRIEND_REQUEST
        FRIEND_ACCEPTED
        POST_LIKED
        POST_COMMENTED
        POST_SHARED
        MENTIONED_IN_POST
        MENTIONED_IN_COMMENT
        MESSAGE_RECEIVED
        GROUP_INVITED
        BIRTHDAY_REMINDER
    }
    
    class NotificationPublisher {
        -List~NotificationObserver~ observers
        +subscribe(observer)
        +unsubscribe(observer)
        +notifyObservers(event)
    }
    
    class NotificationObserver {
        <<interface>>
        +onEvent(event)
    }
    
    class PushNotificationService {
        +onEvent(event)
        +sendPush(device, message)
    }
    
    class EmailNotificationService {
        +onEvent(event)
        +sendEmail(address, subject, body)
    }
    
    class InAppNotificationService {
        +onEvent(event)
        +deliverInApp(userId, notification)
    }
    
    %% Search - Facade Pattern
    class SearchFacade {
        -UserSearchIndex userIndex
        -PostSearchIndex postIndex
        -GroupSearchIndex groupIndex
        -PageSearchIndex pageIndex
        +search(query, filters)
        +searchUsers(query)
        +searchPosts(query)
        +searchGroups(query)
        +searchPages(query)
    }
    
    class SearchIndex {
        <<abstract>>
        #Map~String, Set~UUID~~ index
        +indexDocument(doc)
        +search(query)
        +removeDocument(docId)
    }
    
    class UserSearchIndex {
        +indexDocument(doc)
        +search(query)
        +searchByName(name)
        +searchByEmail(email)
    }
    
    class PostSearchIndex {
        +indexDocument(doc)
        +search(query)
        +searchByKeyword(keyword)
        +searchByHashtag(tag)
    }
    
    class GraphTraversal {
        +findShortestPath(user1, user2)
        +findMutualFriends(user1, user2)
        +suggestFriends(user, limit)
        +detectCommunities()
    }
    
    %% Moderation
    class ContentReport {
        -UUID reportId
        -RegularUser reporter
        -ReportableContent content
        -ReportReason reason
        -String details
        -ReportStatus status
        -Administrator assignedTo
        -DateTime createdAt
        +assign(admin)
        +resolve(action)
    }
    
    class ReportStatus {
        <<enumeration>>
        PENDING
        UNDER_REVIEW
        RESOLVED
        DISMISSED
    }
    
    class ModerationAction {
        -UUID actionId
        -Administrator moderator
        -ReportableContent content
        -ActionType actionType
        -String reason
        -DateTime executedAt
        +execute()
        +revert()
    }
    
    class ReportableContent {
        <<interface>>
        +getContentId()
        +getAuthor()
        +takedown()
    }
    
    %% Relationships
    UserAccount <|-- RegularUser
    UserAccount <|-- Administrator
    UserAccount --> AccountState
    AccountState <|.. ActiveState
    AccountState <|.. SuspendedState
    AccountState <|.. DeactivatedState
    AccountState <|.. DeletedState
    
    RegularUser *-- UserProfile
    RegularUser *-- SocialGraph
    RegularUser *-- NotificationCenter
    RegularUser *-- NewsFeed
    
    UserProfile --> PersonalInfo
    UserProfile *-- WorkExperience
    UserProfile *-- Education
    UserProfile --> PrivacySettings
    
    PrivacySettings *-- PrivacyList
    PrivacyList --> RegularUser
    
    SocialGraph *-- Friendship
    SocialGraph *-- Following
    SocialGraph *-- FriendRequest
    Friendship --> RegularUser
    Following --> RegularUser
    FriendRequest --> RegularUser
    FriendRequest --> RequestStatus
    
    ContentFactory <|.. PostFactory
    PostFactory ..> Post
    Post <|-- TextPost
    Post <|-- PhotoPost
    Post <|-- VideoPost
    Post <|-- LinkPost
    Post *-- Comment
    Post *-- Reaction
    Post --> RegularUser
    Comment *-- Comment
    Comment *-- Reaction
    Reaction --> ReactionType
    
    Group --> GroupType
    Group *-- GroupMember
    Group *-- Post
    GroupMember --> RegularUser
    GroupMember --> GroupRole
    
    Page *-- PageReview
    Page --> PageAnalytics
    Page *-- Post
    PageReview --> RegularUser
    
    Conversation *-- Message
    Conversation --> RegularUser
    Message --> RegularUser
    Message *-- MediaAttachment
    
    NewsFeed --> FeedRankingStrategy
    FeedRankingStrategy <|.. ChronologicalRanking
    FeedRankingStrategy <|.. EdgeRankAlgorithm
    FeedRankingStrategy <|.. EngagementBasedRanking
    
    NotificationCenter *-- Notification
    Notification --> NotificationType
    Notification --> RegularUser
    
    NotificationPublisher --> NotificationObserver
    NotificationObserver <|.. PushNotificationService
    NotificationObserver <|.. EmailNotificationService
    NotificationObserver <|.. InAppNotificationService
    
    SearchFacade --> UserSearchIndex
    SearchFacade --> PostSearchIndex
    SearchFacade --> GroupSearchIndex
    SearchFacade --> PageSearchIndex
    SearchIndex <|-- UserSearchIndex
    SearchIndex <|-- PostSearchIndex
    
    ContentReport --> ReportableContent
    ContentReport --> ReportStatus
    ContentReport --> RegularUser
    ContentReport --> Administrator
    
    ModerationAction --> Administrator
    ModerationAction --> ReportableContent
    
    Post ..|> ReportableContent
    Comment ..|> ReportableContent

Activity Diagrams

1. Friend Request and Connection Flow

This diagram shows the complete flow of sending, receiving, and processing friend requests, including validation, notification, and mutual friend discovery.

graph TD
    Start([User Initiates Friend Request]) --> CheckAuth{User Authenticated?}
    CheckAuth -->|No| AuthError[Return Authentication Error]
    CheckAuth -->|Yes| CheckSelf{Target is Self?}
    
    CheckSelf -->|Yes| SelfError[Return Cannot Friend Self Error]
    CheckSelf -->|No| CheckBlocked{Users Blocked Each Other?}
    
    CheckBlocked -->|Yes| BlockedError[Return Blocked Error]
    CheckBlocked -->|No| CheckExisting{Friendship Already Exists?}
    
    CheckExisting -->|Yes| AlreadyFriendsError[Return Already Friends Error]
    CheckExisting -->|No| CheckPending{Request Already Pending?}
    
    CheckPending -->|Yes| PendingError[Return Duplicate Request Error]
    CheckPending -->|No| CheckPrivacy{Target Accepts Requests?}
    
    CheckPrivacy -->|No| PrivacyError[Return Privacy Settings Block]
    CheckPrivacy -->|Yes| CreateRequest[Create FriendRequest Object]
    
    CreateRequest --> SetMetadata[Set Sender, Recipient, Timestamp, PENDING Status]
    SetMetadata --> PersistRequest[Persist Request to Database]
    
    PersistRequest --> NotifyRecipient[Publish Friend Request Event]
    NotifyRecipient --> CreateNotification[NotificationCenter Creates Notification]
    CreateNotification --> SendPush[Push Notification Sent]
    SendPush --> SendEmail[Email Notification Sent]
    SendEmail --> UpdateInApp[In-App Notification Updated]
    
    UpdateInApp --> WaitForResponse{Recipient Action}
    
    WaitForResponse -->|Accept| ValidateAccept{Request Still Pending?}
    ValidateAccept -->|No| ExpiredError[Return Request Expired Error]
    ValidateAccept -->|Yes| CreateFriendship[Create Friendship Object]
    
    CreateFriendship --> LinkUsers[Link user1 ↔ user2]
    LinkUsers --> SetTimestamp[Set establishedAt Timestamp]
    SetTimestamp --> UpdateStatus[Update Request Status to ACCEPTED]
    
    UpdateStatus --> AddToGraph1[Add to Sender's SocialGraph]
    AddToGraph1 --> AddToGraph2[Add to Recipient's SocialGraph]
    AddToGraph2 --> NotifyAcceptance[Notify Sender of Acceptance]
    NotifyAcceptance --> TriggerFeedUpdate[Trigger News Feed Update]
    
    TriggerFeedUpdate --> CalculateMutual[Calculate Mutual Friends]
    CalculateMutual --> UpdateSuggestions[Update Friend Suggestions for Both]
    UpdateSuggestions --> RecalculateStrength[Calculate Friendship Strength]
    RecalculateStrength --> Success1([Connection Established])
    
    WaitForResponse -->|Reject| ValidateReject{Request Still Pending?}
    ValidateReject -->|No| ExpiredError2[Return Request Expired Error]
    ValidateReject -->|Yes| UpdateStatusRejected[Update Request Status to REJECTED]
    
    UpdateStatusRejected --> NotifyRejection[Optionally Notify Sender]
    NotifyRejection --> RemoveRequest[Archive Request]
    RemoveRequest --> Success2([Request Rejected])
    
    WaitForResponse -->|Cancel| ValidateCancel{Sender Can Cancel?}
    ValidateCancel -->|No| CancelError[Return Permission Error]
    ValidateCancel -->|Yes| UpdateStatusCancelled[Update Request Status to CANCELLED]
    
    UpdateStatusCancelled --> RemoveNotification[Remove Recipient Notification]
    RemoveNotification --> Success3([Request Cancelled])
    
    WaitForResponse -->|Ignore| Timeout{Request Expired?}
    Timeout -->|Yes| AutoArchive[Auto-Archive Request]
    AutoArchive --> Success4([Request Expired])
    Timeout -->|No| KeepPending[Keep in Pending State]
    KeepPending --> WaitForResponse
    
    AuthError --> End([End])
    SelfError --> End
    BlockedError --> End
    AlreadyFriendsError --> End
    PendingError --> End
    PrivacyError --> End
    ExpiredError --> End
    ExpiredError2 --> End
    CancelError --> End
    Success1 --> End
    Success2 --> End
    Success3 --> End
    Success4 --> End
    
    style Start fill:#4caf50,stroke:#2e7d32,stroke-width:3px,color:#fff
    style End fill:#f44336,stroke:#c62828,stroke-width:3px,color:#fff
    style CheckAuth fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CheckSelf fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CheckBlocked fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CheckExisting fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CheckPending fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CheckPrivacy fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style WaitForResponse fill:#e1bee7,stroke:#8e24aa,stroke-width:2px
    style ValidateAccept fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style ValidateReject fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style ValidateCancel fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style Timeout fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CreateFriendship fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px
    style NotifyRecipient fill:#bbdefb,stroke:#1976d2,stroke-width:2px
    style CalculateMutual fill:#b2dfdb,stroke:#00695c,stroke-width:2px
    style UpdateSuggestions fill:#b2dfdb,stroke:#00695c,stroke-width:2px
    style Success1 fill:#4caf50,stroke:#2e7d32,stroke-width:3px,color:#fff
    style Success2 fill:#ff9800,stroke:#e65100,stroke-width:3px,color:#fff
    style Success3 fill:#ff9800,stroke:#e65100,stroke-width:3px,color:#fff
    style Success4 fill:#9e9e9e,stroke:#424242,stroke-width:3px,color:#fff

2. News Feed Generation and Ranking

This diagram illustrates the personalized news feed generation process using the EdgeRank algorithm, including content aggregation, filtering, ranking, and caching.

graph TD
    Start([User Opens News Feed]) --> CheckCache{Feed Cache Valid?}
    CheckCache -->|Valid & Fresh| ServeCached[Serve Cached Feed]
    ServeCached --> End1([Display Feed])
    
    CheckCache -->|Expired or Missing| LoadUserProfile[Load User Profile & Preferences]
    LoadUserProfile --> GetStrategy[Get Feed Ranking Strategy]
    
    GetStrategy --> CheckStrategyType{Strategy Type?}
    CheckStrategyType -->|Chronological| UseChronological[Use Chronological Ranking]
    CheckStrategyType -->|EdgeRank| UseEdgeRank[Use EdgeRank Algorithm]
    CheckStrategyType -->|Engagement-Based| UseEngagement[Use Engagement Prediction]
    
    UseChronological --> AggregateContent[Aggregate Content Sources]
    UseEdgeRank --> AggregateContent
    UseEngagement --> AggregateContent
    
    AggregateContent --> GetFriendPosts[Get Posts from Friends]
    GetFriendPosts --> GetFollowingPosts[Get Posts from Followed Users]
    GetFollowingPosts --> GetPagePosts[Get Posts from Followed Pages]
    GetPagePosts --> GetGroupPosts[Get Posts from Joined Groups]
    
    GetGroupPosts --> ApplyPrivacy[Apply Privacy Filters]
    ApplyPrivacy --> FilterBlocked[Filter Blocked Users]
    FilterBlocked --> FilterHidden[Filter Hidden Content]
    FilterHidden --> FilterReported[Filter Reported/Removed Content]
    
    FilterReported --> ContentPool[Candidate Content Pool]
    ContentPool --> CheckRankingStrategy{Which Strategy?}
    
    CheckRankingStrategy -->|Chronological| SortByTime[Sort by Timestamp DESC]
    SortByTime --> TakeTop100[Take Top 100 Posts]
    TakeTop100 --> CacheFeed[Cache Generated Feed]
    
    CheckRankingStrategy -->|EdgeRank| CalculateEdgeRank[Calculate EdgeRank Scores]
    
    CalculateEdgeRank --> ForEachPost{For Each Post}
    ForEachPost --> CalcAffinity[Calculate Affinity Score]
    
    CalcAffinity --> CountInteractions[Count Previous Interactions with Author]
    CountInteractions --> CheckMutualFriends[Check Mutual Friends]
    CheckMutualFriends --> CheckMessageHistory[Check Message History]
    CheckMessageHistory --> CheckProfileViews[Check Profile View Frequency]
    CheckProfileViews --> ComputeAffinity[Compute Affinity = f interactions, mutuals, messages]
    
    ComputeAffinity --> CalcWeight[Calculate Weight Score]
    CalcWeight --> IdentifyPostType{Post Type?}
    
    IdentifyPostType -->|Photo/Video| HighWeight[Weight = 1.0]
    IdentifyPostType -->|Link| MediumWeight[Weight = 0.7]
    IdentifyPostType -->|Text Only| LowWeight[Weight = 0.5]
    
    HighWeight --> CalcTimeDecay[Calculate Time Decay]
    MediumWeight --> CalcTimeDecay
    LowWeight --> CalcTimeDecay
    
    CalcTimeDecay --> GetPostAge[Get Post Age in Hours]
    GetPostAge --> ApplyDecayFunction[Apply Decay = e^-age/24]
    
    ApplyDecayFunction --> ComputeEdgeRank[EdgeRank = Affinity × Weight × TimeDecay]
    ComputeEdgeRank --> CheckMorePosts{More Posts?}
    CheckMorePosts -->|Yes| ForEachPost
    CheckMorePosts -->|No| SortByEdgeRank[Sort by EdgeRank Score DESC]
    
    SortByEdgeRank --> TakeTop100EdgeRank[Take Top 100 Posts]
    TakeTop100EdgeRank --> CacheFeed
    
    CheckRankingStrategy -->|Engagement| PredictEngagement[Predict Engagement Probability]
    PredictEngagement --> LoadMLModel[Load ML Engagement Model]
    LoadMLModel --> ExtractFeatures[Extract Features: Author, Type, Length, Media, Reactions]
    ExtractFeatures --> RunInference[Run Model Inference]
    RunInference --> SortByPrediction[Sort by Predicted Engagement DESC]
    SortByPrediction --> TakeTop100ML[Take Top 100 Posts]
    TakeTop100ML --> CacheFeed
    
    CacheFeed --> SetTTL[Set Cache TTL = 5 minutes]
    SetTTL --> PreloadMedia[Preload Media URLs]
    PreloadMedia --> MarkSeen[Mark Posts as Seen]
    MarkSeen --> LogImpression[Log Feed Impression Event]
    LogImpression --> ServeRankedFeed[Serve Ranked Feed to User]
    
    ServeRankedFeed --> UserScrolls{User Scrolls?}
    UserScrolls -->|Load More| Paginate[Fetch Next Page from Cache]
    Paginate --> UserScrolls
    UserScrolls -->|Refresh| InvalidateCache[Invalidate Cache]
    InvalidateCache --> Start
    UserScrolls -->|Close| End2([End])
    
    End1 --> FinalEnd([End])
    End2 --> FinalEnd
    
    style Start fill:#4caf50,stroke:#2e7d32,stroke-width:3px,color:#fff
    style FinalEnd fill:#f44336,stroke:#c62828,stroke-width:3px,color:#fff
    style End1 fill:#4caf50,stroke:#2e7d32,stroke-width:2px,color:#fff
    style End2 fill:#4caf50,stroke:#2e7d32,stroke-width:2px,color:#fff
    style CheckCache fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CheckStrategyType fill:#e1bee7,stroke:#8e24aa,stroke-width:2px
    style CheckRankingStrategy fill:#e1bee7,stroke:#8e24aa,stroke-width:2px
    style UserScrolls fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style UseEdgeRank fill:#bbdefb,stroke:#1976d2,stroke-width:2px
    style CalculateEdgeRank fill:#b2dfdb,stroke:#00695c,stroke-width:2px
    style ForEachPost fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CheckMorePosts fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style IdentifyPostType fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CalcAffinity fill:#ffe0b2,stroke:#ef6c00,stroke-width:2px
    style CalcWeight fill:#ffe0b2,stroke:#ef6c00,stroke-width:2px
    style CalcTimeDecay fill:#ffe0b2,stroke:#ef6c00,stroke-width:2px
    style ComputeEdgeRank fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px
    style CacheFeed fill:#ce93d8,stroke:#6a1b9a,stroke-width:2px

3. Real-Time Messaging with Delivery Confirmation

This diagram shows the end-to-end message delivery flow with real-time websocket notifications, read receipts, and offline message queuing.

graph TD
    Start([User Composes Message]) --> ValidateRecipient{Valid Recipient?}
    ValidateRecipient -->|No| RecipientError[Return Invalid Recipient Error]
    ValidateRecipient -->|Yes| CheckBlocked{Recipient Blocked Sender?}
    
    CheckBlocked -->|Yes| BlockedError[Return Blocked Error]
    CheckBlocked -->|No| GetConversation{Conversation Exists?}
    
    GetConversation -->|Yes| LoadConversation[Load Existing Conversation]
    GetConversation -->|No| CreateConversation[Create New Conversation]
    
    CreateConversation --> AddParticipants[Add Sender & Recipient as Participants]
    AddParticipants --> SetMetadata[Set Created Timestamp, Last Activity]
    SetMetadata --> PersistConversation[Persist Conversation to DB]
    PersistConversation --> LoadConversation
    
    LoadConversation --> CreateMessage[Create Message Object]
    CreateMessage --> SetMessageData[Set Sender, Content, Timestamp, UUID]
    SetMessageData --> CheckAttachments{Has Attachments?}
    
    CheckAttachments -->|Yes| ValidateAttachments{Attachments Valid?}
    ValidateAttachments -->|No| AttachmentError[Return Invalid Attachment Error]
    ValidateAttachments -->|Yes| UploadToStorage[Upload to Media Storage]
    UploadToStorage --> GenerateURLs[Generate CDN URLs]
    GenerateURLs --> AttachToMessage[Attach Media URLs to Message]
    
    CheckAttachments -->|No| AttachToMessage
    AttachToMessage --> PersistMessage[Persist Message to DB]
    
    PersistMessage --> AddToConversation[Add Message to Conversation.messages]
    AddToConversation --> UpdateLastActivity[Update Conversation.lastActivity]
    UpdateLastActivity --> IndexMessage[Index Message for Search]
    
    IndexMessage --> CheckRecipientStatus{Recipient Online?}
    
    CheckRecipientStatus -->|Yes| GetWebSocket[Get Recipient WebSocket Connection]
    GetWebSocket --> SendRealTime[Send Message via WebSocket]
    SendRealTime --> DeliveryAck{Delivery Acknowledged?}
    
    DeliveryAck -->|Yes| MarkDelivered[Mark Message as Delivered]
    MarkDelivered --> NotifyDelivery[Send Delivery Receipt to Sender]
    NotifyDelivery --> DisplayMessage[Display Message to Recipient]
    
    DisplayMessage --> WaitForRead{Message Viewed?}
    WaitForRead -->|Yes| MarkAsRead[Mark Message as Read]
    MarkAsRead --> RecordReadReceipt[Record ReadReceipt with Timestamp]
    RecordReadReceipt --> SendReadReceipt[Send Read Receipt to Sender]
    SendReadReceipt --> UpdateSenderUI[Update Sender UI with Double Check]
    UpdateSenderUI --> Success1([Message Delivered & Read])
    
    WaitForRead -->|No| WaitTimeout{Timeout Reached?}
    WaitTimeout -->|No| WaitForRead
    WaitTimeout -->|Yes| Success2([Message Delivered but Unread])
    
    DeliveryAck -->|No| RetryDelivery{Retry Count < 3?}
    RetryDelivery -->|Yes| WaitRetry[Wait 2 Seconds]
    WaitRetry --> SendRealTime
    RetryDelivery -->|No| QueueForOffline[Queue for Offline Delivery]
    
    CheckRecipientStatus -->|No| QueueForOffline
    QueueForOffline --> StoreInQueue[Store in Offline Message Queue]
    StoreInQueue --> CreatePushNotif[Create Push Notification]
    
    CreatePushNotif --> GetDeviceTokens[Get Recipient Device Tokens]
    GetDeviceTokens --> SendPush[Send Push Notification]
    SendPush --> CreateEmailNotif[Create Email Notification]
    CreateEmailNotif --> CheckEmailPrefs{Email Notifications Enabled?}
    
    CheckEmailPrefs -->|Yes| SendEmail[Send Email Notification]
    CheckEmailPrefs -->|No| SkipEmail[Skip Email]
    
    SendEmail --> WaitForOnline{Recipient Comes Online?}
    SkipEmail --> WaitForOnline
    
    WaitForOnline -->|Yes| DeliverQueued[Deliver Queued Messages]
    DeliverQueued --> GetWebSocket
    WaitForOnline -->|No| KeepInQueue{Queue Age < 30 Days?}
    KeepInQueue -->|Yes| WaitForOnline
    KeepInQueue -->|No| ArchiveMessage[Archive Old Message]
    ArchiveMessage --> Success3([Message Archived])
    
    RecipientError --> End([End])
    BlockedError --> End
    AttachmentError --> End
    Success1 --> End
    Success2 --> End
    Success3 --> End
    
    style Start fill:#4caf50,stroke:#2e7d32,stroke-width:3px,color:#fff
    style End fill:#f44336,stroke:#c62828,stroke-width:3px,color:#fff
    style ValidateRecipient fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CheckBlocked fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style GetConversation fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CheckAttachments fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style ValidateAttachments fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CheckRecipientStatus fill:#e1bee7,stroke:#8e24aa,stroke-width:2px
    style DeliveryAck fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style WaitForRead fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style WaitTimeout fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style RetryDelivery fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CheckEmailPrefs fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style WaitForOnline fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style KeepInQueue fill:#fff9c4,stroke:#f9a825,stroke-width:2px
    style CreateMessage fill:#c8e6c9,stroke:#2e7d32,stroke-width:2px
    style SendRealTime fill:#bbdefb,stroke:#1976d2,stroke-width:2px
    style SendPush fill:#ffcc80,stroke:#ef6c00,stroke-width:2px
    style MarkAsRead fill:#b2dfdb,stroke:#00695c,stroke-width:2px
    style Success1 fill:#4caf50,stroke:#2e7d32,stroke-width:3px,color:#fff
    style Success2 fill:#ff9800,stroke:#e65100,stroke-width:3px,color:#fff
    style Success3 fill:#9e9e9e,stroke:#424242,stroke-width:3px,color:#fff

Implementation

Java Implementation

package com.socialnetwork.core;

import java.time.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;

/**
 * Core domain value objects and enumerations
 */

enum AccountStatus {
    ACTIVE, SUSPENDED, DEACTIVATED, DELETED
}

enum VisibilityLevel {
    PUBLIC, FRIENDS, FRIENDS_OF_FRIENDS, CUSTOM, ONLY_ME
}

enum Gender {
    MALE, FEMALE, NON_BINARY, PREFER_NOT_TO_SAY
}

enum RelationshipStatus {
    SINGLE, IN_A_RELATIONSHIP, ENGAGED, MARRIED, COMPLICATED, DIVORCED, WIDOWED
}

enum RequestStatus {
    PENDING, ACCEPTED, REJECTED, CANCELLED
}

enum ReactionType {
    LIKE, LOVE, HAHA, WOW, SAD, ANGRY
}

enum GroupType {
    PUBLIC, CLOSED, SECRET
}

enum GroupRole {
    MEMBER, MODERATOR, ADMIN
}

enum PageCategory {
    BUSINESS, CELEBRITY, COMMUNITY, ENTERTAINMENT, ORGANIZATION, BRAND, LOCAL_BUSINESS
}

enum MediaType {
    PHOTO, VIDEO, AUDIO, DOCUMENT
}

enum NotificationType {
    FRIEND_REQUEST, FRIEND_ACCEPTED, POST_LIKED, POST_COMMENTED, POST_SHARED,
    MENTIONED_IN_POST, MENTIONED_IN_COMMENT, MESSAGE_RECEIVED,
    GROUP_INVITED, BIRTHDAY_REMINDER
}

enum ReportReason {
    SPAM, HARASSMENT, HATE_SPEECH, VIOLENCE, NUDITY, FALSE_INFORMATION, OTHER
}

enum ReportStatus {
    PENDING, UNDER_REVIEW, RESOLVED, DISMISSED
}

enum ActionType {
    WARN, REMOVE_CONTENT, SUSPEND_ACCOUNT, BAN_ACCOUNT, DISMISS
}

/**
 * State Pattern: Account state management
 */
interface AccountState {
    boolean handleLogin();
    boolean allowPosting();
    AccountState transitionTo(AccountStatus status);
}

class ActiveState implements AccountState {
    @Override
    public boolean handleLogin() {
        return true;
    }
    
    @Override
    public boolean allowPosting() {
        return true;
    }
    
    @Override
    public AccountState transitionTo(AccountStatus status) {
        switch (status) {
            case SUSPENDED: return new SuspendedState();
            case DEACTIVATED: return new DeactivatedState();
            case DELETED: return new DeletedState();
            default: return this;
        }
    }
}

class SuspendedState implements AccountState {
    @Override
    public boolean handleLogin() {
        throw new IllegalStateException("Account is suspended");
    }
    
    @Override
    public boolean allowPosting() {
        return false;
    }
    
    @Override
    public AccountState transitionTo(AccountStatus status) {
        if (status == AccountStatus.ACTIVE) {
            return new ActiveState();
        }
        return this;
    }
}

class DeactivatedState implements AccountState {
    @Override
    public boolean handleLogin() {
        return true; // Can reactivate by logging in
    }
    
    @Override
    public boolean allowPosting() {
        return false;
    }
    
    @Override
    public AccountState transitionTo(AccountStatus status) {
        if (status == AccountStatus.ACTIVE) {
            return new ActiveState();
        }
        return this;
    }
}

class DeletedState implements AccountState {
    @Override
    public boolean handleLogin() {
        throw new IllegalStateException("Account has been deleted");
    }
    
    @Override
    public boolean allowPosting() {
        return false;
    }
    
    @Override
    public AccountState transitionTo(AccountStatus status) {
        return this; // Cannot transition from deleted
    }
}

/**
 * Core identity and profile classes
 */
class SecuritySettings {
    private boolean twoFactorEnabled;
    private Set<String> trustedDevices;
    private LocalDateTime lastPasswordChange;
    
    public SecuritySettings() {
        this.twoFactorEnabled = false;
        this.trustedDevices = new HashSet<>();
        this.lastPasswordChange = LocalDateTime.now();
    }
    
    public void enableTwoFactor() {
        this.twoFactorEnabled = true;
    }
    
    public void addTrustedDevice(String deviceId) {
        trustedDevices.add(deviceId);
    }
}

abstract class UserAccount {
    protected UUID accountId;
    protected String email;
    protected String passwordHash;
    protected LocalDateTime createdAt;
    protected AccountState state;
    protected SecuritySettings security;
    
    public UserAccount(String email, String password) {
        this.accountId = UUID.randomUUID();
        this.email = email;
        this.passwordHash = hashPassword(password);
        this.createdAt = LocalDateTime.now();
        this.state = new ActiveState();
        this.security = new SecuritySettings();
    }
    
    public boolean authenticate(String password) {
        return state.handleLogin() && 
               hashPassword(password).equals(passwordHash);
    }
    
    public void deactivate() {
        this.state = state.transitionTo(AccountStatus.DEACTIVATED);
    }
    
    public void reactivate() {
        this.state = state.transitionTo(AccountStatus.ACTIVE);
    }
    
    public void changePassword(String newPassword) {
        this.passwordHash = hashPassword(newPassword);
        this.security.lastPasswordChange = LocalDateTime.now();
    }
    
    private String hashPassword(String password) {
        // In production: use BCrypt or Argon2
        return Integer.toString(password.hashCode());
    }
    
    public UUID getAccountId() {
        return accountId;
    }
    
    public String getEmail() {
        return email;
    }
}

class PersonalInfo {
    private String fullName;
    private LocalDate birthDate;
    private Gender gender;
    private String hometown;
    private String currentCity;
    private RelationshipStatus status;
    
    public PersonalInfo(String fullName, LocalDate birthDate) {
        this.fullName = fullName;
        this.birthDate = birthDate;
    }
    
    public String getFullName() {
        return fullName;
    }
    
    public int getAge() {
        return Period.between(birthDate, LocalDate.now()).getYears();
    }
}

class WorkExperience {
    private String company;
    private String position;
    private String location;
    private LocalDate startDate;
    private LocalDate endDate;
    private String description;
    
    public WorkExperience(String company, String position, LocalDate startDate) {
        this.company = company;
        this.position = position;
        this.startDate = startDate;
    }
    
    public void end(LocalDate endDate) {
        this.endDate = endDate;
    }
}

class Education {
    private String institution;
    private String degree;
    private String fieldOfStudy;
    private int graduationYear;
    
    public Education(String institution, String degree, String field, int year) {
        this.institution = institution;
        this.degree = degree;
        this.fieldOfStudy = field;
        this.graduationYear = year;
    }
}

class PrivacyList {
    private UUID listId;
    private String name;
    private Set<RegularUser> members;
    
    public PrivacyList(String name) {
        this.listId = UUID.randomUUID();
        this.name = name;
        this.members = new HashSet<>();
    }
    
    public void addMember(RegularUser user) {
        members.add(user);
    }
    
    public void removeMember(RegularUser user) {
        members.remove(user);
    }
    
    public boolean contains(RegularUser user) {
        return members.contains(user);
    }
}

class PrivacySettings {
    private VisibilityLevel profileVisibility;
    private VisibilityLevel postsVisibility;
    private VisibilityLevel friendListVisibility;
    private Map<String, PrivacyList> customLists;
    
    public PrivacySettings() {
        this.profileVisibility = VisibilityLevel.FRIENDS;
        this.postsVisibility = VisibilityLevel.FRIENDS;
        this.friendListVisibility = VisibilityLevel.FRIENDS;
        this.customLists = new HashMap<>();
        
        // Default lists
        customLists.put("close_friends", new PrivacyList("Close Friends"));
        customLists.put("acquaintances", new PrivacyList("Acquaintances"));
        customLists.put("restricted", new PrivacyList("Restricted"));
    }
    
    public void updateSetting(String key, VisibilityLevel value) {
        switch (key) {
            case "profile": profileVisibility = value; break;
            case "posts": postsVisibility = value; break;
            case "friends": friendListVisibility = value; break;
        }
    }
    
    public boolean canView(RegularUser viewer, String resourceType) {
        // Simplified visibility check
        VisibilityLevel level = getVisibilityFor(resourceType);
        switch (level) {
            case PUBLIC: return true;
            case ONLY_ME: return false;
            case FRIENDS: // Would check if viewer is friend
            case CUSTOM: // Would check custom lists
            default: return false;
        }
    }
    
    private VisibilityLevel getVisibilityFor(String resource) {
        switch (resource) {
            case "profile": return profileVisibility;
            case "posts": return postsVisibility;
            case "friends": return friendListVisibility;
            default: return VisibilityLevel.FRIENDS;
        }
    }
}

class MediaItem {
    private UUID itemId;
    private String url;
    private MediaType type;
    private LocalDateTime uploadedAt;
    
    public MediaItem(String url, MediaType type) {
        this.itemId = UUID.randomUUID();
        this.url = url;
        this.type = type;
        this.uploadedAt = LocalDateTime.now();
    }
}

class UserProfile {
    private PersonalInfo info;
    private List<WorkExperience> workHistory;
    private List<Education> educationHistory;
    private List<MediaItem> photos;
    private PrivacySettings privacy;
    private LocalDateTime lastUpdated;
    
    public UserProfile(PersonalInfo info) {
        this.info = info;
        this.workHistory = new ArrayList<>();
        this.educationHistory = new ArrayList<>();
        this.photos = new ArrayList<>();
        this.privacy = new PrivacySettings();
        this.lastUpdated = LocalDateTime.now();
    }
    
    public void updateBio(String text) {
        // Bio update logic
        this.lastUpdated = LocalDateTime.now();
    }
    
    public void addWorkExperience(WorkExperience work) {
        workHistory.add(work);
        this.lastUpdated = LocalDateTime.now();
    }
    
    public void addEducation(Education edu) {
        educationHistory.add(edu);
        this.lastUpdated = LocalDateTime.now();
    }
    
    public void setProfilePicture(MediaItem photo) {
        photos.add(0, photo);
        this.lastUpdated = LocalDateTime.now();
    }
    
    public PersonalInfo getInfo() {
        return info;
    }
}

/**
 * Social graph relationships
 */
enum FriendshipStrength {
    WEAK, MODERATE, STRONG
}

class Friendship {
    private RegularUser user1;
    private RegularUser user2;
    private LocalDateTime establishedAt;
    private FriendshipStrength strength;
    
    public Friendship(RegularUser u1, RegularUser u2) {
        this.user1 = u1;
        this.user2 = u2;
        this.establishedAt = LocalDateTime.now();
        this.strength = calculateStrength();
    }
    
    public FriendshipStrength calculateStrength() {
        // Simplified: would analyze interaction frequency, messages, etc.
        return FriendshipStrength.MODERATE;
    }
    
    public RegularUser getOtherUser(RegularUser user) {
        return user.equals(user1) ? user2 : user1;
    }
}

class Following {
    private RegularUser follower;
    private RegularUser followee;
    private LocalDateTime since;
    private boolean notificationsEnabled;
    
    public Following(RegularUser follower, RegularUser followee) {
        this.follower = follower;
        this.followee = followee;
        this.since = LocalDateTime.now();
        this.notificationsEnabled = true;
    }
}

class FriendRequest {
    private UUID requestId;
    private RegularUser sender;
    private RegularUser recipient;
    private RequestStatus status;
    private LocalDateTime sentAt;
    
    public FriendRequest(RegularUser sender, RegularUser recipient) {
        this.requestId = UUID.randomUUID();
        this.sender = sender;
        this.recipient = recipient;
        this.status = RequestStatus.PENDING;
        this.sentAt = LocalDateTime.now();
    }
    
    public void accept() {
        if (status != RequestStatus.PENDING) {
            throw new IllegalStateException("Request not pending");
        }
        this.status = RequestStatus.ACCEPTED;
    }
    
    public void reject() {
        if (status != RequestStatus.PENDING) {
            throw new IllegalStateException("Request not pending");
        }
        this.status = RequestStatus.REJECTED;
    }
    
    public void cancel() {
        if (status != RequestStatus.PENDING) {
            throw new IllegalStateException("Request not pending");
        }
        this.status = RequestStatus.CANCELLED;
    }
    
    public RequestStatus getStatus() {
        return status;
    }
    
    public RegularUser getSender() {
        return sender;
    }
    
    public RegularUser getRecipient() {
        return recipient;
    }
}

class SocialGraph {
    private List<Friendship> friends;
    private List<Following> followings;
    private List<FriendRequest> pendingRequests;
    private Set<RegularUser> blockedUsers;
    
    public SocialGraph() {
        this.friends = new ArrayList<>();
        this.followings = new ArrayList<>();
        this.pendingRequests = new ArrayList<>();
        this.blockedUsers = new HashSet<>();
    }
    
    public void sendFriendRequest(RegularUser user, RegularUser target) {
        if (blockedUsers.contains(target)) {
            throw new IllegalArgumentException("Cannot send request to blocked user");
        }
        FriendRequest request = new FriendRequest(user, target);
        pendingRequests.add(request);
    }
    
    public void acceptRequest(UUID requestId) {
        FriendRequest request = findRequest(requestId);
        request.accept();
        
        // Create friendship
        Friendship friendship = new Friendship(request.getSender(), request.getRecipient());
        friends.add(friendship);
        
        // Remove from pending
        pendingRequests.remove(request);
    }
    
    public void rejectRequest(UUID requestId) {
        FriendRequest request = findRequest(requestId);
        request.reject();
        pendingRequests.remove(request);
    }
    
    public void unfriend(RegularUser user) {
        friends.removeIf(f -> f.getOtherUser(null) != null && 
                              f.getOtherUser(null).equals(user));
    }
    
    public void follow(RegularUser follower, RegularUser followee) {
        followings.add(new Following(follower, followee));
    }
    
    public void unfollow(RegularUser followee) {
        followings.removeIf(f -> f.followee.equals(followee));
    }
    
    public Set<RegularUser> getMutualFriends(RegularUser user) {
        // Simplified implementation
        return new HashSet<>();
    }
    
    public List<RegularUser> getSuggestions() {
        // Would implement friend-of-friend algorithm
        return new ArrayList<>();
    }
    
    private FriendRequest findRequest(UUID requestId) {
        return pendingRequests.stream()
            .filter(r -> r.requestId.equals(requestId))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("Request not found"));
    }
    
    public List<Friendship> getFriends() {
        return friends;
    }
}

/**
 * Factory Pattern: Post creation
 */
interface ContentFactory {
    Post createPost(String type, Map<String, Object> data);
}

class PostFactory implements ContentFactory {
    @Override
    public Post createPost(String type, Map<String, Object> data) {
        RegularUser author = (RegularUser) data.get("author");
        String content = (String) data.get("content");
        
        switch (type.toLowerCase()) {
            case "text":
                return createTextPost(author, content);
            case "photo":
                @SuppressWarnings("unchecked")
                List<String> photos = (List<String>) data.get("photos");
                return createPhotoPost(author, content, photos);
            case "video":
                String video = (String) data.get("video");
                return createVideoPost(author, content, video);
            case "link":
                String url = (String) data.get("url");
                return createLinkPost(author, content, url);
            default:
                throw new IllegalArgumentException("Unknown post type: " + type);
        }
    }
    
    private TextPost createTextPost(RegularUser author, String text) {
        return new TextPost(author, text);
    }
    
    private PhotoPost createPhotoPost(RegularUser author, String caption, List<String> photoUrls) {
        return new PhotoPost(author, caption, photoUrls);
    }
    
    private VideoPost createVideoPost(RegularUser author, String caption, String videoUrl) {
        return new VideoPost(author, caption, videoUrl);
    }
    
    private LinkPost createLinkPost(RegularUser author, String content, String url) {
        return new LinkPost(author, content, url);
    }
}

/**
 * Content classes
 */
class Reaction {
    private RegularUser user;
    private ReactionType type;
    private LocalDateTime timestamp;
    
    public Reaction(RegularUser user, ReactionType type) {
        this.user = user;
        this.type = type;
        this.timestamp = LocalDateTime.now();
    }
}

class Comment {
    private UUID commentId;
    private RegularUser author;
    private String text;
    private LocalDateTime createdAt;
    private List<Comment> replies;
    private List<Reaction> reactions;
    
    public Comment(RegularUser author, String text) {
        this.commentId = UUID.randomUUID();
        this.author = author;
        this.text = text;
        this.createdAt = LocalDateTime.now();
        this.replies = new ArrayList<>();
        this.reactions = new ArrayList<>();
    }
    
    public void addReply(Comment reply) {
        replies.add(reply);
    }
    
    public void react(RegularUser user, ReactionType type) {
        // Remove existing reaction from this user
        reactions.removeIf(r -> r.user.equals(user));
        // Add new reaction
        reactions.add(new Reaction(user, type));
    }
    
    public void delete() {
        // Soft delete implementation
    }
}

abstract class Post {
    protected UUID postId;
    protected RegularUser author;
    protected String content;
    protected LocalDateTime createdAt;
    protected LocalDateTime editedAt;
    protected VisibilityLevel visibility;
    protected List<Comment> comments;
    protected List<Reaction> reactions;
    protected int shareCount;
    protected List<RegularUser> taggedUsers;
    
    public Post(RegularUser author, String content) {
        this.postId = UUID.randomUUID();
        this.author = author;
        this.content = content;
        this.createdAt = LocalDateTime.now();
        this.visibility = VisibilityLevel.FRIENDS;
        this.comments = new ArrayList<>();
        this.reactions = new ArrayList<>();
        this.shareCount = 0;
        this.taggedUsers = new ArrayList<>();
    }
    
    public void edit(String newContent) {
        this.content = newContent;
        this.editedAt = LocalDateTime.now();
    }
    
    public void delete() {
        // Soft delete implementation
    }
    
    public void addComment(Comment comment) {
        comments.add(comment);
    }
    
    public void react(RegularUser user, ReactionType type) {
        reactions.removeIf(r -> r.user.equals(user));
        reactions.add(new Reaction(user, type));
    }
    
    public void share(RegularUser user) {
        shareCount++;
    }
    
    public UUID getPostId() {
        return postId;
    }
    
    public RegularUser getAuthor() {
        return author;
    }
    
    public LocalDateTime getCreatedAt() {
        return createdAt;
    }
    
    public int getTotalEngagement() {
        return reactions.size() + comments.size() + shareCount;
    }
}

class TextPost extends Post {
    private String formattedText;
    
    public TextPost(RegularUser author, String text) {
        super(author, text);
        this.formattedText = text;
    }
}

class PhotoPost extends Post {
    private List<String> photoUrls;
    
    public PhotoPost(RegularUser author, String caption, List<String> photos) {
        super(author, caption);
        this.photoUrls = new ArrayList<>(photos);
    }
}

class VideoPost extends Post {
    private String videoUrl;
    private String thumbnailUrl;
    
    public VideoPost(RegularUser author, String caption, String video) {
        super(author, caption);
        this.videoUrl = video;
        this.thumbnailUrl = video + "_thumb.jpg";
    }
}

class LinkPost extends Post {
    private String url;
    private String previewTitle;
    private String previewImage;
    
    public LinkPost(RegularUser author, String content, String url) {
        super(author, content);
        this.url = url;
        // Would fetch preview data
    }
}

/**
 * Strategy Pattern: Feed ranking algorithms
 */
interface FeedRankingStrategy {
    List<Post> rankPosts(List<Post> posts, RegularUser user);
}

class ChronologicalRanking implements FeedRankingStrategy {
    @Override
    public List<Post> rankPosts(List<Post> posts, RegularUser user) {
        return posts.stream()
            .sorted((p1, p2) -> p2.getCreatedAt().compareTo(p1.getCreatedAt()))
            .collect(Collectors.toList());
    }
}

class EdgeRankAlgorithm implements FeedRankingStrategy {
    @Override
    public List<Post> rankPosts(List<Post> posts, RegularUser user) {
        Map<Post, Double> scores = new HashMap<>();
        
        for (Post post : posts) {
            double affinity = calculateAffinity(user, post.getAuthor());
            double weight = calculateWeight(post);
            double timeDecay = calculateTimeDecay(post);
            
            double edgeRank = affinity * weight * timeDecay;
            scores.put(post, edgeRank);
        }
        
        return scores.entrySet().stream()
            .sorted((e1, e2) -> Double.compare(e2.getValue(), e1.getValue()))
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());
    }
    
    private double calculateAffinity(RegularUser user, RegularUser author) {
        // Simplified: would analyze interaction history
        return 0.7;
    }
    
    private double calculateWeight(Post post) {
        if (post instanceof PhotoPost || post instanceof VideoPost) {
            return 1.0;
        } else if (post instanceof LinkPost) {
            return 0.7;
        }
        return 0.5;
    }
    
    private double calculateTimeDecay(Post post) {
        long hoursOld = Duration.between(post.getCreatedAt(), LocalDateTime.now()).toHours();
        return Math.exp(-hoursOld / 24.0);
    }
}

class EngagementBasedRanking implements FeedRankingStrategy {
    @Override
    public List<Post> rankPosts(List<Post> posts, RegularUser user) {
        return posts.stream()
            .sorted((p1, p2) -> Integer.compare(
                predictEngagement(p2, user),
                predictEngagement(p1, user)))
            .collect(Collectors.toList());
    }
    
    private int predictEngagement(Post post, RegularUser user) {
        // Simplified ML prediction
        return post.getTotalEngagement();
    }
}

/**
 * News Feed
 */
class NewsFeed {
    private RegularUser user;
    private FeedRankingStrategy rankingStrategy;
    private List<Post> cachedFeed;
    private LocalDateTime lastUpdated;
    
    public NewsFeed(RegularUser user) {
        this.user = user;
        this.rankingStrategy = new EdgeRankAlgorithm();
        this.cachedFeed = new ArrayList<>();
    }
    
    public void refreshFeed() {
        // Aggregate posts from friends, followings, pages, groups
        List<Post> allPosts = new ArrayList<>();
        // ... collect posts ...
        
        this.cachedFeed = rankingStrategy.rankPosts(allPosts, user);
        this.lastUpdated = LocalDateTime.now();
    }
    
    public void setRankingStrategy(FeedRankingStrategy strategy) {
        this.rankingStrategy = strategy;
        refreshFeed();
    }
    
    public List<Post> getNextPage(int page, int pageSize) {
        int start = page * pageSize;
        int end = Math.min(start + pageSize, cachedFeed.size());
        return cachedFeed.subList(start, end);
    }
}

/**
 * Observer Pattern: Notifications
 */
class Notification {
    private UUID notificationId;
    private NotificationType type;
    private RegularUser recipient;
    private RegularUser actor;
    private String content;
    private LocalDateTime createdAt;
    private boolean read;
    
    public Notification(NotificationType type, RegularUser recipient, 
                       RegularUser actor, String content) {
        this.notificationId = UUID.randomUUID();
        this.type = type;
        this.recipient = recipient;
        this.actor = actor;
        this.content = content;
        this.createdAt = LocalDateTime.now();
        this.read = false;
    }
    
    public void markAsRead() {
        this.read = true;
    }
}

interface NotificationObserver {
    void onEvent(Notification notification);
}

class PushNotificationService implements NotificationObserver {
    @Override
    public void onEvent(Notification notification) {
        // Send push notification
        System.out.println("Push: " + notification.content);
    }
}

class EmailNotificationService implements NotificationObserver {
    @Override
    public void onEvent(Notification notification) {
        // Send email
        System.out.println("Email: " + notification.content);
    }
}

class InAppNotificationService implements NotificationObserver {
    @Override
    public void onEvent(Notification notification) {
        // Update in-app notification center
        System.out.println("In-App: " + notification.content);
    }
}

class NotificationPublisher {
    private List<NotificationObserver> observers;
    
    public NotificationPublisher() {
        this.observers = new ArrayList<>();
    }
    
    public void subscribe(NotificationObserver observer) {
        observers.add(observer);
    }
    
    public void unsubscribe(NotificationObserver observer) {
        observers.remove(observer);
    }
    
    public void notifyObservers(Notification notification) {
        for (NotificationObserver observer : observers) {
            observer.onEvent(notification);
        }
    }
}

class NotificationCenter {
    private RegularUser user;
    private List<Notification> notifications;
    private NotificationPublisher publisher;
    
    public NotificationCenter(RegularUser user) {
        this.user = user;
        this.notifications = new ArrayList<>();
        this.publisher = new NotificationPublisher();
        
        // Subscribe default services
        publisher.subscribe(new PushNotificationService());
        publisher.subscribe(new EmailNotificationService());
        publisher.subscribe(new InAppNotificationService());
    }
    
    public void sendNotification(Notification notification) {
        notifications.add(notification);
        publisher.notifyObservers(notification);
    }
    
    public void markAsRead(UUID notificationId) {
        notifications.stream()
            .filter(n -> n.notificationId.equals(notificationId))
            .findFirst()
            .ifPresent(Notification::markAsRead);
    }
}

/**
 * Main user classes
 */
class RegularUser extends UserAccount {
    private UserProfile profile;
    private SocialGraph connections;
    private List<Post> timeline;
    private List<Conversation> messages;
    private NotificationCenter notifications;
    private NewsFeed newsFeed;
    
    public RegularUser(String email, String password, PersonalInfo info) {
        super(email, password);
        this.profile = new UserProfile(info);
        this.connections = new SocialGraph();
        this.timeline = new ArrayList<>();
        this.messages = new ArrayList<>();
        this.notifications = new NotificationCenter(this);
        this.newsFeed = new NewsFeed(this);
    }
    
    public Post createPost(String type, Map<String, Object> data) {
        data.put("author", this);
        PostFactory factory = new PostFactory();
        Post post = factory.createPost(type, data);
        timeline.add(post);
        return post;
    }
    
    public void sendFriendRequest(RegularUser target) {
        connections.sendFriendRequest(this, target);
        
        // Notify target
        Notification notif = new Notification(
            NotificationType.FRIEND_REQUEST,
            target,
            this,
            profile.getInfo().getFullName() + " sent you a friend request"
        );
        target.notifications.sendNotification(notif);
    }
    
    public void sendMessage(RegularUser recipient, String text) {
        // Find or create conversation
        Conversation conv = messages.stream()
            .filter(c -> c.hasParticipant(recipient))
            .findFirst()
            .orElseGet(() -> new Conversation(Arrays.asList(this, recipient)));
        
        Message msg = new Message(this, text);
        conv.sendMessage(msg);
    }
    
    public UserProfile getProfile() {
        return profile;
    }
    
    public SocialGraph getConnections() {
        return connections;
    }
    
    public NewsFeed getNewsFeed() {
        return newsFeed;
    }
}

class Administrator extends UserAccount {
    private Set<String> permissions;
    
    public Administrator(String email, String password) {
        super(email, password);
        this.permissions = new HashSet<>(Arrays.asList(
            "REVIEW_REPORTS", "SUSPEND_ACCOUNTS", "DELETE_CONTENT", "BAN_USERS"
        ));
    }
    
    public void reviewReport(UUID reportId) {
        // Review content report
    }
    
    public void suspendAccount(UUID userId) {
        // Suspend user account
    }
    
    public void deleteContent(UUID contentId) {
        // Delete violating content
    }
}

/**
 * Groups and Pages
 */
class GroupMember {
    private RegularUser user;
    private GroupRole role;
    private LocalDateTime joinedAt;
    
    public GroupMember(RegularUser user, GroupRole role) {
        this.user = user;
        this.role = role;
        this.joinedAt = LocalDateTime.now();
    }
    
    public void promoteToAdmin() {
        this.role = GroupRole.ADMIN;
    }
    
    public void demote() {
        this.role = GroupRole.MEMBER;
    }
}

class Group {
    private UUID groupId;
    private String name;
    private String description;
    private GroupType type;
    private RegularUser creator;
    private List<GroupMember> members;
    private List<Post> posts;
    private LocalDateTime createdAt;
    
    public Group(String name, String description, GroupType type, RegularUser creator) {
        this.groupId = UUID.randomUUID();
        this.name = name;
        this.description = description;
        this.type = type;
        this.creator = creator;
        this.members = new ArrayList<>();
        this.posts = new ArrayList<>();
        this.createdAt = LocalDateTime.now();
        
        // Add creator as admin
        members.add(new GroupMember(creator, GroupRole.ADMIN));
    }
    
    public void addMember(RegularUser user, GroupRole role) {
        members.add(new GroupMember(user, role));
    }
    
    public void removeMember(RegularUser user) {
        members.removeIf(m -> m.user.equals(user));
    }
    
    public void createPost(Post post) {
        posts.add(post);
    }
}

class PageReview {
    private UUID reviewId;
    private RegularUser author;
    private int rating;
    private String text;
    private LocalDateTime createdAt;
    private String adminResponse;
    
    public PageReview(RegularUser author, int rating, String text) {
        this.reviewId = UUID.randomUUID();
        this.author = author;
        this.rating = Math.max(1, Math.min(5, rating));
        this.text = text;
        this.createdAt = LocalDateTime.now();
    }
    
    public void respond(String response) {
        this.adminResponse = response;
    }
}

class Page {
    private UUID pageId;
    private String name;
    private String description;
    private PageCategory category;
    private List<RegularUser> admins;
    private Set<RegularUser> followers;
    private List<Post> posts;
    private List<PageReview> reviews;
    
    public Page(String name, String description, PageCategory category) {
        this.pageId = UUID.randomUUID();
        this.name = name;
        this.description = description;
        this.category = category;
        this.admins = new ArrayList<>();
        this.followers = new HashSet<>();
        this.posts = new ArrayList<>();
        this.reviews = new ArrayList<>();
    }
    
    public void publishPost(Post post) {
        posts.add(post);
    }
    
    public void addFollower(RegularUser user) {
        followers.add(user);
    }
    
    public void respondToReview(UUID reviewId, String response) {
        reviews.stream()
            .filter(r -> r.reviewId.equals(reviewId))
            .findFirst()
            .ifPresent(r -> r.respond(response));
    }
}

/**
 * Messaging
 */
class MediaAttachment {
    private UUID attachmentId;
    private MediaType type;
    private String url;
    private int size;
    
    public MediaAttachment(MediaType type, String url, int size) {
        this.attachmentId = UUID.randomUUID();
        this.type = type;
        this.url = url;
        this.size = size;
    }
}

class Message {
    private UUID messageId;
    private RegularUser sender;
    private String content;
    private LocalDateTime sentAt;
    private Map<RegularUser, LocalDateTime> readReceipts;
    private List<MediaAttachment> attachments;
    
    public Message(RegularUser sender, String content) {
        this.messageId = UUID.randomUUID();
        this.sender = sender;
        this.content = content;
        this.sentAt = LocalDateTime.now();
        this.readReceipts = new HashMap<>();
        this.attachments = new ArrayList<>();
    }
    
    public void markAsRead(RegularUser user) {
        readReceipts.put(user, LocalDateTime.now());
    }
    
    public void delete() {
        // Soft delete
    }
}

class Conversation {
    private UUID conversationId;
    private List<RegularUser> participants;
    private List<Message> messages;
    private LocalDateTime createdAt;
    private LocalDateTime lastActivity;
    
    public Conversation(List<RegularUser> participants) {
        this.conversationId = UUID.randomUUID();
        this.participants = new ArrayList<>(participants);
        this.messages = new ArrayList<>();
        this.createdAt = LocalDateTime.now();
        this.lastActivity = LocalDateTime.now();
    }
    
    public void sendMessage(Message message) {
        messages.add(message);
        this.lastActivity = LocalDateTime.now();
    }
    
    public void addParticipant(RegularUser user) {
        participants.add(user);
    }
    
    public void removeParticipant(RegularUser user) {
        participants.remove(user);
    }
    
    public void markAsRead(RegularUser user) {
        for (Message msg : messages) {
            if (!msg.sender.equals(user)) {
                msg.markAsRead(user);
            }
        }
    }
    
    public boolean hasParticipant(RegularUser user) {
        return participants.contains(user);
    }
}

/**
 * Facade Pattern: Search
 */
abstract class SearchIndex {
    protected Map<String, Set<UUID>> index;
    
    public SearchIndex() {
        this.index = new HashMap<>();
    }
    
    public abstract void indexDocument(Object doc);
    public abstract List<?> search(String query);
    
    public void removeDocument(UUID docId) {
        index.values().forEach(set -> set.remove(docId));
    }
}

class UserSearchIndex extends SearchIndex {
    private Map<UUID, RegularUser> users;
    
    public UserSearchIndex() {
        super();
        this.users = new HashMap<>();
    }
    
    @Override
    public void indexDocument(Object doc) {
        RegularUser user = (RegularUser) doc;
        users.put(user.getAccountId(), user);
        
        String name = user.getProfile().getInfo().getFullName().toLowerCase();
        for (String word : name.split("\\s+")) {
            index.computeIfAbsent(word, k -> new HashSet<>())
                 .add(user.getAccountId());
        }
    }
    
    @Override
    public List<RegularUser> search(String query) {
        Set<UUID> results = index.getOrDefault(query.toLowerCase(), new HashSet<>());
        return results.stream()
            .map(users::get)
            .collect(Collectors.toList());
    }
}

class PostSearchIndex extends SearchIndex {
    private Map<UUID, Post> posts;
    
    public PostSearchIndex() {
        super();
        this.posts = new HashMap<>();
    }
    
    @Override
    public void indexDocument(Object doc) {
        Post post = (Post) doc;
        posts.put(post.getPostId(), post);
        
        String content = post.content.toLowerCase();
        for (String word : content.split("\\s+")) {
            index.computeIfAbsent(word, k -> new HashSet<>())
                 .add(post.getPostId());
        }
    }
    
    @Override
    public List<Post> search(String query) {
        Set<UUID> results = index.getOrDefault(query.toLowerCase(), new HashSet<>());
        return results.stream()
            .map(posts::get)
            .collect(Collectors.toList());
    }
}

class SearchFacade {
    private UserSearchIndex userIndex;
    private PostSearchIndex postIndex;
    
    public SearchFacade() {
        this.userIndex = new UserSearchIndex();
        this.postIndex = new PostSearchIndex();
    }
    
    public Map<String, List<?>> search(String query) {
        Map<String, List<?>> results = new HashMap<>();
        results.put("users", userIndex.search(query));
        results.put("posts", postIndex.search(query));
        return results;
    }
    
    public List<RegularUser> searchUsers(String query) {
        return userIndex.search(query);
    }
    
    public List<Post> searchPosts(String query) {
        return postIndex.search(query);
    }
}

/**
 * Graph Traversal for friend suggestions
 */
class GraphTraversal {
    public List<RegularUser> suggestFriends(RegularUser user, int limit) {
        // BFS to find friends of friends
        Set<RegularUser> visited = new HashSet<>();
        Map<RegularUser, Integer> mutualCount = new HashMap<>();
        
        visited.add(user);
        
        // Level 1: Direct friends
        Set<RegularUser> directFriends = user.getConnections().getFriends().stream()
            .map(f -> f.getOtherUser(user))
            .collect(Collectors.toSet());
        
        visited.addAll(directFriends);
        
        // Level 2: Friends of friends
        for (RegularUser friend : directFriends) {
            Set<RegularUser> friendsOfFriend = friend.getConnections().getFriends().stream()
                .map(f -> f.getOtherUser(friend))
                .filter(u -> !visited.contains(u))
                .collect(Collectors.toSet());
            
            for (RegularUser candidate : friendsOfFriend) {
                mutualCount.merge(candidate, 1, Integer::sum);
            }
        }
        
        // Sort by mutual friend count and return top N
        return mutualCount.entrySet().stream()
            .sorted((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue()))
            .limit(limit)
            .map(Map.Entry::getKey)
            .collect(Collectors.toList());
    }
    
    public int findShortestPath(RegularUser user1, RegularUser user2) {
        // BFS to find shortest path
        if (user1.equals(user2)) return 0;
        
        Queue<RegularUser> queue = new LinkedList<>();
        Map<RegularUser, Integer> distances = new HashMap<>();
        
        queue.offer(user1);
        distances.put(user1, 0);
        
        while (!queue.isEmpty()) {
            RegularUser current = queue.poll();
            int distance = distances.get(current);
            
            Set<RegularUser> neighbors = current.getConnections().getFriends().stream()
                .map(f -> f.getOtherUser(current))
                .collect(Collectors.toSet());
            
            for (RegularUser neighbor : neighbors) {
                if (!distances.containsKey(neighbor)) {
                    distances.put(neighbor, distance + 1);
                    queue.offer(neighbor);
                    
                    if (neighbor.equals(user2)) {
                        return distance + 1;
                    }
                }
            }
        }
        
        return -1; // No path found
    }
}

/**
 * Moderation
 */
interface ReportableContent {
    UUID getContentId();
    RegularUser getAuthor();
    void takedown();
}

class ContentReport {
    private UUID reportId;
    private RegularUser reporter;
    private ReportableContent content;
    private ReportReason reason;
    private String details;
    private ReportStatus status;
    private Administrator assignedTo;
    private LocalDateTime createdAt;
    
    public ContentReport(RegularUser reporter, ReportableContent content, 
                        ReportReason reason, String details) {
        this.reportId = UUID.randomUUID();
        this.reporter = reporter;
        this.content = content;
        this.reason = reason;
        this.details = details;
        this.status = ReportStatus.PENDING;
        this.createdAt = LocalDateTime.now();
    }
    
    public void assign(Administrator admin) {
        this.assignedTo = admin;
        this.status = ReportStatus.UNDER_REVIEW;
    }
    
    public void resolve(ActionType action) {
        this.status = ReportStatus.RESOLVED;
        // Execute moderation action
    }
}

/**
 * Demo usage
 */
class SocialNetworkDemo {
    public static void main(String[] args) {
        // Create users
        PersonalInfo aliceInfo = new PersonalInfo("Alice Smith", LocalDate.of(1990, 5, 15));
        PersonalInfo bobInfo = new PersonalInfo("Bob Johnson", LocalDate.of(1988, 8, 20));
        
        RegularUser alice = new RegularUser("[email protected]", "password123", aliceInfo);
        RegularUser bob = new RegularUser("[email protected]", "password456", bobInfo);
        
        // Alice sends friend request to Bob
        alice.sendFriendRequest(bob);
        
        // Bob accepts (simulated)
        // In real system, Bob would call acceptRequest on his SocialGraph
        
        // Alice creates a post
        Map<String, Object> postData = new HashMap<>();
        postData.put("content", "Hello, world! This is my first post.");
        Post post = alice.createPost("text", postData);
        
        // Bob reacts to Alice's post
        post.react(bob, ReactionType.LIKE);
        
        // Bob comments
        Comment comment = new Comment(bob, "Great post, Alice!");
        post.addComment(comment);
        
        // Alice sends a message to Bob
        alice.sendMessage(bob, "Hey Bob, thanks for the like!");
        
        // Create a group
        Group developers = new Group("Java Developers", 
                                    "A community for Java enthusiasts",
                                    GroupType.PUBLIC,
                                    alice);
        developers.addMember(bob, GroupRole.MEMBER);
        
        // Search functionality
        SearchFacade search = new SearchFacade();
        search.userIndex.indexDocument(alice);
        search.userIndex.indexDocument(bob);
        search.postIndex.indexDocument(post);
        
        List<RegularUser> searchResults = search.searchUsers("Alice");
        System.out.println("Found " + searchResults.size() + " users matching 'Alice'");
        
        // Friend suggestions
        GraphTraversal graph = new GraphTraversal();
        List<RegularUser> suggestions = graph.suggestFriends(alice, 10);
        System.out.println("Friend suggestions for Alice: " + suggestions.size());
        
        System.out.println("\nSocial Network System demonstration completed!");
    }
}

Python Implementation

"""
Social Networking Platform - Python Implementation
Demonstrates OOD patterns: State, Strategy, Observer, Factory, Composite, Facade
"""

from __future__ import annotations
from dataclasses import dataclass, field
from typing import List, Dict, Set, Optional, Protocol, Any
from abc import ABC, abstractmethod
from enum import Enum, auto
from datetime import datetime, date, timedelta
from uuid import UUID, uuid4
from collections import defaultdict, deque
import hashlib
import math

# ==================== Enumerations ====================

class AccountStatus(Enum):
    ACTIVE = auto()
    SUSPENDED = auto()
    DEACTIVATED = auto()
    DELETED = auto()

class VisibilityLevel(Enum):
    PUBLIC = auto()
    FRIENDS = auto()
    FRIENDS_OF_FRIENDS = auto()
    CUSTOM = auto()
    ONLY_ME = auto()

class Gender(Enum):
    MALE = auto()
    FEMALE = auto()
    NON_BINARY = auto()
    PREFER_NOT_TO_SAY = auto()

class RelationshipStatus(Enum):
    SINGLE = auto()
    IN_A_RELATIONSHIP = auto()
    ENGAGED = auto()
    MARRIED = auto()
    COMPLICATED = auto()
    DIVORCED = auto()
    WIDOWED = auto()

class RequestStatus(Enum):
    PENDING = auto()
    ACCEPTED = auto()
    REJECTED = auto()
    CANCELLED = auto()

class ReactionType(Enum):
    LIKE = auto()
    LOVE = auto()
    HAHA = auto()
    WOW = auto()
    SAD = auto()
    ANGRY = auto()

class GroupType(Enum):
    PUBLIC = auto()
    CLOSED = auto()
    SECRET = auto()

class GroupRole(Enum):
    MEMBER = auto()
    MODERATOR = auto()
    ADMIN = auto()

class PageCategory(Enum):
    BUSINESS = auto()
    CELEBRITY = auto()
    COMMUNITY = auto()
    ENTERTAINMENT = auto()
    ORGANIZATION = auto()
    BRAND = auto()
    LOCAL_BUSINESS = auto()

class MediaType(Enum):
    PHOTO = auto()
    VIDEO = auto()
    AUDIO = auto()
    DOCUMENT = auto()

class NotificationType(Enum):
    FRIEND_REQUEST = auto()
    FRIEND_ACCEPTED = auto()
    POST_LIKED = auto()
    POST_COMMENTED = auto()
    POST_SHARED = auto()
    MENTIONED_IN_POST = auto()
    MENTIONED_IN_COMMENT = auto()
    MESSAGE_RECEIVED = auto()
    GROUP_INVITED = auto()
    BIRTHDAY_REMINDER = auto()

class ReportReason(Enum):
    SPAM = auto()
    HARASSMENT = auto()
    HATE_SPEECH = auto()
    VIOLENCE = auto()
    NUDITY = auto()
    FALSE_INFORMATION = auto()
    OTHER = auto()

class ReportStatus(Enum):
    PENDING = auto()
    UNDER_REVIEW = auto()
    RESOLVED = auto()
    DISMISSED = auto()

class FriendshipStrength(Enum):
    WEAK = auto()
    MODERATE = auto()
    STRONG = auto()

# ==================== State Pattern ====================

class AccountState(Protocol):
    """Protocol for account state management"""
    def handle_login(self) -> bool: ...
    def allow_posting(self) -> bool: ...
    def transition_to(self, status: AccountStatus) -> AccountState: ...

@dataclass
class ActiveState:
    def handle_login(self) -> bool:
        return True
    
    def allow_posting(self) -> bool:
        return True
    
    def transition_to(self, status: AccountStatus) -> AccountState:
        if status == AccountStatus.SUSPENDED:
            return SuspendedState()
        elif status == AccountStatus.DEACTIVATED:
            return DeactivatedState()
        elif status == AccountStatus.DELETED:
            return DeletedState()
        return self

@dataclass
class SuspendedState:
    def handle_login(self) -> bool:
        raise Exception("Account is suspended")
    
    def allow_posting(self) -> bool:
        return False
    
    def transition_to(self, status: AccountStatus) -> AccountState:
        if status == AccountStatus.ACTIVE:
            return ActiveState()
        return self

@dataclass
class DeactivatedState:
    def handle_login(self) -> bool:
        return True  # Can reactivate by logging in
    
    def allow_posting(self) -> bool:
        return False
    
    def transition_to(self, status: AccountStatus) -> AccountState:
        if status == AccountStatus.ACTIVE:
            return ActiveState()
        return self

@dataclass
class DeletedState:
    def handle_login(self) -> bool:
        raise Exception("Account has been deleted")
    
    def allow_posting(self) -> bool:
        return False
    
    def transition_to(self, status: AccountStatus) -> AccountState:
        return self  # Cannot transition from deleted

# ==================== Core Identity ====================

@dataclass
class SecuritySettings:
    two_factor_enabled: bool = False
    trusted_devices: Set[str] = field(default_factory=set)
    last_password_change: datetime = field(default_factory=datetime.now)
    
    def enable_two_factor(self) -> None:
        self.two_factor_enabled = True
    
    def add_trusted_device(self, device_id: str) -> None:
        self.trusted_devices.add(device_id)

class UserAccount(ABC):
    def __init__(self, email: str, password: str):
        self.account_id: UUID = uuid4()
        self.email: str = email
        self.password_hash: str = self._hash_password(password)
        self.created_at: datetime = datetime.now()
        self.state: AccountState = ActiveState()
        self.security: SecuritySettings = SecuritySettings()
    
    def authenticate(self, password: str) -> bool:
        return (self.state.handle_login() and 
                self._hash_password(password) == self.password_hash)
    
    def deactivate(self) -> None:
        self.state = self.state.transition_to(AccountStatus.DEACTIVATED)
    
    def reactivate(self) -> None:
        self.state = self.state.transition_to(AccountStatus.ACTIVE)
    
    def change_password(self, new_password: str) -> None:
        self.password_hash = self._hash_password(new_password)
        self.security.last_password_change = datetime.now()
    
    @staticmethod
    def _hash_password(password: str) -> str:
        return hashlib.sha256(password.encode()).hexdigest()

# ==================== Profile ====================

@dataclass
class PersonalInfo:
    full_name: str
    birth_date: date
    gender: Optional[Gender] = None
    hometown: Optional[str] = None
    current_city: Optional[str] = None
    relationship_status: Optional[RelationshipStatus] = None
    
    def get_age(self) -> int:
        today = date.today()
        return today.year - self.birth_date.year - (
            (today.month, today.day) < (self.birth_date.month, self.birth_date.day)
        )

@dataclass
class WorkExperience:
    company: str
    position: str
    start_date: date
    location: Optional[str] = None
    end_date: Optional[date] = None
    description: Optional[str] = None
    
    def end(self, end_date: date) -> None:
        self.end_date = end_date

@dataclass
class Education:
    institution: str
    degree: str
    field_of_study: str
    graduation_year: int

@dataclass
class PrivacyList:
    list_id: UUID = field(default_factory=uuid4)
    name: str = ""
    members: Set[RegularUser] = field(default_factory=set)
    
    def add_member(self, user: RegularUser) -> None:
        self.members.add(user)
    
    def remove_member(self, user: RegularUser) -> None:
        self.members.discard(user)
    
    def contains(self, user: RegularUser) -> bool:
        return user in self.members

@dataclass
class PrivacySettings:
    profile_visibility: VisibilityLevel = VisibilityLevel.FRIENDS
    posts_visibility: VisibilityLevel = VisibilityLevel.FRIENDS
    friend_list_visibility: VisibilityLevel = VisibilityLevel.FRIENDS
    custom_lists: Dict[str, PrivacyList] = field(default_factory=dict)
    
    def __post_init__(self):
        if not self.custom_lists:
            self.custom_lists = {
                'close_friends': PrivacyList(name="Close Friends"),
                'acquaintances': PrivacyList(name="Acquaintances"),
                'restricted': PrivacyList(name="Restricted")
            }
    
    def update_setting(self, key: str, value: VisibilityLevel) -> None:
        if key == 'profile':
            self.profile_visibility = value
        elif key == 'posts':
            self.posts_visibility = value
        elif key == 'friends':
            self.friend_list_visibility = value
    
    def can_view(self, viewer: RegularUser, resource_type: str) -> bool:
        level = self._get_visibility_for(resource_type)
        if level == VisibilityLevel.PUBLIC:
            return True
        elif level == VisibilityLevel.ONLY_ME:
            return False
        # Simplified - would check actual friendship
        return False
    
    def _get_visibility_for(self, resource: str) -> VisibilityLevel:
        mapping = {
            'profile': self.profile_visibility,
            'posts': self.posts_visibility,
            'friends': self.friend_list_visibility
        }
        return mapping.get(resource, VisibilityLevel.FRIENDS)

@dataclass
class MediaItem:
    item_id: UUID = field(default_factory=uuid4)
    url: str = ""
    media_type: MediaType = MediaType.PHOTO
    uploaded_at: datetime = field(default_factory=datetime.now)

@dataclass
class UserProfile:
    info: PersonalInfo
    work_history: List[WorkExperience] = field(default_factory=list)
    education_history: List[Education] = field(default_factory=list)
    photos: List[MediaItem] = field(default_factory=list)
    privacy: PrivacySettings = field(default_factory=PrivacySettings)
    last_updated: datetime = field(default_factory=datetime.now)
    
    def update_bio(self, text: str) -> None:
        self.last_updated = datetime.now()
    
    def add_work_experience(self, work: WorkExperience) -> None:
        self.work_history.append(work)
        self.last_updated = datetime.now()
    
    def add_education(self, edu: Education) -> None:
        self.education_history.append(edu)
        self.last_updated = datetime.now()
    
    def set_profile_picture(self, photo: MediaItem) -> None:
        self.photos.insert(0, photo)
        self.last_updated = datetime.now()

# ==================== Social Graph ====================

@dataclass
class Friendship:
    user1: RegularUser
    user2: RegularUser
    established_at: datetime = field(default_factory=datetime.now)
    strength: FriendshipStrength = FriendshipStrength.MODERATE
    
    def calculate_strength(self) -> FriendshipStrength:
        # Simplified - would analyze interactions
        return FriendshipStrength.MODERATE
    
    def get_other_user(self, user: RegularUser) -> Optional[RegularUser]:
        if user == self.user1:
            return self.user2
        elif user == self.user2:
            return self.user1
        return None

@dataclass
class Following:
    follower: RegularUser
    followee: RegularUser
    since: datetime = field(default_factory=datetime.now)
    notifications_enabled: bool = True

@dataclass
class FriendRequest:
    request_id: UUID = field(default_factory=uuid4)
    sender: Optional[RegularUser] = None
    recipient: Optional[RegularUser] = None
    status: RequestStatus = RequestStatus.PENDING
    sent_at: datetime = field(default_factory=datetime.now)
    
    def accept(self) -> None:
        if self.status != RequestStatus.PENDING:
            raise Exception("Request not pending")
        self.status = RequestStatus.ACCEPTED
    
    def reject(self) -> None:
        if self.status != RequestStatus.PENDING:
            raise Exception("Request not pending")
        self.status = RequestStatus.REJECTED
    
    def cancel(self) -> None:
        if self.status != RequestStatus.PENDING:
            raise Exception("Request not pending")
        self.status = RequestStatus.CANCELLED

@dataclass
class SocialGraph:
    friends: List[Friendship] = field(default_factory=list)
    followings: List[Following] = field(default_factory=list)
    pending_requests: List[FriendRequest] = field(default_factory=list)
    blocked_users: Set[RegularUser] = field(default_factory=set)
    
    def send_friend_request(self, user: RegularUser, target: RegularUser) -> None:
        if target in self.blocked_users:
            raise Exception("Cannot send request to blocked user")
        request = FriendRequest(sender=user, recipient=target)
        self.pending_requests.append(request)
    
    def accept_request(self, request_id: UUID) -> None:
        request = self._find_request(request_id)
        request.accept()
        
        friendship = Friendship(user1=request.sender, user2=request.recipient)
        self.friends.append(friendship)
        self.pending_requests.remove(request)
    
    def reject_request(self, request_id: UUID) -> None:
        request = self._find_request(request_id)
        request.reject()
        self.pending_requests.remove(request)
    
    def unfriend(self, user: RegularUser) -> None:
        self.friends = [f for f in self.friends 
                       if f.get_other_user(user) != user]
    
    def follow(self, follower: RegularUser, followee: RegularUser) -> None:
        self.followings.append(Following(follower=follower, followee=followee))
    
    def unfollow(self, followee: RegularUser) -> None:
        self.followings = [f for f in self.followings 
                          if f.followee != followee]
    
    def get_mutual_friends(self, user: RegularUser) -> Set[RegularUser]:
        # Simplified implementation
        return set()
    
    def get_suggestions(self) -> List[RegularUser]:
        # Would implement friend-of-friend algorithm
        return []
    
    def _find_request(self, request_id: UUID) -> FriendRequest:
        for req in self.pending_requests:
            if req.request_id == request_id:
                return req
        raise Exception("Request not found")

# ==================== Factory Pattern ====================

class ContentFactory(Protocol):
    """Protocol for content creation"""
    def create_post(self, post_type: str, data: Dict[str, Any]) -> Post: ...

@dataclass
class PostFactory:
    def create_post(self, post_type: str, data: Dict[str, Any]) -> Post:
        author = data['author']
        content = data.get('content', '')
        
        if post_type == 'text':
            return TextPost(author=author, content=content)
        elif post_type == 'photo':
            return PhotoPost(author=author, content=content, 
                           photo_urls=data.get('photos', []))
        elif post_type == 'video':
            return VideoPost(author=author, content=content,
                           video_url=data.get('video', ''))
        elif post_type == 'link':
            return LinkPost(author=author, content=content,
                          url=data.get('url', ''))
        else:
            raise ValueError(f"Unknown post type: {post_type}")

# ==================== Content ====================

@dataclass
class Reaction:
    user: RegularUser
    reaction_type: ReactionType
    timestamp: datetime = field(default_factory=datetime.now)

@dataclass
class Comment:
    comment_id: UUID = field(default_factory=uuid4)
    author: Optional[RegularUser] = None
    text: str = ""
    created_at: datetime = field(default_factory=datetime.now)
    replies: List[Comment] = field(default_factory=list)
    reactions: List[Reaction] = field(default_factory=list)
    
    def add_reply(self, reply: Comment) -> None:
        self.replies.append(reply)
    
    def react(self, user: RegularUser, reaction_type: ReactionType) -> None:
        # Remove existing reaction from this user
        self.reactions = [r for r in self.reactions if r.user != user]
        self.reactions.append(Reaction(user=user, reaction_type=reaction_type))
    
    def delete(self) -> None:
        pass  # Soft delete

@dataclass
class Post(ABC):
    post_id: UUID = field(default_factory=uuid4)
    author: Optional[RegularUser] = None
    content: str = ""
    created_at: datetime = field(default_factory=datetime.now)
    edited_at: Optional[datetime] = None
    visibility: VisibilityLevel = VisibilityLevel.FRIENDS
    comments: List[Comment] = field(default_factory=list)
    reactions: List[Reaction] = field(default_factory=list)
    share_count: int = 0
    tagged_users: List[RegularUser] = field(default_factory=list)
    
    def edit(self, new_content: str) -> None:
        self.content = new_content
        self.edited_at = datetime.now()
    
    def delete(self) -> None:
        pass  # Soft delete
    
    def add_comment(self, comment: Comment) -> None:
        self.comments.append(comment)
    
    def react(self, user: RegularUser, reaction_type: ReactionType) -> None:
        self.reactions = [r for r in self.reactions if r.user != user]
        self.reactions.append(Reaction(user=user, reaction_type=reaction_type))
    
    def share(self, user: RegularUser) -> None:
        self.share_count += 1
    
    def get_total_engagement(self) -> int:
        return len(self.reactions) + len(self.comments) + self.share_count

@dataclass
class TextPost(Post):
    formatted_text: str = ""
    
    def __post_init__(self):
        if not self.formatted_text:
            self.formatted_text = self.content

@dataclass
class PhotoPost(Post):
    photo_urls: List[str] = field(default_factory=list)

@dataclass
class VideoPost(Post):
    video_url: str = ""
    thumbnail_url: str = ""
    
    def __post_init__(self):
        if not self.thumbnail_url and self.video_url:
            self.thumbnail_url = self.video_url + "_thumb.jpg"

@dataclass
class LinkPost(Post):
    url: str = ""
    preview_title: str = ""
    preview_image: str = ""

# ==================== Strategy Pattern ====================

class FeedRankingStrategy(Protocol):
    """Protocol for feed ranking algorithms"""
    def rank_posts(self, posts: List[Post], user: RegularUser) -> List[Post]: ...

@dataclass
class ChronologicalRanking:
    def rank_posts(self, posts: List[Post], user: RegularUser) -> List[Post]:
        return sorted(posts, key=lambda p: p.created_at, reverse=True)

@dataclass
class EdgeRankAlgorithm:
    def rank_posts(self, posts: List[Post], user: RegularUser) -> List[Post]:
        scores: Dict[Post, float] = {}
        
        for post in posts:
            affinity = self._calculate_affinity(user, post.author)
            weight = self._calculate_weight(post)
            time_decay = self._calculate_time_decay(post)
            
            edge_rank = affinity * weight * time_decay
            scores[post] = edge_rank
        
        return sorted(posts, key=lambda p: scores.get(p, 0), reverse=True)
    
    def _calculate_affinity(self, user: RegularUser, author: Optional[RegularUser]) -> float:
        # Simplified - would analyze interaction history
        return 0.7
    
    def _calculate_weight(self, post: Post) -> float:
        if isinstance(post, (PhotoPost, VideoPost)):
            return 1.0
        elif isinstance(post, LinkPost):
            return 0.7
        return 0.5
    
    def _calculate_time_decay(self, post: Post) -> float:
        hours_old = (datetime.now() - post.created_at).total_seconds() / 3600
        return math.exp(-hours_old / 24.0)

@dataclass
class EngagementBasedRanking:
    def rank_posts(self, posts: List[Post], user: RegularUser) -> List[Post]:
        return sorted(posts, 
                     key=lambda p: self._predict_engagement(p, user),
                     reverse=True)
    
    def _predict_engagement(self, post: Post, user: RegularUser) -> int:
        # Simplified ML prediction
        return post.get_total_engagement()

@dataclass
class NewsFeed:
    user: RegularUser
    ranking_strategy: FeedRankingStrategy = field(default_factory=EdgeRankAlgorithm)
    cached_feed: List[Post] = field(default_factory=list)
    last_updated: Optional[datetime] = None
    
    def refresh_feed(self) -> None:
        # Aggregate posts from friends, followings, pages, groups
        all_posts: List[Post] = []
        # ... collect posts ...
        
        self.cached_feed = self.ranking_strategy.rank_posts(all_posts, self.user)
        self.last_updated = datetime.now()
    
    def set_ranking_strategy(self, strategy: FeedRankingStrategy) -> None:
        self.ranking_strategy = strategy
        self.refresh_feed()
    
    def get_next_page(self, page: int, page_size: int) -> List[Post]:
        start = page * page_size
        end = min(start + page_size, len(self.cached_feed))
        return self.cached_feed[start:end]

# ==================== Observer Pattern ====================

@dataclass
class Notification:
    notification_id: UUID = field(default_factory=uuid4)
    notification_type: NotificationType = NotificationType.POST_LIKED
    recipient: Optional[RegularUser] = None
    actor: Optional[RegularUser] = None
    content: str = ""
    created_at: datetime = field(default_factory=datetime.now)
    read: bool = False
    
    def mark_as_read(self) -> None:
        self.read = True

class NotificationObserver(Protocol):
    """Protocol for notification delivery"""
    def on_event(self, notification: Notification) -> None: ...

@dataclass
class PushNotificationService:
    def on_event(self, notification: Notification) -> None:
        print(f"Push: {notification.content}")

@dataclass
class EmailNotificationService:
    def on_event(self, notification: Notification) -> None:
        print(f"Email: {notification.content}")

@dataclass
class InAppNotificationService:
    def on_event(self, notification: Notification) -> None:
        print(f"In-App: {notification.content}")

@dataclass
class NotificationPublisher:
    observers: List[NotificationObserver] = field(default_factory=list)
    
    def subscribe(self, observer: NotificationObserver) -> None:
        self.observers.append(observer)
    
    def unsubscribe(self, observer: NotificationObserver) -> None:
        self.observers.remove(observer)
    
    def notify_observers(self, notification: Notification) -> None:
        for observer in self.observers:
            observer.on_event(notification)

@dataclass
class NotificationCenter:
    user: RegularUser
    notifications: List[Notification] = field(default_factory=list)
    publisher: NotificationPublisher = field(default_factory=NotificationPublisher)
    
    def __post_init__(self):
        # Subscribe default services
        self.publisher.subscribe(PushNotificationService())
        self.publisher.subscribe(EmailNotificationService())
        self.publisher.subscribe(InAppNotificationService())
    
    def send_notification(self, notification: Notification) -> None:
        self.notifications.append(notification)
        self.publisher.notify_observers(notification)
    
    def mark_as_read(self, notification_id: UUID) -> None:
        for notif in self.notifications:
            if notif.notification_id == notification_id:
                notif.mark_as_read()
                break

# ==================== User Classes ====================

class RegularUser(UserAccount):
    def __init__(self, email: str, password: str, info: PersonalInfo):
        super().__init__(email, password)
        self.profile: UserProfile = UserProfile(info=info)
        self.connections: SocialGraph = SocialGraph()
        self.timeline: List[Post] = []
        self.messages: List[Conversation] = []
        self.notifications: NotificationCenter = NotificationCenter(user=self)
        self.news_feed: NewsFeed = NewsFeed(user=self)
    
    def create_post(self, post_type: str, data: Dict[str, Any]) -> Post:
        data['author'] = self
        factory = PostFactory()
        post = factory.create_post(post_type, data)
        self.timeline.append(post)
        return post
    
    def send_friend_request(self, target: RegularUser) -> None:
        self.connections.send_friend_request(self, target)
        
        # Notify target
        notif = Notification(
            notification_type=NotificationType.FRIEND_REQUEST,
            recipient=target,
            actor=self,
            content=f"{self.profile.info.full_name} sent you a friend request"
        )
        target.notifications.send_notification(notif)
    
    def send_message(self, recipient: RegularUser, text: str) -> None:
        # Find or create conversation
        conv = next((c for c in self.messages if c.has_participant(recipient)), None)
        if not conv:
            conv = Conversation(participants=[self, recipient])
            self.messages.append(conv)
        
        msg = Message(sender=self, content=text)
        conv.send_message(msg)

class Administrator(UserAccount):
    def __init__(self, email: str, password: str):
        super().__init__(email, password)
        self.permissions: Set[str] = {
            'REVIEW_REPORTS', 'SUSPEND_ACCOUNTS', 
            'DELETE_CONTENT', 'BAN_USERS'
        }
    
    def review_report(self, report_id: UUID) -> None:
        pass
    
    def suspend_account(self, user_id: UUID) -> None:
        pass
    
    def delete_content(self, content_id: UUID) -> None:
        pass

# ==================== Groups and Pages ====================

@dataclass
class GroupMember:
    user: RegularUser
    role: GroupRole
    joined_at: datetime = field(default_factory=datetime.now)
    
    def promote_to_admin(self) -> None:
        self.role = GroupRole.ADMIN
    
    def demote(self) -> None:
        self.role = GroupRole.MEMBER

@dataclass
class Group:
    group_id: UUID = field(default_factory=uuid4)
    name: str = ""
    description: str = ""
    group_type: GroupType = GroupType.PUBLIC
    creator: Optional[RegularUser] = None
    members: List[GroupMember] = field(default_factory=list)
    posts: List[Post] = field(default_factory=list)
    created_at: datetime = field(default_factory=datetime.now)
    
    def __post_init__(self):
        if self.creator and not self.members:
            self.members.append(GroupMember(user=self.creator, role=GroupRole.ADMIN))
    
    def add_member(self, user: RegularUser, role: GroupRole) -> None:
        self.members.append(GroupMember(user=user, role=role))
    
    def remove_member(self, user: RegularUser) -> None:
        self.members = [m for m in self.members if m.user != user]
    
    def create_post(self, post: Post) -> None:
        self.posts.append(post)

@dataclass
class PageReview:
    review_id: UUID = field(default_factory=uuid4)
    author: Optional[RegularUser] = None
    rating: int = 5
    text: str = ""
    created_at: datetime = field(default_factory=datetime.now)
    admin_response: str = ""
    
    def __post_init__(self):
        self.rating = max(1, min(5, self.rating))
    
    def respond(self, response: str) -> None:
        self.admin_response = response

@dataclass
class Page:
    page_id: UUID = field(default_factory=uuid4)
    name: str = ""
    description: str = ""
    category: PageCategory = PageCategory.BUSINESS
    admins: List[RegularUser] = field(default_factory=list)
    followers: Set[RegularUser] = field(default_factory=set)
    posts: List[Post] = field(default_factory=list)
    reviews: List[PageReview] = field(default_factory=list)
    
    def publish_post(self, post: Post) -> None:
        self.posts.append(post)
    
    def add_follower(self, user: RegularUser) -> None:
        self.followers.add(user)
    
    def respond_to_review(self, review_id: UUID, response: str) -> None:
        for review in self.reviews:
            if review.review_id == review_id:
                review.respond(response)
                break

# ==================== Messaging ====================

@dataclass
class MediaAttachment:
    attachment_id: UUID = field(default_factory=uuid4)
    media_type: MediaType = MediaType.PHOTO
    url: str = ""
    size: int = 0

@dataclass
class Message:
    message_id: UUID = field(default_factory=uuid4)
    sender: Optional[RegularUser] = None
    content: str = ""
    sent_at: datetime = field(default_factory=datetime.now)
    read_receipts: Dict[RegularUser, datetime] = field(default_factory=dict)
    attachments: List[MediaAttachment] = field(default_factory=list)
    
    def mark_as_read(self, user: RegularUser) -> None:
        self.read_receipts[user] = datetime.now()
    
    def delete(self) -> None:
        pass  # Soft delete

@dataclass
class Conversation:
    conversation_id: UUID = field(default_factory=uuid4)
    participants: List[RegularUser] = field(default_factory=list)
    messages: List[Message] = field(default_factory=list)
    created_at: datetime = field(default_factory=datetime.now)
    last_activity: datetime = field(default_factory=datetime.now)
    
    def send_message(self, message: Message) -> None:
        self.messages.append(message)
        self.last_activity = datetime.now()
    
    def add_participant(self, user: RegularUser) -> None:
        self.participants.append(user)
    
    def remove_participant(self, user: RegularUser) -> None:
        self.participants.remove(user)
    
    def mark_as_read(self, user: RegularUser) -> None:
        for msg in self.messages:
            if msg.sender != user:
                msg.mark_as_read(user)
    
    def has_participant(self, user: RegularUser) -> bool:
        return user in self.participants

# ==================== Facade Pattern ====================

class SearchIndex(ABC):
    def __init__(self):
        self.index: Dict[str, Set[UUID]] = defaultdict(set)
    
    @abstractmethod
    def index_document(self, doc: Any) -> None: ...
    
    @abstractmethod
    def search(self, query: str) -> List[Any]: ...
    
    def remove_document(self, doc_id: UUID) -> None:
        for uuid_set in self.index.values():
            uuid_set.discard(doc_id)

@dataclass
class UserSearchIndex(SearchIndex):
    users: Dict[UUID, RegularUser] = field(default_factory=dict)
    
    def index_document(self, doc: RegularUser) -> None:
        self.users[doc.account_id] = doc
        
        name = doc.profile.info.full_name.lower()
        for word in name.split():
            self.index[word].add(doc.account_id)
    
    def search(self, query: str) -> List[RegularUser]:
        results = self.index.get(query.lower(), set())
        return [self.users[uid] for uid in results if uid in self.users]

@dataclass
class PostSearchIndex(SearchIndex):
    posts: Dict[UUID, Post] = field(default_factory=dict)
    
    def index_document(self, doc: Post) -> None:
        self.posts[doc.post_id] = doc
        
        content = doc.content.lower()
        for word in content.split():
            self.index[word].add(doc.post_id)
    
    def search(self, query: str) -> List[Post]:
        results = self.index.get(query.lower(), set())
        return [self.posts[pid] for pid in results if pid in self.posts]

@dataclass
class SearchFacade:
    user_index: UserSearchIndex = field(default_factory=UserSearchIndex)
    post_index: PostSearchIndex = field(default_factory=PostSearchIndex)
    
    def search(self, query: str) -> Dict[str, List[Any]]:
        return {
            'users': self.user_index.search(query),
            'posts': self.post_index.search(query)
        }
    
    def search_users(self, query: str) -> List[RegularUser]:
        return self.user_index.search(query)
    
    def search_posts(self, query: str) -> List[Post]:
        return self.post_index.search(query)

# ==================== Graph Traversal ====================

@dataclass
class GraphTraversal:
    def suggest_friends(self, user: RegularUser, limit: int) -> List[RegularUser]:
        """BFS to find friends of friends"""
        visited: Set[RegularUser] = {user}
        mutual_count: Dict[RegularUser, int] = defaultdict(int)
        
        # Level 1: Direct friends
        direct_friends = {f.get_other_user(user) for f in user.connections.friends 
                         if f.get_other_user(user)}
        visited.update(direct_friends)
        
        # Level 2: Friends of friends
        for friend in direct_friends:
            if friend:
                friends_of_friend = {f.get_other_user(friend) 
                                    for f in friend.connections.friends
                                    if f.get_other_user(friend) and 
                                    f.get_other_user(friend) not in visited}
                
                for candidate in friends_of_friend:
                    mutual_count[candidate] += 1
        
        # Sort by mutual friend count
        suggestions = sorted(mutual_count.items(), 
                           key=lambda x: x[1], 
                           reverse=True)
        return [user for user, _ in suggestions[:limit]]
    
    def find_shortest_path(self, user1: RegularUser, user2: RegularUser) -> int:
        """BFS to find shortest path between two users"""
        if user1 == user2:
            return 0
        
        queue: deque = deque([(user1, 0)])
        visited: Set[RegularUser] = {user1}
        
        while queue:
            current, distance = queue.popleft()
            
            neighbors = {f.get_other_user(current) 
                        for f in current.connections.friends
                        if f.get_other_user(current)}
            
            for neighbor in neighbors:
                if neighbor and neighbor not in visited:
                    if neighbor == user2:
                        return distance + 1
                    visited.add(neighbor)
                    queue.append((neighbor, distance + 1))
        
        return -1  # No path found

# ==================== Demo ====================

def main():
    # Create users
    alice_info = PersonalInfo(full_name="Alice Smith", birth_date=date(1990, 5, 15))
    bob_info = PersonalInfo(full_name="Bob Johnson", birth_date=date(1988, 8, 20))
    
    alice = RegularUser(email="[email protected]", password="pass123", info=alice_info)
    bob = RegularUser(email="[email protected]", password="pass456", info=bob_info)
    
    # Alice sends friend request to Bob
    alice.send_friend_request(bob)
    
    # Alice creates a post
    post = alice.create_post('text', {'content': 'Hello, world! First post.'})
    
    # Bob reacts
    post.react(bob, ReactionType.LIKE)
    
    # Bob comments
    comment = Comment(author=bob, text="Great post, Alice!")
    post.add_comment(comment)
    
    # Alice sends message to Bob
    alice.send_message(bob, "Hey Bob, thanks for the like!")
    
    # Create a group
    developers = Group(
        name="Java Developers",
        description="A community for Java enthusiasts",
        group_type=GroupType.PUBLIC,
        creator=alice
    )
    developers.add_member(bob, GroupRole.MEMBER)
    
    # Search
    search = SearchFacade()
    search.user_index.index_document(alice)
    search.user_index.index_document(bob)
    search.post_index.index_document(post)
    
    results = search.search_users("Alice")
    print(f"Found {len(results)} users matching 'Alice'")
    
    # Friend suggestions
    graph = GraphTraversal()
    suggestions = graph.suggest_friends(alice, 10)
    print(f"Friend suggestions for Alice: {len(suggestions)}")
    
    print("\nSocial Network System demonstration completed!")

if __name__ == "__main__":
    main()

Key Design Decisions

1. State Pattern for Account Management

Decision: Use the State pattern to manage account lifecycle (Active, Suspended, Deactivated, Deleted).

Rationale:

  • Each state has different behavioral rules (login permissions, posting capabilities)
  • State transitions are complex with conditional logic
  • Future account states (e.g., Verified, Premium) can be added without modifying existing code

Trade-offs:

  • Pro: Clean separation of state-specific behavior; easy to add new states
  • Con: More classes to maintain; slight performance overhead from delegation

Example: A suspended account cannot post content but can view public content. The SuspendedState class encapsulates this behavior without polluting the UserAccount class with conditional statements.

2. Strategy Pattern for Feed Ranking

Decision: Implement multiple feed ranking algorithms (Chronological, EdgeRank, Engagement-based) using the Strategy pattern.

Rationale:

  • Different users prefer different ranking methods
  • Algorithm complexity varies greatly (simple timestamp sort vs. ML-based prediction)
  • Need to A/B test different algorithms without code changes
  • Real-time algorithm switching based on user preferences

Trade-offs:

  • Pro: Algorithm swapping at runtime; easy to add new ranking strategies
  • Con: All strategies must share the same interface, limiting flexibility

Example: During the News Feed load, the system can switch from EdgeRank to Chronological ranking based on user settings without recomputing the entire feed.

3. Observer Pattern for Notifications

Decision: Use Observer pattern with multiple notification channels (Push, Email, In-App).

Rationale:

  • Single event (e.g., friend request) triggers multiple notification types
  • Notification preferences vary by user
  • Easy to add new channels (SMS, Webhook) without modifying event publishers
  • Decouples event source from notification delivery

Trade-offs:

  • Pro: Loose coupling; dynamic subscription management; parallel notification delivery
  • Con: Debugging can be challenging with many observers; potential for notification storms

Example: When Alice sends a friend request to Bob, the NotificationPublisher notifies all registered observers (Push, Email, In-App services) simultaneously without Alice's code knowing about each channel.

4. Factory Pattern for Content Creation

Decision: Use Factory pattern to create different post types (Text, Photo, Video, Link).

Rationale:

  • Post creation involves complex initialization (media upload, preview generation, metadata extraction)
  • Each post type has different validation rules
  • Centralized creation logic simplifies testing and maintenance
  • Future content types (Poll, Event, Live Video) can be added easily

Trade-offs:

  • Pro: Single point of creation; consistent initialization; type safety
  • Con: Additional abstraction layer; factory becomes complex with many types

Example: Creating a LinkPost requires fetching URL metadata (title, image, description) from external sources. The PostFactory encapsulates this complexity, returning a fully-initialized LinkPost object.

5. Composite Pattern for Comment Threads

Decision: Implement nested comment replies as a tree structure using Composite pattern.

Rationale:

  • Comments can have unlimited reply depth
  • Operations (count reactions, search text) should work uniformly on comments and replies
  • Simplifies rendering of threaded discussions

Trade-offs:

  • Pro: Uniform treatment of comments and replies; recursive traversal; flexible depth
  • Con: Can lead to very deep trees; performance concerns with excessive nesting

Example: Rendering a comment thread with 3 levels of replies uses the same traversal logic as a flat comment list, treating each node uniformly.

6. Facade Pattern for Search

Decision: Provide a unified SearchFacade over multiple specialized search indexes (Users, Posts, Groups, Pages).

Rationale:

  • Each entity type requires different indexing strategies (name-based for users, full-text for posts)
  • Client code should not know about multiple indexes
  • Simplifies query routing and result aggregation
  • Allows index implementation changes without affecting clients

Trade-offs:

  • Pro: Simplified client interface; centralized search logic; easy to add new indexes
  • Con: Can become a "god object"; may hide useful index-specific features

Example: A global search query "Java" is routed to both UserSearchIndex (finds users named Java) and PostSearchIndex (finds posts containing "Java"), with results aggregated in a single response.

7. Bidirectional vs. Asymmetric Relationships

Decision: Support both symmetric friendships (mutual consent required) and asymmetric following (one-way, no consent).

Rationale:

  • Friendships imply reciprocal access and visibility
  • Following allows users to subscribe to public figures without mutual relationship
  • Matches real-world social dynamics (friends vs. followers)
  • Privacy controls differ for each relationship type

Trade-offs:

  • Pro: Flexibility for different use cases; aligns with user expectations
  • Con: More complex access control logic; potential user confusion

Example: Bob can follow Celebrity Alice (asymmetric) to see her public posts, while Bob and Charlie are friends (symmetric) and share private content.

8. Privacy Settings Architecture

Decision: Implement granular, resource-specific privacy controls with custom privacy lists.

Rationale:

  • Users need different visibility levels for profile, posts, photos, friend list
  • Custom lists (Close Friends, Acquaintances, Restricted) enable fine-grained control
  • Privacy decisions are context-dependent (work vs. personal content)
  • Compliance with privacy regulations (GDPR, CCPA)

Trade-offs:

  • Pro: User control; regulatory compliance; flexible visibility rules
  • Con: Complex access control logic; potential performance impact on content delivery

Example: Alice shares vacation photos with "Close Friends" list, work updates with "Public" visibility, and personal thoughts with "Only Me" privacy.

9. Graph Traversal for Friend Suggestions

Decision: Use Breadth-First Search (BFS) with mutual friend counting for connection suggestions.

Rationale:

  • Friends-of-friends are statistically likely to become friends
  • BFS ensures shortest social distance
  • Mutual friend count is a strong predictor of connection probability
  • Efficient for limited search depth (2-3 levels)

Trade-offs:

  • Pro: Simple implementation; interpretable results; good accuracy
  • Con: Doesn't consider shared interests, location, or other signals; limited scalability

Example: The algorithm suggests Bob to Alice because they have 5 mutual friends (Charlie, David, Eve, Frank, Grace), even though they've never met.

10. Message Delivery with Read Receipts

Decision: Implement real-time message delivery with WebSocket and offline queuing with read receipt tracking.

Rationale:

  • Users expect instant messaging experience
  • WebSocket enables push-based delivery without polling
  • Offline users should receive messages when they reconnect
  • Read receipts provide sender confirmation
  • Fallback to Push/Email notifications ensures message visibility

Trade-offs:

  • Pro: Real-time experience; reliability; user awareness
  • Con: Complex delivery infrastructure; privacy concerns with read receipts; increased server load

Example: When Alice sends a message to Bob at 2:00 PM, if Bob is online, he receives it via WebSocket within 100ms. If offline, the message queues and Bob receives a push notification. When Bob reads the message at 2:15 PM, Alice sees "Read at 2:15 PM."

Comments