import { buildClaimUrl } from '../claim/claim-service.js'
import { getClaimTokenById } from '../../repositories/claim-token-repo.js'
import {
  getInventoryItemById,
  listInventoryItems,
  listInventorySkuSuggestions,
} from '../../repositories/inventory-repo.js'
import { listOrderItemsByOrderId } from '../../repositories/order-item-repo.js'
import { getOrderById, listOrders } from '../../repositories/order-repo.js'
import { getTaskById, listTasks, listTasksByOrderId } from '../../repositories/task-repo.js'
import { listTaskInventoryBindingsByTaskId } from '../../repositories/task-inventory-binding-repo.js'
import { listTaskEventsByTaskId } from '../../repositories/task-event-repo.js'
import { getWebhookEventById, listWebhookEvents, listWebhookEventsByOrderId } from '../../repositories/webhook-event-repo.js'
import { createHttpError } from '../../utils/http.js'
import { formatFenToAmount, normalizeFen } from '../../utils/money.js'
import { getTencentBrowserSessionReviewScreenshotPath } from '../session/session.js'
import { normalizeDateQuery, normalizePage, normalizePageSize, safeParseJson } from './admin-query-utils.js'
import {
  canViewerCloseTask,
  canRegenerateClaimLinkForViewer,
  canViewerConfirmAssistedRole,
  canViewerRedeemAssistedTask,
  createAdminViewerContext,
  getTaskPrimaryClaimTokenId,
  getTaskPrimaryInventoryItemId,
  isAssistedClaimTask,
  isManualDispatchTask,
  mapKuaishouCloudFulfillmentContext,
  mapManualDispatchContext,
  mapRedeemResolutionContext,
  parseTaskContext,
  parseTaskState,
  resolveAdminTaskScreenshotUrl,
  resolveDisplayShopName,
  resolveOrderItemDeliveryMode,
  resolveOrderItemTitle,
} from './admin-read-shared-helpers.js'
import { mapAdminInventoryListItem } from './admin-inventory-read-helpers.js'
import { mapAdminOrderListItem, summarizeOrderItems } from './admin-order-read-helpers.js'
import { mapAdminWebhookEvent } from './admin-webhook-read-helpers.js'
import {
  buildOrderAgisoAutoDeliverySummary,
  buildOrderBindingSummary,
  createTaskBindingSummaryFromBindings,
  getRequiredTask,
  getTaskBindingSummary,
  getTaskBindingSummaryMap,
  mapAdminTaskEvent,
  mapAdminTaskInventoryBinding,
  mapAdminTaskListItem,
  mapAdminTaskSummary,
} from './admin-task-read-helpers.js'

import type {
  AdminInventoryListResponse,
  AdminInventorySkuSuggestionResponse,
  AdminOrderListResponse,
  AdminTaskListResponse,
  AdminWebhookEventListResponse,
} from '../../types/admin-read-models.js'
import type {
  AdminEntityIdInput,
  AdminInventoryListQueryInput,
  AdminInventorySkuSuggestionQueryInput,
  AdminOrderListQueryInput,
  AdminTaskListQueryInput,
  AdminViewerSessionInput,
  AdminWebhookEventListQueryInput,
} from '../../types/admin-read-inputs.js'

type JsonRecord = Record<string, any>

export async function getAdminOrders(query: AdminOrderListQueryInput = {}): Promise<AdminOrderListResponse> {
  const page = normalizePage(query.page)
  const pageSize = normalizePageSize(query.pageSize)
  const { items, total } = await listOrders({
    page,
    pageSize,
    platformOrderId: String(query.platformOrderId || '').trim(),
    payStatus: String(query.payStatus || '').trim(),
    skuCode: String(query.skuCode || '').trim(),
    dateFrom: normalizeDateQuery(query.dateFrom),
    dateTo: normalizeDateQuery(query.dateTo, true),
  })

  return {
    items: await Promise.all(items.map((item) => mapAdminOrderListItem(item))),
    pagination: { page, pageSize, total },
  }
}

