"""
startup_recovery.py — Letakkan di app/utils/ atau app/services/

Dipanggil saat server startup untuk membersihkan task yang
nyangkut di status 'pending' atau 'processing' akibat server
restart sebelumnya. Task-task ini tidak akan pernah selesai
sendiri karena background worker-nya sudah hilang.

Cara pakai di main.py (di dalam fungsi lifespan, setelah migrate_and_seed_db()):

    from app.utils.startup_recovery import recover_stale_tasks
    
    db = SessionLocal()
    try:
        recover_stale_tasks(db)
    finally:
        db.close()
"""

import logging
from datetime import datetime, timezone, timedelta

from sqlalchemy.orm import Session

from app.models.transkripsi import TranskripsiTask

logger = logging.getLogger(__name__)

# Task yang sudah "pending/processing" lebih dari N menit dianggap nyangkut.
# Sesuaikan dengan estimasi waktu transkripsi terlama di sistem Anda.
_STALE_THRESHOLD_MINUTES = int(30)


def recover_stale_tasks(db: Session) -> int:
    """
    Set task yang nyangkut (pending/processing terlalu lama) menjadi 'failed'.
    
    Returns:
        Jumlah task yang di-recover.
    """
    cutoff = datetime.now(timezone.utc) - timedelta(minutes=_STALE_THRESHOLD_MINUTES)

    stale_tasks = (
        db.query(TranskripsiTask)
        .filter(
            TranskripsiTask.status.in_(["pending", "processing"]),
            TranskripsiTask.updated_at < cutoff,
        )
        .all()
    )

    if not stale_tasks:
        logger.info("[Recovery] Tidak ada task yang nyangkut. Semua bersih.")
        return 0

    count = len(stale_tasks)
    for task in stale_tasks:
        logger.warning(
            "[Recovery] Task #%d (status='%s', updated_at=%s) dianggap nyangkut. "
            "Di-set ke 'failed'.",
            task.id,
            task.status,
            task.updated_at,
        )
        task.status        = "failed"
        task.progress      = 0
        task.error_message = (
            "Task dihentikan otomatis saat server restart. "
            "Silakan upload ulang file untuk mencoba lagi."
        )
        task.partial_result = ""
        task.segments_json  = "[]"

    db.commit()
    logger.info(
        "[Recovery] %d task nyangkut berhasil di-recover menjadi 'failed'.", count
    )
    return count


def recover_stale_tasks_aggressive(db: Session) -> int:
    """
    Versi agresif: semua task pending/processing APAPUN usianya langsung di-fail.
    Gunakan ini jika Anda yakin tidak ada worker yang sedang berjalan
    (misalnya single-process, tanpa Celery/queue).
    
    Ini lebih aman untuk deployment sederhana (Uvicorn single worker).
    """
    stale_tasks = (
        db.query(TranskripsiTask)
        .filter(TranskripsiTask.status.in_(["pending", "processing"]))
        .all()
    )

    if not stale_tasks:
        logger.info("[Recovery] Tidak ada task pending/processing. Semua bersih.")
        return 0

    count = len(stale_tasks)
    for task in stale_tasks:
        logger.warning(
            "[Recovery] Task #%d (status='%s') di-reset ke 'failed' saat startup.",
            task.id, task.status,
        )
        task.status         = "failed"
        task.progress       = 0
        task.error_message  = (
            "Task dihentikan otomatis saat server restart. "
            "Silakan upload ulang file untuk mencoba lagi."
        )
        task.partial_result = ""
        task.segments_json  = "[]"

    db.commit()
    logger.info("[Recovery] %d task di-recover ke 'failed'.", count)
    return count