import { getOrderById } from '../../../repositories/order-repo.js'
import { updateTask } from '../../../repositories/task-repo.js'
import { createTaskEvent } from '../../../repositories/task-event-repo.js'
import {
  buyCloudtentaclesSku,
  getCloudtentaclesAsset,
  listCloudtentaclesSku,
  useCloudtentaclesSku,
} from '../../platforms/cloudtentacles/catalog-service.js'
import { getCloudtentaclesKnapsack } from '../../platforms/cloudtentacles/knapsack-service.js'
import {
  backCloudtentaclesVirtualNumber,
  getCloudtentaclesBindInfo,
} from '../../platforms/cloudtentacles/virtual-number-service.js'
import { consumeKuaishouEticket } from '../../platforms/kuaishou-eticket/consume-service.js'
import {
  getKuaishouEticketSourceConfig,
  resolveKuaishouEticketShopConfig,
} from '../../platforms/kuaishou-eticket/source-config-service.js'
import { createHttpError } from '../../../utils/http.js'
import { nowIso } from '../../../utils/time.js'
import {
  createAdminViewerContext,
  parseTaskContext,
} from '../admin-read-shared-helpers.js'
import {
  getRequiredTask,
  mapTaskActionPayload,
} from '../admin-task-read-helpers.js'
import {
  ensureTaskClaimLink,
  getTaskClaimExpiresAt,
  maskCode,
  maskPhone,
} from './shared.js'
import {
  isKuaishouCloudTask,
  normalizeKuaishouCloudFlow,
  normalizeKuaishouCloudRoleInfo,
  prepareKuaishouCloudBindResourceWithFallback,
  resolveKuaishouCloudBindUrlExpiresAt,
  resolveKuaishouCloudBindingResources,
  resolveKuaishouCloudVnKeyCandidates,
  resolvePersistedCloudtentaclesContext,
} from './kuaishou-cloud-helpers.js'

import type {
  AdminEntityIdInput,
  AdminViewerSessionInput,
} from '../../../types/admin-read-inputs.js'
import type { AdminTaskKuaishouCloudDispatchInput } from '../../../types/admin-write-inputs.js'
import type { AdminTaskActionResponse } from '../../../types/admin-write-models.js'

