import {
  addWorkerWalletCredit,
  type WorkerFinanceRequestRow,
  type WorkerLevelRow,
  type WorkerUserRow,
  type WorkerWalletLedgerRow,
} from '../../repositories/worker-platform/index.js'
import { safeParseJson } from '../admin/admin-query-utils.js'
import { refreshUploadedFileUrls } from '../file-storage/file-storage-service.js'
import { createWorkerSessionToken } from './worker-auth-utils.js'
import {
  normalizeBoolean,
  normalizeInteger,
  normalizePositiveInteger,
} from './worker-normalizers.js'
import { resolveVisibleDelaySeconds, resolveWorkerPermissions } from './worker-permission-utils.js'
import { normalizeUploadedFiles } from './worker-input-normalizers.js'
import { mapAcceptanceForResponse } from './work-order-material-mappers.js'
import { WORKER_RENAME_COOLDOWN_MS } from './worker-rename-service.js'

export const DEFAULT_LEVEL_KEY = 'vip1'
export const DEFAULT_LEVEL_NAME = 'VIP1'
export const DEFAULT_CATEGORY_KEY = 'default'
export const DEFAULT_DEPOSIT_THRESHOLD_AMOUNT = 20_000
export const INVITE_CODE_LENGTH = 8
export const INVITE_CODE_RETRY_LIMIT = 5
export const WORKER_CANCEL_LIMIT_PER_WINDOW = 5
export const WORKER_CANCEL_LIMIT_WINDOW_MS = 30 * 24 * 60 * 60 * 1000

export function createWorkerSession(worker: WorkerUserRow) {
  const session = createWorkerSessionToken(worker)
  return {
    ...session,
    worker: mapWorkerUser(worker),
  }
}

export function mapWorkerLevel(level: WorkerLevelRow | null | undefined) {
  if (!level) return null
  const permission = safeParseJson(level.permission_json)
  return {
    levelId: Number(level.id),
    levelKey: level.level_key,
    name: level.name,
    sortOrder: Number(level.sort_order || 100),
    status: level.status,
    depositFreeAmount: normalizeInteger(permission.depositFreeAmount, 0),
    maxActiveOrders: normalizePositiveInteger(permission.maxActiveOrders, 1),
    upgradeThreshold: normalizeInteger(permission.upgradeThreshold, 0),
    autoAcceptWithoutEvidence: normalizeBoolean(permission.autoAcceptWithoutEvidence, false),
    visibleDelaySeconds: resolveVisibleDelaySeconds(
      level.level_key,
      permission.visibleDelaySeconds,
    ),
    createdAt: level.created_at,
    updatedAt: level.updated_at,
  }
}

export function normalizeWorkerType(value: unknown): 'internal' | 'external' {
  return String(value || '').trim() === 'internal' ? 'internal' : 'external'
}

export function mapWorkerUser(worker: WorkerUserRow) {
  const permissions = resolveWorkerPermissions(worker)
  return {
    workerId: Number(worker.id),
    username: worker.username,
    displayName: worker.display_name || worker.username,
    phone: worker.phone,
    status: worker.status,
    workerType: normalizeWorkerType(worker.worker_type),
    reviewNote: worker.review_note || '',
    freezeReason: worker.frozen_reason || '',
    frozenAt: worker.frozen_at,
    inviteCode: worker.invite_code || '',
    inviter: worker.inviter_id
      ? {
          workerId: Number(worker.inviter_id),
          username: worker.inviter_username || '',
          displayName: worker.inviter_display_name || worker.inviter_username || '',
        }
      : null,
    level: worker.level_id
      ? {
          levelId: Number(worker.level_id),
          levelKey: worker.level_key || '',
          name: worker.level_name || '',
          permissions,
        }
      : null,
    personalDepositFreeAmount: permissions.personalDepositFreeAmount,
    levelDepositFreeAmount: permissions.levelDepositFreeAmount,
    effectiveDepositFreeAmount: permissions.depositFreeAmount,
    wallet: {
      availableAmount: Number(worker.available_amount || 0),
      frozenDepositAmount: Number(worker.frozen_deposit_amount || 0),
      pendingUnfreezeAmount: Number(worker.pending_unfreeze_amount || 0),
      totalCreditedAmount: Number(worker.total_credited_amount || 0),
      totalSettledAmount: Number(worker.total_settled_amount || 0),
    },
    createdAt: worker.created_at,
    updatedAt: worker.updated_at,
    reviewedAt: worker.reviewed_at,
    renameCards: Number(worker.rename_cards ?? 1),
    lastRenamedAt: worker.last_renamed_at || null,
    renameUnlockedAt: worker.last_renamed_at
      ? new Date(Date.parse(worker.last_renamed_at) + WORKER_RENAME_COOLDOWN_MS).toISOString()
      : null,
  }
}

