import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
import {
  createWorkOrderEvent,
  deleteWorkOrder,
  listWorkOrderShares,
  listWorkOrders,
  publishUnassignedWorkOrder,
  reopenCancelledWorkOrder,
  resolveProblemWorkOrder,
  updateWorkOrder,
  updateWorkOrderBasic,
  updateWorkOrderAdminNote,
} 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 { resolveAdminNotificationEntity } from '../admin/admin-notification-service.js'
import { publishWorkOrderRealtimeChange } from '../realtime/realtime-event-service.js'
import {
  consumeIndustryVouchersBeforeWorkOrderPublish,
  type WorkOrderVoucherConsumeResult,
} from './publish-voucher-service.js'
import {
  mapWorkOrderAdmin,
  normalizeAmountFen,
  normalizeInteger,
  normalizeOptionalId,
  normalizeProblemResolutionAction,
  normalizeRequirementFieldsFromPayload,
  resolveRequirementFields,
} from './mappers.js'
import { resolveWorkOrderRealtimeWorkerIds } from './admin-work-order-realtime-service.js'
import { getWorkerHallConfig } from './worker-hall-config-service.js'
import { getRequiredWorkOrder } from './worker-session-context-service.js'
import { normalizeWorkOrderTimeoutPolicy } from './work-order-timeout-policy.js'

export async function updateAdminWorkOrder(
  workOrderId: number | string,
  payload: JsonObject = {},
  options: { canEditRequirementFields?: boolean; actorName?: string } = {},
) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (!mapWorkOrderAdmin(workOrder).capabilities.canEdit) {
    throw createHttpError('只有待完善、未分配或待抢单的工单可以编辑', {
      statusCode: 409,
      errorCode: 'work_order_edit_status_invalid',
    })
  }
  if (workOrder.assigned_worker_id) {
    throw createHttpError('工单已被打手接走，不能编辑', {
      statusCode: 409,
      errorCode: 'work_order_edit_assigned_invalid',
    })
  }

  const fields =
    options.canEditRequirementFields === false
      ? resolveRequirementFields(workOrder)
      : normalizeRequirementFieldsFromPayload(payload)
  const rewardAmount =
    payload.rewardAmount === undefined
      ? workOrder.reward_amount
      : normalizeAmountFen(payload.rewardAmount, workOrder.reward_amount)
  const requiredDepositAmount =
    payload.requiredDepositAmount === undefined
      ? workOrder.required_deposit_amount
      : normalizeAmountFen(payload.requiredDepositAmount, workOrder.required_deposit_amount)
  const depositThresholdAmount =
    payload.depositThresholdAmount === undefined
      ? workOrder.deposit_threshold_amount
      : normalizeAmountFen(payload.depositThresholdAmount, workOrder.deposit_threshold_amount)
  const categoryId =
    payload.categoryId === undefined || payload.categoryId === null || payload.categoryId === ''
      ? workOrder.category_id
      : (normalizeOptionalId(payload.categoryId) ?? workOrder.category_id)

  const now = nowIso()
  const updated = await updateWorkOrderBasic(workOrder.id, {
    productName: String(payload.productName ?? workOrder.product_name).trim(),
    platformOrderId: String(payload.platformOrderId ?? workOrder.platform_order_id ?? '').trim(),
    categoryId,
    rewardAmount,
    requiredDepositAmount,
    depositThresholdAmount,
    timeoutMinutes:
      payload.timeoutMinutes === undefined
        ? workOrder.timeout_minutes
        : Math.max(0, normalizeInteger(payload.timeoutMinutes, workOrder.timeout_minutes)),
    timeoutPolicy: normalizeWorkOrderTimeoutPolicy(
      payload.timeoutPolicy ?? workOrder.timeout_policy,
    ),
    requirementJson: JSON.stringify({ fields }),
    updatedAt: now,
  })
  await createWorkOrderEvent({
    workOrderId: workOrder.id,
    actorType: 'admin',
    actorId: options.actorName || '',
    eventType: 'edited',
    fromStatus: workOrder.status,
    toStatus: workOrder.status,
    payloadJson: JSON.stringify({
      productName: updated?.product_name,
      rewardAmount,
      requiredDepositAmount,
      timeoutMinutes: updated?.timeout_minutes,
      timeoutPolicy: updated?.timeout_policy,
      fields,
    }),
    now,
  })
  publishWorkOrderRealtimeChange({
    workOrderId: Number(workOrder.id),
    hallChanged: workOrder.status === WORK_ORDER_STATUS.OPEN,
  })
  return { order: mapWorkOrderAdmin(updated || workOrder) }
}

