import { asJsonObject, type JsonObject } from '../../types/json.js'
import {
  findKuaishouIndustryVoucherByCode,
  listKuaishouIndustryVouchersByOid,
  listKuaishouIndustryVouchersByTaskId,
  listKuaishouIndustryVouchersForAdmin,
  updateKuaishouIndustryVoucherByCode,
  type KuaishouIndustryVoucherAdminListQuery,
  type KuaishouIndustryVoucherAdminListRow,
} from '../../repositories/kuaishou-industry-voucher-repo.js'
import { getOrderById } from '../../repositories/order-repo.js'
import { getTaskById } from '../../repositories/task-repo.js'
import { createHttpError } from '../../utils/http.js'
import { maskSecret } from '../../utils/masking.js'
import {
  checkKuaishouIndustryEticketAvailable,
  isKuaishouIndustryEticketDestroyableStatus,
  KUAISHOU_INDUSTRY_DESTROYABLE_DISPLAY_STATUS,
  resolveKuaishouIndustryEticketDisplayStatus,
} from '../platforms/kuaishou-industry/check-available-service.js'
import {
  getKuaishouIndustrySourceConfig,
  listKuaishouIndustryShopConfigs,
  type KuaishouIndustrySourceConfig,
} from '../platforms/kuaishou-industry/source-config-service.js'
import { resendKuaishouIndustryVoucherSendCallback } from '../platforms/kuaishou-industry/send-code-service.js'
import {
  consumeKuaishouIndustryVoucher,
  destroyKuaishouIndustryVoucher,
  resolveKuaishouIndustryEticketType,
} from '../platforms/kuaishou-industry/voucher-service.js'
import {
  approveKuaishouIndustryRefund,
  disagreeKuaishouIndustryRefund,
  listKuaishouIndustryRefunds,
} from '../platforms/kuaishou-industry/refund-service.js'
import { reverseKuaishouIndustryCallback } from '../platforms/kuaishou-industry/reverse-callback-service.js'
import { attachKuaishouIndustryVoucherToTask } from '../platforms/kuaishou-industry/voucher-binding-service.js'
import type { KuaishouIndustryOpenApiCallResult } from '../platforms/kuaishou-industry/openapi-client.js'
import type { KuaishouIndustryVoucherRow, TaskRow } from '../../types/repository/rows.js'

export async function listAdminKuaishouIndustryVouchers(
  input: KuaishouIndustryVoucherAdminListQuery = {},
) {
  const result = await listKuaishouIndustryVouchersForAdmin(input)
  const shopNameBySellerId = buildKuaishouIndustryShopNameMap()

  return {
    items: result.items.map((voucher) =>
      mapAdminKuaishouIndustryVoucher(voucher, shopNameBySellerId),
    ),
    pagination: {
      page: result.page,
      pageSize: result.pageSize,
      total: result.total,
    },
  }
}

/** 轻量店铺选项：仅展示名与 ID，供筛选/下拉使用（不含 token 等敏感字段） */
export function listAdminKuaishouIndustryShops() {
  const shops = listKuaishouIndustryShopConfigs(getKuaishouIndustrySourceConfig())

  return {
    shops: shops
      .map((shop) => {
        const sellerId = String(shop.sellerId || '').trim()
        const shopId = String(shop.shopId || '').trim()
        const shopName = String(shop.customShopName || shop.shopName || '').trim()
        return {
          sellerId,
          shopId,
          shopName,
          enabled: shop.enabled !== false,
        }
      })
      .filter((shop) => shop.sellerId || shop.shopId),
  }
}

export async function listAdminKuaishouIndustryRefunds(input: JsonObject = {}) {
  assertRequired(input.beginTime, '开始时间未填写')
  assertRequired(input.endTime, '结束时间未填写')

  const payload = await buildRefundOpenApiPayload(input)

  return mapOpenApiResult(await listKuaishouIndustryRefunds(payload))
}