export async function getAdminOrderDetail(orderId: AdminEntityIdInput): Promise<JsonRecord> {
  const order = await getOrderById(Number(orderId))

  if (!order) {
    throw createHttpError('订单不存在', {
      statusCode: 404,
      errorCode: 'admin_order_not_found',
    })
  }

  const [items, tasks, webhookEvents] = await Promise.all([
    listOrderItemsByOrderId(order.id),
    listTasksByOrderId(order.id),
    listWebhookEventsByOrderId(order.id),
  ])
  const taskBindingSummaryMap = await getTaskBindingSummaryMap(tasks.map((task) => task.id))
  const itemSummary = summarizeOrderItems(items)

  return {
    order: {
      orderId: order.id,
      provider: order.provider || 'agiso',
      platform: order.platform,
      shopId: order.shop_id || '',
      shopName: resolveDisplayShopName(order.provider, order.shop_id, order.shop_name),
      platformOrderId: order.platform_order_id,
      orderStatus: order.order_status,
      payStatus: order.pay_status,
      buyerId: order.buyer_id,
      buyerName: order.buyer_name,
      receiverContact: order.receiver_contact,
      totalAmount: formatFenToAmount(order.total_amount),
      totalAmountFen: normalizeFen(order.total_amount),
      currency: order.currency,
      paidAt: order.paid_at,
      createdAt: order.created_at,
      updatedAt: order.updated_at,
      itemSummary,
      rawPayload: order.raw_payload_json && typeof order.raw_payload_json === 'object'
        ? order.raw_payload_json
        : JSON.parse(String(order.raw_payload_json || '{}')),
      bindingSummary: buildOrderBindingSummary(tasks, taskBindingSummaryMap),
      agisoAutoDelivery: buildOrderAgisoAutoDeliverySummary(order, tasks),
    },
    items: items.map((item) => ({
      orderItemId: item.id,
      skuCode: item.sku_code,
      skuName: item.sku_name,
      itemTitle: resolveOrderItemTitle(item),
      quantity: item.quantity,
      deliveryMode: resolveOrderItemDeliveryMode(tasks, item.id),
      spec: item.spec_json && typeof item.spec_json === 'object'
        ? item.spec_json
        : JSON.parse(String(item.spec_json || '{}')),
    })),
    tasks: tasks.map((task) => mapAdminTaskSummary(task, getTaskBindingSummary(taskBindingSummaryMap, task.id))),
    webhookEvents: webhookEvents.map((event) => ({
      eventId: event.id,
      provider: event.provider || 'agiso',
      platform: event.platform,
      shopId: event.shop_id || '',
      shopName: resolveDisplayShopName(event.provider, event.shop_id, event.shop_name),
      eventType: event.event_type,
      eventKey: event.event_key,
      signatureValid: Boolean(event.signature_valid),
      processed: Boolean(event.processed),
      processError: event.process_error,
      createdAt: event.created_at,
    })),
  }
}

export async function getAdminTasks(
  query: AdminTaskListQueryInput = {},
  session: AdminViewerSessionInput | null = null,
): Promise<AdminTaskListResponse> {
  const page = normalizePage(query.page)
  const pageSize = normalizePageSize(query.pageSize)
  const { items, total } = await listTasks({
    page,
    pageSize,
    status: String(query.status || '').trim(),
    platformOrderId: String(query.platformOrderId || '').trim(),
    taskNo: String(query.taskNo || '').trim(),
    skuCode: String(query.skuCode || '').trim(),
    roleId: String(query.roleId || '').trim(),
    dateFrom: normalizeDateQuery(query.dateFrom),
    dateTo: normalizeDateQuery(query.dateTo, true),
  })
  const taskBindingSummaryMap = await getTaskBindingSummaryMap(items.map((item) => item.id))
  const viewerContext = createAdminViewerContext(session)

  return {
    items: items.map((item) => mapAdminTaskListItem(
      item,
      getTaskBindingSummary(taskBindingSummaryMap, item.id),
      viewerContext,
    )),
    pagination: { page, pageSize, total },
  }
}

