# -*- coding: utf-8 -*-
"""
有效期轮询器（Task Expiry Checker）

每小时运行一次，检查 expires_at 不为 NULL 且已过期的 active 任务，
将其标记为 inactive 并记录 history。

由 trigger_jobs 中的 task_expiry_check 配置驱动。
"""

import json
import logging

logger = logging.getLogger(__name__)


def _get_connection():
    """延迟导入 get_connection，避免模块级导入失败。"""
    from app.database import get_connection

    return get_connection()


def _insert_history(
    cur,
    task_id: int,
    action: str,
    old_status: str | None = None,
    new_status: str | None = None,
    old_task_type: str | None = None,
    new_task_type: str | None = None,
    detail: dict | None = None,
) -> None:
    """在 coach_task_history 中记录变更。"""
    cur.execute(
        """
        INSERT INTO biz.coach_task_history
            (task_id, action, old_status, new_status,
             old_task_type, new_task_type, detail)
        VALUES (%s, %s, %s, %s, %s, %s, %s)
        """,
        (
            task_id,
            action,
            old_status,
            new_status,
            old_task_type,
            new_task_type,
            json.dumps(detail) if detail else None,
        ),
    )


def run() -> dict:
    """
    有效期轮询主流程。

    1. SELECT id, task_type FROM biz.coach_tasks
       WHERE expires_at IS NOT NULL AND expires_at < NOW() AND status = 'active'
    2. 逐条 UPDATE status = 'inactive'
    3. INSERT coach_task_history (action='expired')

    每条过期任务独立事务，失败不影响其他。

    返回: {"expired_count": int}
    """
    expired_count = 0

    conn = _get_connection()
    try:
        # 查询所有已过期的 active 任务
        with conn.cursor() as cur:
            cur.execute(
                """
                SELECT id, task_type
                FROM biz.coach_tasks
                WHERE expires_at IS NOT NULL
                  AND expires_at < NOW()
                  AND status = 'active'
                """
            )
            expired_tasks = cur.fetchall()
        conn.commit()

        # 逐条处理，每条独立事务
        for task_id, task_type in expired_tasks:
            try:
                with conn.cursor() as cur:
                    cur.execute("BEGIN")
                    cur.execute(
                        """
                        UPDATE biz.coach_tasks
                        SET status = 'inactive', updated_at = NOW()
                        WHERE id = %s AND status = 'active'
                        """,
                        (task_id,),
                    )
                    _insert_history(
                        cur,
                        task_id,
                        action="expired",
                        old_status="active",
                        new_status="inactive",
                        old_task_type=task_type,
                        new_task_type=task_type,
                    )
                conn.commit()
                expired_count += 1
            except Exception:
                logger.exception("处理过期任务失败: task_id=%s", task_id)
                conn.rollback()

    finally:
        conn.close()

    logger.info("有效期轮询完成: expired_count=%d", expired_count)
    return {"expired_count": expired_count}
