from __future__ import annotations from yuxi.channel.domain.exception.agent_config_not_found import AgentConfigNotFoundException from yuxi.channel.domain.exception.duplicate_binding import DuplicateBindingException from yuxi.channel.domain.model.binding.channel_binding import ChannelBinding from yuxi.channel.domain.port.agent_config_lookup_port import AgentConfigLookupPort from yuxi.channel.domain.repository.binding_repository import BindingRepositoryPort class BindingService: def __init__( self, binding_repo: BindingRepositoryPort, agent_config_lookup: AgentConfigLookupPort | None = None, ) -> None: self._repo = binding_repo self._agent_config_lookup = agent_config_lookup async def create( self, *, channel_type: str, account_id: str, group_id: str, agent_config_id: int, created_by: str | None = None, ) -> ChannelBinding: existing = await self._repo.find_binding(channel_type=channel_type, account_id=account_id, group_id=group_id) if existing: raise DuplicateBindingException(channel_type, account_id, group_id) if self._agent_config_lookup and not await self._agent_config_lookup.exists(agent_config_id): raise AgentConfigNotFoundException(agent_config_id) return await self._repo.create_binding( channel_type=channel_type, account_id=account_id, group_id=group_id, agent_config_id=agent_config_id, created_by=created_by, ) async def update( self, binding_id: int, *, agent_config_id: int | None = None, is_enabled: bool | None = None, updated_by: str | None = None, ) -> ChannelBinding | None: return await self._repo.update_binding( binding_id, agent_config_id=agent_config_id, is_enabled=is_enabled, updated_by=updated_by ) async def delete(self, binding_id: int) -> bool: return await self._repo.delete_binding(binding_id) async def get(self, binding_id: int) -> ChannelBinding | None: return await self._repo.get_binding(binding_id) async def list( self, *, channel_type: str | None = None, offset: int = 0, limit: int = 50 ) -> tuple[list[ChannelBinding], int]: return await self._repo.list_bindings(channel_type=channel_type, offset=offset, limit=limit)