export async function updateAdminWorkOrderNote(
  workOrderId: number | string,
  note: unknown,
  actorName = '',
) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  const normalizedNote = String(note ?? '').trim()
  if (normalizedNote.length > 2000) {
    throw createHttpError('备注不能超过 2000 个字符', {
      statusCode: 400,
      errorCode: 'work_order_admin_note_too_long',
    })
  }
  const now = nowIso()
  const updated = await updateWorkOrderAdminNote(workOrder.id, normalizedNote, now)
  if (!updated) {
    throw createHttpError('保存工单备注失败', {
      statusCode: 409,
      errorCode: 'work_order_admin_note_update_failed',
    })
  }
  await createWorkOrderEvent({
    workOrderId: workOrder.id,
    actorType: 'admin',
    actorId: actorName,
    eventType: 'admin_note_updated',
    fromStatus: workOrder.status,
    toStatus: workOrder.status,
    payloadJson: JSON.stringify({ note: normalizedNote }),
    now,
  })
  return { order: mapWorkOrderAdmin(updated) }
}

export async function deleteAdminWorkOrder(workOrderId: number | string) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (!mapWorkOrderAdmin(workOrder).capabilities.canDelete) {
    throw createHttpError('只有待完善、未分配或已取消的工单可以删除', {
      statusCode: 409,
      errorCode: 'work_order_delete_status_invalid',
    })
  }
  if (workOrder.assigned_worker_id) {
    throw createHttpError('工单已被打手接走，不能删除', {
      statusCode: 409,
      errorCode: 'work_order_delete_assigned_invalid',
    })
  }
  const shares = await listWorkOrderShares(workOrder.id)
  const activeShares = shares.filter((share) => share.status !== 'cancelled')
  if (activeShares.length > 0) {
    throw createHttpError('工单存在参与中的拼单，不能删除', {
      statusCode: 409,
      errorCode: 'work_order_delete_has_shares',
    })
  }
  const deleted = await deleteWorkOrder(workOrder.id)
  if (!deleted) {
    throw createHttpError('工单删除失败', {
      statusCode: 500,
      errorCode: 'work_order_delete_failed',
    })
  }
  publishWorkOrderRealtimeChange({
    workOrderId: Number(workOrder.id),
    hallChanged: workOrder.status === WORK_ORDER_STATUS.OPEN,
  })
  return { deleted: true }
}

export async function reopenAdminCancelledWorkOrder(workOrderId: number | string, actorName = '') {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (!mapWorkOrderAdmin(workOrder).capabilities.canReopen) {
    throw createHttpError('只有没有有效拼单份额的已取消订单可以重新启用', {
      statusCode: 409,
      errorCode: 'work_order_reopen_status_invalid',
    })
  }

  const { order: updated, failureReason } = await reopenCancelledWorkOrder({
    workOrderId: Number(workOrder.id),
    now: nowIso(),
    actorName,
  })
  if (failureReason === 'work_order_has_active_shares') {
    throw createHttpError('该订单仍有有效拼单份额，不能重新启用', {
      statusCode: 409,
      errorCode: 'work_order_reopen_has_active_shares',
    })
  }
  if (!updated) {
    throw createHttpError('订单状态已变化，无法重新启用', {
      statusCode: 409,
      errorCode: 'work_order_reopen_conflict',
    })
  }

  publishWorkOrderRealtimeChange({ workOrderId: Number(workOrder.id), hallChanged: true })
  return { order: mapWorkOrderAdmin(updated) }
}

