""" Device Management API — Register and manage phones/softphones. """ import uuid from datetime import datetime from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from api.deps import get_gateway from core.gateway import AIPSTNGateway from db.database import Device as DeviceDB from db.database import get_db from models.device import Device, DeviceCreate, DeviceStatus, DeviceUpdate router = APIRouter() @router.post("/", response_model=Device) async def register_device( device: DeviceCreate, gateway: AIPSTNGateway = Depends(get_gateway), db: AsyncSession = Depends(get_db), ): """Register a new device with the gateway.""" device_id = f"dev_{uuid.uuid4().hex[:8]}" # Save to DB db_device = DeviceDB( id=device_id, name=device.name, type=device.type.value, sip_uri=device.sip_uri, phone_number=device.phone_number, priority=device.priority, capabilities=device.capabilities, is_online="false", ) db.add(db_device) await db.flush() # Register with gateway dev = Device(id=device_id, **device.model_dump()) gateway.register_device(dev) return dev @router.get("/", response_model=list[DeviceStatus]) async def list_devices( gateway: AIPSTNGateway = Depends(get_gateway), ): """List all registered devices and their status.""" return [ DeviceStatus( id=d.id, name=d.name, type=d.type, is_online=d.is_online, last_seen=d.last_seen, can_receive_call=d.can_receive_call, ) for d in gateway.devices.values() ] @router.get("/{device_id}", response_model=Device) async def get_device( device_id: str, gateway: AIPSTNGateway = Depends(get_gateway), ): """Get a specific device.""" device = gateway.devices.get(device_id) if not device: raise HTTPException(status_code=404, detail=f"Device {device_id} not found") return device @router.put("/{device_id}", response_model=Device) async def update_device( device_id: str, update: DeviceUpdate, gateway: AIPSTNGateway = Depends(get_gateway), db: AsyncSession = Depends(get_db), ): """Update a device.""" device = gateway.devices.get(device_id) if not device: raise HTTPException(status_code=404, detail=f"Device {device_id} not found") # Update in-memory update_data = update.model_dump(exclude_unset=True) for key, value in update_data.items(): setattr(device, key, value) # Update in DB result = await db.execute( select(DeviceDB).where(DeviceDB.id == device_id) ) db_device = result.scalar_one_or_none() if db_device: for key, value in update_data.items(): if key == "type" and value is not None: value = value.value if hasattr(value, "value") else value setattr(db_device, key, value) return device @router.delete("/{device_id}") async def unregister_device( device_id: str, gateway: AIPSTNGateway = Depends(get_gateway), db: AsyncSession = Depends(get_db), ): """Unregister a device.""" if device_id not in gateway.devices: raise HTTPException(status_code=404, detail=f"Device {device_id} not found") gateway.unregister_device(device_id) result = await db.execute( select(DeviceDB).where(DeviceDB.id == device_id) ) db_device = result.scalar_one_or_none() if db_device: await db.delete(db_device) return {"status": "unregistered", "device_id": device_id}