from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from pydantic import BaseModel from typing import Optional from uuid import UUID from datetime import datetime from app.database import get_db from app.api.deps import get_current_user, require_role from app.models.user import User from app.utils.security import hash_password router = APIRouter() class UserResponse(BaseModel): id: UUID tenant_id: UUID email: str full_name: Optional[str] full_name_ar: Optional[str] role: str phone: Optional[str] is_active: bool last_login: Optional[datetime] created_at: datetime model_config = {"from_attributes": True} class UserCreate(BaseModel): email: str password: str full_name: str full_name_ar: Optional[str] = None role: str = "agent" phone: Optional[str] = None class UserUpdate(BaseModel): full_name: Optional[str] = None full_name_ar: Optional[str] = None role: Optional[str] = None phone: Optional[str] = None is_active: Optional[bool] = None @router.get("", response_model=list[UserResponse]) async def list_users( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(User).where(User.tenant_id == current_user.tenant_id).order_by(User.created_at)) return [UserResponse.model_validate(u) for u in result.scalars().all()] @router.post("", response_model=UserResponse, status_code=201) async def create_user( data: UserCreate, current_user: User = Depends(require_role("owner", "admin", "manager")), db: AsyncSession = Depends(get_db), ): existing = await db.execute(select(User).where(User.email == data.email, User.tenant_id == current_user.tenant_id)) if existing.scalar_one_or_none(): raise HTTPException(status_code=400, detail="Email already exists in this company") user = User( tenant_id=current_user.tenant_id, email=data.email, password_hash=hash_password(data.password), full_name=data.full_name, full_name_ar=data.full_name_ar, role=data.role, phone=data.phone, ) db.add(user) await db.flush() await db.refresh(user) return UserResponse.model_validate(user) @router.put("/{user_id}", response_model=UserResponse) async def update_user( user_id: UUID, data: UserUpdate, current_user: User = Depends(require_role("owner", "admin")), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(User).where(User.id == user_id, User.tenant_id == current_user.tenant_id)) user = result.scalar_one_or_none() if not user: raise HTTPException(status_code=404, detail="User not found") for field, value in data.model_dump(exclude_none=True).items(): setattr(user, field, value) await db.flush() await db.refresh(user) return UserResponse.model_validate(user) @router.delete("/{user_id}", status_code=204) async def delete_user( user_id: UUID, current_user: User = Depends(require_role("owner", "admin")), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(User).where(User.id == user_id, User.tenant_id == current_user.tenant_id)) user = result.scalar_one_or_none() if not user: raise HTTPException(status_code=404, detail="User not found") if user.id == current_user.id: raise HTTPException(status_code=400, detail="Cannot delete yourself") user.is_active = False await db.flush()