import crypto from 'node:crypto'

import { runtimeConfig } from '../../config/runtime.js'
import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
import { listOrderItemsByOrderId } from '../../repositories/order-item-repo.js'
import { findLatestOrderByAnyPlatformOrderId, getOrderById } from '../../repositories/order-repo.js'
import {
  acceptWorkOrderAndSettle,
  addWorkerWalletCredit,
  countWorkerAcceptedOrders,
  countWorkerActiveOrders,
  countWorkCategoryUsages,
  countWorkerLevelUsages,
  countWorkOrderPendingSharingSubmissions,
  countTimeoutEventsByWorkerIds,
  cancelWorkerWorkOrder,
  countWorkerCancellationsSince,
  createWorkOrder,
  createWorkOrderEvent,
  createWorkerFinanceRequest,
  createWorkerUser,
  deductPendingDepositUnfreeze,
  deleteWorkCategory,
  deleteWorkOrder,
  deleteWorkerLevel,
  getWorkerFinanceRequestById,
  getWorkerFinanceRequestSummary,
  getWorkCategoryById,
  getWorkCategoryByKey,
  getWorkerLevelById,
  getWorkerLevelByKey,
  getWorkerUserByInviteCode,
  getWorkerUserById,
  getWorkerUserByUsername,
  getWorkOrderById,
  getWorkOrderByOrderItemId,
  getWorkOrderShare,
  grabWorkOrder,
  incrementWorkerSessionVersion,
  joinWorkOrderShare,
  listAllWorkCategories,
  listPendingMaterialWorkOrdersByPlatformOrderId,
  listWorkerFinanceRequests,
  listWorkerSharesByWorker,
  listWorkerWalletLedgers,
  listWorkCategories,
  listWorkOrders,
  listWorkProductRules,
  listWorkerLevels,
  listWorkerUsers,
  listWorkOrderShares,
  listWorkOrderSharesByOrderIds,
  sumPendingUnfreezeByOrderIds,
  resolveProblemWorkOrder,
  reviewWorkerFinanceRequest,
  submitWorkOrderShareAcceptance,
  updateWorkOrder,
  updateWorkOrderBasic,
  updateWorkerPassword,
  updateWorkerUser,
  upsertWorkCategory,
  upsertWorkProductRule,
  upsertWorkerLevel,
  type WorkCategoryRow,
  type WorkerFinanceRequestRow,
  type WorkOrderRow,
  type WorkProductRuleRow,
  type WorkerLevelRow,
  type WorkOrderShareRow,
  type WorkerWalletLedgerRow,
  type WorkerUserRow,
  type GrabWorkOrderFailureReason,
  type ProblemWorkOrderResolutionAction,
} from '../../repositories/worker-platform/index.js'
import type { JsonObject } from '../../types/json.js'
import type { OrderItemRow, OrderRow } from '../../types/repository/rows.js'
import { createHttpError } from '../../utils/http.js'
import { randomId } from '../../utils/random.js'
import { nowIso, addHours } from '../../utils/time.js'
import { normalizePage, normalizePageSize, safeParseJson } from '../admin/admin-query-utils.js'
import {
  normalizeStoredFileUrl,
  refreshStoredFileUrl,
  refreshUploadedFileUrls,
} from '../file-storage/file-storage-service.js'
import {
  getWorkerFinanceConfig,
  saveWorkerFinanceConfig,
} from './worker-finance-config-service.js'

import { DEFAULT_CATEGORY_KEY, DEFAULT_DEPOSIT_THRESHOLD_AMOUNT, DEFAULT_LEVEL_KEY, DEFAULT_LEVEL_NAME, mapFinanceRequest, mapWallet, mapWorkCategory, mapWorkOrderAdmin, mapWorkOrderShare, mapWorkProductRule, mapWorkerLevel, mapWorkerUser, normalizeAdminFinanceReviewStatus, normalizeAmountFen, normalizeBoolean, normalizeEnabledStatus, normalizeFinanceRequestStatus, normalizeFinanceRequestType, normalizeInteger, normalizeMatchType, normalizeOptionalId, normalizePositiveInteger, normalizeProblemResolutionAction, normalizeRequirementFields, normalizeRequirementFieldsFromPayload, normalizeReviewStatus, normalizeSessionVersion, normalizeSlugKey, normalizeSubmittedFields, normalizeUploadedFiles, resolveMatchingProductRule, resolveRequirementFields } from './mappers.js'
import { ensureWorkerPlatformDefaults, getRequiredWorkOrder, getRequiredWorker, normalizeWorkOrderTimeoutPolicy } from './worker-service.js'

export async function listAdminWorkerLevels() {
  await ensureWorkerPlatformDefaults()
  return { items: (await listWorkerLevels()).map(mapWorkerLevel) }
}

