import {
  countTimeoutEventsByWorkerIds,
  getWorkerLevelById,
  listWorkerUsers,
  revokeAllWorkerSessions,
  updateWorkerPassword,
  updateWorkerUser,
} 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 { normalizePage, normalizePageSize } from '../admin/admin-query-utils.js'
import {
  hashWorkerPassword,
  mapWorkerUser,
  normalizeAmountFen,
  normalizeOptionalId,
  normalizeReviewStatus,
  normalizeSessionVersion,
  normalizeWorkerFreezeReason,
  normalizeWorkerType,
  validateWorkerPassword,
} from './mappers.js'
import { ensureWorkerPlatformDefaults } from './worker-platform-defaults.js'
import { getRequiredWorker } from './worker-session-context-service.js'

export async function listAdminWorkerUsers(query: JsonObject = {}) {
  const page = normalizePage(query.page)
  const pageSize = normalizePageSize(query.pageSize)
  const workerId = normalizeOptionalId(query.workerId ?? query.worker_id) || 0
  const levelId = normalizeOptionalId(query.levelId ?? query.level_id) || 0
  const { items, total } = await listWorkerUsers({
    page,
    pageSize,
    workerId,
    levelId,
    status: String(query.status || '').trim(),
    keyword: String(query.keyword || '').trim(),
    workerType: String(query.workerType || query.worker_type || '').trim(),
  })
  const timeoutCounts = await countTimeoutEventsByWorkerIds(items.map((item) => Number(item.id)))
  return {
    items: items.map((item) => ({
      ...mapWorkerUser(item),
      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 freezeReason =
    status === 'rejected'
      ? normalizeWorkerFreezeReason(payload.freezeReason ?? payload.freeze_reason)
      : worker.frozen_reason || ''
  const workerType = normalizeWorkerType(payload.workerType ?? payload.worker_type)
  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,
    worker_type: workerType,
    level_id: levelId,
    review_note:
      status === 'rejected'
        ? freezeReason
        : String((payload.reviewNote ?? payload.note ?? worker.review_note) || '').trim(),
    frozen_reason: freezeReason,
    frozen_at: status === 'rejected' ? now : worker.frozen_at,
    session_version: normalizeSessionVersion(worker.session_version) + 1,
    reviewed_at: now,
    updated_at: now,
  })
  await revokeAllWorkerSessions(worker.id, now)
  return { worker: mapWorkerUser(updated || worker) }
}

/** 设置单个打手的追加免押额度，会与该打手等级的免押额度叠加。 */
export async function setAdminWorkerPersonalDepositFreeAmount(
  workerId: number | string,
  payload: JsonObject = {},
) {
  const worker = await getRequiredWorker(workerId)
  const rawAmount = payload.depositFreeAmount ?? payload.deposit_free_amount
  const clearPersonalAmount =
    rawAmount === null || rawAmount === undefined || String(rawAmount).trim() === ''
  if (!clearPersonalAmount) {
    const amount = Number(rawAmount)
    if (!Number.isFinite(amount) || amount < 0) {
      throw createHttpError('个人免押额度必须是不小于 0 的金额', {
        statusCode: 400,
        errorCode: 'worker_personal_deposit_free_amount_invalid',
      })
    }
  }
  const updated = await updateWorkerUser(worker.id, {
    personal_deposit_free_amount: clearPersonalAmount ? null : normalizeAmountFen(rawAmount, 0),
    updated_at: nowIso(),
  })
  return { worker: mapWorkerUser(updated || worker) }
}

export async function resetAdminWorkerPassword(
  workerId: number | string,
  payload: JsonObject = {},
) {
  const worker = await getRequiredWorker(workerId)
  const password = String(payload.password || payload.newPassword || '').trim()
  if (!password) {
    throw createHttpError('请输入新密码', {
      statusCode: 400,
      errorCode: 'worker_password_required',
    })
  }
  validateWorkerPassword(password)
  const now = nowIso()
  const updated = await updateWorkerPassword({
    workerId: worker.id,
    passwordHash: hashWorkerPassword(password),
    sessionVersion: normalizeSessionVersion(worker.session_version) + 1,
    now,
  })
  await revokeAllWorkerSessions(worker.id, now)
  return { worker: mapWorkerUser(updated || worker), reloginRequired: true }
}
