import asyncio
import json
import logging
from datetime import datetime, timedelta
from typing import List, Optional, Dict, Set
import math

import httpx
from fastapi import BackgroundTasks, Depends, FastAPI, HTTPException, Query, status, WebSocket, WebSocketDisconnect
from fastapi.middleware.cors import CORSMiddleware
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from sqlalchemy import func, select, update, desc, and_, or_
from sqlalchemy.ext.asyncio import AsyncSession

from services.emergency_service.models import EmergencyAlert, EmergencyResponse, EmergencyReport, SafetyCheck
from services.emergency_service.schemas import (
    AlertStatus,
    AlertType,
    EmergencyAlertCreate,
    EmergencyAlertResponse,
    EmergencyAlertUpdate,
    EmergencyResponseCreate,
    EmergencyResponseResponse,
    EmergencyStatistics,
    EmergencyReportCreate,
    EmergencyReportResponse,
    NearbyAlertResponse,
    SafetyCheckCreate,
    SafetyCheckResponse,
    EmergencyEventDetails,
    UserInfo,
)
# Import User model from user_service
from services.user_service.models import User

from shared.auth import get_current_user_from_token
from shared.config import settings
from shared.database import AsyncSessionLocal

# Database dependency
async def get_db():
    async with AsyncSessionLocal() as session:
        try:
            yield session
        except Exception:
            await session.rollback()
            raise
        finally:
            await session.close()

app = FastAPI(
    title="Emergency Service", 
    version="1.0.0",
    description="""
    Emergency Service API для системы безопасности женщин.
    
    ## Авторизация
    Все эндпоинты требуют Bearer токен в заголовке Authorization.
    
    Получить токен можно через User Service:
    ```
    POST /api/v1/auth/login
    ```
    
    Использование токена:
    ```
    Authorization: Bearer <your_jwt_token>
    ```
    """,
    contact={
        "name": "Women's Safety App Team",
        "url": "https://example.com/support",
        "email": "support@example.com",
    },
)

# Configure logger
logger = logging.getLogger(__name__)

# Security scheme for OpenAPI documentation
security = HTTPBearer(
    scheme_name="JWT Bearer Token",
    description="JWT Bearer токен для авторизации. Получите токен через User Service /api/v1/auth/login"
)

# CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.CORS_ORIGINS,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