export async function approveAdminKuaishouIndustryRefund(input: JsonObject = {}) {
  assertRequired(input.refundId, '退款单编号未填写')
  assertRequired(input.refundAmount, '退款金额未填写')

  const payload = await buildRefundOpenApiPayload(input)

  return mapOpenApiResult(await approveKuaishouIndustryRefund(payload))
}

export async function disagreeAdminKuaishouIndustryRefund(input: JsonObject = {}) {
  assertRequired(input.refundId, '退款单编号未填写')
  assertRequired(input.sellerDisagreeReason, '拒绝原因未填写')
  assertRequired(input.sellerDisagreeDesc, '拒绝说明未填写')
  assertRequired(input.status, '退款单当前状态未填写')
  assertRequired(input.negotiateStatus, '协商状态未填写')

  const payload = await buildRefundOpenApiPayload(input)

  return mapOpenApiResult(await disagreeKuaishouIndustryRefund(payload))
}

export async function checkAdminKuaishouIndustryVoucherAvailable(input: JsonObject = {}) {
  const voucher = await resolveOptionalVoucher(input)
  const payload = buildVoucherOpenApiPayload(input, voucher)

  assertRequired(payload.sellerId, '卖家编号未填写')
  assertRequired(
    payload.eticketType || payload.bizTypeCode,
    '电子凭证类型未填写（请选择券码或手动填写类型）',
  )
  assertEtickets(payload.etickets, '电子凭证列表未填写')

  const result = mapOpenApiResult(await checkKuaishouIndustryEticketAvailable(payload))
  return {
    ...result,
    eticketType: String(payload.eticketType || payload.bizTypeCode || ''),
    voucher: voucher ? mapAdminKuaishouIndustryVoucher(voucher) : null,
  }
}

export async function reverseAdminKuaishouIndustryVoucher(input: JsonObject = {}) {
  const voucher = await resolveOptionalVoucher(input)
  const payload = buildVoucherOpenApiPayload(input, voucher)

  assertRequired(payload.oid, '订单号未填写')
  assertEtickets(payload.etickets, '冲正券码列表未填写')

  const result = await reverseKuaishouIndustryCallback(payload)
  let updatedVoucher: KuaishouIndustryVoucherRow | null = null

  if (result.success && voucher) {
    updatedVoucher = await updateKuaishouIndustryVoucherByCode(voucher.voucher_code, {
      status: 'UNUSED',
      consumeSerialNum: '',
      consumeDetailsJson: [],
      consumedAt: null,
      destroyedAt: null,
      updatedAt: new Date().toISOString(),
    })
  }

  return {
    ...mapOpenApiResult(result),
    voucher: updatedVoucher ? mapAdminKuaishouIndustryVoucher(updatedVoucher) : null,
  }
}

export async function consumeAdminKuaishouIndustryVoucherByCode(input: JsonObject = {}) {
  const voucher = await resolveRequiredVoucher(input)
  const task = voucher.task_id ? await getTaskById(voucher.task_id) : null
  const consumeType = String(input.consumeType || '').trim()
  const consumeInput: Parameters<typeof consumeKuaishouIndustryVoucher>[1] = {
    source: 'admin_tool_manual_consume',
    token: String(input.token || voucher.token || '').trim(),
    consumeTime: Date.now(),
    ...(consumeType ? { consumeType } : {}),
    ...(input.serialNum ? { serialNum: String(input.serialNum).trim() } : {}),
    ...(input.storeName ? { storeName: String(input.storeName).trim() } : {}),
    ...(input.storeAddress ? { storeAddress: String(input.storeAddress).trim() } : {}),
    ...(input.expressCode ? { expressCode: String(input.expressCode).trim() } : {}),
    ...(input.expressNo ? { expressNo: String(input.expressNo).trim() } : {}),
  }
  if (task) {
    consumeInput.task = task
  }

  const result = await consumeKuaishouIndustryVoucher(voucher, consumeInput)

  if (!result.ok || !result.voucher) {
    throw createHttpError(result.errorMessage || '电子凭证核销失败', {
      statusCode: 409,
      errorCode: 'admin_kuaishou_industry_consume_failed',
    })
  }

  return {
    success: true,
    voucher: mapAdminKuaishouIndustryVoucher(result.voucher),
    task: task ? mapTaskReference(task) : null,
  }
}

