import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
import {
  acceptWorkOrderAndSettle,
  acceptWorkOrderShareAndSettle,
  cancelWorkOrderShare,
  cancelWorkOrderSharing,
  countWorkOrderPendingSharingSubmissions,
  updateWorkOrder,
} from '../../repositories/worker-platform/index.js'
import type { JsonObject } from '../../types/json.js'
import { createHttpError } from '../../utils/http.js'
import { getWorkerFinanceConfig } from './worker-finance-config-service.js'
import { nowIso } from '../../utils/time.js'
import { resolveAdminNotificationEntity } from '../admin/admin-notification-service.js'
import {
  publishWorkerWalletRealtimeChange,
  publishWorkOrderRealtimeChange,
} from '../realtime/realtime-event-service.js'
import {
  mapWorkOrderAdmin,
  mapWorkOrderShare,
  normalizeOptionalId,
  resolveWorkOrderOperationalStatus,
} from './mappers.js'
import { resolveWorkOrderRealtimeWorkerIds } from './admin-work-order-realtime-service.js'
import { getRequiredWorkOrder } from './worker-session-context-service.js'

export async function acceptAdminWorkOrder(workOrderId: number | string, actorName = '') {
  let workOrder = await getRequiredWorkOrder(workOrderId)
  if (!mapWorkOrderAdmin(workOrder).capabilities.canAccept) {
    throw createHttpError('只有待验收订单可以通过验收', {
      statusCode: 409,
      errorCode: 'work_order_accept_status_invalid',
    })
  }
  // 历史拼单订单可能仍保留 open，验收前先补齐母工单生命周期状态。
  if (workOrder.status === WORK_ORDER_STATUS.OPEN) {
    const promoted = await updateWorkOrder(workOrder.id, {
      status: WORK_ORDER_STATUS.PENDING_ACCEPTANCE,
      updated_at: nowIso(),
    })
    if (promoted) workOrder = promoted
  }
  const now = nowIso()
  const { order: updated, failureReason } = await acceptWorkOrderAndSettle({
    workOrderId: workOrder.id,
    ...resolveAcceptanceFinanceOptions(),
    now,
    actorType: 'admin',
    actorName,
  })
  if (failureReason === 'sharing_pending_submissions') {
    throw createHttpError('还有拼单打手未提交验收资料，暂不能统一验收', {
      statusCode: 409,
      errorCode: 'work_order_sharing_pending_submissions',
    })
  }
  if (!updated) {
    throw createHttpError('验收失败，订单状态可能已变化', {
      statusCode: 409,
      errorCode: 'work_order_accept_conflict',
    })
  }
  await resolveAdminNotificationEntity('work_order', Number(workOrder.id), 'accepted')
  const workerIds = await resolveWorkOrderRealtimeWorkerIds(workOrder)
  publishWorkOrderRealtimeChange({ workOrderId: Number(workOrder.id), workerIds })
  for (const workerId of workerIds) publishWorkerWalletRealtimeChange(workerId)
  return { order: mapWorkOrderAdmin(updated || workOrder) }
}

export async function acceptAdminWorkOrderShare(
  workOrderId: number | string,
  shareId: number | string,
  actorName = '',
) {
  const result = await acceptWorkOrderShareAndSettle({
    workOrderId: Number(workOrderId),
    shareId: Number(shareId),
    ...resolveAcceptanceFinanceOptions(),
    now: nowIso(),
    actorType: 'admin',
    actorName,
  })
  if (result.failureReason === 'work_order_not_accepting') {
    throw createHttpError('当前母工单不能验收拼单份额', {
      statusCode: 409,
      errorCode: 'work_order_sharing_accept_status_invalid',
    })
  }
  if (result.failureReason === 'share_not_submitted' || !result.share || !result.order) {
    throw createHttpError('该拼单参与者尚未提交验收资料或已被验收', {
      statusCode: 409,
      errorCode: 'work_order_sharing_share_accept_status_invalid',
    })
  }
  const workerId = Number(result.share.worker_id || 0)
  publishWorkOrderRealtimeChange({
    workOrderId: Number(workOrderId),
    workerIds: workerId > 0 ? [workerId] : [],
  })
  if (workerId > 0) publishWorkerWalletRealtimeChange(workerId)
  if (result.order.status === WORK_ORDER_STATUS.ACCEPTED) {
    await resolveAdminNotificationEntity('work_order', Number(workOrderId), 'accepted')
  }
  return { order: mapWorkOrderAdmin(result.order), share: mapWorkOrderShare(result.share) }
}

function resolveAcceptanceFinanceOptions() {
  const financeConfig = getWorkerFinanceConfig()
  return {
    unfreezeDays: financeConfig.depositUnfreezeDays,
    rewardUnfreezeEnabled: financeConfig.rewardUnfreezeEnabled,
  }
}