class WebSocketManager:
    """Manage WebSocket connections for emergency notifications"""
    
    def __init__(self):
        self.active_connections: Dict[int, WebSocket] = {}
        self.connection_info: Dict[int, dict] = {}  # Дополнительная информация о подключениях
    
    async def connect(self, websocket: WebSocket, user_id: int):
        """Connect a WebSocket for a specific user"""
        await websocket.accept()
        self.active_connections[user_id] = websocket
        
        # Сохраняем информацию о подключении
        self.connection_info[user_id] = {
            "connected_at": datetime.now(),
            "client_host": websocket.client.host if websocket.client else "unknown",
            "client_port": websocket.client.port if websocket.client else 0,
            "last_ping": datetime.now(),
            "message_count": 0,
            "status": "connected"
        }
        
        print(f"WebSocket connected for user {user_id} from {websocket.client}")
        
        # Отправляем приветственное сообщение
        await self.send_personal_message(json.dumps({
            "type": "connection_established",
            "message": "WebSocket connection established successfully",
            "user_id": user_id,
            "timestamp": datetime.now().isoformat()
        }), user_id)
    
    def disconnect(self, user_id: int):
        """Disconnect a WebSocket for a specific user"""
        if user_id in self.active_connections:
            del self.active_connections[user_id]
            
        if user_id in self.connection_info:
            self.connection_info[user_id]["status"] = "disconnected"
            self.connection_info[user_id]["disconnected_at"] = datetime.now()
            
        print(f"WebSocket disconnected for user {user_id}")
    
    async def send_personal_message(self, message: str, user_id: int):
        """Send a message to a specific user"""
        if user_id in self.active_connections:
            websocket = self.active_connections[user_id]
            try:
                await websocket.send_text(message)
                # Обновляем статистику
                if user_id in self.connection_info:
                    self.connection_info[user_id]["message_count"] += 1
                    self.connection_info[user_id]["last_ping"] = datetime.now()
            except Exception as e:
                print(f"Error sending message to user {user_id}: {e}")
                self.disconnect(user_id)
    
    async def broadcast_alert(self, alert_data: dict, user_ids: Optional[List[int]] = None):
        """Broadcast alert to specific users or all connected users"""
        message = json.dumps({
            "type": "emergency_alert",
            "data": alert_data
        })
        
        target_users = user_ids if user_ids else list(self.active_connections.keys())
        
        for user_id in target_users:
            await self.send_personal_message(message, user_id)
    
    async def send_alert_update(self, alert_id: int, alert_data: dict, user_ids: Optional[List[int]] = None):
        """Send alert update to specific users"""
        message = json.dumps({
            "type": "alert_update", 
            "alert_id": alert_id,
            "data": alert_data
        })
        
        target_users = user_ids if user_ids else list(self.active_connections.keys())
        
        for user_id in target_users:
            await self.send_personal_message(message, user_id)
    
    def get_connected_users_count(self) -> int:
        """Получить количество подключенных пользователей"""
        return len(self.active_connections)
    
    def get_connected_users_list(self) -> List[int]:
        """Получить список ID подключенных пользователей"""
        return list(self.active_connections.keys())
    
    def get_connection_info(self, user_id: Optional[int] = None) -> dict:
        """Получить информацию о подключениях"""
        if user_id:
            return self.connection_info.get(user_id, {})
        
        # Возвращаем общую статистику
        active_count = len(self.active_connections)
        total_messages = sum(info.get("message_count", 0) for info in self.connection_info.values())
        
        connection_details = {}
        for user_id, info in self.connection_info.items():
            if info.get("status") == "connected":
                connected_at = info.get("connected_at")
                last_ping = info.get("last_ping")
                
                connection_details[user_id] = {
                    "connected_at": connected_at.isoformat() if connected_at else None,
                    "client_host": info.get("client_host"),
                    "client_port": info.get("client_port"),
                    "last_ping": last_ping.isoformat() if last_ping else None,
                    "message_count": info.get("message_count", 0),
                    "status": info.get("status"),
                    "duration_seconds": int((datetime.now() - connected_at).total_seconds()) 
                        if connected_at and info.get("status") == "connected" else None
                }
        
        return {
            "active_connections": active_count,
            "total_messages_sent": total_messages,
            "connected_users": list(self.active_connections.keys()),
            "connection_details": connection_details
        }
    
    async def ping_all_connections(self):
        """Проверить все WebSocket подключения"""
        disconnected_users = []
        
        for user_id, websocket in list(self.active_connections.items()):
            try:
                ping_message = json.dumps({
                    "type": "ping",
                    "timestamp": datetime.now().isoformat()
                })
                await websocket.send_text(ping_message)
                
                # Обновляем время последнего пинга
                if user_id in self.connection_info:
                    self.connection_info[user_id]["last_ping"] = datetime.now()
                    
            except Exception as e:
                print(f"Connection lost for user {user_id}: {e}")
                disconnected_users.append(user_id)
        
        # Удаляем неактивные подключения
        for user_id in disconnected_users:
            self.disconnect(user_id)
        
        return {
            "active_connections": len(self.active_connections),
            "disconnected_users": disconnected_users,
            "ping_time": datetime.now().isoformat()
        }


# Global WebSocket manager instance
ws_manager = WebSocketManager()


async def get_current_user(
    credentials: HTTPAuthorizationCredentials = Depends(security),
    db: AsyncSession = Depends(get_db),
):
    """
    Get current user from JWT Bearer token for OpenAPI documentation.
    
    Требует Bearer токен в заголовке Authorization:
    Authorization: Bearer <your_jwt_token>
    
    Returns simplified User object to avoid SQLAlchemy issues.
    """
    try:
        # Получаем данные пользователя из токена напрямую
        from shared.auth import verify_token
        user_data = verify_token(credentials.credentials)
        
        if user_data is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Could not validate credentials",
                headers={"WWW-Authenticate": "Bearer"},
            )
        
        # Возвращаем упрощенный объект пользователя
        return type('User', (), {
            'id': user_data["user_id"],
            'email': user_data.get("email", "unknown@example.com"),
            'username': user_data.get("username", f"user_{user_data['user_id']}")
        })()
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Authentication failed: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Could not validate credentials",
            headers={"WWW-Authenticate": "Bearer"},
        )


async def get_current_user_websocket(token: str):
    """Get current user from WebSocket token - PRODUCTION READY"""
    try:
        from shared.auth import verify_token
        import logging
        
        # Логируем попытку аутентификации (без токена в логах!)
        print(f"🔐 WebSocket auth: Attempting authentication for token length={len(token)}")
        
        # ВАЖНО: Никаких заглушек! Только настоящие JWT токены
        if token.startswith("temp_token") or token.startswith("test_token"):
            print(f"❌ WebSocket auth: REJECTED - Temporary tokens not allowed in production!")
            print(f"❌ Token prefix: {token[:20]}...")
            return None
        
        # Проверяем JWT токен
        user_data = verify_token(token)
        if not user_data:
            print(f"❌ WebSocket auth: Invalid or expired JWT token")
            return None
            
        print(f"✅ WebSocket auth: JWT token valid for user_id={user_data['user_id']}, email={user_data.get('email', 'N/A')}")
        
        # Создаем объект пользователя из токена
        class AuthenticatedUser:
            def __init__(self, user_id, email):
                self.id = user_id
                self.email = email
                    
        return AuthenticatedUser(user_data['user_id'], user_data.get('email', f'user_{user_data["user_id"]}'))
        
    except Exception as e:
        print(f"❌ WebSocket auth error: {e}")
        return None


