import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
import {
  cancelAssignedWorkOrder,
  returnAssignedWorkOrderToHall,
  unassignWorkOrder,
} from '../../repositories/worker-platform/index.js'
import type { JsonObject } from '../../types/json.js'
import { createHttpError } from '../../utils/http.js'
import { nowIso } from '../../utils/time.js'
import {
  publishWorkerWalletRealtimeChange,
  publishWorkOrderRealtimeChange,
} from '../realtime/realtime-event-service.js'
import { mapWorkOrderAdmin } from './mappers.js'
import { getRequiredWorkOrder } from './worker-session-context-service.js'

export async function unassignAdminWorkOrder(workOrderId: number | string, actorName = '') {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (workOrder.status !== WORK_ORDER_STATUS.IN_PROGRESS || !workOrder.assigned_worker_id) {
    throw createHttpError('只有进行中且已指派打手的订单可以取消指派', {
      statusCode: 409,
      errorCode: 'work_order_unassign_status_invalid',
    })
  }
  const { order: updated, failureReason } = await unassignWorkOrder({
    workOrderId: workOrder.id,
    now: nowIso(),
    actorName,
  })
  if (failureReason === 'work_order_not_in_progress') {
    throw createHttpError('订单状态已变化，无法取消指派', {
      statusCode: 409,
      errorCode: 'work_order_unassign_status_invalid',
    })
  }
  if (failureReason === 'work_order_no_worker') {
    throw createHttpError('该订单未指派打手', {
      statusCode: 409,
      errorCode: 'work_order_unassign_no_worker',
    })
  }
  if (!updated) {
    throw createHttpError('取消指派失败，订单状态可能已变化', {
      statusCode: 409,
      errorCode: 'work_order_unassign_conflict',
    })
  }
  const workerId = Number(workOrder.assigned_worker_id)
  publishWorkOrderRealtimeChange({ workOrderId: Number(workOrder.id), workerIds: [workerId] })
  publishWorkerWalletRealtimeChange(workerId)
  return { order: mapWorkOrderAdmin(updated) }
}

export async function cancelAdminWorkOrder(
  workOrderId: number | string,
  payload: JsonObject = {},
  actorName = '',
  actorPermissions: string[] = [],
) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (workOrder.status !== WORK_ORDER_STATUS.IN_PROGRESS || !workOrder.assigned_worker_id) {
    throw createHttpError('只有代练中且已接单的订单可以撤单', {
      statusCode: 409,
      errorCode: 'work_order_cancel_status_invalid',
    })
  }
  const action = String(payload.action || '').trim()
  if (!['return_to_hall', 'cancel_order'].includes(action)) {
    throw createHttpError('请选择撤单处理方式', {
      statusCode: 400,
      errorCode: 'work_order_cancel_action_required',
    })
  }
  const requiredPermission =
    action === 'return_to_hall' ? 'worker_order.return_to_hall' : 'worker_order.cancel'
  if (!actorPermissions.includes(requiredPermission)) {
    throw createHttpError('当前账号没有此撤单权限', {
      statusCode: 403,
      errorCode: 'admin_permission_denied',
    })
  }
  const reason = String(payload.reason || '').trim()
  if (action === 'cancel_order' && !reason) {
    throw createHttpError('取消订单时请填写退款或撤单原因', {
      statusCode: 400,
      errorCode: 'work_order_cancel_reason_required',
    })
  }
  const input = { workOrderId: workOrder.id, now: nowIso(), reason, actorName }
  const { order: updated, failureReason } =
    action === 'return_to_hall'
      ? await returnAssignedWorkOrderToHall(input)
      : await cancelAssignedWorkOrder(input)
  if (failureReason === 'work_order_not_in_progress') {
    throw createHttpError('订单状态已变化，无法撤单', {
      statusCode: 409,
      errorCode: 'work_order_cancel_status_invalid',
    })
  }
  if (failureReason === 'work_order_no_worker') {
    throw createHttpError('该订单尚未被打手接取', {
      statusCode: 409,
      errorCode: 'work_order_cancel_no_worker',
    })
  }
  if (!updated) {
    throw createHttpError('撤单失败，订单状态可能已变化', {
      statusCode: 409,
      errorCode: 'work_order_cancel_conflict',
    })
  }
  const workerId = Number(workOrder.assigned_worker_id)
  publishWorkOrderRealtimeChange({
    workOrderId: Number(workOrder.id),
    workerIds: workerId ? [workerId] : [],
    hallChanged: action === 'return_to_hall',
  })
  if (workerId) publishWorkerWalletRealtimeChange(workerId)
  return { order: mapWorkOrderAdmin(updated), action }
}