export async function resendAdminKuaishouIndustryVoucherCode(input: JsonObject = {}) {
  const voucher = await resolveRequiredVoucher(input)
  const order = voucher.order_id ? await getOrderById(voucher.order_id) : null
  const result = await resendKuaishouIndustryVoucherSendCallback({
    voucherCode: voucher.voucher_code,
    oid: voucher.oid,
    preferredTotalGoodsValue: Number(order?.total_amount || 0) || 0,
  })

  return {
    success: result.success,
    response: 'response' in result ? result.response || null : null,
    error: result.error || '',
    voucher: result.voucher ? mapAdminKuaishouIndustryVoucher(result.voucher) : null,
  }
}

export async function destroyAdminKuaishouIndustryVoucherByCode(input: JsonObject = {}) {
  const voucher = await resolveRequiredVoucher(input)
  const checkPayload = buildVoucherOpenApiPayload(input, voucher)

  assertRequired(checkPayload.sellerId, '卖家编号未填写，无法在销毁前查询卡券状态')
  assertRequired(
    checkPayload.eticketType || checkPayload.bizTypeCode,
    '电子凭证类型未填写，无法在销毁前查询卡券状态',
  )
  assertEtickets(checkPayload.etickets, '电子凭证列表未填写，无法在销毁前查询卡券状态')

  const checkResult = await checkKuaishouIndustryEticketAvailable(checkPayload)
  if (!checkResult.success || checkResult.skippedReason) {
    const platformMessage = String(
      checkResult.error || checkResult.response?.error_msg || checkResult.response?.msg || '',
    ).trim()
    throw createHttpError(
      `销毁前查询卡券状态失败，已取消销毁${platformMessage ? `：${platformMessage}` : ''}`,
      {
        statusCode: 409,
        errorCode: 'admin_kuaishou_industry_destroy_status_check_failed',
      },
    )
  }

  const displayStatus = resolveKuaishouIndustryEticketDisplayStatus(
    checkResult.response,
    voucher.voucher_code,
  )
  if (!isKuaishouIndustryEticketDestroyableStatus(displayStatus)) {
    throw createHttpError(
      displayStatus
        ? `卡券当前展示状态为 ${displayStatus}，仅 ${KUAISHOU_INDUSTRY_DESTROYABLE_DISPLAY_STATUS}（冻结）状态可以销毁`
        : `未获取到卡券展示状态，仅 ${KUAISHOU_INDUSTRY_DESTROYABLE_DISPLAY_STATUS}（冻结）状态可以销毁`,
      {
        statusCode: 409,
        errorCode: 'admin_kuaishou_industry_voucher_not_frozen',
      },
    )
  }

  const task = voucher.task_id ? await getTaskById(voucher.task_id) : null
  const destroyInput: Parameters<typeof destroyKuaishouIndustryVoucher>[1] = {
    source: 'admin_tool_manual_destroy',
    reason: String(input.reason || '').trim(),
    token: String(input.token || voucher.token || '').trim(),
    eticketType: resolveKuaishouIndustryEticketType(voucher, input.eticketType),
  }
  if (task) {
    destroyInput.task = task
  }

  const result = await destroyKuaishouIndustryVoucher(voucher, destroyInput)

  if (!result.ok || !result.voucher) {
    throw createHttpError(result.errorMessage || '电子凭证销毁失败', {
      statusCode: 409,
      errorCode: 'admin_kuaishou_industry_destroy_failed',
    })
  }

  const nextTask = result.task || task
  if (nextTask && result.voucher && !result.alreadyDestroyed) {
    await attachKuaishouIndustryVoucherToTask(nextTask, result.voucher, {
      source: 'admin_tool_manual_destroy',
      now: new Date().toISOString(),
    })
  }

  return {
    success: true,
    alreadyDestroyed: Boolean(result.alreadyDestroyed),
    reason: result.reason || '',
    voucher: mapAdminKuaishouIndustryVoucher(result.voucher),
    task: nextTask ? mapTaskReference(nextTask) : null,
  }
}

