"""
Internal Team Chat Routes for enterprise communication.
Enables messaging between admin, staff, and housekeeping users.
"""
from fastapi import APIRouter, Depends, HTTPException, status, WebSocket, WebSocketDisconnect, Query
from sqlalchemy.orm import Session, joinedload
from sqlalchemy import and_, or_, desc, func
from typing import List, Optional
from datetime import datetime
from pydantic import BaseModel, Field
import json

from ...shared.config.database import get_db
from ...shared.config.logging_config import get_logger
from ...security.middleware.auth import get_current_user, authorize_roles
from ...auth.models.user import User
from ...auth.models.role import Role
from ..models.team_chat import (
    TeamChannel, TeamMessage, TeamMessageReadReceipt, UserPresence,
    ChannelType, MessagePriority, team_channel_members
)

logger = get_logger(__name__)
router = APIRouter(prefix='/team-chat', tags=['team-chat'])


# ============== Pydantic Schemas ==============

class ChannelCreate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    channel_type: ChannelType = ChannelType.group
    department: Optional[str] = None
    is_private: bool = False
    member_ids: List[int] = Field(default_factory=list)


class ChannelUpdate(BaseModel):
    name: Optional[str] = None
    description: Optional[str] = None
    is_private: Optional[bool] = None


class MessageCreate(BaseModel):
    content: str = Field(..., min_length=1, max_length=5000)
    priority: MessagePriority = MessagePriority.normal
    reply_to_id: Optional[int] = None
    reference_type: Optional[str] = None
    reference_id: Optional[int] = None


class MessageUpdate(BaseModel):
    content: str = Field(..., min_length=1, max_length=5000)


class DirectMessageCreate(BaseModel):
    recipient_id: int
    content: str = Field(..., min_length=1, max_length=5000)
    priority: MessagePriority = MessagePriority.normal


class PresenceUpdate(BaseModel):
    status: str = Field(..., pattern='^(online|away|busy|offline)$')
    custom_status: Optional[str] = Field(None, max_length=100)


# ============== WebSocket Manager ==============

class TeamChatManager:
    """Manages WebSocket connections for team chat."""
    
    def __init__(self):
        # Map of channel_id -> list of (user_id, websocket)
        self.channel_connections: dict[int, list[tuple[int, WebSocket]]] = {}
        # Map of user_id -> websocket for direct notifications
        self.user_connections: dict[int, WebSocket] = {}
    
    async def connect(self, websocket: WebSocket, user_id: int, channel_id: Optional[int] = None):
        await websocket.accept()
        self.user_connections[user_id] = websocket
        if channel_id:
            if channel_id not in self.channel_connections:
                self.channel_connections[channel_id] = []
            self.channel_connections[channel_id].append((user_id, websocket))
    
    def disconnect(self, user_id: int, channel_id: Optional[int] = None):
        if user_id in self.user_connections:
            del self.user_connections[user_id]
        if channel_id and channel_id in self.channel_connections:
            self.channel_connections[channel_id] = [
                (uid, ws) for uid, ws in self.channel_connections[channel_id]
                if uid != user_id
            ]
    
    async def broadcast_to_channel(self, channel_id: int, message: dict, exclude_user_id: Optional[int] = None):
        """Send message to all users in a channel."""
        if channel_id not in self.channel_connections:
            return
        
        disconnected = []
        for user_id, websocket in self.channel_connections[channel_id]:
            if exclude_user_id and user_id == exclude_user_id:
                continue
            try:
                await websocket.send_json(message)
            except Exception as e:
                logger.error(f"Error sending to user {user_id}: {e}")
                disconnected.append(user_id)
        
        # Clean up disconnected
        for uid in disconnected:
            self.disconnect(uid, channel_id)
    
    async def send_to_user(self, user_id: int, message: dict):
        """Send message directly to a user."""
        if user_id in self.user_connections:
            try:
                await self.user_connections[user_id].send_json(message)
            except Exception as e:
                logger.error(f"Error sending to user {user_id}: {e}")
                self.disconnect(user_id)
    
    async def broadcast_to_users(self, user_ids: List[int], message: dict):
        """Send message to multiple users."""
        for user_id in user_ids:
            await self.send_to_user(user_id, message)


