import { WORK_ORDER_STATUS } from '../../domain/work-order-status.js'
import {
  createAfterSalesCase,
  getAfterSalesCaseById,
  listAfterSalesCaseEvents,
  listAfterSalesCases,
  listWorkerAfterSalesCases,
  resolveAfterSalesCase,
  submitWorkerAfterSalesResponse,
} from '../../repositories/worker-platform/after-sales-repo.js'
import { createWorkOrderEvent } from '../../repositories/worker-platform/work-order-event-repo.js'
import type { JsonObject } from '../../types/json.js'
import { createHttpError } from '../../utils/http.js'
import { randomId } from '../../utils/random.js'
import { nowIso } from '../../utils/time.js'
import { normalizePage, normalizePageSize, safeParseJson } from '../admin/admin-query-utils.js'
import {
  publishWorkerWalletRealtimeChange,
  publishWorkOrderRealtimeChange,
} from '../realtime/realtime-event-service.js'
import {
  mapWorkerAfterSalesCase,
  normalizeAmountFen,
  normalizeOptionalId,
  normalizeProofFiles,
  normalizeUploadedFiles,
} from './mappers.js'
import { requireActiveWorkerSession, type WorkerSession } from './worker-session-context-service.js'

export async function listAdminAfterSalesCases(query: JsonObject = {}) {
  const page = normalizePage(query.page)
  const pageSize = normalizePageSize(query.pageSize)
  const workOrderId = normalizeOptionalId(query.workOrderId ?? query.work_order_id)
  const result = await listAfterSalesCases({
    page,
    pageSize,
    status: String(query.status || '').trim(),
    keyword: String(query.keyword || '').trim(),
    ...(workOrderId ? { workOrderId } : {}),
  })
  return {
    items: result.items.map(mapWorkerAfterSalesCase),
    pagination: { page, pageSize, total: result.total },
  }
}

export async function getAdminAfterSalesCaseEvents(caseId: number | string) {
  const afterSalesCase = await getAfterSalesCaseById(caseId)
  if (!afterSalesCase) {
    throw createHttpError('售后问题单不存在', {
      statusCode: 404,
      errorCode: 'after_sales_case_not_found',
    })
  }
  return {
    items: (await listAfterSalesCaseEvents(afterSalesCase.id)).map((event) => ({
      eventId: Number(event.id),
      actorType: event.actor_type,
      actorId: event.actor_id,
      eventType: event.event_type,
      payload: safeParseJson(event.payload_json),
      createdAt: event.created_at,
    })),
  }
}

export async function createAdminAfterSalesCase(
  workOrderId: number | string,
  payload: JsonObject = {},
  actorName = '',
) {
  const complaintNote = String(payload.complaintNote || payload.note || '').trim()
  if (!complaintNote) {
    throw createHttpError('请填写用户投诉说明', {
      statusCode: 400,
      errorCode: 'after_sales_case_complaint_required',
    })
  }
  if (complaintNote.length > 2_000) {
    throw createHttpError('用户投诉说明不能超过 2000 个字符', {
      statusCode: 400,
      errorCode: 'after_sales_case_complaint_too_long',
    })
  }
  const problemType = String(payload.problemType || 'fake_evidence').trim() || 'fake_evidence'
  if (problemType.length > 64) {
    throw createHttpError('问题类型不正确', {
      statusCode: 400,
      errorCode: 'after_sales_case_problem_type_invalid',
    })
  }
  const shareId = normalizeOptionalId(payload.shareId ?? payload.workOrderShareId)
  const now = nowIso()
  const result = await createAfterSalesCase({
    caseNo: randomId('AS'),
    workOrderId: Number(workOrderId),
    workOrderShareId: shareId || null,
    problemType,
    complaintNote,
    complaintFilesJson: JSON.stringify(normalizeProofFiles(payload.files || payload.proofFiles)),
    createdBy: actorName,
    now,
  })
  if (result.failureReason === 'work_order_not_accepted') {
    throw createHttpError('只有已验收的工单可以发起售后问题单', {
      statusCode: 409,
      errorCode: 'after_sales_case_work_order_status_invalid',
    })
  }
  if (result.failureReason === 'work_order_share_not_accepted') {
    throw createHttpError('该拼单份额尚未验收，不能发起售后问题单', {
      statusCode: 409,
      errorCode: 'after_sales_case_share_status_invalid',
    })
  }
  if (result.failureReason === 'worker_missing') {
    throw createHttpError('请指定已验收的责任打手或拼单份额', {
      statusCode: 409,
      errorCode: 'after_sales_case_worker_required',
    })
  }
  if (result.failureReason === 'active_case_exists' || !result.case) {
    throw createHttpError('该责任打手已有处理中售后问题单', {
      statusCode: 409,
      errorCode: 'after_sales_case_active_exists',
    })
  }
  await createWorkOrderEvent({
    workOrderId: Number(result.case.work_order_id),
    actorType: 'admin',
    actorId: actorName,
    eventType: 'after_sales_case_created',
    fromStatus: WORK_ORDER_STATUS.ACCEPTED,
    toStatus: WORK_ORDER_STATUS.ACCEPTED,
    payloadJson: JSON.stringify({
      caseId: Number(result.case.id),
      caseNo: result.case.case_no,
      workerId: Number(result.case.worker_id),
      shareId: result.case.work_order_share_id ? Number(result.case.work_order_share_id) : null,
      problemType,
    }),
    now,
  })
  publishWorkOrderRealtimeChange({
    workOrderId: Number(result.case.work_order_id),
    workerIds: [Number(result.case.worker_id)],
  })
  return { case: mapWorkerAfterSalesCase(result.case) }
}