function buildVoucherOpenApiPayload(
  input: JsonObject,
  voucher: KuaishouIndustryVoucherRow | null,
): JsonObject {
  const etickets = normalizeAdminEtickets(input.etickets)
  const voucherCode = String(voucher?.voucher_code || input.voucherCode || '').trim()
  const eticketType = resolveKuaishouIndustryEticketType(
    voucher,
    input.eticketType || input.bizTypeCode,
  )

  return {
    ...input,
    sellerId: String(input.sellerId || voucher?.seller_id || '').trim(),
    oid: String(input.oid || input.orderId || voucher?.oid || '').trim(),
    orderId: String(input.orderId || input.oid || voucher?.oid || '').trim(),
    token: String(input.token || voucher?.token || '').trim(),
    serialNum: String(input.serialNum || voucher?.consume_serial_num || '').trim(),
    eticketType,
    ...(eticketType ? { bizTypeCode: eticketType } : {}),
    etickets:
      etickets.length > 0
        ? etickets
        : voucherCode
          ? [{ id: voucherCode, code: voucherCode, num: 1 }]
          : [],
  }
}

async function buildRefundOpenApiPayload(input: JsonObject): Promise<JsonObject> {
  const source = getKuaishouIndustrySourceConfig()
  const sellerId =
    String(input.sellerId || '').trim() ||
    (await resolveRefundSellerIdFromLocalVoucher(input)) ||
    resolveSingleEnabledKuaishouIndustrySellerId(source)

  if (!sellerId && hasMultipleEnabledKuaishouIndustryShops(source)) {
    throw createHttpError('存在多个快手售后退款店铺授权，请先选择 sellerId', {
      statusCode: 400,
      errorCode: 'admin_kuaishou_industry_refund_seller_id_required',
    })
  }

  return {
    ...input,
    ...(sellerId ? { sellerId } : {}),
  }
}

async function resolveRefundSellerIdFromLocalVoucher(input: JsonObject): Promise<string> {
  const voucherCode = String(input.voucherCode || '').trim()
  const oid = String(input.oid || input.orderId || '').trim()
  if (voucherCode) {
    const voucher = await findKuaishouIndustryVoucherByCode(voucherCode, oid)
    return String(voucher?.seller_id || '').trim()
  }

  const taskId = Number(input.taskId || 0)
  if (Number.isFinite(taskId) && taskId > 0) {
    return resolveSingleSellerIdFromVouchers(
      await listKuaishouIndustryVouchersByTaskId(Math.trunc(taskId)),
      '当前任务关联多个卖家，请指定 sellerId',
    )
  }

  if (oid) {
    return resolveSingleSellerIdFromVouchers(
      await listKuaishouIndustryVouchersByOid(oid),
      '当前订单关联多个卖家，请指定 sellerId',
    )
  }

  return ''
}

function resolveSingleSellerIdFromVouchers(
  vouchers: KuaishouIndustryVoucherRow[],
  multipleMessage: string,
): string {
  const sellerIds = Array.from(
    new Set(vouchers.map((voucher) => String(voucher.seller_id || '').trim()).filter(Boolean)),
  )

  if (sellerIds.length > 1) {
    throw createHttpError(multipleMessage, {
      statusCode: 409,
      errorCode: 'admin_kuaishou_industry_refund_seller_id_ambiguous',
    })
  }

  return sellerIds[0] || ''
}

function resolveSingleEnabledKuaishouIndustrySellerId(
  source: KuaishouIndustrySourceConfig,
): string {
  const enabledShops = listEnabledKuaishouIndustryShops(source)

  return enabledShops.length === 1
    ? String(enabledShops[0]?.sellerId || enabledShops[0]?.shopId || '').trim()
    : ''
}