export async function listAdminWorkCategories() {
  await ensureWorkerPlatformDefaults()
  return { items: (await listAllWorkCategories()).map(mapWorkCategory) }
}

export async function saveAdminWorkCategory(payload: JsonObject = {}) {
  const now = nowIso()
  const categoryKey = normalizeSlugKey(
    payload.categoryKey || payload.category_key || payload.name,
    DEFAULT_CATEGORY_KEY,
  )
  const name = String(payload.name || '').trim() || '默认分类'
  const category = await upsertWorkCategory({
    categoryKey,
    name,
    sortOrder: normalizeInteger(payload.sortOrder, 100),
    status: normalizeEnabledStatus(payload.status),
    now,
  })
  return { category: mapWorkCategory(category) }
}

export async function deleteAdminWorkCategory(categoryId: number | string) {
  const category = await getWorkCategoryById(Number(categoryId))
  if (!category) {
    throw createHttpError('分类不存在', {
      statusCode: 404,
      errorCode: 'work_category_not_found',
    })
  }
  const usages = await countWorkCategoryUsages(Number(categoryId))
  if (usages.workOrderCount > 0 || usages.productRuleCount > 0) {
    throw createHttpError(
      `该分类已被 ${usages.workOrderCount} 个工单和 ${usages.productRuleCount} 条物品规则使用，无法删除，请先停用`,
      {
        statusCode: 409,
        errorCode: 'work_category_in_use',
      },
    )
  }
  const { deleted } = await deleteWorkCategory(Number(categoryId))
  return { deleted }
}

export async function saveAdminWorkerLevel(payload: JsonObject = {}) {
  const now = nowIso()
  const levelKey = String(payload.levelKey || payload.level_key || '').trim() || DEFAULT_LEVEL_KEY
  const name = String(payload.name || '').trim() || DEFAULT_LEVEL_NAME
  const permissions = {
    depositFreeAmount: normalizeAmountFen(
      payload.depositFreeAmount ?? payload.depositFreeAmountYuan,
      0,
    ),
    maxActiveOrders: normalizePositiveInteger(payload.maxActiveOrders, 1),
    upgradeThreshold: normalizeInteger(payload.upgradeThreshold, 0),
    visibleDelaySeconds: normalizeInteger(payload.visibleDelaySeconds, -1),
  }
  const level = await upsertWorkerLevel({
    levelKey,
    name,
    sortOrder: normalizeInteger(payload.sortOrder, 100),
    status: String(payload.status || 'active').trim() === 'disabled' ? 'disabled' : 'active',
    permissionJson: JSON.stringify(permissions),
    now,
  })
  return { level: mapWorkerLevel(level) }
}

export async function deleteAdminWorkerLevel(levelId: number | string) {
  const level = await getWorkerLevelById(Number(levelId))
  if (!level) {
    throw createHttpError('等级不存在', {
      statusCode: 404,
      errorCode: 'worker_level_not_found',
    })
  }
  if (level.level_key === DEFAULT_LEVEL_KEY) {
    throw createHttpError('默认等级（VIP1）不可删除', {
      statusCode: 409,
      errorCode: 'worker_level_default_protected',
    })
  }
  const usageCount = await countWorkerLevelUsages(Number(levelId))
  if (usageCount > 0) {
    throw createHttpError(`该等级正在被 ${usageCount} 名打手使用，请先调整打手等级后再删除`, {
      statusCode: 409,
      errorCode: 'worker_level_in_use',
    })
  }
  const { deleted } = await deleteWorkerLevel(Number(levelId))
  return { deleted }
}

export async function listAdminWorkProductRules(query: JsonObject = {}) {
  await ensureWorkerPlatformDefaults()
  const enabledValue = String(query.enabled ?? '').trim()
  const enabled = enabledValue
    ? ['true', '1', 'enabled', 'active'].includes(enabledValue.toLowerCase())
    : null
  const items = await listWorkProductRules({
    enabled,
    keyword: String(query.keyword || '').trim(),
  })
  return { items: items.map(mapWorkProductRule) }
}

