"""Privacy-aware hydration of Match candidates for API responses (spec §14). - Unknown dogs are shown at ZIP level only. The shelter/vet where a found dog is being held (``current_location_detail``) IS included: it's a public place, and telling the owner where to reclaim their dog is the whole point. Only *home* locations are withheld — those are never collected below ZIP granularity and contact stays mediated. - Known dogs show appearance fields; owner contact is mediated, never inlined. """ from __future__ import annotations from sqlalchemy.orm import Session from ..models import KnownDog, Match, UnknownDog from ..models.base import SubjectType from ..schemas.case import MatchOut from .helpers import estimated_breeds_for, pictures_for def build_match_out(db: Session, match: Match) -> MatchOut: out = MatchOut.model_validate(match) if match.candidate_type == SubjectType.unknown: dog = db.get(UnknownDog, match.candidate_id) if dog: out.candidate = { "type": "unknown", "id": dog.id, "description": dog.description, "est_breed": dog.est_breed, "est_age": dog.est_age, "color": dog.color, "size": dog.size.value if dog.size else None, "current_zip": dog.current_zip, # ZIP-level only (home locations stay private) # Shelter/vet holding the dog — a public place, shown so the owner can reclaim it. "current_location_detail": dog.current_location_detail, "status": dog.status.value, "estimated_breeds": estimated_breeds_for(db, SubjectType.unknown, dog.id), "pictures": [p.model_dump() for p in pictures_for(db, SubjectType.unknown, dog.id)], } else: dog = db.get(KnownDog, match.candidate_id) if dog: out.candidate = { "type": "known", "id": dog.id, "name": dog.name, "breed": dog.breed, "age": dog.age, "color": dog.color, "size": dog.size.value if dog.size else None, "last_known_zip": dog.last_known_zip, "status": dog.status.value, "estimated_breeds": estimated_breeds_for(db, SubjectType.known, dog.id), "pictures": [p.model_dump() for p in pictures_for(db, SubjectType.known, dog.id)], } return out