export async function getAdminTaskDetail(
  taskId: AdminEntityIdInput,
  session: AdminViewerSessionInput | null = null,
): Promise<JsonRecord> {
  const task = await getTaskById(Number(taskId))

  if (!task) {
    throw createHttpError('任务不存在', {
      statusCode: 404,
      errorCode: 'admin_task_not_found',
    })
  }

  const [order, claimToken, inventoryItem, taskEvents, inventoryBindings] = await Promise.all([
    getOrderById(task.order_id),
    getTaskPrimaryClaimTokenId(task) ? getClaimTokenById(getTaskPrimaryClaimTokenId(task)) : Promise.resolve(null),
    getTaskPrimaryInventoryItemId(task) ? getInventoryItemById(getTaskPrimaryInventoryItemId(task)) : Promise.resolve(null),
    listTaskEventsByTaskId(task.id),
    listTaskInventoryBindingsByTaskId(task.id),
  ])
  const orderItems = order ? await listOrderItemsByOrderId(order.id) : []
  const orderItem = orderItems.find((item) => item.id === task.order_item_id) || null
  const taskContext = parseTaskContext(task)
  const taskState = parseTaskState(task)
  const taskBindingSummary = createTaskBindingSummaryFromBindings(inventoryBindings)
  const viewerContext = createAdminViewerContext(session)
  const mappedInventoryBindings = inventoryBindings.map((binding) => mapAdminTaskInventoryBinding(binding, task, viewerContext))
  const claimUrl = claimToken ? buildClaimUrl(claimToken.token) : ''
  const screenshotUrl = await resolveAdminTaskScreenshotUrl(task, viewerContext)
  const kuaishouCloudFulfillment = mapKuaishouCloudFulfillmentContext(taskContext.kuaishouCloudFulfillment)

  return {
    task: mapAdminTaskListItem({
      ...task,
      sku_code: orderItem?.sku_code || '',
      sku_name: orderItem?.sku_name || '',
      inventory_display_value: inventoryItem?.display_value || '',
      claim_token: claimToken?.token || '',
    }, taskBindingSummary, viewerContext),
    order: order
      ? {
        orderId: order.id,
        provider: order.provider || 'agiso',
        platform: order.platform,
        shopId: order.shop_id || '',
        shopName: order.shop_name || '',
        platformOrderId: order.platform_order_id,
        payStatus: order.pay_status,
        orderStatus: order.order_status,
      }
      : null,
    orderItem: orderItem
      ? {
        orderItemId: orderItem.id,
        skuCode: orderItem.sku_code,
        skuName: orderItem.sku_name,
        quantity: orderItem.quantity,
      }
      : null,
    claimToken: claimToken
      ? {
        primaryClaimTokenId: claimToken.id,
        token: viewerContext.canViewSensitiveTaskData ? claimToken.token : '',
        status: claimToken.status,
        expiredAt: claimToken.expired_at,
        claimUrl,
      }
      : null,
    inventory: inventoryItem
      ? {
        inventoryItemId: inventoryItem.id,
        skuCode: inventoryItem.sku_code,
        batchNo: inventoryItem.batch_no,
        credentialType: inventoryItem.credential_type || 'tencent_code',
        displayValue: viewerContext.canViewSensitiveTaskData ? inventoryItem.display_value : '',
        status: inventoryItem.status,
      }
      : null,
    inventoryBindings: mappedInventoryBindings,
    artifacts: viewerContext.canViewSensitiveTaskData ? safeParseJson(task.artifacts_json) : {},
    screenshotUrl,
    review: {
      required: isAssistedClaimTask(task),
      screenshotCapturedAt: String(taskState.reviewCapturedAt || '').trim() || null,
      roleId: String(taskState.reviewRoleId || '').trim() || '',
      roleName: String(taskState.reviewRoleName || '').trim() || '',
    },
    redeemResolution: mapRedeemResolutionContext(taskContext.redeemResolution),
    kuaishouCloudFulfillment,
    manualDispatch: mapManualDispatchContext(taskContext.manualDispatch, viewerContext),
    events: taskEvents.map(mapAdminTaskEvent),
    operations: {
      canRetry: viewerContext.canManageTaskLifecycle
        && !isManualDispatchTask(task)
        && ['retry_pending', 'manual_review', 'waiting_inventory'].includes(task.task_status),
      canReleaseInventory: mappedInventoryBindings.some((binding) => binding.canRelease),
      canRegenerateClaimLink: canRegenerateClaimLinkForViewer(task, viewerContext),
      canClose: canViewerCloseTask(task, viewerContext),
      canMarkManualReview: viewerContext.canManageTaskLifecycle && !['redeemed', 'closed', 'manual_review'].includes(task.task_status),
      canCompleteManualDispatch: viewerContext.canManageTaskLifecycle && isManualDispatchTask(task) && !['redeemed', 'closed'].includes(task.task_status),
      canPrepareKuaishouCloudFulfillment: viewerContext.canManageTaskLifecycle
        && String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
        && String(kuaishouCloudFulfillment?.dispatch.status || 'pending').trim() === 'pending'
        && String(kuaishouCloudFulfillment?.returnNumber.status || 'pending').trim() === 'pending'
        && ['pending_binding_prepare', 'manual_review', 'failed'].includes(String(task.task_status || '').trim()),
      canRefreshKuaishouCloudRoleInfo: viewerContext.canOperateAssistedTask
        && String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
        && Number(kuaishouCloudFulfillment?.binding.vnId || 0) > 0,
      canDispatchKuaishouCloudFulfillment: viewerContext.canManageTaskLifecycle
        && String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
        && ['waiting_binding'].includes(String(task.task_status || '').trim()),
      canReturnKuaishouCloudFulfillment: viewerContext.canManageTaskLifecycle
        && String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
        && ['dispatched_pending_return'].includes(String(task.task_status || '').trim()),
      canSupportConfirmRole: canViewerConfirmAssistedRole(task, viewerContext),
      canSupportRedeem: canViewerRedeemAssistedTask(task, viewerContext),
      canViewSensitiveTaskData: viewerContext.canViewSensitiveTaskData,
    },
  }
}

