import { createTaskEvent } from '../../../repositories/task-event-repo.js'
import { updateTask } from '../../../repositories/task-repo.js'
import { createHttpError } from '../../../utils/http.js'
import { nowIso } from '../../../utils/time.js'
import { TASK_STATUS, normalizeTaskStatus, type TaskStatus } from '../../../domain/task-status.js'
import { backCloudtentaclesVirtualNumber } from '../../platforms/cloudtentacles/virtual-number-service.js'
import { consumeKuaishouIndustryVouchersForTask } from '../../platforms/kuaishou-industry/voucher-service.js'
import type { TaskRow } from '../../../types/repository/rows.js'
import {
  isIndustryEVoucherTask,
  isKuaishouCloudTask,
  maskCode,
  maskPhone,
  normalizeKuaishouCloudFlow,
  type JsonObject,
} from './domain.js'
import { resolvePersistedCloudtentaclesContextBySourceKeys } from './cloudtentacles-context.js'
import { normalizeActor, parseTaskContext } from './task-context.js'

/**
 * lewan 退还虚拟号。
 *
 * - 默认（发货后 autoFinalize）：退号 + 尝试行业电子凭证核销收尾
 * - `consumeIndustryVoucher: false`（admin 清理）：只退虚拟号，避免占号；与核销无关
 */
