from typing import Any, Dict, List, Optional from sqlalchemy.future import select from api.db.base_client import BaseDBClient from api.db.models import OrganizationConfigurationModel class OrganizationConfigurationClient(BaseDBClient): async def get_configuration( self, organization_id: int, key: str ) -> Optional[OrganizationConfigurationModel]: """Get a specific configuration for an organization by key.""" async with self.async_session() as session: result = await session.execute( select(OrganizationConfigurationModel).where( OrganizationConfigurationModel.organization_id == organization_id, OrganizationConfigurationModel.key == key, ) ) return result.scalars().first() async def get_all_configurations( self, organization_id: int ) -> list[OrganizationConfigurationModel]: """Get all configurations for an organization.""" async with self.async_session() as session: result = await session.execute( select(OrganizationConfigurationModel).where( OrganizationConfigurationModel.organization_id == organization_id ) ) return result.scalars().all() async def upsert_configuration( self, organization_id: int, key: str, value: Any ) -> OrganizationConfigurationModel: """Create or update a configuration for an organization.""" async with self.async_session() as session: # First try to get existing configuration result = await session.execute( select(OrganizationConfigurationModel).where( OrganizationConfigurationModel.organization_id == organization_id, OrganizationConfigurationModel.key == key, ) ) config = result.scalars().first() if config: # Update existing configuration config.value = value else: # Create new configuration config = OrganizationConfigurationModel( organization_id=organization_id, key=key, value=value, ) session.add(config) try: await session.commit() except Exception as e: await session.rollback() raise e await session.refresh(config) return config async def delete_configuration(self, organization_id: int, key: str) -> bool: """Delete a configuration for an organization.""" async with self.async_session() as session: result = await session.execute( select(OrganizationConfigurationModel).where( OrganizationConfigurationModel.organization_id == organization_id, OrganizationConfigurationModel.key == key, ) ) config = result.scalars().first() if not config: return False await session.delete(config) try: await session.commit() except Exception as e: await session.rollback() raise e return True async def get_configuration_value( self, organization_id: int, key: str, default: Any = None ) -> Any: """Get the value of a configuration, returning default if not found.""" config = await self.get_configuration(organization_id, key) return config.value if config else default async def get_all_configurations_by_key(self, key: str) -> list[dict[str, Any]]: """Get all organization configurations for a given key. Returns a list of dicts with organization_id and the config value. """ async with self.async_session() as session: result = await session.execute( select(OrganizationConfigurationModel).where( OrganizationConfigurationModel.key == key, ) ) return [ { "organization_id": config.organization_id, "value": config.value, } for config in result.scalars().all() if config.value ] async def get_configurations_by_provider( self, key: str, provider: str ) -> List[Dict[str, Any]]: """Get all organization configurations for a given key filtered by provider. Returns a list of dicts with organization_id and the config value. """ async with self.async_session() as session: result = await session.execute( select(OrganizationConfigurationModel).where( OrganizationConfigurationModel.key == key, ) ) configs = result.scalars().all() return [ { "organization_id": config.organization_id, "value": config.value, } for config in configs if config.value and config.value.get("provider") == provider ]