export async function cancelAdminWorkOrderShare(
  workOrderId: number | string,
  shareId: number | string,
  payload: JsonObject = {},
  actorName = '',
) {
  const result = await cancelWorkOrderShare({
    workOrderId: Number(workOrderId),
    shareId: Number(shareId),
    now: nowIso(),
    reason: String(payload.reason || '').trim(),
    actorName,
  })
  if (result.failureReason === 'work_order_not_cancellable') {
    throw createHttpError('当前拼单状态不能撤销参与者', {
      statusCode: 409,
      errorCode: 'work_order_sharing_cancel_status_invalid',
    })
  }
  if (result.failureReason === 'share_not_found') {
    throw createHttpError('未找到该拼单参与记录', {
      statusCode: 404,
      errorCode: 'work_order_sharing_share_not_found',
    })
  }
  if (result.failureReason === 'share_status_not_cancellable' || !result.share || !result.order) {
    throw createHttpError('只有已参与或已提交验收的拼单份额可以撤单', {
      statusCode: 409,
      errorCode: 'work_order_sharing_share_cancel_status_invalid',
    })
  }
  const workerId = Number(result.share.worker_id || 0)
  publishWorkOrderRealtimeChange({
    workOrderId: Number(workOrderId),
    workerIds: await resolveWorkOrderRealtimeWorkerIds(result.order),
    hallChanged: true,
  })
  if (workerId > 0) publishWorkerWalletRealtimeChange(workerId)
  return {
    order: mapWorkOrderAdmin(result.order),
    share: mapWorkOrderShare(result.share),
    releasedDepositAmount: result.releasedDepositAmount,
  }
}

export async function cancelAdminWorkOrderSharing(
  workOrderId: number | string,
  payload: JsonObject = {},
  actorName = '',
  actorPermissions: string[] = [],
) {
  const action = String(payload.action || '').trim()
  if (!['return_to_hall', 'cancel_order'].includes(action)) {
    throw createHttpError('请选择拼单撤单处理方式', {
      statusCode: 400,
      errorCode: 'work_order_sharing_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_sharing_cancel_reason_required',
    })
  }
  const result = await cancelWorkOrderSharing({
    workOrderId: Number(workOrderId),
    action: action as 'return_to_hall' | 'cancel_order',
    reason,
    now: nowIso(),
    actorName,
  })
  if (result.failureReason === 'work_order_not_cancellable') {
    throw createHttpError('当前订单不是可撤单的拼单', {
      statusCode: 409,
      errorCode: 'work_order_sharing_cancel_status_invalid',
    })
  }
  if (result.failureReason === 'no_cancellable_shares') {
    throw createHttpError('没有可撤销的未验收拼单份额', {
      statusCode: 409,
      errorCode: 'work_order_sharing_cancel_no_cancellable_shares',
    })
  }
  if (result.failureReason === 'accepted_shares_present') {
    throw createHttpError('存在已验收份额，不能取消整单；请通过售后处理退款', {
      statusCode: 409,
      errorCode: 'work_order_sharing_cancel_accepted_shares_present',
    })
  }
  if (!result.order) {
    throw createHttpError('拼单撤单失败，订单状态可能已变化', {
      statusCode: 409,
      errorCode: 'work_order_sharing_cancel_conflict',
    })
  }
  const activeWorkerIds = await resolveWorkOrderRealtimeWorkerIds(result.order)
  const workerIds = [...new Set([...activeWorkerIds, ...result.cancelledWorkerIds])]
  publishWorkOrderRealtimeChange({
    workOrderId: Number(workOrderId),
    workerIds,
    hallChanged: action === 'return_to_hall',
  })
  for (const workerId of result.cancelledWorkerIds) publishWorkerWalletRealtimeChange(workerId)
  return {
    order: mapWorkOrderAdmin(result.order),
    action,
    cancelledShareCount: result.cancelledShareCount,
    releasedDepositAmount: result.releasedDepositAmount,
  }
}

export async function acceptAdminWorkOrders(payload: JsonObject = {}, actorName = '') {
  const workOrderIds = [
    ...new Set(
      (Array.isArray(payload.workOrderIds) ? payload.workOrderIds : [])
        .map((item) => normalizeOptionalId(item))
        .filter((item): item is number => item !== null),
    ),
  ]
  if (workOrderIds.length === 0) {
    throw createHttpError('请至少选择一个待验收订单', {
      statusCode: 400,
      errorCode: 'work_order_batch_accept_required',
    })
  }
  const workOrders = await Promise.all(
    workOrderIds.map((workOrderId) => getRequiredWorkOrder(workOrderId)),
  )
  if (
    workOrders.some(
      (workOrder) =>
        resolveWorkOrderOperationalStatus(workOrder) !== WORK_ORDER_STATUS.PENDING_ACCEPTANCE,
    )
  ) {
    throw createHttpError('选中的订单包含非待验收状态，请刷新后重试', {
      statusCode: 409,
      errorCode: 'work_order_batch_accept_status_invalid',
    })
  }
  const pendingSharingCounts = await Promise.all(
    workOrders.map((workOrder) => countWorkOrderPendingSharingSubmissions(workOrder.id)),
  )
  if (pendingSharingCounts.some((count) => count > 0)) {
    throw createHttpError('选中的订单存在拼单打手未提交验收资料，暂不能统一验收', {
      statusCode: 409,
      errorCode: 'work_order_batch_accept_sharing_pending_submissions',
    })
  }
  const results = []
  for (const workOrder of workOrders)
    results.push(await acceptAdminWorkOrder(workOrder.id, actorName))
  return { orders: results.map((result) => result.order) }
}