export async function returnKuaishouCloudFulfillmentTask(task: TaskRow, options: JsonObject = {}) {
  if (!isKuaishouCloudTask(task)) {
    throw createHttpError('当前任务不是 kuaishou-lewan 履约任务', {
      statusCode: 409,
      errorCode: 'kuaishou_cloud_task_invalid',
    })
  }

  const actor = normalizeActor(options.actor)
  const now = nowIso()
  const taskContext = parseTaskContext(task)
  const flow = normalizeKuaishouCloudFlow(taskContext.kuaishouCloudFulfillment)
  const cloudContext = resolvePersistedCloudtentaclesContextBySourceKeys([
    flow.binding.resolvedSourceKey,
    ...flow.binding.cloudSourceKeys,
  ])
  // admin 退号是清理虚拟号；只有发货收尾路径才顺带核销
  const allowConsumeIndustryVoucher = options.consumeIndustryVoucher !== false

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

  const taskStatus = normalizeTaskStatus(task.task_status)
  if (
    flow.returnNumber.status === 'success' &&
    (taskStatus === TASK_STATUS.COMPLETED || taskStatus === TASK_STATUS.MANUAL_REVIEW)
  ) {
    return { task, flow }
  }

  try {
    await backCloudtentaclesVirtualNumber({
      ...cloudContext,
      key: flow.binding.vnKey,
      id: flow.binding.vnId,
    })
  } catch (error) {
    // 号码已被上游回收/手动退回/账号换 token 无权限：视为已释放，继续完成核销收尾
    if (isNumberAlreadyReleasedError(error)) {
      await createTaskEvent(
        task.id,
        'kuaishou_cloud_number_already_released',
        {
          source: String(options.source || 'system').trim() || 'system',
          vnId: flow.binding.vnId,
          vnPhoneMasked: maskPhone(flow.binding.vnPhone),
          errorMessage: error instanceof Error ? error.message : String(error || ''),
          actor,
        },
        now,
      )
    } else {
      throw error
    }
  }

  const ticketCode = String(flow.ticket.code || '').trim()
  let consumeStatus
  let consumeErrorMessage = ''
  let consumedAt: string | null = null
  let nextTaskStatus: TaskStatus = TASK_STATUS.COMPLETED
  let nextResultCode = 'kuaishou_cloud_completed'
  const consumeAlreadyCompleted = flow.consume.status === 'success'
  const hasIndustryVoucher = hasKuaishouIndustryVoucherContext(taskContext)
  const isIndustryTask = isIndustryEVoucherTask(task)
  const shouldConsumeIndustryVoucher =
    allowConsumeIndustryVoucher && (hasIndustryVoucher || isIndustryTask)
  let nextResultMessage = shouldConsumeIndustryVoucher
    ? 'cloudtentacles 发货、退号并完成电子凭证核销'
    : allowConsumeIndustryVoucher
      ? 'cloudtentacles 发货、退号并收口'
      : '虚拟号已退还（清理占号，未执行核销）'
  let industryVoucherContextPatch: JsonObject | null = null

  if (consumeAlreadyCompleted) {
    consumeStatus = 'success'
    consumedAt = (flow.consume.consumedAt as string | null) || now
    if (!allowConsumeIndustryVoucher) {
      nextResultMessage = '虚拟号已退还；电子凭证此前已核销'
    }
  } else if (shouldConsumeIndustryVoucher) {
    const industryResult = hasIndustryVoucher
      ? await consumeKuaishouIndustryVouchersForTask(task, {
          source: String(options.source || 'system_auto_finalize').trim() || 'system_auto_finalize',
          token: String(
            isPlainObject(taskContext.kuaishouIndustryVoucher)
              ? taskContext.kuaishouIndustryVoucher.token || ''
              : '',
          ).trim(),
          consumeTime: Date.now(),
        })
      : {
          ok: true,
          consumed: [] as Array<Record<string, unknown>>,
          failed: [] as Array<{ errorMessage?: string }>,
        }

    if (industryResult.ok) {
      consumeStatus = 'success'
      consumedAt = now
      const consumedVoucher = industryResult.consumed[0] || null
      if (consumedVoucher) {
        industryVoucherContextPatch = {
          oid: consumedVoucher.oid,
          token: consumedVoucher.token,
          eticketId: consumedVoucher.voucher_code,
          voucherCode: consumedVoucher.voucher_code,
          unitIndex: Number(consumedVoucher.unit_index || 0) || 0,
          status: 'CONSUMED',
          validStartTime: Number(consumedVoucher.valid_start_time || 0) || 0,
          validEndTime: Number(consumedVoucher.valid_end_time || 0) || 0,
          consumedAt: now,
          consumeSerialNum:
            consumedVoucher.consume_serial_num || `CONSUME-${consumedVoucher.voucher_code}`,
        }
      }
    } else {
      consumeStatus = 'failed'
      consumeErrorMessage =
        industryResult.failed[0]?.errorMessage || '电子凭证核销回调失败，请人工处理'
    }
  } else {
    // cleanup 或无凭证：不碰核销
    consumeStatus = 'skipped'
    consumeErrorMessage = ''
  }

  if (consumeStatus !== 'success') {
    if (shouldConsumeIndustryVoucher) {
      nextTaskStatus = TASK_STATUS.MANUAL_REVIEW
      nextResultCode = 'kuaishou_cloud_consume_failed'
      nextResultMessage = consumeErrorMessage || '号码已退还，但电子凭证核销未完成，请人工处理'
    } else {
      nextResultCode = allowConsumeIndustryVoucher
        ? 'kuaishou_cloud_completed_without_eticket_consume'
        : 'kuaishou_cloud_number_returned_cleanup'
    }
  }

  const nextContext = {
    ...taskContext,
    ...(industryVoucherContextPatch
      ? {
          kuaishouIndustryVoucher: {
            ...(isPlainObject(taskContext.kuaishouIndustryVoucher)
              ? taskContext.kuaishouIndustryVoucher
              : {}),
            ...industryVoucherContextPatch,
          },
        }
      : {}),
    kuaishouCloudFulfillment: {
      ...flow,
      returnNumber: {
        ...flow.returnNumber,
        status: 'success',
        returnedAt: now,
        returnedBy: actor,
      },
      consume: {
        ...flow.consume,
        status: consumeStatus,
        shopId: flow.consume.shopId,
        shopName: flow.consume.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 === 'failed' ? task.redeemed_at : now,
    last_error: consumeErrorMessage,
    context_json: JSON.stringify(nextContext),
    updated_at: now,
  })

  await createTaskEvent(
    task.id,
    'kuaishou_cloud_number_returned',
    {
      source: String(options.source || 'system').trim() || 'system',
      vnId: flow.binding.vnId,
      vnPhoneMasked: maskPhone(flow.binding.vnPhone),
      actor,
    },
    now,
  )

  const consumeEventType = consumeAlreadyCompleted
    ? 'kuaishou_cloud_consume_already_completed'
    : consumeStatus === 'success'
      ? 'kuaishou_cloud_consumed'
      : consumeStatus === 'skipped'
        ? 'kuaishou_cloud_consume_skipped'
        : 'kuaishou_cloud_consume_failed'

  await createTaskEvent(
    task.id,
    consumeEventType,
    {
      source: String(options.source || 'system').trim() || 'system',
      ticketCodeMasked: maskCode(ticketCode),
      shopId: flow.consume.shopId,
      shopName: flow.consume.shopName,
      consumeStatus,
      consumeMode: shouldConsumeIndustryVoucher
        ? 'industry_voucher'
        : allowConsumeIndustryVoucher
          ? 'legacy_writeoff_disabled'
          : 'cleanup_skip_consume',
      errorMessage: consumeErrorMessage,
      actor,
    },
    now,
  )

  return {
    task: updatedTask,
    flow: normalizeKuaishouCloudFlow(parseTaskContext(updatedTask).kuaishouCloudFulfillment),
  }
}

function hasKuaishouIndustryVoucherContext(value: JsonObject): boolean {
  const voucher = isPlainObject(value.kuaishouIndustryVoucher) ? value.kuaishouIndustryVoucher : {}
  const voucherCode = String(voucher.voucherCode || voucher.eticketId || '').trim()
  const status = String(voucher.status || 'UNUSED')
    .trim()
    .toUpperCase()
  const sendCallbackStatus = String(voucher.sendCallbackStatus || 'success')
    .trim()
    .toLowerCase()
  return Boolean(voucherCode && status !== 'DESTROYED' && sendCallbackStatus === 'success')
}

function isPlainObject(value: unknown): value is JsonObject {
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
}

/** 号码已被上游回收/手动退回/账号换 token 后无操作权限：退号视为已释放 */
function isNumberAlreadyReleasedError(error: unknown) {
  const message = error instanceof Error ? error.message : String(error || '')
  return (
    message.includes('权限不足') ||
    message.includes('没有权限') ||
    message.includes('不存在') ||
    message.includes('已释放') ||
    message.includes('已回收') ||
    message.includes('已退还')
  )
}