export async function prepareAdminTaskKuaishouCloudFulfillment(
  taskId: AdminEntityIdInput,
  session: AdminViewerSessionInput | null = null,
): Promise<AdminTaskActionResponse> {
  const task = await getRequiredTask(taskId)
  const now = nowIso()
  const viewerContext = createAdminViewerContext(session)

  if (!viewerContext.canManageTaskLifecycle) {
    throw createHttpError('当前账号没有权限准备绑定资源', {
      statusCode: 403,
      errorCode: 'admin_task_prepare_kuaishou_cloud_forbidden',
    })
  }

  if (!isKuaishouCloudTask(task)) {
    throw createHttpError('当前任务不是快手 cloud 履约任务', {
      statusCode: 409,
      errorCode: 'admin_task_not_kuaishou_cloud',
    })
  }

  const taskContext = parseTaskContext(task)
  const flow = normalizeKuaishouCloudFlow(taskContext.kuaishouCloudFulfillment)
  const cloudContext = resolvePersistedCloudtentaclesContext()
  const [knapsack, skuList] = await Promise.all([
    getCloudtentaclesKnapsack(cloudContext),
    listCloudtentaclesSku(cloudContext),
  ])
  const resolvedBinding = resolveKuaishouCloudBindingResources(flow, {
    skuItems: Array.isArray(skuList.items) ? skuList.items : [],
    knapsackItems: Array.isArray(knapsack.items) ? knapsack.items : [],
  })
  const vnKeyCandidates = resolveKuaishouCloudVnKeyCandidates({
    flow,
    binding: resolvedBinding,
  })

  if (!resolvedBinding.skuId || vnKeyCandidates.length === 0) {
    throw createHttpError('当前任务缺少可用 cloud 资源，且无法根据商品名自动解析 SKU / VN Key', {
      statusCode: 409,
      errorCode: 'admin_task_kuaishou_cloud_missing_binding_config',
    })
  }

  const flowWithResolvedBinding = {
    ...flow,
    binding: {
      ...flow.binding,
      skuId: resolvedBinding.skuId,
      skuName: resolvedBinding.skuName,
      vnKey: resolvedBinding.vnKey,
    },
  }
  const knapsackItem = resolvedBinding.knapsackItem
  let usedKnapsack = Number(knapsackItem?.count || 0) > 0
  let purchaseTriggered = false
  let assetBefore = 0
  let assetAfter = 0
  const claimLinkState = await ensureTaskClaimLink(task)

  if (!usedKnapsack) {
    if (!flowWithResolvedBinding.purchase.autoBuyEnabled) {
      throw createHttpError('背包中没有现成库存，且当前配置未开启自动购买', {
        statusCode: 409,
        errorCode: 'admin_task_kuaishou_cloud_auto_buy_disabled',
      })
    }

    const asset = await getCloudtentaclesAsset(cloudContext)
    const targetSku = resolvedBinding.skuItem

    if (!targetSku) {
      throw createHttpError(`cloudtentacles 未找到 SKU ${flowWithResolvedBinding.binding.skuId}`, {
        statusCode: 404,
        errorCode: 'admin_task_kuaishou_cloud_sku_not_found',
      })
    }

    assetBefore = Number(asset.asset || 0) || 0
    const targetPrice = Number(targetSku.price || 0) || 0
    const requiredAsset = targetPrice + flowWithResolvedBinding.purchase.minAssetReserve
    if (assetBefore < requiredAsset) {
      throw createHttpError(`余额不足，当前 ${assetBefore}，至少需要 ${requiredAsset}`, {
        statusCode: 409,
        errorCode: 'admin_task_kuaishou_cloud_asset_not_enough',
      })
    }

    await buyCloudtentaclesSku({
      ...cloudContext,
      id: flowWithResolvedBinding.binding.skuId,
      count: 1,
    })
    purchaseTriggered = true

    const assetResult = await getCloudtentaclesAsset(cloudContext)
    assetAfter = Number(assetResult.asset || 0) || 0
  }

  const preparedBinding = await prepareKuaishouCloudBindResourceWithFallback({
    cloudContext,
    vnKeyCandidates,
  })
  const vnId = preparedBinding.vnId
  const vnPhone = preparedBinding.vnPhone

  const nextContext = {
    ...taskContext,
    kuaishouCloudFulfillment: {
      ...flowWithResolvedBinding,
      binding: {
        ...flowWithResolvedBinding.binding,
        vnKey: preparedBinding.vnKey,
        prepareStatus: 'ready',
        vnId,
        vnPhone,
        bindUrl: preparedBinding.bindUrl,
        bindPreparedAt: now,
        bindExpiresAt: resolveKuaishouCloudBindUrlExpiresAt(now),
        bindProbeAt: null,
        bindProbeStatus: 'pending',
        bindProbeMessage: '',
        roleName: '',
        roleId: '',
      },
      role: {
        status: 'pending',
        name: '',
        rid: '',
        refreshedAt: null,
        errorMessage: '',
        rawInfo: null,
      },
      purchase: {
        ...flowWithResolvedBinding.purchase,
        usedKnapsack,
        purchaseTriggered,
        assetBefore,
        assetAfter,
        purchaseAt: purchaseTriggered ? now : flowWithResolvedBinding.purchase.purchaseAt,
      },
    },
  }

  const updatedTask = await updateTask(task.id, {
    task_status: 'waiting_binding',
    inventory_status: 'not_required',
    user_action_status: 'pending',
    claim_token: claimLinkState.token || task.claim_token || '',
    claim_expires_at: claimLinkState.expiredAt || getTaskClaimExpiresAt(task),
    last_error: '',
    context_json: JSON.stringify(nextContext),
    updated_at: now,
  })

  await createTaskEvent(task.id, 'kuaishou_cloud_binding_prepared', {
    skuId: flowWithResolvedBinding.binding.skuId,
    skuName: flowWithResolvedBinding.binding.skuName,
    vnKey: preparedBinding.vnKey,
    vnId,
    vnPhoneMasked: maskPhone(vnPhone),
    bindUrl: preparedBinding.bindUrl,
    purchaseTriggered,
    usedKnapsack,
    resolvedByName: resolvedBinding.resolvedByName,
  }, now)

  return {
    task: mapTaskActionPayload(updatedTask),
    claimUrl: claimLinkState.claimUrl,
    token: claimLinkState.token,
  }
}

