import {
  summarizeWorkerFinanceRequests,
  addWorkerWalletCredit,
  getWorkerFinanceRequestById,
  listWorkerFinanceRequests,
  listWorkerWithdrawalAccounts,
  reviewWorkerFinanceRequest,
  upsertWorkerWithdrawalAccount,
} from '../../repositories/worker-platform/worker-repo.js'
import type { WorkerWithdrawalAccountRow } from '../../repositories/worker-platform/types.js'
import type { JsonObject } from '../../types/json.js'
import { createHttpError } from '../../utils/http.js'
import { nowIso } from '../../utils/time.js'
import {
  normalizeDateTimeString,
  normalizePage,
  normalizePageSize,
  safeParseJson,
} from '../admin/admin-query-utils.js'
import { resolveAdminNotificationEntity } from '../admin/admin-notification-service.js'
import { refreshUploadedFileUrls } from '../file-storage/file-storage-service.js'
import {
  publishWorkerFinanceRealtimeChange,
  publishWorkerWalletRealtimeChange,
} from '../realtime/realtime-event-service.js'
import {
  mapFinanceRequest,
  mapWallet,
  mapWorkerUser,
  normalizeAdminFinanceReviewStatus,
  normalizeAmountFen,
  normalizeFinanceRequestStatus,
  normalizeFinanceRequestType,
  normalizeOptionalId,
  normalizeProofFiles,
  normalizeWithdrawChannel,
} from './mappers.js'
import { getRequiredWorker } from './worker-session-context-service.js'
import { getWorkerFinanceConfig, saveWorkerFinanceConfig } from './worker-finance-config-service.js'

function mapAdminWorkerWithdrawalAccount(account: WorkerWithdrawalAccountRow) {
  const alipayQrCodeImage = refreshUploadedFileUrls(safeParseJson(account.alipay_qr_code_json))
  const wechatQrCodeImage = refreshUploadedFileUrls(safeParseJson(account.wechat_qr_code_json))
  return {
    accountChannel: account.account_channel,
    accountName: account.account_name,
    accountNo: account.account_channel === 'alipay' ? account.account_no : '',
    alipayQrCodeImage: String(alipayQrCodeImage.url || '').trim() ? alipayQrCodeImage : null,
    wechatQrCodeImage: String(wechatQrCodeImage.url || '').trim() ? wechatQrCodeImage : null,
    createdAt: account.created_at,
  }
}

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(),
  })
  publishWorkerWalletRealtimeChange(Number(workerId))
  return { wallet: mapWallet(wallet) }
}

export async function listAdminWorkerWithdrawalAccounts(workerId: number | string) {
  const worker = await getRequiredWorker(workerId)
  const items = await listWorkerWithdrawalAccounts(worker.id)
  return {
    worker: mapWorkerUser(worker),
    items: items.map(mapAdminWorkerWithdrawalAccount),
  }
}

export async function saveAdminWorkerWithdrawalAccount(
  workerId: number | string,
  accountChannelValue: unknown,
  payload: JsonObject = {},
) {
  const worker = await getRequiredWorker(workerId)
  const accountChannel = normalizeWithdrawChannel(accountChannelValue)
  const currentAccounts = await listWorkerWithdrawalAccounts(worker.id)
  const current = currentAccounts.find((item) => item.account_channel === accountChannel)
  const accountName = String(payload.accountName || payload.realName || '').trim()
  const accountNo =
    accountChannel === 'alipay'
      ? String(payload.accountNo || payload.account || current?.account_no || '').trim()
      : ''
  const uploadedAlipayQrCode = normalizeProofFiles(
    payload.alipayQrCodeImages || payload.alipayQrCodes,
  )[0]
  const alipayQrCodeImage =
    accountChannel === 'alipay'
      ? uploadedAlipayQrCode || safeParseJson(current?.alipay_qr_code_json)
      : {}
  const uploadedWechatQrCode = normalizeProofFiles(
    payload.wechatQrCodeImages || payload.wechatQrCodes,
  )[0]
  const wechatQrCodeImage =
    accountChannel === 'wechat'
      ? uploadedWechatQrCode || safeParseJson(current?.wechat_qr_code_json)
      : {}

  if (!accountName) {
    throw createHttpError('请填写收款人姓名', {
      statusCode: 400,
      errorCode: 'admin_worker_withdraw_account_name_required',
    })
  }
  if (accountChannel === 'alipay' && !current && !accountNo) {
    throw createHttpError('请填写支付宝账号', {
      statusCode: 400,
      errorCode: 'admin_worker_withdraw_alipay_account_required',
    })
  }
  if (accountChannel === 'alipay' && !String(alipayQrCodeImage.url || '').trim()) {
    throw createHttpError('请上传支付宝收款二维码', {
      statusCode: 400,
      errorCode: 'admin_worker_withdraw_alipay_qr_required',
    })
  }
  if (accountChannel === 'wechat' && !String(wechatQrCodeImage.url || '').trim()) {
    throw createHttpError('请上传微信收款二维码', {
      statusCode: 400,
      errorCode: 'admin_worker_withdraw_wechat_qr_required',
    })
  }

  const saved = await upsertWorkerWithdrawalAccount({
    workerId: worker.id,
    accountChannel,
    accountName,
    accountNo,
    alipayQrCodeJson: JSON.stringify(alipayQrCodeImage),
    wechatQrCodeJson: JSON.stringify(wechatQrCodeImage),
    now: nowIso(),
  })
  if (!saved) {
    throw createHttpError('保存打手提现信息失败', {
      statusCode: 500,
      errorCode: 'admin_worker_withdraw_account_save_failed',
    })
  }
  return { account: mapAdminWorkerWithdrawalAccount(saved) }
}

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 requestId = normalizeOptionalId(query.requestId ?? query.request_id) || 0
  const status = normalizeFinanceRequestStatus(query.status)
  const requestType = normalizeFinanceRequestType(query.requestType)
  const keyword = String(query.keyword || '').trim()
  const createdFrom = normalizeDateTimeString(query.createdFrom)
  const createdTo = normalizeDateTimeString(query.createdTo)
  const accountChannel = ['alipay', 'wechat'].includes(String(query.accountChannel || ''))
    ? String(query.accountChannel)
    : ''
  const listFilters = {
    requestId,
    status,
    requestType,
    keyword,
    ...(createdFrom ? { createdFrom } : {}),
    ...(createdTo ? { createdTo } : {}),
    ...(accountChannel ? { accountChannel } : {}),
  }
  const [listResult, channels] = await Promise.all([
    listWorkerFinanceRequests({ page, pageSize, ...listFilters }),
    summarizeWorkerFinanceRequests(listFilters),
  ])
  const { items, total } = listResult
  const summary = {
    channels,
    totalCount: channels.reduce((sum, item) => sum + item.count, 0),
    totalAmount: channels.reduce((sum, item) => sum + item.amount, 0),
  }
  return {
    items: items.map(mapFinanceRequest),
    pagination: { page, pageSize, total },
    summary,
  }
}

export async function reviewAdminWorkerFinanceRequest(
  requestId: number | string,
  payload: JsonObject = {},
  reviewedBy = '',
) {
  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(),
    reviewedBy: String(reviewedBy || '').trim(),
  })

  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',
    })
  }

  await resolveAdminNotificationEntity(
    'worker_finance_request',
    Number(reviewed.request.id),
    'finance_request_reviewed',
  )
  publishWorkerFinanceRealtimeChange({
    requestId: Number(reviewed.request.id),
    workerId: Number(reviewed.request.worker_id),
    walletChanged: reviewed.request.request_type === 'withdraw',
  })

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