import { getTaskById } from '../../repositories/task-repo.js'
import { createHttpError } from '../../utils/http.js'
import { safeParseJson } from './admin-query-utils.js'
import { asJsonObject, type JsonRecord } from '../../types/json.js'
import {
  TASK_STATUS,
  isTaskFulfillmentCompletedStatus,
  normalizeTaskStatus,
} from '../../domain/task-status.js'
import {
  createAdminViewerContext,
  getTaskPrimaryClaimTokenId,
} from './admin-read-shared-helpers.js'

import type {
  AdminOrderFulfillmentProgress,
  AdminTaskListItem,
} from '../../types/admin/read-models.js'
import type { AdminTaskActionPayload } from '../../types/admin/write-models.js'
import type { TaskEventRow, TaskRow } from '../../types/repository/rows.js'
import type { AdminViewerContext } from './admin-read-shared-helpers.js'

type TaskFulfillmentState = {
  resourceStatus: string
  customerStatus: string
}

export function mapAdminTaskSummary(task: TaskRow): JsonRecord {
  const fulfillment = buildTaskFulfillmentState(task)

  return {
    taskId: task.id,
    taskNo: task.task_no,
    deliveryStatus: task.delivery_status || '',
    status: task.task_status,
    resourceStatus: fulfillment.resourceStatus,
    customerStatus: fulfillment.customerStatus,
    loginType: task.login_type,
    runtimeSessionId: task.runtime_session_id,
    claimedAt: task.claimed_at,
    roleConfirmedAt: task.role_confirmed_at,
    redeemedAt: task.redeemed_at,
    lastError: task.last_error,
    retryCount: getTaskRetryCount(task),
    createdAt: task.created_at,
    updatedAt: task.updated_at,
  }
}

export function mapTaskActionPayload(task: any): AdminTaskActionPayload {
  const primaryClaimTokenId = getTaskPrimaryClaimTokenId(task)

  return {
    taskId: task.id,
    taskNo: task.task_no,
    status: task.task_status,
    deliveryStatus: task.delivery_status,
    resultCode: task.result_code,
    resultMessage: task.result_message,
    primaryClaimTokenId,
    lastError: task.last_error,
    updatedAt: task.updated_at,
  }
}

export async function getRequiredTask(taskId: number | string): Promise<TaskRow> {
  const task = await getTaskById(Number(taskId))

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

  return task
}

export function mapAdminTaskListItem(
  task: TaskRow,
  viewerContext: AdminViewerContext = createAdminViewerContext(),
): AdminTaskListItem {
  const fulfillment = buildTaskFulfillmentState(task)

  return {
    taskId: task.id,
    taskNo: task.task_no,
    platformOrderId: task.platform_order_id,
    skuCode: task.sku_code || '',
    skuName: task.sku_name || '',
    status: task.task_status,
    executorKey: task.executor_key || '',
    deliveryStatus: task.delivery_status || '',
    resultCode: task.result_code || '',
    resultMessage: task.result_message || '',
    resourceStatus: fulfillment.resourceStatus,
    customerStatus: fulfillment.customerStatus,
    loginType: task.login_type,
    roleName: resolveTaskDisplayRoleName(task),
    roleId: resolveTaskDisplayRoleId(task),
    runtimeSessionId: task.runtime_session_id,
    claimedAt: task.claimed_at,
    roleConfirmedAt: task.role_confirmed_at,
    redeemedAt: task.redeemed_at,
    retryCount: getTaskRetryCount(task),
    lastError: task.last_error,
    createdAt: task.created_at,
    updatedAt: task.updated_at,
    claimToken: viewerContext.canViewSensitiveTaskData
      ? task.primary_claim_token || task.claim_token || ''
      : '',
    screenshotPath: viewerContext.role === 'support' ? '' : task.screenshot_path || '',
  }
}

export function mapAdminTaskEvent(event: TaskEventRow): JsonRecord {
  const payload = safeParseJson(event.payload_json)

  return {
    eventId: event.id,
    eventType: String(event.event_type || '').trim(),
    payload: normalizeRecord(payload),
    createdAt: event.created_at,
  }
}