export async function saveAdminWorkProductRule(payload: JsonObject = {}) {
  const defaults = await ensureWorkerPlatformDefaults()
  const productName = String(
    payload.productName || payload.product_name || payload.skuName || '',
  ).trim()
  const skuCode = String(payload.skuCode || payload.sku_code || '').trim()
  if (!productName && !skuCode) {
    throw createHttpError('请填写商品名或 SKU', {
      statusCode: 400,
      errorCode: 'work_product_rule_target_required',
    })
  }

  const rewardAmount = normalizeAmountFen(payload.rewardAmount ?? payload.rewardAmountYuan, 0)
  const sharingEnabled = normalizeBoolean(
    payload.sharingEnabled ?? payload.sharing_enabled,
    false,
  )
  const sharingUnitReward = normalizeAmountFen(
    payload.sharingUnitReward ?? payload.sharingUnitRewardYuan,
    0,
  )
  const sharingTotalAmount = normalizeAmountFen(
    payload.sharingTotalAmount ?? payload.sharingTotalAmountYuan,
    0,
  )
  const sharingTotalQuantity = resolveSharingQuantity(
    sharingTotalAmount,
    normalizePositiveInteger(payload.sharingTotalQuantity ?? payload.sharing_total_quantity, 1),
    sharingUnitReward,
  )
  const resolvedSharingTotalAmount =
    sharingTotalAmount > 0 ? sharingTotalAmount : sharingUnitReward * sharingTotalQuantity
  if (sharingEnabled) {
    if (resolvedSharingTotalAmount <= 0) {
      throw createHttpError('启用拼单时请填写拼单总价或单价', {
        statusCode: 400,
        errorCode: 'work_product_rule_sharing_amount_invalid',
      })
    }
  } else if (rewardAmount <= 0) {
    throw createHttpError('接单金额必须大于 0', {
      statusCode: 400,
      errorCode: 'work_product_rule_reward_invalid',
    })
  }
  const finalRewardAmount = sharingEnabled ? resolvedSharingTotalAmount : rewardAmount

  const depositThresholdAmount = normalizeAmountFen(
    payload.depositThresholdAmount ?? payload.depositThresholdAmountYuan,
    DEFAULT_DEPOSIT_THRESHOLD_AMOUNT,
  )
  const requiredDepositAmount =
    payload.requiredDepositAmount === undefined && payload.requiredDepositAmountYuan === undefined
      ? finalRewardAmount > depositThresholdAmount
        ? finalRewardAmount
        : 0
      : normalizeAmountFen(payload.requiredDepositAmount ?? payload.requiredDepositAmountYuan, 0)
  const fields = normalizeRequirementFieldsFromPayload(payload)
  const rule = await upsertWorkProductRule({
    ruleKey: normalizeSlugKey(
      payload.ruleKey || payload.rule_key || skuCode || productName,
      `rule-${Date.now()}`,
    ),
    provider: String(payload.provider || '').trim(),
    platform: String(payload.platform || '').trim(),
    shopId: String(payload.shopId || payload.shop_id || '').trim(),
    skuCode,
    productName,
    matchType: normalizeMatchType(payload.matchType || payload.match_type),
    categoryId:
      normalizeOptionalId(payload.categoryId || payload.category_id) ||
      defaults.category?.id ||
      null,
    enabled: normalizeBoolean(payload.enabled, true),
    autoCreate: normalizeBoolean(payload.autoCreate ?? payload.auto_create, false),
    rewardAmount: finalRewardAmount,
    requiredDepositAmount,
    depositThresholdAmount,
    sharingEnabled,
    sharingTotalQuantity,
    sharingUnitReward,
    timeoutMinutes: Math.max(0, normalizeInteger(payload.timeoutMinutes, 0)),
    timeoutPolicy: normalizeWorkOrderTimeoutPolicy(payload.timeoutPolicy),
    requirementJson: JSON.stringify({ fields }),
    sortOrder: normalizeInteger(payload.sortOrder, 100),
    now: nowIso(),
  })
  return { rule: mapWorkProductRule(rule) }
}

export async function listAdminWorkerUsers(query: JsonObject = {}) {
  const page = normalizePage(query.page)
  const pageSize = normalizePageSize(query.pageSize)
  const { items, total } = await listWorkerUsers({
    page,
    pageSize,
    status: String(query.status || '').trim(),
    keyword: String(query.keyword || '').trim(),
  })
  const timeoutCounts = await countTimeoutEventsByWorkerIds(
    items.map((item) => Number(item.id)),
  )
  return {
    items: items.map((item) => {
      const worker = mapWorkerUser(item)
      return {
        ...worker,
        timeoutOrderCount: timeoutCounts.get(Number(item.id)) || 0,
      }
    }),
    pagination: { page, pageSize, total },
  }
}

export async function reviewAdminWorkerUser(workerId: number | string, payload: JsonObject = {}) {
  const worker = await getRequiredWorker(workerId)
  const status = normalizeReviewStatus(payload.status)
  const requestedLevelId = normalizeOptionalId(payload.levelId)
  let levelId = worker.level_id || null
  if (requestedLevelId) {
    const level = await getWorkerLevelById(requestedLevelId)
    if (!level) {
      throw createHttpError('接单等级不存在', {
        statusCode: 404,
        errorCode: 'worker_level_not_found',
      })
    }
    levelId = Number(level.id)
  }
  if (!levelId) {
    levelId = (await ensureWorkerPlatformDefaults()).level?.id || null
  }
  const now = nowIso()
  const updated = await updateWorkerUser(worker.id, {
    status,
    level_id: levelId,
    review_note: String(payload.reviewNote || payload.note || '').trim(),
    session_version: normalizeSessionVersion(worker.session_version) + 1,
    reviewed_at: now,
    updated_at: now,
  })
  return { worker: mapWorkerUser(updated || worker) }
}