def calculate_distance(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
    """Calculate distance between two points in kilometers using Haversine formula."""
    # Convert latitude and longitude from degrees to radians
    lat1, lon1, lat2, lon2 = map(math.radians, [lat1, lon1, lat2, lon2])
    
    # Haversine formula
    dlat = lat2 - lat1
    dlon = lon2 - lon1
    a = math.sin(dlat/2)**2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon/2)**2
    c = 2 * math.asin(math.sqrt(a))
    
    # Radius of earth in kilometers
    r = 6371
    return c * r

@app.get("/health")
async def health_check():
    """Health check endpoint"""
    return {"status": "healthy", "service": "emergency_service"}


@app.get("/alerts")
async def get_alerts_public(db: AsyncSession = Depends(get_db)):
    """Get all emergency alerts (public endpoint for testing)"""
    result = await db.execute(
        select(EmergencyAlert)
        .order_by(EmergencyAlert.created_at.desc())
        .limit(50)
    )
    alerts = result.scalars().all()
    return [EmergencyAlertResponse.model_validate(alert) for alert in alerts]


@app.post("/alerts")
async def create_alert_public(
    alert_data: dict,
    db: AsyncSession = Depends(get_db)
):
    """Create emergency alert (public endpoint for testing)"""
    try:
        new_alert = EmergencyAlert(
            user_id=alert_data.get("user_id", 1),
            alert_type=alert_data.get("alert_type", "medical"),
            latitude=alert_data.get("latitude", 0),
            longitude=alert_data.get("longitude", 0),
            title=alert_data.get("title", "Emergency Alert"),
            description=alert_data.get("description", ""),
            is_resolved=False
        )
        db.add(new_alert)
        await db.commit()
        await db.refresh(new_alert)
        return {"status": "success", "alert_id": new_alert.id}
    except Exception as e:
        await db.rollback()
        return {"status": "error", "detail": str(e)}


@app.websocket("/api/v1/emergency/ws/{user_id}")
async def websocket_endpoint(websocket: WebSocket, user_id: str):
    """WebSocket endpoint for emergency notifications"""
    
    print(f"🔌 WebSocket connection attempt from {websocket.client}")
    print(f"📝 user_id: {user_id}")
    print(f"🔗 Query params: {dict(websocket.query_params)}")
    
    # Get token from query parameter
    token = websocket.query_params.get("token")
    print(f"🎫 Token received: {token}")
    
    if not token:
        print("❌ No token provided, closing connection")
        await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
        return
    
    # Authenticate user
    authenticated_user = await get_current_user_websocket(token)
    if not authenticated_user:
        print("❌ Authentication failed, closing connection")
        await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
        return
    
    # Get user ID as integer - authenticated_user is an instance with id attribute
    auth_user_id = authenticated_user.id
    print(f"✅ User authenticated: {authenticated_user.email} (ID: {auth_user_id})")
    
    # Verify user_id matches authenticated user
    try:
        if int(user_id) != auth_user_id:
            await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
            return
    except ValueError:
        if user_id != "current_user_id":
            await websocket.close(code=status.WS_1008_POLICY_VIOLATION) 
            return
        # Handle special case where client uses 'current_user_id' as placeholder
        user_id = str(auth_user_id)
    
    # Connect WebSocket
    await ws_manager.connect(websocket, auth_user_id)
    
    try:
        # Send initial connection message
        await ws_manager.send_personal_message(
            json.dumps({
                "type": "connection_established",
                "message": "Connected to emergency notifications",
                "user_id": auth_user_id
            }),
            auth_user_id
        )
        
        # Keep connection alive and listen for messages
        while True:
            try:
                # Wait for messages (ping/pong, etc.)
                data = await websocket.receive_text()
                message = json.loads(data)
                
                # Handle different message types
                if message.get("type") == "ping":
                    await ws_manager.send_personal_message(
                        json.dumps({"type": "pong"}), 
                        auth_user_id
                    )
                
            except WebSocketDisconnect:
                break
            except Exception as e:
                print(f"WebSocket error: {e}")
                break
                
    except WebSocketDisconnect:
        pass
    finally:
        ws_manager.disconnect(auth_user_id)


