import uuid from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from app.models.organization import Organization from app.models.user import User from app.schemas.user import UserRegister, UserUpdate from app.services.auth_service import hash_password async def get_by_id(db: AsyncSession, user_id: str | uuid.UUID) -> User | None: uid = user_id if isinstance(user_id, uuid.UUID) else uuid.UUID(str(user_id)) result = await db.execute( select(User).where(User.id == uid).options(selectinload(User.organization)) ) return result.scalar_one_or_none() async def get_by_email(db: AsyncSession, email: str) -> User | None: result = await db.execute( select(User).where(User.email == email.lower()).options(selectinload(User.organization)) ) return result.scalar_one_or_none() async def create(db: AsyncSession, data: UserRegister) -> User: user = User( email=data.email.lower(), hashed_password=hash_password(data.password), full_name=data.full_name, phone=data.phone, instagram_handle=data.instagram_handle, role=data.requested_role, # Members are auto-approved; organizers require admin review status="approved" if data.requested_role == "member" else "pending", ) db.add(user) await db.flush() # get user.id for the FK # Create Organization row for organizer registrations if data.requested_role == "organizer" and data.organization_name: org = Organization( user_id=user.id, name=data.organization_name, status="pending", verified=False, ) db.add(org) await db.commit() await db.refresh(user, attribute_names=["organization"]) return user async def update(db: AsyncSession, user: User, data: UserUpdate) -> User: user_fields = data.model_dump(exclude_none=True, exclude={"organization_name"}) for field, value in user_fields.items(): setattr(user, field, value) # Route org field updates to Organization table if data.organization_name is not None and user.organization: user.organization.name = data.organization_name await db.commit() await db.refresh(user, attribute_names=["organization"]) return user async def set_status(db: AsyncSession, user: User, status: str) -> User: user.status = status await db.commit() await db.refresh(user) return user async def list_all(db: AsyncSession, skip: int = 0, limit: int = 100) -> list[User]: result = await db.execute( select(User).options(selectinload(User.organization)).offset(skip).limit(limit) ) return list(result.scalars().all())