import json import logging from fastapi import APIRouter, Depends, Request, status from fastapi.responses import PlainTextResponse, Response from pydantic import ValidationError from sqlalchemy.orm import Session from app.config import Settings from app.dependencies import ( get_app_settings, get_db, get_homeassistant_client, get_poo_db, get_ticktick_client, ) from app.integrations.homeassistant import ( HomeAssistantClient, HomeAssistantConfigError, HomeAssistantRequestError, ) from app.integrations.ticktick import TickTickClient, TickTickConfigError, TickTickRequestError from app.schemas.homeassistant import HomeAssistantPublishEnvelope from app.services.homeassistant_inbound import ( UnsupportedHomeAssistantMessage, handle_homeassistant_message, ) router = APIRouter(tags=["homeassistant"]) logger = logging.getLogger(__name__) BAD_REQUEST_MESSAGE = "bad request" INTERNAL_SERVER_ERROR_MESSAGE = "internal server error" @router.post("/homeassistant/publish") async def publish_from_homeassistant( request: Request, db: Session = Depends(get_db), poo_db: Session = Depends(get_poo_db), settings: Settings = Depends(get_app_settings), homeassistant_client: HomeAssistantClient = Depends(get_homeassistant_client), ticktick_client: TickTickClient = Depends(get_ticktick_client), ) -> Response: try: raw_payload = await request.body() data = json.loads(raw_payload) envelope = HomeAssistantPublishEnvelope.model_validate(data) handle_homeassistant_message( db, envelope, ticktick_client=ticktick_client, poo_session=poo_db, settings=settings, homeassistant_client=homeassistant_client, ) except json.JSONDecodeError as exc: logger.warning("Rejected Home Assistant publish request due to invalid JSON: %s", exc) return PlainTextResponse(BAD_REQUEST_MESSAGE, status_code=status.HTTP_400_BAD_REQUEST) except ValidationError as exc: logger.warning( "Rejected Home Assistant publish request due to validation failure: %s", exc ) return PlainTextResponse(BAD_REQUEST_MESSAGE, status_code=status.HTTP_400_BAD_REQUEST) except UnsupportedHomeAssistantMessage as exc: logger.warning("Home Assistant publish target/action unsupported: %s", exc) return PlainTextResponse( INTERNAL_SERVER_ERROR_MESSAGE, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, ) except ( TickTickConfigError, TickTickRequestError, HomeAssistantConfigError, HomeAssistantRequestError, RuntimeError, ) as exc: logger.warning("Home Assistant publish request failed during integration handling: %s", exc) return PlainTextResponse( INTERNAL_SERVER_ERROR_MESSAGE, status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, ) except ValueError as exc: logger.warning("Rejected Home Assistant publish request due to invalid content: %s", exc) return PlainTextResponse(BAD_REQUEST_MESSAGE, status_code=status.HTTP_400_BAD_REQUEST) return Response(status_code=status.HTTP_200_OK)