async def get_nearby_users(
    latitude: float, longitude: float, radius_km: float = 1.0
) -> List[dict]:
    """Get users within radius using Location Service"""
    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(
                f"http://localhost:8003/api/v1/nearby-users",
                params={
                    "latitude": latitude,
                    "longitude": longitude,
                    "radius_km": radius_km,
                },
                timeout=5.0,
            )
            if response.status_code == 200:
                return response.json()
            return []
        except Exception:
            return []


async def send_websocket_notifications_to_nearby_users(alert, nearby_users: List[dict]) -> int:
    """Send real-time WebSocket notifications to nearby users who are online"""
    online_count = 0
    
    # Create notification message
    notification = {
        "type": "emergency_alert",
        "alert_id": alert.id,
        "alert_type": alert.alert_type,
        "latitude": alert.latitude,
        "longitude": alert.longitude,
        "address": alert.address,
        "message": alert.message or "Экстренная ситуация рядом с вами!",
        "created_at": alert.created_at.isoformat(),
        "distance_km": None  # Will be calculated per user
    }
    
    print(f"🔔 Sending WebSocket notifications to {len(nearby_users)} nearby users")
    
    for user in nearby_users:
        user_id = user.get("user_id")
        distance = user.get("distance_km", 0)
        
        # Update distance in notification
        notification["distance_km"] = round(distance, 2)
        
        # Check if user has active WebSocket connection
        if user_id in ws_manager.active_connections:
            try:
                # Send notification via WebSocket
                await ws_manager.send_personal_message(
                    json.dumps(notification, ensure_ascii=False, default=str), 
                    user_id
                )
                online_count += 1
                print(f"📡 Sent WebSocket notification to user {user_id} ({distance:.1f}km away)")
            except Exception as e:
                print(f"❌ Failed to send WebSocket to user {user_id}: {e}")
        else:
            print(f"💤 User {user_id} is offline - will receive push notification only")
    
    print(f"✅ WebSocket notifications sent to {online_count}/{len(nearby_users)} online users")
    return online_count


async def send_emergency_notifications(alert_id: int, nearby_users: List[dict]):
    """Send push notifications to nearby users"""
    if not nearby_users:
        return
        
    print(f"📱 Sending push notifications to {len(nearby_users)} users via Notification Service")
    
    async with httpx.AsyncClient() as client:
        try:
            response = await client.post(
                "http://localhost:8005/api/v1/send-emergency-notifications",
                json={
                    "alert_id": alert_id,
                    "user_ids": [user["user_id"] for user in nearby_users],
                    "message": "🚨 Экстренная ситуация рядом с вами! Проверьте приложение.",
                    "title": "Экстренное уведомление"
                },
                timeout=10.0,
            )
            if response.status_code == 200:
                print(f"✅ Push notifications sent successfully")
            else:
                print(f"⚠️ Push notification service responded with {response.status_code}")
        except Exception as e:
            print(f"❌ Failed to send push notifications: {e}")