export async function publishAdminWorkOrder(workOrderId: number | string, actorName = '') {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (workOrder.status !== WORK_ORDER_STATUS.UNASSIGNED) {
    throw createHttpError('只有未分配订单可以发布到大厅', {
      statusCode: 409,
      errorCode: 'work_order_publish_status_invalid',
    })
  }
  if (Number(workOrder.reward_amount || 0) <= 0) {
    throw createHttpError('接单金额为 0，无法发布到大厅', {
      statusCode: 409,
      errorCode: 'work_order_publish_reward_invalid',
    })
  }

  const now = nowIso()
  const published = await publishUnassignedWorkOrder({
    workOrderId: workOrder.id,
    now,
    actorName,
  })
  if (!published.order) {
    throw createHttpError('订单状态已变化，无法发布，请刷新后重试', {
      statusCode: 409,
      errorCode: 'work_order_publish_conflict',
    })
  }

  let voucherConsume: WorkOrderVoucherConsumeResult
  try {
    voucherConsume = await consumeIndustryVouchersBeforeWorkOrderPublish(published.order)
  } catch (error) {
    voucherConsume = {
      ok: false,
      voucherCount: 0,
      consumedCount: 0,
      alreadyConsumedCount: 0,
      failedCount: 1,
      voucherCodes: [],
      errorMessage: error instanceof Error ? error.message : '电子凭证核销失败',
    }
  }
  if (!voucherConsume.ok) {
    await createWorkOrderEvent({
      workOrderId: workOrder.id,
      actorType: 'system',
      actorId: 'kuaishou_send_code',
      eventType: 'publish_voucher_consume_failed',
      fromStatus: WORK_ORDER_STATUS.OPEN,
      toStatus: WORK_ORDER_STATUS.OPEN,
      payloadJson: JSON.stringify(voucherConsume),
      now: nowIso(),
    })
  }

  const currentOrder = await getRequiredWorkOrder(workOrder.id)
  publishWorkOrderRealtimeChange({ workOrderId: Number(workOrder.id), hallChanged: true })
  const hallConfig = getWorkerHallConfig()
  const hallEntry = await listWorkOrders({
    page: 1,
    pageSize: 1,
    workOrderId: Number(workOrder.id),
    statuses: [WORK_ORDER_STATUS.OPEN],
    hallCandidateLimit: hallConfig.maxVisibleOrders,
    hallCategoryLimits: hallConfig.categoryMaxVisibleOrders,
    excludeFilledSharing: true,
  })
  return {
    order: mapWorkOrderAdmin(currentOrder),
    voucherConsume,
    hallVisible: hallEntry.total > 0,
  }
}

export async function unpublishAdminWorkOrder(workOrderId: number | string, actorName = '') {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (!mapWorkOrderAdmin(workOrder).capabilities.canUnpublish) {
    throw createHttpError('只有待抢单且未被接走的订单可以下架', {
      statusCode: 409,
      errorCode: 'work_order_unpublish_status_invalid',
    })
  }
  const now = nowIso()
  const updated = await updateWorkOrder(workOrder.id, {
    status: WORK_ORDER_STATUS.UNASSIGNED,
    published_at: null,
    updated_at: now,
  })
  await createWorkOrderEvent({
    workOrderId: workOrder.id,
    actorType: 'admin',
    actorId: actorName,
    eventType: 'unpublished',
    fromStatus: workOrder.status,
    toStatus: WORK_ORDER_STATUS.UNASSIGNED,
    now,
  })
  publishWorkOrderRealtimeChange({ workOrderId: Number(workOrder.id), hallChanged: true })
  return { order: mapWorkOrderAdmin(updated || workOrder) }
}

