// 超时检查框架
//
// TimeoutChecker 定期扫描 tasks 表中已超时但仍处于 pending 状态的任务，
// 发布 task.timeout 事件用于升级通知。

use chrono::Utc;
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
use uuid::Uuid;

use crate::entity::task;
use crate::error::WorkflowResult;

/// 超时检查服务。
pub struct TimeoutChecker;

impl TimeoutChecker {
    /// 查询指定租户下已超时但未完成的任务列表。
    ///
    /// 返回 due_date < now 且 status = 'pending' 的任务 ID。
    pub async fn find_overdue_tasks(
        tenant_id: Uuid,
        db: &sea_orm::DatabaseConnection,
    ) -> WorkflowResult<Vec<Uuid>> {
        let now = Utc::now();
        let overdue = task::Entity::find()
            .filter(task::Column::TenantId.eq(tenant_id))
            .filter(task::Column::Status.eq("pending"))
            .filter(task::Column::DueDate.lt(now))
            .filter(task::Column::DeletedAt.is_null())
            .all(db)
            .await
            .map_err(|e| crate::error::WorkflowError::Validation(e.to_string()))?;

        Ok(overdue.iter().map(|t| t.id).collect())
    }

    /// 查询所有租户中已超时但未完成的任务列表。
    ///
    /// 返回 due_date < now 且 status = 'pending' 的任务 ID。
    /// 用于后台定时任务的全量扫描。
    pub async fn find_all_overdue_tasks(
        db: &sea_orm::DatabaseConnection,
    ) -> WorkflowResult<Vec<Uuid>> {
        let now = Utc::now();
        let overdue = task::Entity::find()
            .filter(task::Column::Status.eq("pending"))
            .filter(task::Column::DueDate.lt(now))
            .filter(task::Column::DeletedAt.is_null())
            .all(db)
            .await
            .map_err(|e| crate::error::WorkflowError::Validation(e.to_string()))?;

        Ok(overdue.iter().map(|t| t.id).collect())
    }

    /// 查询所有租户中已超时的任务（含详细信息）。
    ///
    /// 返回 (task_id, tenant_id, instance_id, assignee_id) 元组，
    /// 用于发布 task.timeout 事件。
    pub async fn find_all_overdue_tasks_with_details(
        db: &sea_orm::DatabaseConnection,
    ) -> WorkflowResult<Vec<(Uuid, Uuid, Uuid, Option<Uuid>)>> {
        let now = Utc::now();
        let overdue = task::Entity::find()
            .filter(task::Column::Status.eq("pending"))
            .filter(task::Column::DueDate.lt(now))
            .filter(task::Column::DeletedAt.is_null())
            .all(db)
            .await
            .map_err(|e| crate::error::WorkflowError::Validation(e.to_string()))?;

        Ok(overdue
            .iter()
            .map(|t| (t.id, t.tenant_id, t.instance_id, t.assignee_id))
            .collect())
    }
}