@app.post("/api/v1/alert", response_model=EmergencyAlertResponse)
async def create_emergency_alert(
    alert_data: EmergencyAlertCreate,
    background_tasks: BackgroundTasks,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Create new emergency alert"""
    # Create alert
    db_alert = EmergencyAlert(
        user_id=current_user.id,
        latitude=alert_data.latitude,
        longitude=alert_data.longitude,
        address=alert_data.address,
        alert_type=alert_data.alert_type,
        message=alert_data.message,
    )

    db.add(db_alert)
    await db.commit()
    await db.refresh(db_alert)

    # Process alert in background
    background_tasks.add_task(
        process_emergency_alert_in_background,
        int(db_alert.id),  # Convert to int explicitly
        alert_data.latitude, 
        alert_data.longitude
    )

    return EmergencyAlertResponse.model_validate(db_alert)


async def process_emergency_alert_in_background(alert_id: int, latitude: float, longitude: float):
    """Process emergency alert - notify nearby users via WebSocket and Push notifications"""
    try:
        print(f"🚨 Processing emergency alert {alert_id} at coordinates ({latitude}, {longitude})")
        
        # Get nearby users within 5km radius
        nearby_users = await get_nearby_users(latitude, longitude, radius_km=5.0)
        print(f"📍 Found {len(nearby_users)} nearby users within 5km radius")

        if nearby_users:
            # Create new database session for background task
            from shared.database import AsyncSessionLocal
            async with AsyncSessionLocal() as db:
                try:
                    # Get full alert details for notifications
                    result = await db.execute(select(EmergencyAlert).filter(EmergencyAlert.id == alert_id))
                    alert = result.scalars().first()
                    
                    if not alert:
                        print(f"❌ Alert {alert_id} not found in database")
                        return

                    # Update alert with notification count
                    await db.execute(
                        update(EmergencyAlert)
                        .where(EmergencyAlert.id == alert_id)
                        .values(notified_users_count=len(nearby_users))
                    )
                    await db.commit()
                    
                    print(f"✅ Updated alert {alert_id} with {len(nearby_users)} notified users")

                    # Send real-time WebSocket notifications to online users
                    online_notifications_sent = await send_websocket_notifications_to_nearby_users(alert, nearby_users)
                    
                    # Send push notifications via notification service
                    await send_emergency_notifications(alert_id, nearby_users)
                    
                    print(f"📱 Sent notifications: {online_notifications_sent} WebSocket + {len(nearby_users)} Push")

                except Exception as e:
                    print(f"❌ Error processing emergency alert: {e}")
                    await db.rollback()
        else:
            print(f"ℹ️ No nearby users found for alert {alert_id}")

    except Exception as e:
        print(f"❌ Error in process_emergency_alert_in_background: {e}")


@app.post("/api/v1/alert/{alert_id}/respond", response_model=EmergencyResponseResponse)
async def respond_to_alert(
    alert_id: int,
    response_data: EmergencyResponseCreate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Respond to emergency alert"""
    # Check if alert exists
    result = await db.execute(select(EmergencyAlert).filter(EmergencyAlert.id == alert_id))
    alert = result.scalars().first()
    
    if not alert:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="Alert not found"
        )

    # Check if already responded
    existing_response = await db.execute(
        select(EmergencyResponse).filter(
            EmergencyResponse.alert_id == alert_id,
            EmergencyResponse.responder_id == current_user.id
        )
    )
    if existing_response.scalars().first():
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="You have already responded to this alert"
        )

    # Create response
    db_response = EmergencyResponse(
        alert_id=alert_id,
        responder_id=current_user.id,
        response_type=response_data.response_type,
        message=response_data.message,
        eta_minutes=response_data.eta_minutes,
    )

    db.add(db_response)
    
    # Update responded users count
    await db.execute(
        update(EmergencyAlert)
        .where(EmergencyAlert.id == alert_id)
        .values(responded_users_count=EmergencyAlert.responded_users_count + 1)
    )
    
    await db.commit()
    await db.refresh(db_response)

    # Create response with responder info
    response_dict = db_response.__dict__.copy()
    response_dict['responder_name'] = current_user.username
    response_dict['responder_phone'] = getattr(current_user, 'phone_number', None)

    return EmergencyResponseResponse.model_validate(response_dict)


