# #region orchestrator_run_completion [C:3] [TYPE Module] [SEMANTICS translate, run, completion, failure]
# @BRIEF Post-execution run completion handlers: cancelled, success-with-insert, and failure paths.
# @RELATION DEPENDS_ON -> [TranslationRun]
# @RELATION DEPENDS_ON -> [TranslationJob]
# @RELATION DEPENDS_ON -> [TranslationResultAggregator]
# @RELATION DEPENDS_ON -> [SQLInsertService]
# @RELATION DEPENDS_ON -> [TranslationEventLog]

from datetime import UTC, datetime

from ...core.logger import logger
from ...models.translate import TranslationJob, TranslationRun, TranslationRunLanguageStats


# region handle_executor_failure [TYPE Function]
# @PURPOSE: Handle executor failure — rollback, mark run as FAILED, log event.
# @SIDE_EFFECT  DB writes; event log.
def handle_executor_failure(
    db,
    event_log,
    run: TranslationRun,
    job: TranslationJob,
    error: Exception,
    current_user: str | None = None,
) -> TranslationRun:
    """Handle executor failure — rollback, mark as FAILED, log event."""
    logger.explore("Translation execution failed", {"run_id": run.id, "error": str(error)})
    try:
        db.rollback()
    except Exception:
        pass
    run = db.merge(run)
    run.status = "FAILED"
    run.error_message = f"Translation execution failed: {error}"
    run.completed_at = datetime.now(UTC)
    db.flush()
    event_log.log_event(
        job_id=job.id, run_id=run.id, event_type="RUN_FAILED",
        payload={"error": str(error), "phase": "translation"},
        created_by=current_user,
    )
    db.commit()
    return run
# endregion handle_executor_failure


# region complete_cancelled [TYPE Function]
# @PURPOSE: Finalize a cancelled run — update language stats and log.
# @SIDE_EFFECT  DB writes; event log.
def complete_cancelled(
    db,
    event_log,
    aggregator,
    run: TranslationRun,
    language_stats_map: dict[str, TranslationRunLanguageStats],
    current_user: str | None = None,
) -> TranslationRun:
    """Finalize a cancelled run."""
    aggregator.update_language_stats(run.id, language_stats_map)
    event_log.log_event(
        job_id=run.job_id, run_id=run.id, event_type="RUN_CANCELLED",
        payload={"reason": "cancellation_flag"}, created_by=current_user,
    )
    db.commit()
    return run
# endregion complete_cancelled


# region complete_success [TYPE Function]
# @PURPOSE: Finalize a successful run — update stats, optionally insert SQL, commit.
# @SIDE_EFFECT  DB writes; event log; Superset API call if skip_insert is False.
def complete_success(
    db,
    event_log,
    aggregator,
    sql_service,
    run: TranslationRun,
    job: TranslationJob,
    skip_insert: bool,
    language_stats_map: dict[str, TranslationRunLanguageStats],
    current_user: str | None = None,
) -> TranslationRun:
    """Finalize a successful run with stats update and optional SQL insert."""
    aggregator.update_language_stats(run.id, language_stats_map)
    event_log.log_event(
        job_id=job.id, run_id=run.id, event_type="TRANSLATION_PHASE_COMPLETED",
        payload={
            "total": run.total_records, "successful": run.successful_records,
            "failed": run.failed_records, "skipped": run.skipped_records,
        },
        created_by=current_user,
    )

    if skip_insert:
        run.status = "COMPLETED"
        run.completed_at = datetime.now(UTC)
        db.flush()
        event_log.log_event(
            job_id=job.id, run_id=run.id, event_type="RUN_COMPLETED",
            payload={"skip_insert": True}, created_by=current_user,
        )
        db.commit()
        return run

    insert_result = sql_service.generate_and_insert_sql(job, run)
    run.insert_status = insert_result.get("status")
    run.superset_execution_id = str(insert_result.get("query_id") or "")
    run.superset_execution_log = insert_result
    # Treat "failed" and "timeout" as terminal failures.
    # "skipped" (no records) and "success" are non-failure outcomes.
    if insert_result.get("status") in ("failed", "timeout"):
        run.status = "FAILED"
        if insert_result.get("error_message"):
            run.error_message = insert_result["error_message"]
        elif not run.error_message:
            run.error_message = f"SQL insert phase {insert_result.get('status')}"
    elif run.status != "FAILED":
        run.status = "COMPLETED"
    if insert_result.get("error_message") and not run.error_message:
        run.error_message = insert_result["error_message"]
    run.completed_at = datetime.now(UTC)
    db.flush()

    event_log.log_event(
        job_id=job.id, run_id=run.id, event_type="RUN_COMPLETED",
        payload={
            "insert_status": insert_result.get("status"),
            "query_id": insert_result.get("query_id"),
            "total_records": run.total_records,
            "successful": run.successful_records,
            "failed": run.failed_records,
        },
        created_by=current_user,
    )
    db.commit()
    run = db.query(TranslationRun).filter(TranslationRun.id == run.id).first()
    return run
# endregion complete_success
# #endregion orchestrator_run_completion