export async function creditAdminWorkerWallet(workerId: number | string, payload: JsonObject = {}) {
  await getRequiredWorker(workerId)
  const amount = normalizeAmountFen(payload.amount ?? payload.amountYuan, 0)
  if (amount <= 0) {
    throw createHttpError('充值金额必须大于 0', {
      statusCode: 400,
      errorCode: 'worker_credit_amount_invalid',
    })
  }
  const wallet = await addWorkerWalletCredit({
    workerId: Number(workerId),
    amount,
    note: String(payload.note || '后台人工充值').trim(),
    payloadJson: JSON.stringify({ source: 'admin_manual_credit' }),
    now: nowIso(),
  })
  return { wallet: mapWallet(wallet) }
}

export async function getAdminWorkerFinanceConfig() {
  return getWorkerFinanceConfig()
}

export async function saveAdminWorkerFinanceConfig(payload: JsonObject = {}) {
  const config = await saveWorkerFinanceConfig(payload)
  return config
}

export async function listAdminWorkerFinanceRequests(query: JsonObject = {}) {
  const page = normalizePage(query.page)
  const pageSize = normalizePageSize(query.pageSize)
  const status = normalizeFinanceRequestStatus(query.status)
  const requestType = normalizeFinanceRequestType(query.requestType)
  const keyword = String(query.keyword || '').trim()
  const { items, total } = await listWorkerFinanceRequests({
    page,
    pageSize,
    status,
    requestType,
    keyword,
  })
  return {
    items: items.map(mapFinanceRequest),
    pagination: { page, pageSize, total },
  }
}

export async function reviewAdminWorkerFinanceRequest(
  requestId: number | string,
  payload: JsonObject = {},
) {
  const current = await getWorkerFinanceRequestById(requestId)
  if (!current) {
    throw createHttpError('资金申请不存在', {
      statusCode: 404,
      errorCode: 'worker_finance_request_not_found',
    })
  }

  const status = normalizeAdminFinanceReviewStatus(payload.status)
  const reviewedNote = String(payload.reviewedNote || payload.note || '').trim()
  const reviewed = await reviewWorkerFinanceRequest({
    requestId: Number(current.id),
    status,
    reviewedNote,
    now: nowIso(),
  })

  if (reviewed.failureReason === 'request_not_pending') {
    throw createHttpError('该申请已处理，请刷新后重试', {
      statusCode: 409,
      errorCode: 'worker_finance_request_reviewed',
    })
  }

  if (reviewed.failureReason === 'withdraw_insufficient') {
    throw createHttpError('打手余额不足，暂时无法通过该提现申请', {
      statusCode: 409,
      errorCode: 'worker_finance_request_withdraw_insufficient',
    })
  }

  if (!reviewed.request) {
    throw createHttpError('资金申请不存在', {
      statusCode: 404,
      errorCode: 'worker_finance_request_not_found',
    })
  }

  return {
    request: mapFinanceRequest(reviewed.request),
  }
}

export async function listAdminWorkOrders(query: JsonObject = {}) {
  const page = normalizePage(query.page)
  const pageSize = normalizePageSize(query.pageSize)
  const { items, total } = await listWorkOrders({
    page,
    pageSize,
    status: String(query.status || '').trim(),
    keyword: String(query.keyword || '').trim(),
  })
  const shares = await listWorkOrderSharesByOrderIds(items.map((item) => Number(item.id)))
  const sharesByOrderId = new Map<number, WorkOrderShareRow[]>()
  for (const share of shares) {
    const orderId = Number(share.work_order_id)
    const bucket = sharesByOrderId.get(orderId) || []
    bucket.push(share)
    sharesByOrderId.set(orderId, bucket)
  }
  const pendingUnfreezeByOrderId = await sumPendingUnfreezeByOrderIds(
    items.map((item) => Number(item.id)),
  )
  return {
    items: items.map((item) => {
      const orderShares = sharesByOrderId.get(Number(item.id)) || []
      const joinedQuantity = orderShares
        .filter((share) => share.status !== 'cancelled')
        .reduce((sum, share) => sum + Number(share.quantity || 0), 0)
      const pendingSubmissionCount = orderShares.filter(
        (share) => share.status === 'joined',
      ).length
      return {
        ...mapWorkOrderAdmin(item),
        pendingUnfreezeAmount: pendingUnfreezeByOrderId.get(Number(item.id)) || 0,
        sharingProgress: {
          joinedQuantity,
          pendingSubmissionCount,
        },
      }
    }),
    pagination: { page, pageSize, total },
  }
}