manager = TeamChatManager()


# ============== Helper Functions ==============

def get_or_create_direct_channel(db: Session, user1_id: int, user2_id: int) -> TeamChannel:
    """Get or create a direct message channel between two users."""
    # Look for existing direct channel
    existing = db.query(TeamChannel).filter(
        TeamChannel.channel_type == ChannelType.direct,
        TeamChannel.members.any(User.id == user1_id),
        TeamChannel.members.any(User.id == user2_id)
    ).first()
    
    if existing:
        return existing
    
    # Create new direct channel
    user1 = db.query(User).get(user1_id)
    user2 = db.query(User).get(user2_id)
    
    if not user1 or not user2:
        raise HTTPException(status_code=404, detail="User not found")
    
    channel = TeamChannel(
        channel_type=ChannelType.direct,
        created_by=user1_id,
        is_private=True
    )
    channel.members = [user1, user2]
    db.add(channel)
    db.commit()
    db.refresh(channel)
    return channel


def serialize_channel(channel: TeamChannel, current_user_id: int, unread_count: int = 0) -> dict:
    """Serialize channel for API response."""
    other_members = [m for m in channel.members if m.id != current_user_id]
    
    return {
        "id": channel.id,
        "name": channel.name if channel.channel_type != ChannelType.direct else (
            other_members[0].full_name if other_members else "Direct Message"
        ),
        "description": channel.description,
        "channel_type": channel.channel_type.value,
        "department": channel.department,
        "is_private": channel.is_private,
        "is_active": channel.is_active,
        "created_at": channel.created_at.isoformat(),
        "last_message_at": channel.last_message_at.isoformat() if channel.last_message_at else None,
        "unread_count": unread_count,
        "members": [
            {
                "id": m.id,
                "full_name": m.full_name,
                "email": m.email,
                "avatar_url": m.avatar,  # User model uses 'avatar' field
                "role": m.role.name if m.role else None
            }
            for m in channel.members
        ],
        "last_message": serialize_message(channel.messages[-1]) if channel.messages else None
    }


def serialize_message(message: TeamMessage) -> dict:
    """Serialize message for API response."""
    return {
        "id": message.id,
        "channel_id": message.channel_id,
        "sender_id": message.sender_id,
        "sender": {
            "id": message.sender.id,
            "full_name": message.sender.full_name,
            "avatar_url": message.sender.avatar,  # User model uses 'avatar' field
            "role": message.sender.role.name if message.sender.role else None
        } if message.sender else None,
        "content": message.content if not message.is_deleted else "[Message deleted]",
        "priority": message.priority.value,
        "reply_to_id": message.reply_to_id,
        "reference_type": message.reference_type,
        "reference_id": message.reference_id,
        "is_edited": message.is_edited,
        "is_deleted": message.is_deleted,
        "created_at": message.created_at.isoformat(),
        "edited_at": message.edited_at.isoformat() if message.edited_at else None
    }


# ============== Channel Endpoints ==============