function hasMultipleEnabledKuaishouIndustryShops(source: KuaishouIndustrySourceConfig): boolean {
  return listEnabledKuaishouIndustryShops(source).length > 1
}

function listEnabledKuaishouIndustryShops(source: KuaishouIndustrySourceConfig) {
  return listKuaishouIndustryShopConfigs(source).filter(
    (shop) => shop.enabled !== false && String(shop.sellerId || shop.shopId || '').trim(),
  )
}

async function resolveOptionalVoucher(
  input: JsonObject,
): Promise<KuaishouIndustryVoucherRow | null> {
  const voucherCode = String(input.voucherCode || '').trim()
  if (!voucherCode) {
    return null
  }

  const voucher = await findKuaishouIndustryVoucherByCode(
    voucherCode,
    String(input.oid || input.orderId || '').trim(),
  )
  if (!voucher) {
    throw createHttpError('电子凭证不存在', {
      statusCode: 404,
      errorCode: 'admin_kuaishou_industry_voucher_not_found',
    })
  }

  return voucher
}

async function resolveRequiredVoucher(input: JsonObject): Promise<KuaishouIndustryVoucherRow> {
  const voucher = await resolveOptionalVoucher(input)
  if (voucher) {
    return voucher
  }

  const taskId = Number(input.taskId || 0)
  if (Number.isFinite(taskId) && taskId > 0) {
    const vouchers = await listKuaishouIndustryVouchersByTaskId(Math.trunc(taskId))
    return resolveSingleVoucher(
      vouchers,
      '当前任务没有关联电子凭证',
      '当前任务关联多个电子凭证，请指定券码',
    )
  }

  const oid = String(input.oid || input.orderId || '').trim()
  if (oid) {
    const vouchers = await listKuaishouIndustryVouchersByOid(oid)
    return resolveSingleVoucher(
      vouchers,
      '当前订单没有关联电子凭证',
      '当前订单关联多个电子凭证，请指定券码',
    )
  }

  throw createHttpError('请填写券码、任务 ID 或订单号', {
    statusCode: 400,
    errorCode: 'admin_kuaishou_industry_voucher_selector_missing',
  })
}

function resolveSingleVoucher(
  vouchers: KuaishouIndustryVoucherRow[],
  missingMessage: string,
  multipleMessage: string,
): KuaishouIndustryVoucherRow {
  if (vouchers.length === 0) {
    throw createHttpError(missingMessage, {
      statusCode: 404,
      errorCode: 'admin_kuaishou_industry_voucher_not_found',
    })
  }

  if (vouchers.length > 1) {
    throw createHttpError(multipleMessage, {
      statusCode: 409,
      errorCode: 'admin_kuaishou_industry_voucher_ambiguous',
    })
  }

  return vouchers[0] as KuaishouIndustryVoucherRow
}

function mapOpenApiResult(result: KuaishouIndustryOpenApiCallResult) {
  return {
    success: result.success,
    response: result.response || null,
    error: result.error || '',
    request: sanitizeOpenApiRequest(result.request),
    durationMs: result.durationMs || 0,
    httpStatus: result.httpStatus || 0,
    skippedReason: result.skippedReason || '',
  }
}

function sanitizeOpenApiRequest(request: JsonObject | undefined): JsonObject | null {
  if (!request) {
    return null
  }

  return {
    ...request,
    access_token: maskSecret(request.access_token),
    sign: maskSecret(request.sign),
  }
}

