"""Assembles Company API responses from repository data.""" from __future__ import annotations import uuid from sqlalchemy.ext.asyncio import AsyncSession from app.core.ids import aurora_id, parse_aurora_id from app.models.company import Company from app.models.enums import ArtworkType, CompanyType from app.repositories import company_repository, polymorphic from app.schemas.common import CompanyBriefOut from app.schemas.company import CompanyDetailOut, CompanyListOut from app.services.common import primary_artwork_path from app.services.movie_service import build_movie_summaries from app.services.tv_service import build_series_summaries class CompanyNotFoundError(Exception): pass class InvalidCompanyFilterError(Exception): pass def _resolve_company_id(aid: str) -> uuid.UUID: try: return uuid.UUID(parse_aurora_id(aid, expected_type="company")) except ValueError as exc: raise CompanyNotFoundError(str(exc)) from exc async def get_company_detail(session: AsyncSession, company_aurora_id: str) -> CompanyDetailOut: company_id = _resolve_company_id(company_aurora_id) company = await company_repository.get_company_by_id(session, company_id) if company is None: raise CompanyNotFoundError(company_aurora_id) logos = await polymorphic.get_artwork(session, "company", company_id, ArtworkType.LOGO) external_ids = await polymorphic.get_external_ids(session, "company", company_id) movies = await company_repository.get_company_movies(session, company_id) series = await company_repository.get_company_series(session, company_id) return CompanyDetailOut( id=aurora_id("company", str(company.id)), name=company.name, company_type=company.company_type.value, description=company.description, country=company.country_code, headquarters=company.headquarters, homepage=company.homepage, logo_path=primary_artwork_path(logos, ArtworkType.LOGO), parent_company_id=( aurora_id("company", str(company.parent_company_id)) if company.parent_company_id else None ), external_ids=external_ids, movies=await build_movie_summaries(session, [m.id for m in movies]), series=await build_series_summaries(session, [s.id for s in series]), created_at=company.created_at, updated_at=company.updated_at, ) async def _company_summary_from_row(session: AsyncSession, company: Company) -> CompanyBriefOut: logos = await polymorphic.get_artwork(session, "company", company.id, ArtworkType.LOGO) return CompanyBriefOut( id=aurora_id("company", str(company.id)), name=company.name, company_type=company.company_type.value, logo_path=primary_artwork_path(logos, ArtworkType.LOGO), ) async def build_company_summary( session: AsyncSession, company_id: uuid.UUID ) -> CompanyBriefOut | None: company = await company_repository.get_company_by_id(session, company_id) if company is None: return None return await _company_summary_from_row(session, company) async def build_company_summaries( session: AsyncSession, company_ids: list[uuid.UUID] ) -> list[CompanyBriefOut]: out: list[CompanyBriefOut] = [] for company_id in company_ids: summary = await build_company_summary(session, company_id) if summary is not None: out.append(summary) return out async def list_companies( session: AsyncSession, *, company_type: str | None, country: str | None, page: int, page_size: int, ) -> CompanyListOut: company_type_enum: CompanyType | None = None if company_type is not None: try: company_type_enum = CompanyType(company_type) except ValueError as exc: raise InvalidCompanyFilterError(f"unknown company type: {company_type!r}") from exc companies, total = await company_repository.list_companies( session, company_type=company_type_enum, country_code=country, limit=page_size, offset=(page - 1) * page_size, ) results = [await _company_summary_from_row(session, c) for c in companies] total_pages = (total + page_size - 1) // page_size if total else 0 return CompanyListOut( page=page, page_size=page_size, total_results=total, total_pages=total_pages, results=results )