@router.get('/channels')
async def get_my_channels(
    current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
    db: Session = Depends(get_db)
):
    """Get all channels the current user is a member of."""
    channels = db.query(TeamChannel).options(
        joinedload(TeamChannel.members),
        joinedload(TeamChannel.messages).joinedload(TeamMessage.sender)
    ).filter(
        TeamChannel.is_active == True,
        TeamChannel.members.any(User.id == current_user.id)
    ).order_by(desc(TeamChannel.last_message_at)).all()
    
    result = []
    for channel in channels:
        # Count unread messages
        last_read = db.execute(
            team_channel_members.select().where(
                and_(
                    team_channel_members.c.channel_id == channel.id,
                    team_channel_members.c.user_id == current_user.id
                )
            )
        ).first()
        
        unread_count = 0
        if last_read and last_read.last_read_at:
            unread_count = db.query(func.count(TeamMessage.id)).filter(
                TeamMessage.channel_id == channel.id,
                TeamMessage.created_at > last_read.last_read_at,
                TeamMessage.sender_id != current_user.id,
                TeamMessage.is_deleted == False
            ).scalar()
        else:
            unread_count = db.query(func.count(TeamMessage.id)).filter(
                TeamMessage.channel_id == channel.id,
                TeamMessage.sender_id != current_user.id,
                TeamMessage.is_deleted == False
            ).scalar()
        
        result.append(serialize_channel(channel, current_user.id, unread_count))
    
    return {"success": True, "data": result}


@router.post('/channels')
async def create_channel(
    channel_data: ChannelCreate,
    current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
    db: Session = Depends(get_db)
):
    """Create a new channel."""
    # Only admins can create department or announcement channels
    if channel_data.channel_type in [ChannelType.department, ChannelType.announcement]:
        if current_user.role.name != 'admin':
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Only admins can create department or announcement channels"
            )
    
    channel = TeamChannel(
        name=channel_data.name,
        description=channel_data.description,
        channel_type=channel_data.channel_type,
        department=channel_data.department,
        is_private=channel_data.is_private,
        created_by=current_user.id
    )
    
    # Add creator as member
    channel.members.append(current_user)
    
    # Add other members
    if channel_data.member_ids:
        members = db.query(User).filter(User.id.in_(channel_data.member_ids)).all()
        for member in members:
            if member not in channel.members:
                channel.members.append(member)
    
    db.add(channel)
    db.commit()
    db.refresh(channel)
    
    logger.info(f"Channel created: {channel.id} by user {current_user.id}")
    
    return {"success": True, "data": serialize_channel(channel, current_user.id)}


@router.get('/channels/{channel_id}')
async def get_channel(
    channel_id: int,
    current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
    db: Session = Depends(get_db)
):
    """Get channel details."""
    channel = db.query(TeamChannel).options(
        joinedload(TeamChannel.members)
    ).filter(
        TeamChannel.id == channel_id,
        TeamChannel.is_active == True
    ).first()
    
    if not channel:
        raise HTTPException(status_code=404, detail="Channel not found")
    
    # Check membership
    if current_user not in channel.members and current_user.role.name != 'admin':
        raise HTTPException(status_code=403, detail="Not a member of this channel")
    
    return {"success": True, "data": serialize_channel(channel, current_user.id)}