export async function deductAdminWorkOrderPendingDeposit(
  workOrderId: number | string,
  payload: JsonObject = {},
) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (workOrder.status !== WORK_ORDER_STATUS.ACCEPTED) {
    throw createHttpError('只有已验收的工单可以扣减待解冻押金', {
      statusCode: 409,
      errorCode: 'work_order_deduct_pending_status_invalid',
    })
  }
  const amount = normalizeAmountFen(payload.amount ?? payload.amountYuan, 0)
  const note = String(payload.note || payload.reason || '').trim()
  if (amount <= 0) {
    throw createHttpError('扣减金额必须大于 0', {
      statusCode: 400,
      errorCode: 'work_order_deduct_pending_amount_invalid',
    })
  }
  if (!note) {
    throw createHttpError('请填写扣减原因', {
      statusCode: 400,
      errorCode: 'work_order_deduct_pending_note_required',
    })
  }
  const result = await deductPendingDepositUnfreeze({
    workOrderId: workOrder.id,
    amount,
    note,
    now: nowIso(),
  })
  if (result.failureReason === 'no_pending_deposit') {
    throw createHttpError('该工单没有待解冻的押金', {
      statusCode: 409,
      errorCode: 'work_order_deduct_pending_none',
    })
  }
  if (result.failureReason === 'amount_exceeds_pending') {
    throw createHttpError('扣减金额超过该工单待解冻押金总额', {
      statusCode: 409,
      errorCode: 'work_order_deduct_pending_amount_exceeds',
    })
  }
  await createWorkOrderEvent({
    workOrderId: workOrder.id,
    actorType: 'admin',
    actorId: '',
    eventType: 'pending_deposit_deducted',
    fromStatus: workOrder.status,
    toStatus: workOrder.status,
    payloadJson: JSON.stringify({ amount, note }),
    now: nowIso(),
  })
  return { deductedAmount: result.deductedAmount }
}

export async function getAdminWorkOrderSharing(workOrderId: number | string) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  const shares = await listWorkOrderShares(workOrder.id)
  return {
    order: mapWorkOrderAdmin(workOrder),
    shares: shares.map(mapWorkOrderShare),
  }
}

export async function updateAdminWorkOrderSharing(
  workOrderId: number | string,
  payload: JsonObject = {},
) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (![WORK_ORDER_STATUS.PENDING_MATERIAL, WORK_ORDER_STATUS.UNASSIGNED, WORK_ORDER_STATUS.OPEN].includes(workOrder.status as never)) {
    throw createHttpError('只有待完善、未分配或待抢单的工单可以配置拼单', {
      statusCode: 409,
      errorCode: 'work_order_sharing_config_status_invalid',
    })
  }
  const enabled = normalizeBoolean(
    payload.enabled ?? payload.sharingEnabled ?? payload.sharing_enabled,
    false,
  )
  const unitReward = normalizeAmountFen(
    payload.unitReward ?? payload.sharingUnitReward ?? payload.sharingUnitRewardYuan,
    0,
  )
  const totalAmount = normalizeAmountFen(
    payload.totalAmount ?? payload.sharingTotalAmount ?? payload.sharingTotalAmountYuan,
    0,
  )
  const totalQuantity = resolveSharingQuantity(
    totalAmount,
    normalizePositiveInteger(
      payload.totalQuantity ?? payload.sharingTotalQuantity ?? payload.sharing_total_quantity,
      1,
    ),
    unitReward,
  )
  const resolvedTotalAmount = totalAmount > 0 ? totalAmount : unitReward * totalQuantity
  const now = nowIso()
  const updated = await updateWorkOrder(workOrder.id, {
    sharing_enabled: enabled,
    sharing_total_quantity: totalQuantity,
    sharing_unit_reward: unitReward,
    reward_amount: enabled ? resolvedTotalAmount : workOrder.reward_amount,
    updated_at: now,
  })
  await createWorkOrderEvent({
    workOrderId: workOrder.id,
    actorType: 'admin',
    actorId: '',
    eventType: 'sharing_config_updated',
    fromStatus: workOrder.status,
    toStatus: updated?.status || workOrder.status,
    payloadJson: JSON.stringify({
      enabled,
      totalQuantity,
      unitReward,
      totalAmount: resolvedTotalAmount,
    }),
    now,
  })
  return { order: mapWorkOrderAdmin(updated || workOrder) }
}

