/**
 * Webhook 触发处理器 — 从 src/app/api/webhooks/[taskId]/route.ts 提取。
 * 与 IM / Cron 同属"触发源"层：把外部 HTTP 触发转成 Agent 引擎调用 +
 * 执行记录。本模块负责触发源特有的关注点（token 校验 / 幂等 / 并发控制），
 * 实际任务执行复用 cron/executor 的 executeTask。
 *
 * route.ts 退化为 HTTP 解析 + 调本模块，不再承载业务逻辑。
 */

import crypto from 'crypto'
import { webhookTokenRepo } from '@/lib/database/repositories/webhook-token.repo'
import { cronTaskRepo } from '@/lib/database/repositories/cron-task.repo'
import { taskExecutionRepo } from '@/lib/database/repositories/task-execution.repo'
import { executeTask } from '@/lib/cron/executor'

/** 进程级并发控制：同一 webhook task 同时只跑一个实例。 */
const executingTasks = new Set<string>()

/** webhook 处理结果（route.ts 据此组装 HTTP response）。 */
export interface WebhookResult {
  status: number
  body: {
    status: string
    result?: string
    sessionId?: string
    executedAt?: string
    cached?: boolean
  }
}

/**
 * 处理一次 webhook 触发。
 *
 * @param taskId  路径参数中的任务 ID
 * @param token   从 header / query / body 中已解析出的 token
 * @param requestId 可选的 X-Request-Id（幂等键）
 * @param body    已解析的请求体（可含 action 覆盖）
 */
export async function handleWebhook(
  taskId: string,
  token: string,
  requestId: string | null,
  body: Record<string, unknown>,
): Promise<WebhookResult> {
  // 1. 查找启用了 webhook 的任务
  const task = cronTaskRepo.findById(taskId)
  if (!task || !task.webhookEnabled) {
    return { status: 404, body: { status: 'error', result: 'Webhook task not found' } }
  }

  // 2. Token 校验
  if (!token) {
    return { status: 401, body: { status: 'error', result: 'Missing webhook token' } }
  }
  const tokenRow = webhookTokenRepo.findEnabledByToken(token)
  if (!tokenRow) {
    return { status: 401, body: { status: 'error', result: 'Invalid or disabled token' } }
  }

  // 3. 幂等检查（X-Request-Id）
  if (requestId) {
    const existingId = taskExecutionRepo.findIdByTaskIdAndResultLike(
      taskId,
      `%requestId:${requestId}%`,
    )
    if (existingId) {
      return {
        status: 200,
        body: { status: 'ok', result: 'Duplicate request ignored', cached: true },
      }
    }
  }

  // 4. 并发控制
  if (executingTasks.has(taskId)) {
    return { status: 409, body: { status: 'error', result: 'Task is already executing' } }
  }

  // 5. 可选 action 覆盖
  const overrideAction =
    body.action && typeof body.action === 'string' ? body.action : task.action

  // 6. 执行 + 记录
  executingTasks.add(taskId)
  const startTime = new Date().toISOString()
  try {
    const taskToExecute = { ...task, action: overrideAction }
    const { status, result, sessionId } = await executeTask(taskToExecute)

    const execId = crypto.randomUUID()
    taskExecutionRepo.create({
      id: execId,
      taskId: task.id,
      taskName: task.name,
      status,
      sessionId: sessionId || '',
      executedAt: startTime,
    })
    cronTaskRepo.updateLastRun(task.id, result.slice(0, 200), startTime)
    return {
      status: 200,
      body: {
        status,
        result: result.slice(0, 500),
        sessionId,
        executedAt: startTime,
      },
    }
  } catch (err) {
    const execId = crypto.randomUUID()
    const errorMsg = err instanceof Error ? err.message : 'Unknown error'
    taskExecutionRepo.create({
      id: execId,
      taskId: task.id,
      taskName: task.name,
      result: errorMsg,
      status: 'error',
      sessionId: '',
      executedAt: startTime,
    })
    cronTaskRepo.updateLastRun(task.id, `Error: ${errorMsg.slice(0, 180)}`, startTime)
    return { status: 500, body: { status: 'error', result: errorMsg } }
  } finally {
    executingTasks.delete(taskId)
  }
}