export function mapWorkerCancelRequest(request: {
  id: number
  work_order_id: number
  work_order_share_id: number | null
  worker_id: number
  reason: string
  status: string
  review_note: string
  reviewed_by: string
  created_at: string
  reviewed_at: string | null
  platform_order_id?: string
  shop_name?: string
  worker_username?: string
  worker_display_name?: string
  share_quantity?: number | null
}) {
  return {
    requestId: Number(request.id),
    workOrderId: Number(request.work_order_id),
    shareId: request.work_order_share_id ? Number(request.work_order_share_id) : null,
    workerId: Number(request.worker_id),
    platformOrderId: String(request.platform_order_id || ''),
    shopName: String(request.shop_name || ''),
    workerName: String(request.worker_display_name || request.worker_username || ''),
    shareQuantity: request.share_quantity ? Number(request.share_quantity) : null,
    reason: String(request.reason || ''),
    status: String(request.status || ''),
    reviewNote: String(request.review_note || ''),
    reviewedBy: String(request.reviewed_by || ''),
    createdAt: request.created_at,
    reviewedAt: request.reviewed_at,
  }
}

export function mapWorkerOrderFeedback(feedback: {
  id: number
  work_order_id: number
  work_order_share_id: number | null
  worker_id: number
  content: string
  status: string
  reply: string
  handled_by: string
  created_at: string
  handled_at: string | null
  work_order_no?: string
  product_name?: string
  shop_name?: string
  worker_username?: string
  worker_display_name?: string
  share_quantity?: number | null
}) {
  return {
    feedbackId: Number(feedback.id),
    workOrderId: Number(feedback.work_order_id),
    shareId: feedback.work_order_share_id ? Number(feedback.work_order_share_id) : null,
    workerId: Number(feedback.worker_id),
    workOrderNo: String(feedback.work_order_no || ''),
    productName: String(feedback.product_name || ''),
    shopName: String(feedback.shop_name || ''),
    workerName: String(feedback.worker_display_name || feedback.worker_username || ''),
    shareQuantity: feedback.share_quantity ? Number(feedback.share_quantity) : null,
    content: String(feedback.content || ''),
    status: String(feedback.status || ''),
    reply: String(feedback.reply || ''),
    handledBy: String(feedback.handled_by || ''),
    createdAt: feedback.created_at,
    handledAt: feedback.handled_at,
  }
}

export function mapWorkerAfterSalesCase(afterSalesCase: {
  id: number
  case_no: string
  work_order_id: number
  work_order_share_id: number | null
  worker_id: number
  problem_type: string
  complaint_note: string
  complaint_files_json: unknown
  acceptance_snapshot_json: unknown
  status: string
  worker_response: string
  worker_response_files_json: unknown
  responded_at: string | null
  resolution_action: string
  resolution_note: string
  recovery_amount: number
  pending_deposit_deduction_amount: number
  available_deduction_amount: number
  debt_amount: number
  refunded_amount?: number
  refunded_at?: string | null
  refunded_by?: string
  created_by: string
  resolved_by: string
  resolved_at: string | null
  created_at: string
  updated_at: string
  work_order_no?: string
  platform_order_id?: string
  product_name?: string
  shop_name?: string
  worker_username?: string
  worker_display_name?: string
  share_quantity?: number | null
}) {
  const snapshot = safeParseJson(afterSalesCase.acceptance_snapshot_json)
  return {
    caseId: Number(afterSalesCase.id),
    caseNo: String(afterSalesCase.case_no || ''),
    workOrderId: Number(afterSalesCase.work_order_id),
    shareId: afterSalesCase.work_order_share_id ? Number(afterSalesCase.work_order_share_id) : null,
    workerId: Number(afterSalesCase.worker_id),
    workOrderNo: String(afterSalesCase.work_order_no || ''),
    platformOrderId: String(afterSalesCase.platform_order_id || ''),
    productName: String(afterSalesCase.product_name || ''),
    shopName: String(afterSalesCase.shop_name || ''),
    workerName: String(afterSalesCase.worker_display_name || afterSalesCase.worker_username || ''),
    shareQuantity: afterSalesCase.share_quantity ? Number(afterSalesCase.share_quantity) : null,
    problemType: String(afterSalesCase.problem_type || ''),
    complaintNote: String(afterSalesCase.complaint_note || ''),
    complaintFiles: normalizeUploadedFiles(safeParseJson(afterSalesCase.complaint_files_json)).map(
      refreshUploadedFileUrls,
    ),
    acceptanceSnapshot: {
      ...snapshot,
      acceptance: mapAcceptanceForResponse(snapshot.acceptance),
    },
    status: String(afterSalesCase.status || ''),
    workerResponse: String(afterSalesCase.worker_response || ''),
    workerResponseFiles: normalizeUploadedFiles(
      safeParseJson(afterSalesCase.worker_response_files_json),
    ).map(refreshUploadedFileUrls),
    respondedAt: afterSalesCase.responded_at,
    resolutionAction: String(afterSalesCase.resolution_action || ''),
    resolutionNote: String(afterSalesCase.resolution_note || ''),
    recoveryAmount: Number(afterSalesCase.recovery_amount || 0),
    pendingDepositDeductionAmount: Number(afterSalesCase.pending_deposit_deduction_amount || 0),
    availableDeductionAmount: Number(afterSalesCase.available_deduction_amount || 0),
    debtAmount: Number(afterSalesCase.debt_amount || 0),
    refundedAmount: Number(afterSalesCase.refunded_amount || 0),
    refundedAt: afterSalesCase.refunded_at || null,
    refundedBy: String(afterSalesCase.refunded_by || ''),
    createdBy: String(afterSalesCase.created_by || ''),
    resolvedBy: String(afterSalesCase.resolved_by || ''),
    resolvedAt: afterSalesCase.resolved_at,
    createdAt: afterSalesCase.created_at,
    updatedAt: afterSalesCase.updated_at,
  }
}