@app.put("/api/v1/alert/{alert_id}/resolve")
async def resolve_alert(
    alert_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Resolve emergency alert"""
    result = await db.execute(select(EmergencyAlert).filter(EmergencyAlert.id == alert_id))
    alert = result.scalars().first()
    
    if not alert:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="Alert not found"
        )

    # Only alert creator can resolve
    if alert.user_id != current_user.id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Only alert creator can resolve the alert"
        )

    # Update alert
    await db.execute(
        update(EmergencyAlert)
        .where(EmergencyAlert.id == alert_id)
        .values(
            is_resolved=True,
            resolved_at=datetime.utcnow(),
            resolved_by=current_user.id
        )
    )
    await db.commit()

    return {"message": "Alert resolved successfully"}


@app.get("/api/v1/alerts/my", response_model=List[EmergencyAlertResponse])
async def get_my_alerts(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get current user's emergency alerts"""
    result = await db.execute(
        select(EmergencyAlert)
        .filter(EmergencyAlert.user_id == current_user.id)
        .order_by(EmergencyAlert.created_at.desc())
    )
    alerts = result.scalars().all()
    
    return [EmergencyAlertResponse.model_validate(alert) for alert in alerts]


@app.get("/api/v1/alerts/active", response_model=List[EmergencyAlertResponse])
async def get_active_alerts(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get active emergency alerts"""
    result = await db.execute(
        select(EmergencyAlert)
        .filter(EmergencyAlert.is_resolved == False)
        .order_by(EmergencyAlert.created_at.desc())
        .limit(50)
    )
    alerts = result.scalars().all()
    
    return [EmergencyAlertResponse.model_validate(alert) for alert in alerts]


@app.get("/api/v1/emergency/reports", response_model=List[EmergencyAlertResponse])
async def get_emergency_reports(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get emergency reports/alerts for admin users or general statistics"""
    # For now, return all active alerts (in production, add admin check)
    result = await db.execute(
        select(EmergencyAlert)
        .filter(EmergencyAlert.is_resolved == False)
        .order_by(EmergencyAlert.created_at.desc())
        .limit(50)
    )
    alerts = result.scalars().all()
    
    return [EmergencyAlertResponse.model_validate(alert) for alert in alerts]


@app.get("/api/v1/stats", response_model=EmergencyStatistics)
async def get_emergency_stats(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get emergency statistics"""
    # Get total alerts count
    total_alerts_result = await db.execute(select(func.count(EmergencyAlert.id)))
    total_alerts = total_alerts_result.scalar() or 0
    
    # Get active alerts count  
    active_alerts_result = await db.execute(
        select(func.count(EmergencyAlert.id)).filter(EmergencyAlert.is_resolved == False)
    )
    active_alerts = active_alerts_result.scalar() or 0
    
    # Calculate resolved alerts
    resolved_alerts = total_alerts - active_alerts
    
    # Get total responders count
    total_responders_result = await db.execute(select(func.count(EmergencyResponse.id)))
    total_responders = total_responders_result.scalar() or 0

    return EmergencyStatistics(
        total_alerts=total_alerts,
        active_alerts=active_alerts,
        resolved_alerts=resolved_alerts,
        avg_response_time_minutes=0,  # TODO: Calculate this
        total_responders=total_responders,
    )


@app.get("/api/v1/alerts/nearby", response_model=List[NearbyAlertResponse])
async def get_nearby_alerts(
    latitude: float = Query(..., ge=-90, le=90),
    longitude: float = Query(..., ge=-180, le=180),
    radius_km: float = Query(default=10.0, ge=0.1, le=100),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get nearby emergency alerts within specified radius"""
    # For now, return all active alerts (in production, add distance filtering)
    result = await db.execute(
        select(EmergencyAlert)
        .filter(EmergencyAlert.is_resolved == False)
        .order_by(EmergencyAlert.created_at.desc())
        .limit(20)
    )
    alerts = result.scalars().all()
    
    nearby_alerts = []
    for alert in alerts:
        distance = calculate_distance(latitude, longitude, alert.latitude, alert.longitude)
        if distance <= radius_km:
            nearby_alerts.append(NearbyAlertResponse(
                id=alert.id,
                alert_type=alert.alert_type,
                latitude=alert.latitude,
                longitude=alert.longitude,
                address=alert.address,
                distance_km=round(distance, 2),
                created_at=alert.created_at,
                responded_users_count=alert.responded_users_count or 0
            ))
    
    return sorted(nearby_alerts, key=lambda x: x.distance_km)


@app.post("/api/v1/report", response_model=EmergencyReportResponse)
async def create_emergency_report(
    report_data: EmergencyReportCreate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Create emergency report"""
    db_report = EmergencyReport(
        user_id=current_user.id if not report_data.is_anonymous else None,
        latitude=report_data.latitude,
        longitude=report_data.longitude,
        address=report_data.address,
        report_type=report_data.report_type,
        description=report_data.description,
        is_anonymous=report_data.is_anonymous,
        severity=report_data.severity
    )
    
    db.add(db_report)
    await db.commit()
    await db.refresh(db_report)
    
    return EmergencyReportResponse.model_validate(db_report)


@app.get("/api/v1/reports", response_model=List[EmergencyReportResponse])
async def get_emergency_reports(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get emergency reports"""
    result = await db.execute(
        select(EmergencyReport)
        .order_by(EmergencyReport.created_at.desc())
        .limit(50)
    )
    reports = result.scalars().all()
    
    return [EmergencyReportResponse.model_validate(report) for report in reports]


@app.post("/api/v1/safety-check", response_model=SafetyCheckResponse)
async def create_safety_check(
    check_data: SafetyCheckCreate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Create safety check-in"""
    db_check = SafetyCheck(
        user_id=current_user.id,
        message=check_data.message,
        location_latitude=check_data.location_latitude,
        location_longitude=check_data.location_longitude
    )
    
    db.add(db_check)
    await db.commit()
    await db.refresh(db_check)
    
    return SafetyCheckResponse.model_validate(db_check)


@app.get("/api/v1/safety-checks", response_model=List[SafetyCheckResponse])
async def get_safety_checks(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get user's safety check-ins"""
    result = await db.execute(
        select(SafetyCheck)
        .filter(SafetyCheck.user_id == current_user.id)
        .order_by(SafetyCheck.created_at.desc())
        .limit(50)
    )
    checks = result.scalars().all()
    
    return [SafetyCheckResponse.model_validate(check) for check in checks]


@app.put("/api/v1/alert/{alert_id}", response_model=EmergencyAlertResponse)
async def update_emergency_alert(
    alert_id: int,
    update_data: EmergencyAlertUpdate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Update emergency alert"""
    result = await db.execute(select(EmergencyAlert).filter(EmergencyAlert.id == alert_id))
    alert = result.scalars().first()
    
    if not alert:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="Alert not found"
        )

    # Only alert creator can update
    if alert.user_id != current_user.id:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Only alert creator can update the alert"
        )

    # Update fields
    update_dict = {}
    if update_data.is_resolved is not None:
        update_dict['is_resolved'] = update_data.is_resolved
        if update_data.is_resolved:
            update_dict['resolved_at'] = datetime.utcnow()
            update_dict['resolved_by'] = current_user.id
    
    if update_data.message is not None:
        update_dict['message'] = update_data.message

    if update_dict:
        await db.execute(
            update(EmergencyAlert)
            .where(EmergencyAlert.id == alert_id)
            .values(**update_dict)
        )
        await db.commit()
        await db.refresh(alert)

    return EmergencyAlertResponse.model_validate(alert)


@app.get("/api/v1/alert/{alert_id}/responses", response_model=List[EmergencyResponseResponse])
async def get_alert_responses(
    alert_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get responses for specific alert"""
    # Check if alert exists
    result = await db.execute(select(EmergencyAlert).filter(EmergencyAlert.id == alert_id))
    alert = result.scalars().first()
    
    if not alert:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="Alert not found"
        )

    # Get responses
    responses_result = await db.execute(
        select(EmergencyResponse)
        .filter(EmergencyResponse.alert_id == alert_id)
        .order_by(EmergencyResponse.created_at.desc())
    )
    responses = responses_result.scalars().all()
    
    return [EmergencyResponseResponse.model_validate(response) for response in responses]


@app.get("/api/v1/websocket/connections")
async def get_websocket_connections(
    current_user: User = Depends(get_current_user)
):
    """Получить информацию о WebSocket подключениях"""
    return ws_manager.get_connection_info()


@app.get("/api/v1/websocket/connections/{user_id}")
async def get_user_websocket_info(
    user_id: int,
    current_user: User = Depends(get_current_user)
):
    """Получить информацию о подключении конкретного пользователя"""
    connection_info = ws_manager.get_connection_info(user_id)
    
    if not connection_info:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, 
            detail="User connection not found"
        )
    
    return connection_info


@app.post("/api/v1/websocket/ping")
async def ping_websocket_connections(
    current_user: User = Depends(get_current_user)
):
    """Проверить все WebSocket подключения (пинг)"""
    result = await ws_manager.ping_all_connections()
    return result


@app.get("/api/v1/websocket/stats")
async def get_websocket_stats(
    current_user: User = Depends(get_current_user)
):
    """Получить общую статистику WebSocket подключений"""
    info = ws_manager.get_connection_info()
    
    return {
        "total_connections": info["active_connections"],
        "connected_users": info["connected_users"],
        "total_messages_sent": info["total_messages_sent"],
        "connection_count": len(info["connected_users"]),
        "timestamp": datetime.now().isoformat()
    }


@app.post("/api/v1/websocket/broadcast")
async def broadcast_test_message(
    message: str,
    current_user: User = Depends(get_current_user)
):
    """Отправить тестовое сообщение всем подключенным пользователям"""
    test_data = {
        "type": "test_broadcast",
        "message": message,
        "from_user": current_user.id,
        "timestamp": datetime.now().isoformat()
    }
    
    await ws_manager.broadcast_alert(test_data)
    
    return {
        "message": "Test broadcast sent",
        "recipients": ws_manager.get_connected_users_list(),
        "data": test_data
    }


# MOBILE APP COMPATIBILITY ENDPOINTS
# Мобильное приложение ожидает endpoints с /api/v1/emergency/events

@app.post("/api/v1/emergency/events", response_model=EmergencyAlertResponse)
async def create_emergency_event(
    alert_data: EmergencyAlertCreate,
    background_tasks: BackgroundTasks,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Create emergency event (alias for create_alert for mobile compatibility)"""
    # Используем существующую логику создания alert
    return await create_emergency_alert(alert_data, background_tasks, current_user, db)


@app.get("/api/v1/emergency/events/nearby", response_model=List[NearbyAlertResponse])
async def get_nearby_emergency_events(
    latitude: float = Query(..., description="User latitude"),
    longitude: float = Query(..., description="User longitude"), 
    radius: float = Query(5.0, description="Search radius in km"),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get nearby emergency events (alias for nearby alerts for mobile compatibility)"""
    # Используем существующую логику поиска nearby alerts
    return await get_nearby_alerts(latitude, longitude, radius, current_user, db)


@app.get("/api/v1/emergency/events", response_model=List[EmergencyAlertResponse])
async def get_emergency_events(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get all emergency events (alias for active alerts for mobile compatibility)"""
    # Используем существующую логику получения активных alerts
    return await get_active_alerts(current_user, db)


@app.get("/api/v1/emergency/events/my", response_model=List[EmergencyAlertResponse])
async def get_my_emergency_events(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get my emergency events (alias for my alerts for mobile compatibility)"""
    # Используем существующую логику получения моих alerts
    return await get_my_alerts(current_user, db)


@app.get("/api/v1/emergency/events/{event_id}", response_model=EmergencyEventDetails)
async def get_emergency_event(
    event_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get full detailed information about emergency event by ID"""
    try:
        # Получаем alert с информацией о пользователе
        alert_result = await db.execute(
            select(EmergencyAlert, User)
            .join(User, EmergencyAlert.user_id == User.id)
            .filter(EmergencyAlert.id == event_id)
        )
        alert_data = alert_result.first()
        
        if not alert_data:
            raise HTTPException(
                status_code=status.HTTP_404_NOT_FOUND, 
                detail="Emergency event not found"
            )
        
        alert, user = alert_data
        
        # Получаем все ответы на это событие с информацией о респондентах
        responses_result = await db.execute(
            select(EmergencyResponse, User)
            .join(User, EmergencyResponse.responder_id == User.id)
            .filter(EmergencyResponse.alert_id == event_id)
            .order_by(EmergencyResponse.created_at.desc())
        )
        
        # Формируем список ответов
        responses = []
        for response_data in responses_result:
            emergency_response, responder = response_data
            
            # Формируем полное имя респондента
            responder_name = responder.username
            if responder.first_name and responder.last_name:
                responder_name = f"{responder.first_name} {responder.last_name}"
            elif responder.first_name:
                responder_name = responder.first_name
            elif responder.last_name:
                responder_name = responder.last_name
            
            response_dict = {
                "id": emergency_response.id,
                "alert_id": emergency_response.alert_id,
                "responder_id": emergency_response.responder_id,
                "response_type": emergency_response.response_type,
                "message": emergency_response.message,
                "eta_minutes": emergency_response.eta_minutes,
                "created_at": emergency_response.created_at,
                "responder_name": responder_name,
                "responder_phone": responder.phone
            }
            responses.append(EmergencyResponseResponse(**response_dict))
        
        # Создаем объект с информацией о пользователе
        full_name = None
        if user.first_name and user.last_name:
            full_name = f"{user.first_name} {user.last_name}"
        elif user.first_name:
            full_name = user.first_name
        elif user.last_name:
            full_name = user.last_name
        
        user_info = UserInfo(
            id=user.id,
            username=user.username,
            full_name=full_name,
            phone=user.phone
        )
        
        # Определяем статус события на основе is_resolved
        from services.emergency_service.schemas import AlertStatus
        event_status = AlertStatus.RESOLVED if alert.is_resolved else AlertStatus.ACTIVE
        
        # Формируем полный ответ
        event_details = EmergencyEventDetails(
            id=alert.id,
            uuid=alert.uuid,
            user_id=alert.user_id,
            latitude=alert.latitude,
            longitude=alert.longitude,
            address=alert.address,
            alert_type=alert.alert_type,
            message=alert.message,
            status=event_status,
            created_at=alert.created_at,
            updated_at=alert.updated_at,
            resolved_at=alert.resolved_at,
            user=user_info,
            responses=responses,
            notifications_sent=len(responses),  # Примерная статистика
            websocket_notifications_sent=alert.notified_users_count or 0,
            push_notifications_sent=alert.responded_users_count or 0,
            contact_emergency_services=True,  # Значение по умолчанию
            notify_emergency_contacts=True    # Значение по умолчанию
        )
        
        logger.info(f"Retrieved detailed event info for event_id={event_id}, responses_count={len(responses)}")
        return event_details
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error retrieving emergency event {event_id}: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to retrieve emergency event details"
        )


@app.get("/api/v1/emergency/events/{event_id}/brief", response_model=EmergencyAlertResponse)
async def get_emergency_event_brief(
    event_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Get brief information about emergency event by ID (for mobile apps)"""
    # Получаем конкретный alert
    result = await db.execute(select(EmergencyAlert).filter(EmergencyAlert.id == event_id))
    alert = result.scalars().first()
    
    if not alert:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, 
            detail="Emergency event not found"
        )
    
    logger.info(f"Retrieved brief event info for event_id={event_id}")
    return EmergencyAlertResponse.model_validate(alert)


@app.put("/api/v1/emergency/events/{event_id}/resolve")
async def resolve_emergency_event(
    event_id: int,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Resolve emergency event (alias for resolve alert)"""
    # Используем существующую логику resolve alert
    return await resolve_alert(event_id, current_user, db)


@app.post("/api/v1/emergency/events/{event_id}/respond", response_model=EmergencyResponseResponse)
async def respond_to_emergency_event(
    event_id: int,
    response: EmergencyResponseCreate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """Respond to emergency event (alias for respond to alert)"""
    # Используем существующую логику respond to alert
    return await respond_to_alert(event_id, response, current_user, db)


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8002)