export async function pinAdminWorkOrder(
  workOrderId: number | string,
  payload: JsonObject = {},
  actorName = '',
) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  const pinned = payload.pinned === true
  const capabilities = mapWorkOrderAdmin(workOrder).capabilities
  if (pinned && (!capabilities.canPin || !mapWorkOrderAdmin(workOrder).hallAvailable)) {
    throw createHttpError('只有待抢单订单可以置顶', {
      statusCode: 409,
      errorCode: 'work_order_pin_status_invalid',
    })
  }
  const now = nowIso()
  const updated = await updateWorkOrder(workOrder.id, {
    pinned_at: pinned ? now : null,
    updated_at: now,
  })
  await createWorkOrderEvent({
    workOrderId: workOrder.id,
    actorType: 'admin',
    actorId: actorName,
    eventType: pinned ? 'pinned' : 'unpinned',
    fromStatus: workOrder.status,
    toStatus: workOrder.status,
    now,
  })
  publishWorkOrderRealtimeChange({ workOrderId: Number(workOrder.id), hallChanged: true })
  return { order: mapWorkOrderAdmin(updated || workOrder) }
}

export async function markAdminWorkOrderProblem(
  workOrderId: number | string,
  payload: JsonObject = {},
  actorName = '',
) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (!mapWorkOrderAdmin(workOrder).capabilities.canMarkProblem) {
    throw createHttpError('当前状态不能标记问题单', {
      statusCode: 409,
      errorCode: 'work_order_problem_status_invalid',
    })
  }
  const now = nowIso()
  const note = String(payload.note || payload.problemNote || '').trim()
  const updated = await updateWorkOrder(workOrder.id, {
    status: WORK_ORDER_STATUS.PROBLEM,
    problem_note: note,
    updated_at: now,
  })
  await createWorkOrderEvent({
    workOrderId: workOrder.id,
    actorType: 'admin',
    actorId: actorName,
    eventType: 'marked_problem',
    fromStatus: workOrder.status,
    toStatus: WORK_ORDER_STATUS.PROBLEM,
    payloadJson: JSON.stringify({ note }),
    now,
  })
  if (workOrder.status === WORK_ORDER_STATUS.PENDING_ACCEPTANCE) {
    await resolveAdminNotificationEntity('work_order', Number(workOrder.id), 'marked_problem')
  }
  publishWorkOrderRealtimeChange({
    workOrderId: Number(workOrder.id),
    workerIds: await resolveWorkOrderRealtimeWorkerIds(workOrder),
  })
  return { order: mapWorkOrderAdmin(updated || workOrder) }
}

export async function resolveAdminProblemWorkOrder(
  workOrderId: number | string,
  payload: JsonObject = {},
  actorName = '',
) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (workOrder.status !== WORK_ORDER_STATUS.PROBLEM) {
    throw createHttpError('只有问题单可以执行处置', {
      statusCode: 409,
      errorCode: 'work_order_problem_resolution_status_invalid',
    })
  }

  const action = normalizeProblemResolutionAction(payload.action)
  const note = String(payload.note || '').trim()
  if (!note) {
    throw createHttpError('请填写处置备注', {
      statusCode: 400,
      errorCode: 'work_order_problem_resolution_note_required',
    })
  }

  const updated = await resolveProblemWorkOrder({
    workOrderId: workOrder.id,
    action,
    note,
    now: nowIso(),
    actorName,
  })
  if (!updated) {
    throw createHttpError('问题单处置失败，订单状态可能已变化', {
      statusCode: 409,
      errorCode: 'work_order_problem_resolution_conflict',
    })
  }
  publishWorkOrderRealtimeChange({
    workOrderId: Number(workOrder.id),
    workerIds: await resolveWorkOrderRealtimeWorkerIds(workOrder),
  })
  return { order: mapWorkOrderAdmin(updated) }
}