export async function dispatchAdminTaskKuaishouCloudFulfillment(
  taskId: AdminEntityIdInput,
  payload: AdminTaskKuaishouCloudDispatchInput = {},
  session: AdminViewerSessionInput | null = null,
): Promise<AdminTaskActionResponse> {
  const task = await getRequiredTask(taskId)
  const now = nowIso()
  const viewerContext = createAdminViewerContext(session)

  if (!viewerContext.canManageTaskLifecycle) {
    throw createHttpError('当前账号没有权限执行发货', {
      statusCode: 403,
      errorCode: 'admin_task_dispatch_kuaishou_cloud_forbidden',
    })
  }

  if (!isKuaishouCloudTask(task)) {
    throw createHttpError('当前任务不是快手 cloud 履约任务', {
      statusCode: 409,
      errorCode: 'admin_task_not_kuaishou_cloud',
    })
  }

  const taskContext = parseTaskContext(task)
  const flow = normalizeKuaishouCloudFlow(taskContext.kuaishouCloudFulfillment)
  const cloudContext = resolvePersistedCloudtentaclesContext()

  if (!flow.binding.skuId || !flow.binding.vnId || !flow.binding.vnPhone) {
    throw createHttpError('当前任务还没有准备好绑定资源，请先准备绑定资源', {
      statusCode: 409,
      errorCode: 'admin_task_kuaishou_cloud_not_prepared',
    })
  }

  const ticketCode = String(payload.ticketCode || '').trim()
  const persistedTicketCode = String(flow.ticket.code || '').trim()

  if (!persistedTicketCode && !ticketCode) {
    throw createHttpError('客户还没有在领取页提交核销码，暂时不能直接发货', {
      statusCode: 409,
      errorCode: 'admin_task_kuaishou_cloud_missing_ticket_code',
    })
  }

  const dispatchResult = await useCloudtentaclesSku({
    ...cloudContext,
    id: flow.binding.skuId,
    virtualNumberId: flow.binding.vnId,
    phone: flow.binding.vnPhone,
  })

  const nextContext = {
    ...taskContext,
    kuaishouCloudFulfillment: {
      ...flow,
      ticket: {
        ...flow.ticket,
        code: ticketCode || persistedTicketCode,
        capturedAt: ticketCode ? now : flow.ticket.capturedAt,
        capturedBy: ticketCode && session
          ? {
            userId: Number(session.userId || 0) || 0,
            username: String(session.username || '').trim(),
            role: String(session.role || '').trim(),
          }
          : flow.ticket.capturedBy,
      },
      dispatch: {
        ...flow.dispatch,
        status: 'success',
        dispatchAt: now,
        dispatchBy: session
          ? {
            userId: Number(session.userId || 0) || 0,
            username: String(session.username || '').trim(),
            role: String(session.role || '').trim(),
          }
          : null,
        sendType: Number(dispatchResult.sendType || 0) || 0,
        note: String(dispatchResult.note || dispatchResult.responseMessage || '').trim(),
      },
    },
  }

  const updatedTask = await updateTask(task.id, {
    task_status: 'dispatched_pending_return',
    delivery_status: 'delivered',
    result_code: 'kuaishou_cloud_dispatched',
    result_message: String(dispatchResult.responseMessage || dispatchResult.note || 'cloudtentacles 发货成功').trim(),
    last_error: '',
    context_json: JSON.stringify(nextContext),
    updated_at: now,
  })

  await createTaskEvent(task.id, 'kuaishou_cloud_dispatched', {
    ticketCodeMasked: maskCode(ticketCode || persistedTicketCode),
    skuId: flow.binding.skuId,
    vnId: flow.binding.vnId,
    vnPhoneMasked: maskPhone(flow.binding.vnPhone),
    sendType: dispatchResult.sendType,
    note: dispatchResult.note,
  }, now)

  return {
    task: mapTaskActionPayload(updatedTask),
  }
}