export function mapWalletLedger(ledger: WorkerWalletLedgerRow | null | undefined) {
  if (!ledger) return null
  return {
    ledgerId: Number(ledger.id),
    ledgerType: ledger.ledger_type,
    amount: Number(ledger.amount || 0),
    balanceAfter: Number(ledger.balance_after || 0),
    frozenAfter: Number(ledger.frozen_after || 0),
    relatedWorkOrderId: ledger.related_work_order_id ? Number(ledger.related_work_order_id) : null,
    relatedPlatformOrderId: String(ledger.related_platform_order_id || '').trim() || null,
    auditStatus: ledger.audit_status || '',
    note: ledger.note || '',
    payload: safeParseJson(ledger.payload_json),
    createdAt: ledger.created_at,
  }
}

export function mapFinanceRequest(request: WorkerFinanceRequestRow | null | undefined) {
  if (!request) return null
  const payload = safeParseJson(request.payload_json)
  const alipayQrCodeImage = refreshUploadedFileUrls(payload.alipayQrCodeImage)
  if (String(alipayQrCodeImage.url || '').trim()) {
    payload.alipayQrCodeImage = alipayQrCodeImage
  }
  const wechatQrCodeImage = refreshUploadedFileUrls(payload.wechatQrCodeImage)
  if (String(wechatQrCodeImage.url || '').trim()) {
    payload.wechatQrCodeImage = wechatQrCodeImage
  }
  return {
    requestId: Number(request.id),
    requestType: request.request_type || '',
    status: request.status || '',
    amount: Number(request.amount || 0),
    accountChannel: request.account_channel || '',
    accountName: request.account_name || '',
    accountNo: request.account_no || '',
    note: request.note || '',
    reviewedNote: request.reviewed_note || '',
    payload,
    createdAt: request.created_at,
    updatedAt: request.updated_at,
    reviewedAt: request.reviewed_at,
    worker: request.worker_id
      ? {
          workerId: Number(request.worker_id),
          username: request.worker_username || '',
          displayName: request.worker_display_name || request.worker_username || '',
          phone: request.worker_phone || '',
          workerType: normalizeWorkerType(request.worker_type),
          levelKey: request.worker_level_key || '',
          levelName: request.worker_level_name || '',
          withdrawRequestCount: Number(request.worker_withdraw_request_count || 0),
          totalWithdrawAmount: Number(request.worker_total_withdraw_amount || 0),
        }
      : null,
  }
}

export function mapWallet(wallet: Awaited<ReturnType<typeof addWorkerWalletCredit>>) {
  return {
    workerId: Number(wallet?.worker_id || 0),
    availableAmount: Number(wallet?.available_amount || 0),
    frozenDepositAmount: Number(wallet?.frozen_deposit_amount || 0),
    pendingUnfreezeAmount: Number(wallet?.pending_unfreeze_amount || 0),
    totalCreditedAmount: Number(wallet?.total_credited_amount || 0),
    totalSettledAmount: Number(wallet?.total_settled_amount || 0),
  }
}