export async function resolveAdminAfterSalesCase(
  caseId: number | string,
  payload: JsonObject = {},
  actorName = '',
) {
  const action = String(payload.action || '').trim()
  if (!['not_upheld', 'remedied', 'upheld'].includes(action)) {
    throw createHttpError('售后处置方式不正确', {
      statusCode: 400,
      errorCode: 'after_sales_case_resolution_action_invalid',
    })
  }
  const resolutionNote = String(payload.resolutionNote || payload.note || '').trim()
  if (!resolutionNote) {
    throw createHttpError('请填写售后处置备注', {
      statusCode: 400,
      errorCode: 'after_sales_case_resolution_note_required',
    })
  }
  if (resolutionNote.length > 2_000) {
    throw createHttpError('售后处置备注不能超过 2000 个字符', {
      statusCode: 400,
      errorCode: 'after_sales_case_resolution_note_too_long',
    })
  }
  const recoveryAmount = normalizeAmountFen(payload.recoveryAmount ?? payload.amount, 0)
  if (action === 'upheld' && recoveryAmount <= 0) {
    throw createHttpError('问题成立时请填写大于 0 的追缴金额', {
      statusCode: 400,
      errorCode: 'after_sales_case_recovery_amount_required',
    })
  }
  const result = await resolveAfterSalesCase({
    caseId: Number(caseId),
    action: action as 'not_upheld' | 'remedied' | 'upheld',
    resolutionNote,
    recoveryAmount: action === 'upheld' ? recoveryAmount : 0,
    resolvedBy: actorName,
    now: nowIso(),
  })
  if (result.failureReason === 'not_found') {
    throw createHttpError('售后问题单不存在', {
      statusCode: 404,
      errorCode: 'after_sales_case_not_found',
    })
  }
  if (result.failureReason === 'not_resolvable' || !result.case) {
    throw createHttpError('该售后问题单已处置，请刷新后重试', {
      statusCode: 409,
      errorCode: 'after_sales_case_not_resolvable',
    })
  }
  await createWorkOrderEvent({
    workOrderId: Number(result.case.work_order_id),
    actorType: 'admin',
    actorId: actorName,
    eventType: 'after_sales_case_resolved',
    fromStatus: WORK_ORDER_STATUS.ACCEPTED,
    toStatus: WORK_ORDER_STATUS.ACCEPTED,
    payloadJson: JSON.stringify({
      caseId: Number(result.case.id),
      action,
      recoveryAmount: Number(result.case.recovery_amount || 0),
      debtAmount: Number(result.case.debt_amount || 0),
      refundedTotalAmount: result.refundedTotalAmount,
      refundedRecoveries: result.refundedRecoveries,
    }),
    now: nowIso(),
  })
  const workerId = Number(result.case.worker_id)
  publishWorkOrderRealtimeChange({
    workOrderId: Number(result.case.work_order_id),
    workerIds: workerId > 0 ? [workerId] : [],
  })
  if (workerId > 0) publishWorkerWalletRealtimeChange(workerId)
  return {
    case: mapWorkerAfterSalesCase(result.case),
    refundedTotalAmount: result.refundedTotalAmount,
    refundedRecoveries: result.refundedRecoveries,
  }
}

export async function getWorkerAfterSalesCaseSummary(session: WorkerSession) {
  requireActiveWorkerSession(session)
  return { items: (await listWorkerAfterSalesCases(session.workerId)).map(mapWorkerAfterSalesCase) }
}

export async function submitWorkerAfterSalesCaseResponse(
  caseId: number | string,
  payload: JsonObject = {},
  session: WorkerSession,
) {
  requireActiveWorkerSession(session)
  const response = String(payload.response || payload.note || '').trim()
  const files = normalizeUploadedFiles(payload.files || payload.proofFiles)
  if (!response && files.length === 0) {
    throw createHttpError('请填写说明或上传补救材料', {
      statusCode: 400,
      errorCode: 'after_sales_case_response_required',
    })
  }
  if (response.length > 2_000) {
    throw createHttpError('售后说明不能超过 2000 个字符', {
      statusCode: 400,
      errorCode: 'after_sales_case_response_too_long',
    })
  }
  const now = nowIso()
  const result = await submitWorkerAfterSalesResponse({
    caseId: Number(caseId),
    workerId: Number(session.workerId),
    response,
    filesJson: JSON.stringify(files),
    now,
  })
  if (result.failureReason === 'not_found') {
    throw createHttpError('售后问题单不存在或不属于当前账号', {
      statusCode: 404,
      errorCode: 'after_sales_case_not_found',
    })
  }
  if (result.failureReason === 'not_pending' || !result.case) {
    throw createHttpError('该售后问题单已提交说明或已处置', {
      statusCode: 409,
      errorCode: 'after_sales_case_response_status_invalid',
    })
  }
  await createWorkOrderEvent({
    workOrderId: Number(result.case.work_order_id),
    actorType: 'worker',
    actorId: String(session.workerId),
    eventType: 'after_sales_case_responded',
    fromStatus: WORK_ORDER_STATUS.ACCEPTED,
    toStatus: WORK_ORDER_STATUS.ACCEPTED,
    payloadJson: JSON.stringify({ caseId: Number(result.case.id), fileCount: files.length }),
    now,
  })
  publishWorkOrderRealtimeChange({
    workOrderId: Number(result.case.work_order_id),
    workerIds: [Number(session.workerId)],
  })
  return { case: mapWorkerAfterSalesCase(result.case) }
}