@router.put('/channels/{channel_id}')
async def update_channel(
    channel_id: int,
    channel_data: ChannelUpdate,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Update channel settings."""
    channel = db.query(TeamChannel).filter(TeamChannel.id == channel_id).first()
    
    if not channel:
        raise HTTPException(status_code=404, detail="Channel not found")
    
    # Only creator or admin can update
    if channel.created_by != current_user.id and current_user.role.name != 'admin':
        raise HTTPException(status_code=403, detail="Not authorized to update this channel")
    
    if channel_data.name is not None:
        channel.name = channel_data.name
    if channel_data.description is not None:
        channel.description = channel_data.description
    if channel_data.is_private is not None:
        channel.is_private = channel_data.is_private
    
    db.commit()
    db.refresh(channel)
    
    return {"success": True, "data": serialize_channel(channel, current_user.id)}


@router.post('/channels/{channel_id}/members')
async def add_channel_members(
    channel_id: int,
    member_ids: List[int],
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Add members to a channel."""
    channel = db.query(TeamChannel).options(
        joinedload(TeamChannel.members)
    ).filter(TeamChannel.id == channel_id).first()
    
    if not channel:
        raise HTTPException(status_code=404, detail="Channel not found")
    
    # Check authorization
    if channel.created_by != current_user.id and current_user.role.name != 'admin':
        raise HTTPException(status_code=403, detail="Not authorized")
    
    new_members = db.query(User).filter(User.id.in_(member_ids)).all()
    for member in new_members:
        if member not in channel.members:
            channel.members.append(member)
    
    db.commit()
    
    return {"success": True, "message": f"Added {len(new_members)} members"}


@router.delete('/channels/{channel_id}/members/{user_id}')
async def remove_channel_member(
    channel_id: int,
    user_id: int,
    current_user: User = Depends(authorize_roles('admin', 'staff')),
    db: Session = Depends(get_db)
):
    """Remove a member from a channel."""
    channel = db.query(TeamChannel).options(
        joinedload(TeamChannel.members)
    ).filter(TeamChannel.id == channel_id).first()
    
    if not channel:
        raise HTTPException(status_code=404, detail="Channel not found")
    
    # Check authorization
    if channel.created_by != current_user.id and current_user.role.name != 'admin':
        if user_id != current_user.id:  # Users can leave themselves
            raise HTTPException(status_code=403, detail="Not authorized")
    
    member_to_remove = next((m for m in channel.members if m.id == user_id), None)
    if member_to_remove:
        channel.members.remove(member_to_remove)
        db.commit()
    
    return {"success": True, "message": "Member removed"}


# ============== Message Endpoints ==============

@router.get('/channels/{channel_id}/messages')
async def get_channel_messages(
    channel_id: int,
    limit: int = Query(50, ge=1, le=100),
    before_id: Optional[int] = None,
    current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
    db: Session = Depends(get_db)
):
    """Get messages from a channel."""
    channel = db.query(TeamChannel).filter(
        TeamChannel.id == channel_id,
        TeamChannel.members.any(User.id == current_user.id)
    ).first()
    
    if not channel:
        raise HTTPException(status_code=404, detail="Channel not found or not a member")
    
    query = db.query(TeamMessage).options(
        joinedload(TeamMessage.sender)
    ).filter(TeamMessage.channel_id == channel_id)
    
    if before_id:
        query = query.filter(TeamMessage.id < before_id)
    
    messages = query.order_by(desc(TeamMessage.created_at)).limit(limit).all()
    
    # Mark as read
    db.execute(
        team_channel_members.update().where(
            and_(
                team_channel_members.c.channel_id == channel_id,
                team_channel_members.c.user_id == current_user.id
            )
        ).values(last_read_at=datetime.utcnow())
    )
    db.commit()
    
    return {
        "success": True, 
        "data": [serialize_message(m) for m in reversed(messages)]
    }


@router.post('/channels/{channel_id}/messages')
async def send_message(
    channel_id: int,
    message_data: MessageCreate,
    current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
    db: Session = Depends(get_db)
):
    """Send a message to a channel."""
    channel = db.query(TeamChannel).options(
        joinedload(TeamChannel.members)
    ).filter(
        TeamChannel.id == channel_id,
        TeamChannel.members.any(User.id == current_user.id)
    ).first()
    
    if not channel:
        raise HTTPException(status_code=404, detail="Channel not found or not a member")
    
    # Check if announcement channel (only admins can post)
    if channel.channel_type == ChannelType.announcement and current_user.role.name != 'admin':
        raise HTTPException(status_code=403, detail="Only admins can post in announcement channels")
    
    message = TeamMessage(
        channel_id=channel_id,
        sender_id=current_user.id,
        content=message_data.content,
        priority=message_data.priority,
        reply_to_id=message_data.reply_to_id,
        reference_type=message_data.reference_type,
        reference_id=message_data.reference_id
    )
    
    db.add(message)
    channel.last_message_at = datetime.utcnow()
    db.commit()
    db.refresh(message)
    
    # Broadcast to channel members via WebSocket
    serialized = serialize_message(message)
    await manager.broadcast_to_channel(channel_id, {
        "type": "new_message",
        "data": serialized
    }, exclude_user_id=current_user.id)
    
    # Also notify users not connected to channel
    member_ids = [m.id for m in channel.members if m.id != current_user.id]
    await manager.broadcast_to_users(member_ids, {
        "type": "new_message_notification",
        "data": {
            "channel_id": channel_id,
            "channel_name": channel.name,
            "message": serialized
        }
    })
    
    return {"success": True, "data": serialized}


@router.put('/messages/{message_id}')
async def edit_message(
    message_id: int,
    message_data: MessageUpdate,
    current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
    db: Session = Depends(get_db)
):
    """Edit a message."""
    message = db.query(TeamMessage).filter(TeamMessage.id == message_id).first()
    
    if not message:
        raise HTTPException(status_code=404, detail="Message not found")
    
    if message.sender_id != current_user.id and current_user.role.name != 'admin':
        raise HTTPException(status_code=403, detail="Not authorized to edit this message")
    
    message.content = message_data.content
    message.is_edited = True
    message.edited_at = datetime.utcnow()
    
    db.commit()
    db.refresh(message)
    
    # Broadcast update
    await manager.broadcast_to_channel(message.channel_id, {
        "type": "message_edited",
        "data": serialize_message(message)
    })
    
    return {"success": True, "data": serialize_message(message)}


@router.delete('/messages/{message_id}')
async def delete_message(
    message_id: int,
    current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
    db: Session = Depends(get_db)
):
    """Delete a message (soft delete)."""
    message = db.query(TeamMessage).filter(TeamMessage.id == message_id).first()
    
    if not message:
        raise HTTPException(status_code=404, detail="Message not found")
    
    if message.sender_id != current_user.id and current_user.role.name != 'admin':
        raise HTTPException(status_code=403, detail="Not authorized to delete this message")
    
    message.is_deleted = True
    message.deleted_at = datetime.utcnow()
    
    db.commit()
    
    # Broadcast deletion
    await manager.broadcast_to_channel(message.channel_id, {
        "type": "message_deleted",
        "data": {"id": message_id, "channel_id": message.channel_id}
    })
    
    return {"success": True, "message": "Message deleted"}


# ============== Direct Message Endpoints ==============

@router.post('/direct')
async def send_direct_message(
    dm_data: DirectMessageCreate,
    current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
    db: Session = Depends(get_db)
):
    """Send a direct message to another user."""
    # Verify recipient exists and is staff/admin/housekeeping
    recipient = db.query(User).options(
        joinedload(User.role)
    ).filter(User.id == dm_data.recipient_id).first()
    
    if not recipient:
        raise HTTPException(status_code=404, detail="Recipient not found")
    
    if recipient.role.name not in ['admin', 'staff', 'housekeeping']:
        raise HTTPException(status_code=400, detail="Can only message staff members")
    
    # Get or create direct channel
    channel = get_or_create_direct_channel(db, current_user.id, dm_data.recipient_id)
    
    # Send message
    message = TeamMessage(
        channel_id=channel.id,
        sender_id=current_user.id,
        content=dm_data.content,
        priority=dm_data.priority
    )
    
    db.add(message)
    channel.last_message_at = datetime.utcnow()
    db.commit()
    db.refresh(message)
    
    serialized = serialize_message(message)
    
    # Notify recipient
    await manager.send_to_user(dm_data.recipient_id, {
        "type": "new_direct_message",
        "data": {
            "channel_id": channel.id,
            "sender": {
                "id": current_user.id,
                "full_name": current_user.full_name,
                "avatar_url": current_user.avatar  # User model uses 'avatar' field
            },
            "message": serialized
        }
    })
    
    return {"success": True, "data": {"channel_id": channel.id, "message": serialized}}


# ============== User/Presence Endpoints ==============

@router.get('/users')
async def get_team_users(
    role: Optional[str] = None,
    current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
    db: Session = Depends(get_db)
):
    """Get all team users (admin, staff, housekeeping) for messaging."""
    # Get role IDs for team roles to ensure proper filtering
    team_roles = db.query(Role).filter(
        Role.name.in_(['admin', 'staff', 'housekeeping'])
    ).all()
    team_role_ids = [r.id for r in team_roles]
    
    if not team_role_ids:
        logger.error('No team roles found in database')
        return {"success": True, "data": []}
    
    # Build query with proper role filtering
    query = db.query(User).options(
        joinedload(User.role),
        joinedload(User.presence)
    ).filter(
        User.role_id.in_(team_role_ids),
        User.is_active == True,
        User.id != current_user.id
    )
    
    if role:
        role_obj = db.query(Role).filter(Role.name == role).first()
        if role_obj:
            query = query.filter(User.role_id == role_obj.id)
    
    users = query.order_by(User.full_name).all()
    
    # Debug: Check total count of team users (including inactive) for troubleshooting
    if not users:
        # Check if there are any team users at all (including inactive)
        all_team_users = db.query(User).filter(
            User.role_id.in_(team_role_ids),
            User.id != current_user.id
        ).count()
        
        active_team_users = db.query(User).filter(
            User.role_id.in_(team_role_ids),
            User.is_active == True,
            User.id != current_user.id
        ).count()
        
        logger.warning(
            f'No active team users found for user {current_user.id} ({current_user.email}). '
            f'Total team users (including inactive): {all_team_users}, '
            f'Active team users: {active_team_users}. '
            f'Query filters: role={role}, is_active=True, excluded_user_id={current_user.id}, '
            f'team_role_ids={team_role_ids}'
        )
    
    return {
        "success": True,
        "data": [
            {
                "id": u.id,
                "full_name": u.full_name,
                "email": u.email,
                "avatar_url": u.avatar,  # User model uses 'avatar' field
                "role": u.role.name if u.role else None,
                "status": u.presence.status if u.presence else 'offline',
                "last_seen": u.presence.last_seen_at.isoformat() if u.presence and u.presence.last_seen_at else None
            }
            for u in users
        ]
    }


@router.put('/presence')
async def update_presence(
    presence_data: PresenceUpdate,
    current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
    db: Session = Depends(get_db)
):
    """Update user presence status."""
    presence = db.query(UserPresence).filter(UserPresence.user_id == current_user.id).first()
    
    if not presence:
        presence = UserPresence(user_id=current_user.id)
        db.add(presence)
    
    presence.status = presence_data.status
    presence.custom_status = presence_data.custom_status
    presence.last_seen_at = datetime.utcnow()
    presence.last_active_at = datetime.utcnow()
    
    db.commit()
    
    return {"success": True, "message": "Presence updated"}


# ============== Department Channels ==============

@router.post('/departments/init')
async def initialize_department_channels(
    current_user: User = Depends(authorize_roles('admin')),
    db: Session = Depends(get_db)
):
    """Initialize default department channels (admin only)."""
    departments = [
        {"name": "Housekeeping Team", "department": "housekeeping", "description": "Channel for housekeeping coordination"},
        {"name": "Front Desk", "department": "front-desk", "description": "Front desk staff communication"},
        {"name": "Management", "department": "management", "description": "Management team discussions"},
        {"name": "Announcements", "department": "all", "description": "Hotel-wide announcements"}
    ]
    
    created = []
    for dept in departments:
        existing = db.query(TeamChannel).filter(
            TeamChannel.department == dept["department"],
            TeamChannel.channel_type == ChannelType.department
        ).first()
        
        if not existing:
            channel = TeamChannel(
                name=dept["name"],
                description=dept["description"],
                channel_type=ChannelType.department if dept["department"] != "all" else ChannelType.announcement,
                department=dept["department"],
                created_by=current_user.id,
                is_private=False
            )
            db.add(channel)
            created.append(dept["name"])
    
    db.commit()
    
    return {"success": True, "message": f"Created channels: {', '.join(created)}" if created else "All channels already exist"}


@router.post('/departments/{department}/join')
async def join_department_channel(
    department: str,
    current_user: User = Depends(authorize_roles('admin', 'staff', 'housekeeping')),
    db: Session = Depends(get_db)
):
    """Join a department channel."""
    channel = db.query(TeamChannel).options(
        joinedload(TeamChannel.members)
    ).filter(
        TeamChannel.department == department,
        TeamChannel.channel_type.in_([ChannelType.department, ChannelType.announcement])
    ).first()
    
    if not channel:
        raise HTTPException(status_code=404, detail="Department channel not found")
    
    if current_user not in channel.members:
        channel.members.append(current_user)
        db.commit()
    
    return {"success": True, "data": serialize_channel(channel, current_user.id)}


# ============== WebSocket Endpoint ==============

@router.websocket('/ws')
async def websocket_endpoint(
    websocket: WebSocket,
    db: Session = Depends(get_db)
):
    """WebSocket endpoint for real-time team chat."""
    user_id = None
    try:
        await websocket.accept()
        
        # Wait for authentication message
        auth_data = await websocket.receive_json()
        if auth_data.get("type") != "auth":
            await websocket.close(code=4001, reason="Authentication required")
            return
        
        # In production, verify JWT token here
        user_id = auth_data.get("user_id")
        if not user_id:
            await websocket.close(code=4001, reason="Invalid authentication")
            return
        
        # Verify user exists and has correct role
        user = db.query(User).options(joinedload(User.role)).filter(User.id == user_id).first()
        if not user or user.role.name not in ['admin', 'staff', 'housekeeping']:
            await websocket.close(code=4003, reason="Unauthorized")
            return
        
        # Update presence
        presence = db.query(UserPresence).filter(UserPresence.user_id == user_id).first()
        if not presence:
            presence = UserPresence(user_id=user_id, status='online')
            db.add(presence)
        else:
            presence.status = 'online'
            presence.last_seen_at = datetime.utcnow()
        db.commit()
        
        # Store connection
        manager.user_connections[user_id] = websocket
        
        await websocket.send_json({"type": "connected", "user_id": user_id})
        
        # Listen for messages
        while True:
            data = await websocket.receive_json()
            msg_type = data.get("type")
            
            if msg_type == "join_channel":
                channel_id = data.get("channel_id")
                if channel_id not in manager.channel_connections:
                    manager.channel_connections[channel_id] = []
                manager.channel_connections[channel_id].append((user_id, websocket))
                await websocket.send_json({"type": "joined_channel", "channel_id": channel_id})
            
            elif msg_type == "leave_channel":
                channel_id = data.get("channel_id")
                manager.disconnect(user_id, channel_id)
                await websocket.send_json({"type": "left_channel", "channel_id": channel_id})
            
            elif msg_type == "typing":
                channel_id = data.get("channel_id")
                await manager.broadcast_to_channel(channel_id, {
                    "type": "user_typing",
                    "data": {"user_id": user_id, "channel_id": channel_id}
                }, exclude_user_id=user_id)
            
            elif msg_type == "ping":
                await websocket.send_json({"type": "pong"})
                # Update presence
                presence = db.query(UserPresence).filter(UserPresence.user_id == user_id).first()
                if presence:
                    presence.last_active_at = datetime.utcnow()
                    db.commit()
    
    except WebSocketDisconnect:
        logger.info(f"User {user_id} disconnected from team chat")
    except Exception as e:
        logger.error(f"WebSocket error: {e}")
    finally:
        if user_id:
            manager.disconnect(user_id)
            # Update presence to offline
            presence = db.query(UserPresence).filter(UserPresence.user_id == user_id).first()
            if presence:
                presence.status = 'offline'
                presence.last_seen_at = datetime.utcnow()
                db.commit()

