from __future__ import annotations from datetime import datetime, time from typing import Self from uuid import UUID from zoneinfo import ZoneInfo, ZoneInfoNotFoundError from pydantic import BaseModel, ConfigDict, Field, field_validator from models.automation_jobs import AutomationJob as OrmAutomationJob from models.automation_jobs import AutomationJobStatus, ScheduleType from schemas.automation import AutomationJobConfig class AutomationJobResponse(BaseModel): model_config = ConfigDict(extra="forbid") id: UUID owner_id: UUID bootstrap_key: str | None = None title: str schedule_type: ScheduleType run_at: time timezone: str status: AutomationJobStatus is_system: bool config: AutomationJobConfig next_run_at: datetime last_run_at: datetime | None = None created_at: datetime updated_at: datetime @classmethod def from_orm(cls, obj: OrmAutomationJob) -> Self: return cls( id=obj.id, owner_id=obj.owner_id, bootstrap_key=obj.bootstrap_key, title=obj.title, schedule_type=obj.schedule_type, run_at=obj.run_at.time(), timezone=obj.timezone, status=obj.status, is_system=obj.bootstrap_key is not None, config=AutomationJobConfig.model_validate(obj.config or {}), next_run_at=obj.next_run_at, last_run_at=obj.last_run_at, created_at=obj.created_at, updated_at=obj.updated_at, ) class AutomationJobCreateRequest(BaseModel): model_config = ConfigDict(extra="forbid") title: str = Field(..., min_length=1, max_length=255) schedule_type: ScheduleType run_at: time = Field(..., description="Local time in HH:MM:SS format") timezone: str = Field(..., min_length=1, max_length=50) status: AutomationJobStatus = Field(default=AutomationJobStatus.ACTIVE) config: AutomationJobConfig @field_validator("timezone") @classmethod def validate_timezone(cls, value: str) -> str: try: ZoneInfo(value) except ZoneInfoNotFoundError as exc: raise ValueError("timezone must be a valid IANA timezone") from exc return value class AutomationJobUpdateRequest(BaseModel): model_config = ConfigDict(extra="forbid") title: str | None = Field(None, min_length=1, max_length=255) schedule_type: ScheduleType | None = None run_at: time | None = None timezone: str | None = Field(None, min_length=1, max_length=50) status: AutomationJobStatus | None = None config: AutomationJobConfig | None = None @field_validator("timezone") @classmethod def validate_timezone(cls, value: str | None) -> str | None: if value is None: return value try: ZoneInfo(value) except ZoneInfoNotFoundError as exc: raise ValueError("timezone must be a valid IANA timezone") from exc return value class AutomationJobListResponse(BaseModel): items: list[AutomationJobResponse]