import { updateClaimToken } from '../../../repositories/claim-token-repo.js'
import { updateTask } from '../../../repositories/task-repo.js'
import { createTaskEvent } from '../../../repositories/task-event-repo.js'
import { createHttpError } from '../../../utils/http.js'
import { nowIso } from '../../../utils/time.js'
import { TASK_STATUS } from '../../../domain/task-status.js'
import { canViewerCloseTask, createAdminViewerContext } from '../admin-read-shared-helpers.js'
import { getRequiredTask, mapTaskActionPayload } from '../admin-task-read-helpers.js'

import type {
  AdminEntityIdInput,
  AdminViewerSessionInput,
} from '../../../types/admin/read-inputs.js'
import type { AdminTaskActionResponse } from '../../../types/admin/write-models.js'

export async function closeAdminTask(
  taskId: AdminEntityIdInput,
  session: AdminViewerSessionInput | null = null,
): Promise<AdminTaskActionResponse> {
  const task = await getRequiredTask(taskId)
  const viewerContext = createAdminViewerContext(session)

  if (!canViewerCloseTask(task, viewerContext)) {
    throw createHttpError('当前任务不可关闭', {
      statusCode: 409,
      errorCode: 'admin_task_close_not_allowed',
    })
  }

  const now = nowIso()
  const claimTokenId = Number(task.primary_claim_token_id || 0)

  if (claimTokenId > 0 && String(task.primary_claim_token_status || '').trim() !== 'closed') {
    await updateClaimToken(claimTokenId, {
      status: 'closed',
      expired_at: now,
      updated_at: now,
    })
  }

  const updatedTask = await updateTask(task.id, {
    task_status: TASK_STATUS.CLOSED,
    delivery_status: 'closed',
    result_code: 'closed_by_admin',
    result_message: '任务已关闭，领取链接已失效',
    user_action_status: 'closed',
    last_error: '',
    claim_expires_at: now,
    updated_at: now,
  })

  if (!updatedTask) {
    throw createHttpError('任务关闭失败', {
      statusCode: 500,
      errorCode: 'admin_task_close_failed',
    })
  }

  await createTaskEvent(
    task.id,
    'task_closed',
    {
      closedBy: session
        ? {
            userId: session.userId,
            username: session.username,
            role: session.role,
          }
        : null,
      claimTokenClosed: claimTokenId > 0,
    },
    now,
  )

  return {
    task: mapTaskActionPayload(updatedTask),
  }
}
