import { runtimeConfig } from '../../config/runtime.js'
import {
  countWorkerAcceptedOrders,
  countWorkerActiveOrders,
  countWorkerTimeoutEvents,
  getWorkerFinanceRequestSummary,
  listWorkerFinanceRequests,
  listWorkerLevels,
  listWorkerWalletLedgers,
  listWorkerWithdrawalAccounts,
  type WorkerUserRow,
} from '../../repositories/worker-platform/index.js'
import type { JsonObject } from '../../types/json.js'
import { normalizePage, normalizePageSize, safeParseJson } from '../admin/admin-query-utils.js'
import {
  mapFinanceRequest,
  mapWalletLedger,
  mapWorkerUser,
  normalizeFinanceRequestStatus,
  normalizeFinanceRequestType,
  normalizeInteger,
  normalizeWalletLedgerType,
  resolveWorkerPermissions,
} from './mappers.js'
import { getWorkerFinanceConfig } from './worker-finance-config-service.js'
import { getRequiredWorker, type WorkerSession } from './worker-session-context-service.js'

export {
  createWorkerRechargeRequest,
  createWorkerWithdrawRequest,
  settleDueDepositUnfreezes,
} from './worker-finance-request-service.js'
export {
  createWorkerWithdrawalAccount,
  saveWorkerAlipayWithdrawalQrCode,
} from './worker-withdrawal-account-service.js'
import { mapWithdrawalAccount } from './worker-withdrawal-account-service.js'

export async function getWorkerProfile(session: WorkerSession) {
  const worker = await getRequiredWorker(session.workerId)
  const [
    financeSummary,
    acceptedOrderCount,
    activeOrderCount,
    timeoutOrderCount,
    financeConfig,
    withdrawalAccounts,
  ] = await Promise.all([
    getWorkerFinanceRequestSummary(session.workerId),
    countWorkerAcceptedOrders(session.workerId),
    countWorkerActiveOrders(session.workerId),
    countWorkerTimeoutEvents(session.workerId),
    Promise.resolve(getWorkerFinanceConfig()),
    listWorkerWithdrawalAccounts(session.workerId),
  ])
  const permissions = resolveWorkerPermissions(worker)
  const levelProgress = await resolveLevelProgress(worker, acceptedOrderCount)
  return {
    worker: mapWorkerUser(worker),
    permissions,
    summary: {
      acceptedOrderCount,
      activeOrderCount,
      timeoutOrderCount,
      pendingWithdrawAmount: financeSummary.pendingWithdrawAmount,
      approvedWithdrawAmount: financeSummary.approvedWithdrawAmount,
      pendingRechargeAmount: financeSummary.pendingRechargeAmount,
    },
    levelProgress,
    financeConfig,
    withdrawalAccounts: withdrawalAccounts.map(mapWithdrawalAccount),
    orderTimelineVisible: runtimeConfig.worker.orderTimelineVisible === true,
  }
}

async function resolveLevelProgress(
  worker: WorkerUserRow,
  acceptedOrderCount: number,
): Promise<{
  currentThreshold: number
  nextThreshold: number | null
  progressPercent: number
} | null> {
  if (!worker.level_id) return null
  const levels = await listWorkerLevels()
  const active = levels.filter((level) => level.status === 'active')
  const current = active.find((level) => Number(level.id) === Number(worker.level_id))
  if (!current) return null
  const currentThreshold = normalizeInteger(
    safeParseJson(current.permission_json).upgradeThreshold,
    0,
  )
  const next = active
    .filter(
      (level) =>
        normalizeInteger(safeParseJson(level.permission_json).upgradeThreshold, 0) >
        currentThreshold,
    )
    .sort(
      (a, b) =>
        normalizeInteger(safeParseJson(a.permission_json).upgradeThreshold, 0) -
        normalizeInteger(safeParseJson(b.permission_json).upgradeThreshold, 0),
    )[0]
  const nextThreshold = next
    ? normalizeInteger(safeParseJson(next.permission_json).upgradeThreshold, 0)
    : null
  return {
    currentThreshold,
    nextThreshold,
    progressPercent:
      nextThreshold && nextThreshold > currentThreshold
        ? Math.min(
            100,
            Math.round(
              ((acceptedOrderCount - currentThreshold) / (nextThreshold - currentThreshold)) * 100,
            ),
          )
        : 100,
  }
}

export async function listWorkerProfileWalletLedgers(
  query: JsonObject = {},
  session: WorkerSession,
) {
  const page = normalizePage(query.page)
  const pageSize = normalizePageSize(query.pageSize)
  const ledgerType = normalizeWalletLedgerType(query.ledgerType)
  const { items, total } = await listWorkerWalletLedgers({
    page,
    pageSize,
    workerId: session.workerId,
    ledgerType,
  })
  return {
    items: items.map(mapWalletLedger),
    pagination: { page, pageSize, total },
  }
}

export async function listWorkerProfileFinanceRequests(
  query: JsonObject = {},
  session: WorkerSession,
) {
  const page = normalizePage(query.page)
  const pageSize = normalizePageSize(query.pageSize)
  const status = normalizeFinanceRequestStatus(query.status)
  const requestType = normalizeFinanceRequestType(query.requestType)
  const { items, total } = await listWorkerFinanceRequests({
    page,
    pageSize,
    workerId: session.workerId,
    status,
    requestType,
  })
  return {
    items: items.map(mapFinanceRequest),
    pagination: { page, pageSize, total },
  }
}
