import {
  normalizeCloudtentaclesMatchName,
  resolveCloudtentaclesSkuByProductName,
  type CloudtentaclesNameMatchResult,
} from '../order/cloudtentacles-name-match-service.js'
import {
  resolveKuaishouFeifeiProductByName,
  type KuaishouFeifeiProductMatch,
} from '../platforms/kuaishou-feifei/product-rule-service.js'
import { resolveFulfillmentRoute, type FulfillmentRouteResult } from './routing-config-service.js'
import { getAffiliateDashConfig } from '../platforms/affiliate-dash/config.js'
import { listAllAffiliateDashProducts } from '../platforms/affiliate-dash/product-service.js'
import type { AffiliateDashSkuMapping } from '../../types/runtime-config.js'
import { FULFILLMENT_EXECUTOR_KEYS } from './executors/types.js'
import { logIntegration } from '../../utils/logger.js'

export type FulfillmentItem = {
  itemId?: string
  externalItemId?: string
  skuCode?: string
  skuName?: string
  externalSkuCode?: string
  externalSkuName?: string
  quantity?: number
  spec?: Record<string, unknown>
  snapshot?: Record<string, unknown>
  [key: string]: unknown
}

type ResolveOrderItemForFulfillmentInput = {
  provider?: string
  platform?: string
  item?: FulfillmentItem
}

type HasConfiguredOrderItemsInput = Omit<ResolveOrderItemForFulfillmentInput, 'item'> & {
  items?: FulfillmentItem[]
}

export type AffiliateDashSkuMatch = {
  sku: string
  productNo: string
  skuName: string
  matchMode: 'affiliate_dash_sku_mapping' | 'affiliate_dash_sku_passthrough'
}

type FulfillmentItemCandidate = {
  externalItemId: string
  externalSkuCode: string
  externalSkuName: string
  externalSkuNameNormalized: string
  resolvedSkuCode: string
  cloudtentaclesNameMatch: CloudtentaclesNameMatchResult | null
  kuaishouFeifeiMatch: KuaishouFeifeiProductMatch | null
  affiliateDashMatch: AffiliateDashSkuMatch | null
  fulfillmentRoute: FulfillmentRouteResult | null
  isConfigured: boolean
}

export type ResolvedFulfillmentItem = FulfillmentItem & {
  itemId: string
  externalItemId: string
  externalSkuCode: string
  externalSkuName: string
  skuCode: string
  skuName: string
  snapshot: Record<string, unknown>
  isConfigured: boolean
}

export async function resolveOrderItemForFulfillment({
  provider = '',
  platform = '',
  item = {},
}: ResolveOrderItemForFulfillmentInput): Promise<ResolvedFulfillmentItem> {
  const candidate = await resolveConfiguredItemCandidate({
    provider,
    platform,
    item,
  })
  const {
    externalItemId,
    externalSkuCode,
    externalSkuName,
    externalSkuNameNormalized,
    cloudtentaclesNameMatch,
    kuaishouFeifeiMatch,
    affiliateDashMatch,
    fulfillmentRoute,
  } = candidate

  const selectedExecutorKey = fulfillmentRoute?.selectedExecutorKey || ''
  const resolvedSkuCode = pickFirstNonEmpty([
    selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_FEIFEI
      ? kuaishouFeifeiMatch?.productCode
      : '',
    selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH ? affiliateDashMatch?.sku : '',
    externalSkuCode,
    externalItemId,
  ])
  const resolvedSkuName = pickFirstNonEmpty([
    selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_CLOUD
      ? cloudtentaclesNameMatch?.cloudSkuName
      : '',
    selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_FEIFEI
      ? kuaishouFeifeiMatch?.skuName
      : '',
    selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH ? affiliateDashMatch?.sku : '',
    item.skuName,
    externalSkuName,
    resolvedSkuCode,
  ])
  const snapshot = {
    ...(isPlainObject(item.snapshot) ? item.snapshot : {}),
    externalItemId,
    externalSkuCode,
    externalSkuName,
    externalSkuNameNormalized,
    resolvedSkuCode,
    matchMode:
      selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_CLOUD
        ? cloudtentaclesNameMatch?.matchMode || ''
        : selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_FEIFEI
          ? kuaishouFeifeiMatch?.matchMode || ''
          : selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH
            ? affiliateDashMatch?.matchMode || ''
            : '',
    fulfillmentRoute,
    cloudtentacles: cloudtentaclesNameMatch
      ? {
          matchMode: cloudtentaclesNameMatch.matchMode,
          productName: cloudtentaclesNameMatch.productName,
          normalizedProductName: cloudtentaclesNameMatch.normalizedProductName,
          cloudSkuId: cloudtentaclesNameMatch.cloudSkuId,
          cloudSkuName: cloudtentaclesNameMatch.cloudSkuName,
          cloudSkuPrice: cloudtentaclesNameMatch.cloudSkuPrice,
          cloudSkuInventory: cloudtentaclesNameMatch.cloudSkuInventory,
          cloudSourceKeys: cloudtentaclesNameMatch.cloudSourceKeys,
          resolvedSourceKey: cloudtentaclesNameMatch.resolvedSourceKey,
          deliveryItems: cloudtentaclesNameMatch.deliveryItems,
          skuSnapshot: cloudtentaclesNameMatch.skuSnapshot,
        }
      : null,
    kuaishouFeifei: kuaishouFeifeiMatch
      ? {
          matchMode: kuaishouFeifeiMatch.matchMode,
          productName: kuaishouFeifeiMatch.productName,
          normalizedProductName: kuaishouFeifeiMatch.normalizedProductName,
          productCode: kuaishouFeifeiMatch.productCode,
          skuName: kuaishouFeifeiMatch.skuName,
        }
      : null,
    affiliateDash: affiliateDashMatch
      ? {
          matchMode: affiliateDashMatch.matchMode,
          productNo: affiliateDashMatch.productNo,
          sku: affiliateDashMatch.sku,
          skuName: affiliateDashMatch.skuName,
        }
      : null,
    isConfigured: candidate.isConfigured,
  }

  return {
    ...item,
    itemId: externalItemId,
    externalItemId,
    externalSkuCode,
    externalSkuName,
    skuCode: resolvedSkuCode,
    skuName: resolvedSkuName,
    snapshot,
    isConfigured: candidate.isConfigured,
  }
}