function resolveSharingQuantity(
  totalAmount: number,
  fallbackQuantity: number,
  unitReward: number,
): number {
  if (totalAmount > 0 && unitReward > 0) {
    return Math.max(1, Math.round(totalAmount / unitReward))
  }
  return Math.max(1, fallbackQuantity)
}

export async function submitAdminWorkOrderMaterial(
  workOrderId: number | string,
  payload: JsonObject = {},
) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (
    ![WORK_ORDER_STATUS.PENDING_MATERIAL, WORK_ORDER_STATUS.UNASSIGNED].includes(
      workOrder.status as never,
    )
  ) {
    throw createHttpError('当前状态不能补充资料', {
      statusCode: 409,
      errorCode: 'work_order_material_status_invalid',
    })
  }

  const fields = resolveRequirementFields(workOrder)
  const submittedFields = normalizeSubmittedFields(payload.fields || payload.material || payload)
  const complete = fields.every(
    (field) => !field.required || String(submittedFields[field.key] || '').trim(),
  )
  const now = nowIso()
  const screenshots = normalizeUploadedFiles(payload.screenshots || payload.files)
  const material = {
    ...safeParseJson(workOrder.material_json),
    collect: {
      fields: submittedFields,
      screenshots,
      submittedAt: now,
      complete,
      source: 'admin',
    },
  }
  const nextStatus = complete ? WORK_ORDER_STATUS.UNASSIGNED : WORK_ORDER_STATUS.PENDING_MATERIAL
  const updated = await updateWorkOrder(workOrder.id, {
    status: nextStatus,
    material_json: material,
    updated_at: now,
  })
  await createWorkOrderEvent({
    workOrderId: workOrder.id,
    actorType: 'admin',
    actorId: '',
    eventType: 'material_completed',
    fromStatus: workOrder.status,
    toStatus: nextStatus,
    payloadJson: JSON.stringify({ fields: submittedFields, complete }),
    now,
  })
  return { order: mapWorkOrderAdmin(updated || workOrder), complete }
}

export async function syncAdminWorkerOrdersFromSource(payload: JsonObject = {}) {
  const order = await resolveSourceOrder(payload)
  const orderItems = await listOrderItemsByOrderId(order.id)
  const result = await syncWorkerOrdersForSourceOrder(order, orderItems, {
    source: 'admin_manual_sync',
    autoOnly: false,
  })
  return result
}

export async function createAdminMockWorkOrder(payload: JsonObject = {}) {
  const defaults = await ensureWorkerPlatformDefaults()
  const now = nowIso()
  const rewardAmount = normalizeAmountFen(payload.rewardAmount ?? payload.rewardAmountYuan, 2500)
  const depositThresholdAmount = normalizeAmountFen(
    payload.depositThresholdAmount ?? payload.depositThresholdAmountYuan,
    DEFAULT_DEPOSIT_THRESHOLD_AMOUNT,
  )
  const requiredDepositAmount =
    payload.requiredDepositAmount === undefined
      ? rewardAmount > depositThresholdAmount
        ? rewardAmount
        : 0
      : normalizeAmountFen(payload.requiredDepositAmount, 0)
  const materialComplete = payload.materialComplete === true || payload.materialComplete === 'true'
  const fields = normalizeRequirementFields(payload.fields)
  const platformOrderId = String(
    payload.platformOrderId || payload.orderNo || `MOCKWORK${Date.now()}`,
  ).trim()
  const productName = String(payload.productName || '指挥官秘钥1个').trim()
  const material = materialComplete
    ? {
        collect: {
          complete: true,
          submittedAt: now,
          fields: fields.reduce<Record<string, string>>((result, field) => {
            result[field.key] = String(field.mockValue || `${field.label}测试值`)
            return result
          }, {}),
        },
      }
    : {}
  const workOrder = await createWorkOrder({
    workOrderNo: randomId('WO'),
    platformOrderId,
    productName,
    categoryId: defaults.category?.id || null,
    status: materialComplete ? WORK_ORDER_STATUS.UNASSIGNED : WORK_ORDER_STATUS.PENDING_MATERIAL,
    rewardAmount,
    requiredDepositAmount,
    depositThresholdAmount,
    timeoutMinutes: Math.max(0, normalizeInteger(payload.timeoutMinutes, 0)),
    timeoutPolicy: normalizeWorkOrderTimeoutPolicy(payload.timeoutPolicy),
    materialJson: JSON.stringify(material),
    requirementJson: JSON.stringify({ fields }),
    now,
  })
  if (!workOrder) {
    throw createHttpError('接单工单创建失败', {
      statusCode: 500,
      errorCode: 'work_order_create_failed',
    })
  }
  await createWorkOrderEvent({
    workOrderId: workOrder.id,
    actorType: 'admin',
    actorId: 'dev_mock',
    eventType: 'mock_created',
    fromStatus: '',
    toStatus: workOrder.status,
    payloadJson: JSON.stringify({ platformOrderId, productName, rewardAmount }),
    now,
  })
  return { order: mapWorkOrderAdmin(workOrder) }
}

