# #region validate_job_preconditions [C:3] [TYPE Function] [SEMANTICS validation, preconditions, translate]
# @BRIEF Validate preconditions before starting a translation run.
# @PRE Job exists and db session is valid.
# @POST Raises ValueError if any precondition fails.
# @RELATION DEPENDS_ON -> [TranslationJob]
def validate_job_preconditions(
    job,
    db_session,
    is_scheduled: bool = False,
) -> None:
    """Validate preconditions before starting a translation run.

    Args:
        job: TranslationJob instance.
        db_session: SQLAlchemy Session for querying preview sessions.
        is_scheduled: Whether this is a scheduled (vs manual) run.

    Raises:
        ValueError: If any precondition fails.
    """
    if job.status in ("DRAFT",):
        raise ValueError(
            f"Cannot run job '{job.id}' in status '{job.status}'. "
            f"Job must be READY, ACTIVE, or COMPLETED."
        )
    if not job.target_table:
        raise ValueError(
            f"Job '{job.id}' has no target table configured. "
            "Configure a target table before running."
        )
    if not job.provider_id:
        raise ValueError(
            f"Job '{job.id}' has no LLM provider configured. "
            "Select an LLM provider before running."
        )
    if not job.translation_column:
        raise ValueError(
            f"Job '{job.id}' has no translation column configured. "
            "Select a translation column before running."
        )
    if not is_scheduled:
        # Jobs with a direct Superset datasource can fetch rows from Superset directly
        # (see RunSourceFetcher.fetch_source_rows), so they don't need a preview session.
        # Only require an accepted preview for jobs without a configured datasource.
        if not bool(job.source_datasource_id):
            from ...models.translate import TranslationPreviewSession
            accepted_session = (
                db_session.query(TranslationPreviewSession)
                .filter(
                    TranslationPreviewSession.job_id == job.id,
                    TranslationPreviewSession.status == "APPLIED",
                )
                .order_by(TranslationPreviewSession.created_at.desc())
                .first()
            )
            if not accepted_session:
                raise ValueError(
                    f"Job '{job.id}' has no accepted preview session. "
                    "Run and accept a preview before executing a manual translation run."
                )
# #endregion validate_job_preconditions