export async function hasConfiguredOrderItems({
  provider = '',
  platform = '',
  items = [],
}: HasConfiguredOrderItemsInput): Promise<boolean> {
  const candidates = await Promise.all(
    (Array.isArray(items) ? items : []).map((item) =>
      resolveConfiguredItemCandidate({
        provider,
        platform,
        item,
      }),
    ),
  )

  return candidates.some((item) => item.isConfigured)
}

export function normalizeProductName(value: unknown): string {
  return normalizeCloudtentaclesMatchName(value)
}

function pickFirstNonEmpty(values: unknown[]): string {
  for (const value of values) {
    const normalized = String(value || '').trim()
    if (normalized) {
      return normalized
    }
  }

  return ''
}

async function resolveConfiguredItemCandidate({
  provider = '',
  platform = '',
  item = {},
}: ResolveOrderItemForFulfillmentInput): Promise<FulfillmentItemCandidate> {
  const externalItemId = pickFirstNonEmpty([item.externalItemId, item.itemId])
  const externalSkuCode = pickFirstNonEmpty([item.externalSkuCode, item.skuCode, externalItemId])
  const externalSkuName = pickFirstNonEmpty([item.externalSkuName, item.skuName, externalSkuCode])
  const externalSkuNameNormalized = normalizeProductName(externalSkuName)

  if (isOpen91KuaishouOrder(provider, platform)) {
    const cloudtentaclesNameMatch = await resolveCloudtentaclesSkuByProductName(externalSkuName)
    const kuaishouFeifeiMatch = resolveKuaishouFeifeiProductByName(externalSkuName)
    const affiliateDashMatch = await resolveAffiliateDashSkuByProductNo(item)
    // 指定匹配（显式映射）命中时优先走 affiliate_dash（可配置关闭，默认开）
    const affiliateDashConfig = getAffiliateDashConfig()
    const preferredExecutorKey =
      affiliateDashMatch && affiliateDashConfig.preferredMatchEnabled !== false
        ? FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH
        : ''
    const fulfillmentRoute = resolveFulfillmentRoute({
      productName: externalSkuName,
      preferredExecutorKey,
      candidates: [
        {
          executorKey: FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_CLOUD,
          available: Boolean(cloudtentaclesNameMatch),
          reason: cloudtentaclesNameMatch ? '' : '未命中 cloudtentacles 商品或账号不可用',
        },
        {
          executorKey: FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_FEIFEI,
          available: Boolean(kuaishouFeifeiMatch),
          reason: kuaishouFeifeiMatch ? '' : '未命中 kuaishou-feifei 商品规则',
        },
        {
          executorKey: FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH,
          available: Boolean(affiliateDashMatch),
          reason: affiliateDashMatch ? '' : '未命中 affiliate-dash sku 映射',
        },
      ],
    })
    const selectedExecutorKey = fulfillmentRoute.selectedExecutorKey
    const resolvedSkuCode = pickFirstNonEmpty([
      selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_CLOUD
        ? cloudtentaclesNameMatch?.cloudSkuName
        : '',
      selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_FEIFEI
        ? kuaishouFeifeiMatch?.productCode
        : '',
      selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH
        ? affiliateDashMatch?.sku
        : '',
      externalSkuCode,
      externalItemId,
    ])

    return {
      externalItemId,
      externalSkuCode,
      externalSkuName,
      externalSkuNameNormalized,
      resolvedSkuCode,
      cloudtentaclesNameMatch,
      kuaishouFeifeiMatch,
      affiliateDashMatch,
      fulfillmentRoute,
      isConfigured: Boolean(selectedExecutorKey),
    }
  }

  const resolvedSkuCode = pickFirstNonEmpty([externalSkuCode, externalItemId])

  return {
    externalItemId,
    externalSkuCode,
    externalSkuName,
    externalSkuNameNormalized,
    resolvedSkuCode,
    cloudtentaclesNameMatch: null,
    kuaishouFeifeiMatch: null,
    affiliateDashMatch: null,
    fulfillmentRoute: null,
    isConfigured: false,
  }
}