export async function updateAdminWorkOrder(
  workOrderId: number | string,
  payload: JsonObject = {},
) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (
    ![
      WORK_ORDER_STATUS.PENDING_MATERIAL,
      WORK_ORDER_STATUS.UNASSIGNED,
      WORK_ORDER_STATUS.OPEN,
    ].includes(workOrder.status as never)
  ) {
    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 = 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: '',
    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,
  })
  return { order: mapWorkOrderAdmin(updated || workOrder) }
}

export async function deleteAdminWorkOrder(workOrderId: number | string) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (
    ![
      WORK_ORDER_STATUS.PENDING_MATERIAL,
      WORK_ORDER_STATUS.UNASSIGNED,
      WORK_ORDER_STATUS.CANCELLED,
    ].includes(workOrder.status as never)
  ) {
    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',
    })
  }
  return { deleted: true }
}

export async function publishAdminWorkOrder(workOrderId: number | string) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (workOrder.status !== WORK_ORDER_STATUS.UNASSIGNED) {
    throw createHttpError('只有未分配订单可以发布到大厅', {
      statusCode: 409,
      errorCode: 'work_order_publish_status_invalid',
    })
  }
  const now = nowIso()
  const updated = await updateWorkOrder(workOrder.id, {
    status: WORK_ORDER_STATUS.OPEN,
    published_at: now,
    updated_at: now,
  })
  await createWorkOrderEvent({
    workOrderId: workOrder.id,
    actorType: 'admin',
    actorId: '',
    eventType: 'published',
    fromStatus: workOrder.status,
    toStatus: WORK_ORDER_STATUS.OPEN,
    now,
  })
  return { order: mapWorkOrderAdmin(updated || workOrder) }
}

export async function unpublishAdminWorkOrder(workOrderId: number | string) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (workOrder.status !== WORK_ORDER_STATUS.OPEN || workOrder.assigned_worker_id) {
    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: '',
    eventType: 'unpublished',
    fromStatus: workOrder.status,
    toStatus: WORK_ORDER_STATUS.UNASSIGNED,
    now,
  })
  return { order: mapWorkOrderAdmin(updated || workOrder) }
}

export async function markAdminWorkOrderProblem(
  workOrderId: number | string,
  payload: JsonObject = {},
) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (
    ![WORK_ORDER_STATUS.IN_PROGRESS, WORK_ORDER_STATUS.PENDING_ACCEPTANCE].includes(
      workOrder.status as never,
    )
  ) {
    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: '',
    eventType: 'marked_problem',
    fromStatus: workOrder.status,
    toStatus: WORK_ORDER_STATUS.PROBLEM,
    payloadJson: JSON.stringify({ note }),
    now,
  })
  return { order: mapWorkOrderAdmin(updated || workOrder) }
}

export async function resolveAdminProblemWorkOrder(
  workOrderId: number | string,
  payload: JsonObject = {},
) {
  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(),
  })
  if (!updated) {
    throw createHttpError('问题单处置失败，订单状态可能已变化', {
      statusCode: 409,
      errorCode: 'work_order_problem_resolution_conflict',
    })
  }
  return { order: mapWorkOrderAdmin(updated) }
}

export async function acceptAdminWorkOrder(workOrderId: number | string) {
  const workOrder = await getRequiredWorkOrder(workOrderId)
  if (workOrder.status !== WORK_ORDER_STATUS.PENDING_ACCEPTANCE) {
    throw createHttpError('只有待验收订单可以通过验收', {
      statusCode: 409,
      errorCode: 'work_order_accept_status_invalid',
    })
  }
  const now = nowIso()
  const { order: updated, failureReason } = await acceptWorkOrderAndSettle({
    workOrderId: workOrder.id,
    unfreezeDays: getWorkerFinanceConfig().depositUnfreezeDays,
    now,
  })
  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',
    })
  }
  return { order: mapWorkOrderAdmin(updated || workOrder) }
}

export async function getAdminWorkerPlatformSummary() {
  const [pendingWorkers, pendingMaterial, openOrders, inProgressOrders] = await Promise.all([
    listWorkerUsers({ page: 1, pageSize: 1, status: 'pending_review' }),
    listWorkOrders({ page: 1, pageSize: 1, status: WORK_ORDER_STATUS.PENDING_MATERIAL }),
    listWorkOrders({ page: 1, pageSize: 1, status: WORK_ORDER_STATUS.OPEN }),
    listWorkOrders({ page: 1, pageSize: 1, status: WORK_ORDER_STATUS.IN_PROGRESS }),
  ])
  return {
    pendingWorkerCount: pendingWorkers.total,
    pendingMaterialCount: pendingMaterial.total,
    openOrderCount: openOrders.total,
    inProgressOrderCount: inProgressOrders.total,
  }
}