export async function refreshAdminTaskKuaishouCloudRoleInfo(
  taskId: AdminEntityIdInput,
  session: AdminViewerSessionInput | null = null,
): Promise<AdminTaskActionResponse> {
  const task = await getRequiredTask(taskId)
  const now = nowIso()
  const viewerContext = createAdminViewerContext(session)

  if (!viewerContext.canOperateAssistedTask) {
    throw createHttpError('当前账号没有权限刷新角色信息', {
      statusCode: 403,
      errorCode: 'admin_task_refresh_kuaishou_cloud_role_forbidden',
    })
  }

  if (!isKuaishouCloudTask(task)) {
    throw createHttpError('当前任务不是快手 cloud 履约任务', {
      statusCode: 409,
      errorCode: 'admin_task_not_kuaishou_cloud',
    })
  }

  const taskContext = parseTaskContext(task)
  const flow = normalizeKuaishouCloudFlow(taskContext.kuaishouCloudFulfillment)
  if (!flow.binding.vnId || !flow.binding.vnKey) {
    throw createHttpError('当前任务还没有可查询的绑定角色信息，请先准备绑定资源', {
      statusCode: 409,
      errorCode: 'admin_task_kuaishou_cloud_missing_bind_info_context',
    })
  }

  const cloudContext = resolvePersistedCloudtentaclesContext()
  const bindInfoResult = await getCloudtentaclesBindInfo({
    ...cloudContext,
    key: flow.binding.vnKey,
    id: flow.binding.vnId,
  })

  const bindInfo = normalizeKuaishouCloudRoleInfo(bindInfoResult.bindInfo)
  const nextContext = {
    ...taskContext,
    kuaishouCloudFulfillment: {
      ...flow,
      binding: {
        ...flow.binding,
        roleName: bindInfo.name,
        roleId: bindInfo.rid,
      },
      role: {
        status: bindInfo.name || bindInfo.rid ? 'ready' : 'pending',
        name: bindInfo.name,
        rid: bindInfo.rid,
        refreshedAt: now,
        errorMessage: bindInfo.name || bindInfo.rid ? '' : '当前还没有查询到角色信息，请让客户完成绑定后再刷新',
        rawInfo: bindInfo.rawInfo,
      },
    },
  }

  const updatedTask = await updateTask(task.id, {
    role_id: bindInfo.rid || '',
    role_name: bindInfo.name || '',
    context_json: JSON.stringify(nextContext),
    updated_at: now,
  })

  await createTaskEvent(task.id, 'kuaishou_cloud_role_info_refreshed', {
    roleName: bindInfo.name,
    roleId: bindInfo.rid,
    vnId: flow.binding.vnId,
    refreshedBy: session
      ? {
        userId: Number(session.userId || 0) || 0,
        username: String(session.username || '').trim(),
        role: String(session.role || '').trim(),
      }
      : null,
  }, now)

  return {
    task: mapTaskActionPayload(updatedTask),
  }
}