async function resolveAffiliateDashSkuByProductNo(
  item: FulfillmentItem,
): Promise<AffiliateDashSkuMatch | null> {
  const config = getAffiliateDashConfig()
  if (config.enabled === false || !config.baseUrl) {
    return null
  }

  const snapshot = isPlainObject(item.snapshot) ? item.snapshot : {}
  const productNo = pickFirstNonEmpty([
    snapshot.productNo,
    item.externalSkuCode,
    item.externalItemId,
  ])
  if (!productNo) {
    return null
  }

  // ① 指定映射（运营显式配置）
  const mappedSku = matchAffiliateDashSku(config.skuMapping, String(productNo))
  if (mappedSku) {
    return {
      sku: mappedSku,
      productNo: String(productNo),
      skuName: String(item.externalSkuName || '').trim(),
      matchMode: 'affiliate_dash_sku_mapping',
    }
  }

  // ② 透传：91 商品编码 == affiliate_dash 商品 sku 时直接命中（需商品列表校验，缓存 5 分钟）
  const rawProductNo = String(productNo).trim()
  const skuSet = await getAffiliateDashSkuSet()
  if (matchAffiliateDashSkuPassthrough(rawProductNo, skuSet)) {
    return {
      sku: rawProductNo,
      productNo: rawProductNo,
      skuName: String(item.externalSkuName || '').trim(),
      matchMode: 'affiliate_dash_sku_passthrough',
    }
  }

  return null
}

/** 透传判定：productNo 与 affiliate_dash 商品 sku 完全一致。 */
export function matchAffiliateDashSkuPassthrough(
  productNo: string,
  availableSkus: ReadonlySet<string> | null | undefined,
): boolean {
  const raw = String(productNo || '').trim()
  return Boolean(raw && availableSkus?.has(raw))
}

const AFFILIATE_DASH_SKU_CACHE_TTL_MS = 5 * 60 * 1000
let affiliateDashSkuCache: { skus: Set<string>; fetchedAt: number } | null = null

async function getAffiliateDashSkuSet(): Promise<Set<string>> {
  const now = Date.now()
  if (
    affiliateDashSkuCache &&
    now - affiliateDashSkuCache.fetchedAt < AFFILIATE_DASH_SKU_CACHE_TTL_MS
  ) {
    return affiliateDashSkuCache.skus
  }

  try {
    const result = await listAllAffiliateDashProducts()
    const skus = new Set<string>(
      result.list.map((product) => String(product.sku || '').trim()).filter(Boolean),
    )
    affiliateDashSkuCache = { skus, fetchedAt: now }
    return skus
  } catch (error) {
    // 拉取失败：返回上次缓存（即使过期）或空集合，匹配 miss 走其他通道，不阻塞下单；
    // warn 日志便于线上排查（密钥未配/平台不可用都会导致透传降级为 miss）。
    logIntegration(
      '[affiliate-dash]',
      'affiliate-dash 商品列表拉取失败，透传降级为未命中',
      {
        cachedSkuCount: affiliateDashSkuCache?.skus.size || 0,
        error: error instanceof Error ? error.message : String(error),
      },
      { level: 'warn' },
    )
    return affiliateDashSkuCache?.skus || new Set<string>()
  }
}

/**
 * 91 商品编码为中文名（如「幸运币90个」），映射键查询做归一化：
 * NFKC（全角→半角）→ 去所有空白 → 小写。先原样精确，再归一化遍历。
 */
export function matchAffiliateDashSku(mapping: AffiliateDashSkuMapping, productNo: string): string {
  const raw = String(productNo || '').trim()
  if (!raw) {
    return ''
  }

  const direct = String(mapping[raw] || '').trim()
  if (direct) {
    return direct
  }

  const normalized = normalizeAffiliateDashMappingKey(raw)
  for (const [key, sku] of Object.entries(mapping || {})) {
    if (normalizeAffiliateDashMappingKey(key) === normalized) {
      return String(sku || '').trim()
    }
  }
  return ''
}

export function normalizeAffiliateDashMappingKey(value: unknown): string {
  return String(value || '')
    .normalize('NFKC')
    .replace(/\s+/g, '')
    .toLowerCase()
}

function isOpen91KuaishouOrder(provider: unknown, platform: unknown) {
  return (
    String(provider || '').trim() === '91kaquan' && String(platform || '').trim() === 'kuaishou'
  )
}

function isPlainObject(value: unknown): value is Record<string, unknown> {
  return Object.prototype.toString.call(value) === '[object Object]'
}