export function buildOrderFulfillmentProgress(
  tasks: TaskRow[] | null | undefined,
): AdminOrderFulfillmentProgress {
  const normalizedTasks = Array.isArray(tasks) ? tasks : []
  const totalTaskCount = normalizedTasks.length
  const taskFulfillments = normalizedTasks.map((task) => buildTaskFulfillmentState(task))
  const preparedTaskCount = normalizedTasks.filter((task) => isTaskResourcePrepared(task)).length
  const completedTaskCount = normalizedTasks.filter((task) =>
    isTaskFulfillmentCompleted(task),
  ).length

  let resourceStatus = 'pending_prepare'
  let customerStatus = 'not_started'

  if (totalTaskCount === 0) {
    return {
      totalTaskCount,
      preparedTaskCount,
      completedTaskCount,
      resourceStatus,
      customerStatus,
    }
  }

  if (normalizedTasks.every((task) => isTaskFulfillmentCompleted(task))) {
    resourceStatus = 'resource_ready'
    customerStatus = 'customer_completed'
  } else if (
    taskFulfillments.some((item) =>
      ['customer_processing', 'customer_confirmed', 'link_opened'].includes(item.customerStatus),
    )
  ) {
    resourceStatus = preparedTaskCount > 0 ? 'resource_ready' : 'pending_prepare'
    customerStatus = 'customer_processing'
  } else if (taskFulfillments.some((item) => item.customerStatus === 'waiting_customer')) {
    resourceStatus = preparedTaskCount > 0 ? 'resource_ready' : 'pending_prepare'
    customerStatus = 'waiting_customer'
  } else if (taskFulfillments.some((item) => item.customerStatus === 'customer_exception')) {
    resourceStatus = preparedTaskCount > 0 ? 'resource_ready' : 'pending_prepare'
    customerStatus = 'customer_exception'
  } else if (preparedTaskCount > 0) {
    resourceStatus = 'resource_ready'
  } else if (
    taskFulfillments.some((item) =>
      ['manual_review', 'retry_pending'].includes(item.resourceStatus),
    )
  ) {
    resourceStatus = 'resource_exception'
  }

  return {
    totalTaskCount,
    preparedTaskCount,
    completedTaskCount,
    resourceStatus,
    customerStatus,
  }
}

function buildTaskFulfillmentState(task: TaskRow | null | undefined): TaskFulfillmentState {
  const normalizedStatus = normalizeTaskStatus(task?.task_status)

  if (!normalizedStatus) {
    return {
      resourceStatus: 'pending_prepare',
      customerStatus: 'not_started',
    }
  }

  if (normalizedStatus === TASK_STATUS.PENDING_PAYMENT) {
    return { resourceStatus: 'pending_payment', customerStatus: 'not_started' }
  }

  if (normalizedStatus === TASK_STATUS.PAID) {
    return { resourceStatus: 'pending_prepare', customerStatus: 'not_started' }
  }

  if (normalizedStatus === TASK_STATUS.PENDING_BINDING_PREPARE) {
    return { resourceStatus: 'pending_prepare', customerStatus: 'not_started' }
  }

  if (normalizedStatus === TASK_STATUS.WAITING_BINDING) {
    return { resourceStatus: 'resource_ready', customerStatus: 'waiting_customer' }
  }

  if (normalizedStatus === TASK_STATUS.DISPATCHED_PENDING_RETURN) {
    return { resourceStatus: 'resource_ready', customerStatus: 'customer_completed' }
  }

  if (normalizedStatus === TASK_STATUS.COMPLETED) {
    return { resourceStatus: 'resource_ready', customerStatus: 'customer_completed' }
  }

  if (normalizedStatus === TASK_STATUS.MANUAL_REVIEW) {
    return { resourceStatus: 'manual_review', customerStatus: 'customer_exception' }
  }

  if (normalizedStatus === TASK_STATUS.RETRY_PENDING) {
    return { resourceStatus: 'retry_pending', customerStatus: 'customer_exception' }
  }

  if (normalizedStatus === TASK_STATUS.CLOSED) {
    return { resourceStatus: 'closed', customerStatus: 'closed' }
  }

  if (normalizedStatus === TASK_STATUS.EXPIRED) {
    return { resourceStatus: 'expired', customerStatus: 'expired' }
  }

  if (normalizedStatus === TASK_STATUS.LINK_GENERATED) {
    return { resourceStatus: 'resource_ready', customerStatus: 'waiting_customer' }
  }

  if (normalizedStatus === TASK_STATUS.CLAIMED) {
    return { resourceStatus: 'resource_ready', customerStatus: 'link_opened' }
  }

  if (normalizedStatus === TASK_STATUS.ROLE_CONFIRMED) {
    return { resourceStatus: 'resource_ready', customerStatus: 'customer_confirmed' }
  }

  if (normalizedStatus === TASK_STATUS.REDEEMING) {
    return { resourceStatus: 'resource_ready', customerStatus: 'customer_processing' }
  }

  if (normalizedStatus === TASK_STATUS.REDEEMED) {
    return { resourceStatus: 'resource_ready', customerStatus: 'customer_completed' }
  }

  if (isTaskResourcePrepared(task)) {
    return { resourceStatus: 'resource_ready', customerStatus: 'waiting_customer' }
  }

  return { resourceStatus: 'pending_prepare', customerStatus: 'not_started' }
}

function isTaskResourcePrepared(task: TaskRow | null | undefined): boolean {
  return Boolean(task && getTaskPrimaryClaimTokenId(task))
}

function isTaskFulfillmentCompleted(task: TaskRow | null | undefined): boolean {
  return isTaskFulfillmentCompletedStatus(task?.task_status)
}

function normalizeRecord(value: unknown): JsonRecord {
  return asJsonObject(value)
}

function getTaskRetryCount(task: TaskRow | null | undefined): number {
  return Number(task?.attempt_count || 0)
}

function resolveTaskDisplayRoleName(task: TaskRow): string {
  return String(task.kuaishou_role_name || task.role_name || '').trim()
}

function resolveTaskDisplayRoleId(task: TaskRow): string {
  return String(task.kuaishou_role_id || task.role_id || '').trim()
}