export async function syncWorkerOrdersForSourceOrder(
  order: OrderRow,
  orderItems: OrderItemRow[],
  options: { source?: string; autoOnly?: boolean } = {},
) {
  const rules = await listWorkProductRules({ enabled: true })
  const created: WorkOrderRow[] = []
  const skipped: Array<{ orderItemId: number; reason: string }> = []

  for (const item of orderItems) {
    const rule = resolveMatchingProductRule(order, item, rules)
    if (!rule) {
      skipped.push({ orderItemId: Number(item.id), reason: 'rule_not_matched' })
      continue
    }
    if (options.autoOnly && !rule.auto_create) {
      skipped.push({ orderItemId: Number(item.id), reason: 'auto_create_disabled' })
      continue
    }
    if (await getWorkOrderByOrderItemId(item.id)) {
      skipped.push({ orderItemId: Number(item.id), reason: 'already_exists' })
      continue
    }

    const fields = normalizeRequirementFields(safeParseJson(rule.requirement_json).fields)
    const rewardAmount = Number(rule.reward_amount || 0)
    const depositThresholdAmount = Number(
      rule.deposit_threshold_amount || DEFAULT_DEPOSIT_THRESHOLD_AMOUNT,
    )
    const requiredDepositAmount =
      Number(rule.required_deposit_amount || 0) ||
      (rewardAmount > depositThresholdAmount ? rewardAmount : 0)
    const now = nowIso()
    const materialComplete = fields.every((field) => !field.required)
    const workOrder = await createWorkOrder({
      workOrderNo: randomId('WO'),
      orderId: Number(order.id),
      orderItemId: Number(item.id),
      taskId: null,
      platformOrderId: order.platform_order_id,
      productName: item.sku_name || item.sku_code,
      categoryId: rule.category_id,
      status: materialComplete ? WORK_ORDER_STATUS.UNASSIGNED : WORK_ORDER_STATUS.PENDING_MATERIAL,
      rewardAmount,
      requiredDepositAmount,
      depositThresholdAmount,
      sharingEnabled: rule.sharing_enabled === true,
      sharingTotalQuantity: Number(rule.sharing_total_quantity || 1),
      sharingUnitReward: Number(rule.sharing_unit_reward || 0),
      timeoutMinutes: Number(rule.timeout_minutes || 0),
      timeoutPolicy: String(rule.timeout_policy || 'reopen').trim(),
      materialJson: JSON.stringify({
        source: {
          orderId: Number(order.id),
          orderItemId: Number(item.id),
          provider: order.provider,
          platform: order.platform,
          shopId: order.shop_id,
          skuCode: item.sku_code,
          skuName: item.sku_name,
          quantity: Number(item.quantity || 1),
          syncSource: options.source || 'source_order',
        },
      }),
      requirementJson: JSON.stringify({ fields }),
      now,
    })

    if (workOrder) {
      created.push(workOrder)
      await createWorkOrderEvent({
        workOrderId: workOrder.id,
        actorType: 'system',
        actorId: options.source || 'source_order',
        eventType: 'source_synced',
        fromStatus: '',
        toStatus: workOrder.status,
        payloadJson: JSON.stringify({
          ruleKey: rule.rule_key,
          orderId: order.id,
          orderItemId: item.id,
        }),
        now,
      })
    }
  }

  return {
    created: created.map(mapWorkOrderAdmin),
    skipped,
    createdCount: created.length,
    skippedCount: skipped.length,
  }
}

async function resolveSourceOrder(payload: JsonObject): Promise<OrderRow> {
  const orderId = normalizeOptionalId(payload.orderId || payload.sourceOrderId)
  if (orderId) {
    const order = await getOrderById(orderId)
    if (order) {
      return order
    }
    throw createHttpError('源订单不存在', {
      statusCode: 404,
      errorCode: 'source_order_not_found',
    })
  }

  const platformOrderId = String(payload.platformOrderId || payload.orderNo || '').trim()
  if (!platformOrderId) {
    throw createHttpError('请填写源订单号', {
      statusCode: 400,
      errorCode: 'source_order_no_required',
    })
  }

  const order = await findLatestOrderByAnyPlatformOrderId(platformOrderId)
  if (!order) {
    throw createHttpError('未找到源订单，请确认订单号是否正确', {
      statusCode: 404,
      errorCode: 'source_order_not_found',
    })
  }
  return order
}