export async function getAdminTaskScreenshotPath(
  taskId: AdminEntityIdInput,
  session: AdminViewerSessionInput | null = null,
): Promise<string> {
  const task = await getRequiredTask(taskId)

  if (task.screenshot_path) {
    return task.screenshot_path
  }

  if (task.browser_session_id) {
    return getTencentBrowserSessionReviewScreenshotPath(task.browser_session_id)
  }

  throw createHttpError('当前任务还没有可查看截图', {
    statusCode: 404,
    errorCode: 'admin_task_screenshot_not_found',
  })
}

export async function getAdminInventoryItems(
  query: AdminInventoryListQueryInput = {},
  session: AdminViewerSessionInput | null = null,
): Promise<AdminInventoryListResponse> {
  const page = normalizePage(query.page)
  const pageSize = normalizePageSize(query.pageSize)
  const viewerContext = createAdminViewerContext(session)
  const { items, total } = await listInventoryItems({
    page,
    pageSize,
    skuCode: String(query.skuCode || '').trim(),
    credentialType: String(query.credentialType || '').trim(),
    status: String(query.status || '').trim(),
    batchNo: String(query.batchNo || '').trim(),
    inventoryGroupCode: String(query.inventoryGroupCode || '').trim(),
    allowedInventoryGroupCodes: viewerContext.allowedInventoryGroupCodes,
  })

  return {
    items: await Promise.all(items.map((item) => mapAdminInventoryListItem(item))),
    pagination: { page, pageSize, total },
  }
}

export async function getAdminInventorySkuSuggestions(
  query: AdminInventorySkuSuggestionQueryInput = {},
  session: AdminViewerSessionInput | null = null,
): Promise<AdminInventorySkuSuggestionResponse> {
  const viewerContext = createAdminViewerContext(session)
  const credentialType = String(query.credentialType || '').trim()
  const keyword = String(query.keyword || '').trim()
  const inventoryGroupCode = String(query.inventoryGroupCode || '').trim()
  const requestedLimit = Number(query.limit)
  const limit = Number.isFinite(requestedLimit) && requestedLimit > 0
    ? Math.min(100, Math.floor(requestedLimit))
    : 50
  const items = await listInventorySkuSuggestions({
    credentialType,
    keyword,
    limit,
    inventoryGroupCode,
    allowedInventoryGroupCodes: viewerContext.allowedInventoryGroupCodes,
  })

  return {
    items: items.map((item) => ({
      skuCode: String(item.sku_code || '').trim(),
      credentialType: String(item.credential_type || '').trim() || 'tencent_code',
      inventoryGroupCode: String(item.inventory_group_code || '').trim(),
      totalCount: Number(item.total_count || 0),
      availableCount: Number(item.available_count || 0),
      latestUpdatedAt: item.latest_updated_at || null,
    })),
  }
}

export async function getAdminWebhookEvents(
  query: AdminWebhookEventListQueryInput = {},
): Promise<AdminWebhookEventListResponse> {
  const page = normalizePage(query.page)
  const pageSize = normalizePageSize(query.pageSize)
  const { items, total } = await listWebhookEvents({
    page,
    pageSize,
    provider: String(query.provider || '').trim(),
    platform: String(query.platform || '').trim(),
    platformOrderId: String(query.platformOrderId || '').trim(),
    processed: String(query.processed || '').trim(),
    visibility: String(query.visibility || '').trim() || 'important',
    relatedOrderId: String(query.relatedOrderId || '').trim(),
    dateFrom: normalizeDateQuery(query.dateFrom),
    dateTo: normalizeDateQuery(query.dateTo, true),
  })

  return {
    items: await Promise.all(items.map((item) => mapAdminWebhookEvent(item))),
    pagination: { page, pageSize, total },
  }
}

export async function getAdminWebhookEventDetail(eventId: AdminEntityIdInput): Promise<JsonRecord> {
  const event = await getWebhookEventById(Number(eventId))

  if (!event) {
    throw createHttpError('Webhook 事件不存在', {
      statusCode: 404,
      errorCode: 'admin_webhook_not_found',
    })
  }

  return mapAdminWebhookEvent(event, { includeRaw: true })
}
