from pathlib import Path from uuid import uuid4 from app.core.config import get_settings from app.repositories.observation_repository import ObservationRepository from app.schemas.common import ListResponse from app.schemas.observation import ObservationCreateRequest, ObservationSummary class ObservationService: def __init__(self) -> None: self.repository = ObservationRepository() def create_observation( self, payload: ObservationCreateRequest, ) -> ObservationSummary: observation = ObservationSummary( id=str(uuid4()), modality=payload.modality, duration_ms=payload.duration_ms, sample_rate=payload.sample_rate, channels=payload.channels, tags=payload.tags, capture_metadata=payload.capture_metadata, ) self.repository.save(observation) return observation def create_observation_from_upload( self, *, filename: str, content: bytes, duration_ms: int, sample_rate: int, channels: int, tags: list[str], capture_metadata: dict[str, object], ) -> ObservationSummary: observation_id = str(uuid4()) suffix = Path(filename).suffix or ".bin" upload_name = f"{observation_id}{suffix}" settings = get_settings() upload_dir = Path(settings.upload_dir) upload_dir.mkdir(parents=True, exist_ok=True) stored_path = upload_dir / upload_name stored_path.write_bytes(content) metadata = dict(capture_metadata) metadata.update( { "source": metadata.get("source", "upload"), "original_filename": filename, "stored_filename": upload_name, "stored_path": str(stored_path), "file_size_bytes": len(content), } ) observation = ObservationSummary( id=observation_id, modality="audio", duration_ms=duration_ms, sample_rate=sample_rate, channels=channels, tags=tags, capture_metadata=metadata, ) self.repository.save(observation) return observation def get_observation(self, observation_id: str) -> ObservationSummary | None: return self.repository.get(observation_id) def list_observations(self) -> ListResponse[ObservationSummary]: return self.repository.list()