export async function returnNumberAdminTaskKuaishouCloudFulfillment(
  taskId: AdminEntityIdInput,
  session: AdminViewerSessionInput | null = null,
): Promise<AdminTaskActionResponse> {
  const task = await getRequiredTask(taskId)
  const now = nowIso()
  const viewerContext = createAdminViewerContext(session)

  if (!viewerContext.canManageTaskLifecycle) {
    throw createHttpError('当前账号没有权限退还号码', {
      statusCode: 403,
      errorCode: 'admin_task_return_kuaishou_cloud_forbidden',
    })
  }

  if (!isKuaishouCloudTask(task)) {
    throw createHttpError('当前任务不是快手 cloud 履约任务', {
      statusCode: 409,
      errorCode: 'admin_task_not_kuaishou_cloud',
    })
  }

  const taskContext = parseTaskContext(task)
  const flow = normalizeKuaishouCloudFlow(taskContext.kuaishouCloudFulfillment)
  const cloudContext = resolvePersistedCloudtentaclesContext()

  if (!flow.binding.vnId || !flow.binding.vnKey) {
    throw createHttpError('当前任务缺少可退还的虚拟号信息', {
      statusCode: 409,
      errorCode: 'admin_task_kuaishou_cloud_missing_return_context',
    })
  }

  await backCloudtentaclesVirtualNumber({
    ...cloudContext,
    key: flow.binding.vnKey,
    id: flow.binding.vnId,
  })

  const order = await getOrderById(task.order_id)
  const ticketCode = String(flow.ticket.code || '').trim()
  const shopId = String(flow.consume.shopId || order?.shop_id || '').trim()
  const shopName = String(flow.consume.shopName || order?.shop_name || '').trim()
  const eticketSource = getKuaishouEticketSourceConfig()
  const shopConfig = resolveKuaishouEticketShopConfig({
    shopId,
    shopName,
  })
  let consumeStatus = 'pending'
  let consumeErrorMessage = ''
  let consumedAt = null
  let nextTaskStatus = 'completed'
  let nextResultCode = 'kuaishou_cloud_completed'
  let nextResultMessage = 'cloudtentacles 发货、退号并完成快手核销'

  if (!order) {
    consumeStatus = 'failed'
    consumeErrorMessage = '任务关联订单不存在，无法执行快手核销'
  } else if (!ticketCode) {
    consumeStatus = 'failed'
    consumeErrorMessage = '客户未提交有效核销码，无法执行快手核销'
  } else if (!shopConfig || shopConfig.enabled === false || !String(shopConfig.cookie || '').trim()) {
    consumeStatus = 'failed'
    consumeErrorMessage = '订单对应快手小店缺少可用 Cookie，无法执行快手核销'
  } else {
    try {
      const consumeResult = await consumeKuaishouEticket({
        baseUrl: eticketSource.baseUrl,
        cookie: shopConfig.cookie,
        eTicketId: ticketCode,
        oid: String(flow.ticket.oid || '').trim(),
        formToken: String(flow.ticket.formToken || '').trim(),
      })

      if (consumeResult.consumed) {
        consumeStatus = 'success'
        consumedAt = now
      } else {
        consumeStatus = 'failed'
        consumeErrorMessage = String(consumeResult.errorMessage || '快手核销失败').trim()
      }
    } catch (error) {
      consumeStatus = 'failed'
      consumeErrorMessage = error instanceof Error ? error.message : '快手核销失败'
    }
  }

  if (consumeStatus !== 'success') {
    nextTaskStatus = 'manual_review'
    nextResultCode = 'kuaishou_cloud_consume_failed'
    nextResultMessage = consumeErrorMessage || '号码已退还，但快手核销未完成，请人工处理'
  }

  const nextContext = {
    ...taskContext,
    kuaishouCloudFulfillment: {
      ...flow,
      returnNumber: {
        ...flow.returnNumber,
        status: 'success',
        returnedAt: now,
        returnedBy: session
          ? {
            userId: Number(session.userId || 0) || 0,
            username: String(session.username || '').trim(),
            role: String(session.role || '').trim(),
          }
          : null,
      },
      consume: {
        ...flow.consume,
        status: consumeStatus,
        shopId: shopId || flow.consume.shopId,
        shopName,
        autoConsumeEnabled: flow.consume.autoConsumeEnabled === true,
        consumedAt,
        errorMessage: consumeErrorMessage,
      },
    },
  }

  const updatedTask = await updateTask(task.id, {
    task_status: nextTaskStatus,
    delivery_status: 'delivered',
    result_code: nextResultCode,
    result_message: nextResultMessage,
    redeemed_at: consumeStatus === 'success' ? now : task.redeemed_at,
    last_error: consumeErrorMessage,
    context_json: JSON.stringify(nextContext),
    updated_at: now,
  })

  await createTaskEvent(task.id, 'kuaishou_cloud_number_returned', {
    vnId: flow.binding.vnId,
    vnPhoneMasked: maskPhone(flow.binding.vnPhone),
  }, now)

  await createTaskEvent(
    task.id,
    consumeStatus === 'success' ? 'kuaishou_cloud_consumed' : 'kuaishou_cloud_consume_failed',
    {
      ticketCodeMasked: maskCode(ticketCode),
      shopId,
      shopName,
      consumeStatus,
      errorMessage: consumeErrorMessage,
    },
    now,
  )

  return {
    task: mapTaskActionPayload(updatedTask),
  }
}