function mapAdminKuaishouIndustryVoucher(
  voucher: KuaishouIndustryVoucherRow | KuaishouIndustryVoucherAdminListRow,
  shopNameBySellerId: Map<string, string> = buildKuaishouIndustryShopNameMap(),
) {
  const sellerId = String(voucher.seller_id || '').trim()
  const listRow = voucher as KuaishouIndustryVoucherAdminListRow
  return {
    id: voucher.id,
    voucherCode: voucher.voucher_code,
    oid: voucher.oid,
    orderId: voucher.order_id,
    taskId: voucher.task_id,
    taskNo: String(listRow.task_no || '').trim(),
    unitIndex: voucher.unit_index,
    sellerId,
    shopName: shopNameBySellerId.get(sellerId) || '',
    skuCode: String(listRow.sku_code || '').trim(),
    skuName: String(listRow.sku_name || '').trim(),
    tokenMasked: maskSecret(voucher.token),
    eticketType: resolveKuaishouIndustryEticketType(voucher),
    status: voucher.status,
    validStartTime: Number(voucher.valid_start_time || 0) || 0,
    validEndTime: Number(voucher.valid_end_time || 0) || 0,
    consumeSerialNum: voucher.consume_serial_num,
    consumeDetails: parseJsonArray(voucher.consume_details_json),
    consumedAt: voucher.consumed_at,
    destroyedAt: voucher.destroyed_at,
    sendCallbackStatus: voucher.send_callback_status,
    sendCallbackAttemptCount: voucher.send_callback_attempt_count,
    sendCallbackLastError: voucher.send_callback_last_error,
    sendCallbackSentAt: voucher.send_callback_sent_at,
    rawPayload: parseJsonObject(voucher.raw_payload_json),
    createdAt: voucher.created_at,
    updatedAt: voucher.updated_at,
  }
}

function buildKuaishouIndustryShopNameMap(): Map<string, string> {
  const map = new Map<string, string>()
  const shops = listKuaishouIndustryShopConfigs(getKuaishouIndustrySourceConfig())

  for (const shop of shops) {
    const name = String(shop.customShopName || shop.shopName || '').trim()
    if (!name) {
      continue
    }

    const sellerId = String(shop.sellerId || '').trim()
    const shopId = String(shop.shopId || '').trim()
    if (sellerId) {
      map.set(sellerId, name)
    }
    if (shopId && shopId !== sellerId) {
      map.set(shopId, name)
    }
  }

  return map
}

function mapTaskReference(task: TaskRow) {
  return {
    taskId: task.id,
    taskNo: task.task_no,
    status: task.task_status,
    deliveryStatus: task.delivery_status,
  }
}

function normalizeAdminEtickets(value: unknown): JsonObject[] {
  if (!Array.isArray(value)) {
    return []
  }

  const items: JsonObject[] = []
  for (const item of value) {
    if (!item || typeof item !== 'object' || Array.isArray(item)) {
      continue
    }

    const current = item as JsonObject
    const id = String(current.id || '').trim()
    const code = String(current.code || '').trim()
    const num = Number(current.num || 1)

    if (!id && !code) {
      continue
    }

    items.push({
      ...(id ? { id } : {}),
      ...(code ? { code } : {}),
      num: Number.isInteger(num) && num > 0 ? num : 1,
    })
  }

  return items
}

function assertRequired(value: unknown, message: string) {
  if (value === undefined || value === null || String(value).trim() === '') {
    throw createHttpError(message, {
      statusCode: 400,
      errorCode: 'admin_kuaishou_industry_missing_required_field',
    })
  }
}

function assertEtickets(value: unknown, message: string) {
  if (!Array.isArray(value) || value.length === 0) {
    throw createHttpError(message, {
      statusCode: 400,
      errorCode: 'admin_kuaishou_industry_missing_etickets',
    })
  }
}

function parseJsonObject(value: unknown): JsonObject {
  if (value && typeof value === 'object' && !Array.isArray(value)) {
    return value as JsonObject
  }

  try {
    const parsed = JSON.parse(String(value || '{}'))
    return asJsonObject(parsed)
  } catch {
    return {}
  }
}

function parseJsonArray(value: unknown): JsonObject[] {
  if (Array.isArray(value)) {
    return value.filter((item): item is JsonObject =>
      Boolean(item && typeof item === 'object' && !Array.isArray(item)),
    )
  }

  try {
    const parsed = JSON.parse(String(value || '[]'))
    return Array.isArray(parsed)
      ? parsed.filter((item): item is JsonObject =>
          Boolean(item && typeof item === 'object' && !Array.isArray(item)),
        )
      : []
  } catch {
    return []
  }
}
