import {
  consumeWorkerRenameCard,
  getWorkerUserByDisplayName,
} 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 { mapWorkerUser } from './mappers.js'
import { getRequiredWorker, type WorkerSession } from './worker-session-context-service.js'

/** 改名冷却期：修改昵称后一年内禁止再次修改。 */
export const WORKER_RENAME_COOLDOWN_MS = 365 * 24 * 60 * 60 * 1000

const MAX_DISPLAY_NAME_LENGTH = 32

function normalizeDisplayName(value: unknown): string {
  return String(value || '').trim()
}

/** 打手使用改名卡修改昵称；默认每人 1 张卡，修改后一年内锁定。昵称全平台唯一。 */
export async function renameWorkerAccount(payload: JsonObject = {}, session: WorkerSession) {
  const worker = await getRequiredWorker(session.workerId)
  const nextDisplayName = normalizeDisplayName(payload.displayName || payload.nickname)

  if (!nextDisplayName) {
    throw createHttpError('请输入新的昵称', {
      statusCode: 400,
      errorCode: 'worker_rename_display_name_required',
    })
  }
  if (nextDisplayName.length > MAX_DISPLAY_NAME_LENGTH) {
    throw createHttpError(`昵称最长 ${MAX_DISPLAY_NAME_LENGTH} 个字符`, {
      statusCode: 400,
      errorCode: 'worker_rename_display_name_invalid',
    })
  }
  if (nextDisplayName === String(worker.display_name || '')) {
    throw createHttpError('新昵称不能与当前昵称一致', {
      statusCode: 400,
      errorCode: 'worker_rename_display_name_unchanged',
    })
  }
  if (Number(worker.rename_cards ?? 1) <= 0) {
    throw createHttpError('改名卡已用完，无法再次修改昵称', {
      statusCode: 409,
      errorCode: 'worker_rename_card_exhausted',
    })
  }

  const lastRenamedMs = worker.last_renamed_at ? Date.parse(worker.last_renamed_at) : 0
  if (Number.isFinite(lastRenamedMs) && lastRenamedMs > 0) {
    const unlockedAtMs = lastRenamedMs + WORKER_RENAME_COOLDOWN_MS
    if (Date.now() < unlockedAtMs) {
      const unlockedAt = new Date(unlockedAtMs).toISOString()
      throw createHttpError(
        `修改昵称后一年内无法再次修改，${new Date(unlockedAtMs).toLocaleString('zh-CN')} 后才能修改`,
        { statusCode: 409, errorCode: 'worker_rename_cooldown', context: { unlockedAt } },
      )
    }
  }

  const existing = await getWorkerUserByDisplayName(nextDisplayName)
  if (existing && Number(existing.id) !== Number(worker.id)) {
    throw createHttpError('该昵称已被使用，请更换昵称', {
      statusCode: 409,
      errorCode: 'worker_display_name_taken',
    })
  }

  const updated = await consumeWorkerRenameCard({
    workerId: Number(worker.id),
    displayName: nextDisplayName,
    now: nowIso(),
  }).catch((error: unknown) => {
    if ((error as { code?: string }).code === '23505') {
      throw createHttpError('该昵称已被使用，请更换昵称', {
        statusCode: 409,
        errorCode: 'worker_display_name_taken',
      })
    }
    throw error
  })
  if (!updated) {
    throw createHttpError('改名卡已用完，无法再次修改昵称', {
      statusCode: 409,
      errorCode: 'worker_rename_card_exhausted',
    })
  }

  return {
    worker: mapWorkerUser(updated),
    reloginRequired: false,
  }
}
