import { getFulfillmentProfileByKey } from '../../repositories/fulfillment-profile-repo.js'
import type { JsonObject } from '../../types/json.js'
import type { OrderItemRow, OrderRow } from '../../types/repository/rows.js'
import {
  FULFILLMENT_EXECUTOR_KEYS,
  isAffiliateDashExecutor,
  isKuaishouCloudExecutor,
  isKuaishouFeifeiExecutor,
} from './executors/types.js'

export type FulfillmentBindingLike = {
  id: number
  profile_id?: number
  profile_key?: string
  profile_name?: string
  name?: string
  executor_key?: string
  requires_claim?: boolean
  auto_dispatch?: boolean
  config_json?: string | JsonObject
  [key: string]: unknown
}

export type FulfillmentProfileResolver = (
  profileKey: string,
) => Promise<FulfillmentBindingLike | null>

export type FulfillmentTaskPlan = {
  profile: FulfillmentBindingLike
  profileId: number
  profileKey: string
  profileName: string
  executorKey: string
  requiresClaim: boolean
  autoDispatch: boolean
  context: JsonObject
}

export async function planFulfillmentTaskForOrderItem({
  order,
  item,
  getProfileByKey = getFulfillmentProfileByKey,
}: {
  order: OrderRow
  item: OrderItemRow
  getProfileByKey?: FulfillmentProfileResolver
}): Promise<FulfillmentTaskPlan | null> {
  const profile = await resolveDynamicFulfillmentProfile(item, getProfileByKey)

  if (!profile) {
    return null
  }

  const profileId = Number(profile.profile_id || profile.id || 0)
  const profileKey = String(profile.profile_key || '').trim()
  const profileName = String(profile.profile_name || profile.name || '').trim()
  const executorKey =
    String(profile.executor_key || FULFILLMENT_EXECUTOR_KEYS.MANUAL_DISPATCH).trim() ||
    FULFILLMENT_EXECUTOR_KEYS.MANUAL_DISPATCH
  const fulfillmentConfig = parseJsonObject(profile.config_json)
  const context = buildFulfillmentTaskContext({
    order,
    item,
    profile,
    profileKey,
    profileName,
    executorKey,
    fulfillmentConfig,
  })

  return {
    profile,
    profileId,
    profileKey,
    profileName,
    executorKey,
    requiresClaim: Boolean(profile.requires_claim),
    autoDispatch: Boolean(profile.auto_dispatch),
    context,
  }
}

function buildFulfillmentTaskContext({
  order,
  item,
  profileKey,
  profileName,
  executorKey,
  fulfillmentConfig,
}: {
  order: OrderRow
  item: OrderItemRow
  profile: FulfillmentBindingLike
  profileKey: string
  profileName: string
  executorKey: string
  fulfillmentConfig: JsonObject
}) {
  const itemSnapshot = parseJsonObject(item.item_snapshot_json)
  const cloudtentaclesConfig = parseJsonObject(fulfillmentConfig.cloudtentacles)
  const kuaishouFeifeiConfig = parseJsonObject(fulfillmentConfig.kuaishouFeifei)
  const affiliateDashConfig = parseJsonObject(fulfillmentConfig.affiliateDash)
  const kuaishouConsumeConfig = parseJsonObject(fulfillmentConfig.kuaishouConsume)
  const kuaishouShopConfig = parseJsonObject(fulfillmentConfig.kuaishouShop)
  const cloudSourceKeys = normalizeStringArray(cloudtentaclesConfig.cloudSourceKeys)
  const resolvedCloudSourceKey =
    cloudSourceKeys.length === 1
      ? String(cloudtentaclesConfig.resolvedSourceKey || cloudSourceKeys[0] || '').trim()
      : ''
  const deliveryItems = normalizeCloudDeliveryItems(cloudtentaclesConfig)
  const primaryDeliveryItem = deliveryItems[0] || {
    cloudSkuId: Number(cloudtentaclesConfig.skuId || 0) || 0,
    cloudSkuName: String(cloudtentaclesConfig.skuName || '').trim(),
    quantity: 1,
  }

  return {
    profileKey,
    profileName,
    skuCode: item.sku_code,
    skuName: item.sku_name,
    kuaishouCloudFulfillment: isKuaishouCloudExecutor(executorKey)
      ? {
          flowType: 'kuaishou_cloud_fulfillment',
          configId: String(fulfillmentConfig.configId || '').trim(),
          internalSkuCode: item.sku_code,
          internalSkuName: item.sku_name,
          deliveryItems,
          ticket: {
            code: '',
            status: 'pending',
            capturedAt: null,
            capturedBy: null,
            verifiedAt: null,
            oid: '',
            formToken: '',
            leftCount: 0,
            goodsTitle: '',
          },
          binding: {
            prepareStatus: 'pending',
            cloudSourceKeys,
            resolvedSourceKey: resolvedCloudSourceKey,
            skuId: primaryDeliveryItem.cloudSkuId,
            skuName: primaryDeliveryItem.cloudSkuName,
            vnKey: '1',
            vnId: 0,
            vnPhone: '',
            bindUrl: '',
            bindPreparedAt: null,
            bindExpiresAt: null,
            bindProbeAt: null,
            bindProbeStatus: '',
            bindProbeMessage: '',
          },
          role: {
            status: 'pending',
            name: '',
            rid: '',
            refreshedAt: null,
            errorMessage: '',
            rawInfo: null,
          },
          purchase: {
            autoBuyEnabled: cloudtentaclesConfig.autoBuyEnabled !== false,
            minAssetReserve: Number(cloudtentaclesConfig.minAssetReserve || 0) || 0,
            usedKnapsack: false,
            purchaseTriggered: false,
            assetBefore: 0,
            assetAfter: 0,
            purchaseAt: null,
          },
          dispatch: {
            status: 'pending',
            dispatchAt: null,
            dispatchBy: null,
            sendType: 0,
            note: '',
          },
          returnNumber: {
            status: 'pending',
            returnedAt: null,
            returnedBy: null,
            autoReturnEnabled: cloudtentaclesConfig.autoReturnNumberAfterDispatch === true,
          },
          consume: {
            status: 'pending',
            shopId: String(
              kuaishouConsumeConfig.shopId ||
                kuaishouShopConfig.shopId ||
                itemSnapshot.shopId ||
                order.shop_id ||
                '',
            ).trim(),
            shopName: String(
              kuaishouConsumeConfig.shopName ||
                kuaishouShopConfig.kshopName ||
                itemSnapshot.shopName ||
                order.shop_name ||
                '',
            ).trim(),
            autoConsumeEnabled: kuaishouConsumeConfig.autoConsumeAfterDispatch === true,
            consumedAt: null,
            errorMessage: '',
          },
          notes: String(fulfillmentConfig.notes || '').trim(),
        }
      : null,
    kuaishouFeifei: isKuaishouFeifeiExecutor(executorKey)
      ? {
          flowType: 'kuaishou_feifei',
          productCode: String(kuaishouFeifeiConfig.productCode || '').trim(),
          productName: String(kuaishouFeifeiConfig.productName || item.sku_name || '').trim(),
          platformOrderNo: '',
          orderNo: '',
          rechargeStatus: 0,
          rechargeStatusLabel: '',
          rechargeResultMessage: '',
          claimUrl: '',
          consumeStatus: 'pending',
          h5: {
            entryUrl: '',
            rechargeUrl: '',
          },
          lastSyncedAt: null,
        }
      : null,
    affiliateDash: isAffiliateDashExecutor(executorKey)
      ? {
          flowType: 'affiliate_dash',
          sku: String(affiliateDashConfig.sku || '').trim(),
          productName: String(affiliateDashConfig.productName || item.sku_name || '').trim(),
          orderNo: '',
          clientOrderNo: '',
          orderStatus: '',
          canShip: false,
          cannotShipReason: '',
          providerOrderNo: '',
          failureReason: '',
          amount: 0,
          currency: '',
          bindUuid: '',
          bindUrl: '',
          qrUrl: '',
          gameAccount: '',
          expectedGameAccount: '',
          bindMismatch: false,
          submitStatus: '',
          consumeStatus: 'pending',
          lastSyncedAt: null,
        }
      : null,
  }
}

async function resolveDynamicFulfillmentProfile(
  item: OrderItemRow,
  getProfileByKey: FulfillmentProfileResolver,
): Promise<FulfillmentBindingLike | null> {
  const selectedExecutorKey = resolveSelectedFulfillmentExecutorKey(item)
  if (selectedExecutorKey) {
    if (selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_CLOUD) {
      return resolveDynamicCloudtentaclesProfile(item, getProfileByKey)
    }

    if (selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_FEIFEI) {
      return resolveDynamicKuaishouFeifeiProfile(item, getProfileByKey)
    }

    if (selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH) {
      return resolveDynamicAffiliateDashProfile(item, getProfileByKey)
    }

    if (selectedExecutorKey === FULFILLMENT_EXECUTOR_KEYS.MANUAL_DISPATCH) {
      return resolveDynamicManualDispatchProfile(item, getProfileByKey)
    }
  }

  return (
    (await resolveDynamicCloudtentaclesProfile(item, getProfileByKey)) ||
    (await resolveDynamicKuaishouFeifeiProfile(item, getProfileByKey)) ||
    (await resolveDynamicAffiliateDashProfile(item, getProfileByKey))
  )
}

async function resolveDynamicCloudtentaclesProfile(
  item: OrderItemRow,
  getProfileByKey: FulfillmentProfileResolver,
): Promise<FulfillmentBindingLike | null> {
  const snapshot = parseJsonObject(item.item_snapshot_json)
  const cloudtentacles = parseJsonObject(snapshot.cloudtentacles)
  const cloudSourceKeys = normalizeStringArray(cloudtentacles.cloudSourceKeys)
  const deliveryItems = normalizeCloudDeliveryItems({
    deliveryItems: cloudtentacles.deliveryItems,
    skuId: cloudtentacles.cloudSkuId,
    skuName: cloudtentacles.cloudSkuName || item.sku_name,
  })
  const primaryDeliveryItem = deliveryItems[0] || {
    cloudSkuId: 0,
    cloudSkuName: '',
    quantity: 1,
  }

  if (
    !primaryDeliveryItem.cloudSkuId ||
    !primaryDeliveryItem.cloudSkuName ||
    cloudSourceKeys.length === 0
  ) {
    return null
  }

  const profile = await getProfileByKey(FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_CLOUD)
  if (!profile) {
    return null
  }

  return {
    ...profile,
    profile_id: Number(profile.id || profile.profile_id || 0),
    profile_key: FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_CLOUD,
    profile_name: String(profile.profile_name || profile.name || 'kuaishou-lewan 履约').trim(),
    executor_key: FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_CLOUD,
    requires_claim: false,
    auto_dispatch: false,
    config_json: {
      flowType: 'kuaishou_cloud_fulfillment',
      configId: `${String(cloudtentacles.matchMode || 'cloudtentacles_name').trim()}:${String(cloudtentacles.normalizedProductName || primaryDeliveryItem.cloudSkuId).trim()}`,
      cloudtentacles: {
        cloudSourceKeys,
        skuId: primaryDeliveryItem.cloudSkuId,
        skuName: primaryDeliveryItem.cloudSkuName,
        resolvedSourceKey:
          cloudSourceKeys.length === 1
            ? String(cloudtentacles.resolvedSourceKey || cloudSourceKeys[0] || '').trim()
            : '',
        deliveryItems,
        vnKey: '1',
        autoBuyEnabled: true,
        minAssetReserve: 0,
        autoReturnNumberAfterDispatch: true,
      },
      kuaishouConsume: {
        shopId: String(snapshot.shopId || '').trim(),
        shopName: String(snapshot.shopName || '').trim(),
        autoConsumeAfterDispatch: false,
      },
      notes:
        cloudtentacles.matchMode === 'cloudtentacles_override'
          ? '91卡券商品名命中 cloudtentacles 覆盖规则'
          : '91卡券商品名自动匹配 cloudtentacles 商品',
    },
  }
}

async function resolveDynamicKuaishouFeifeiProfile(
  item: OrderItemRow,
  getProfileByKey: FulfillmentProfileResolver,
): Promise<FulfillmentBindingLike | null> {
  const snapshot = parseJsonObject(item.item_snapshot_json)
  const feifei = parseJsonObject(snapshot.kuaishouFeifei)
  const productCode = String(feifei.productCode || '').trim()
  if (!productCode) {
    return null
  }

  const profile = await getProfileByKey(FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_FEIFEI)
  if (!profile) {
    return null
  }

  return {
    ...profile,
    profile_id: Number(profile.id || profile.profile_id || 0),
    profile_key: FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_FEIFEI,
    profile_name: String(profile.profile_name || profile.name || 'kuaishou-feifei 履约').trim(),
    executor_key: FULFILLMENT_EXECUTOR_KEYS.KUAISHOU_FEIFEI,
    requires_claim: true,
    auto_dispatch: false,
    config_json: {
      flowType: 'kuaishou_feifei',
      configId: `kuaishou_feifei:${productCode}`,
      kuaishouFeifei: {
        productCode,
        productName: String(feifei.skuName || feifei.productName || item.sku_name || '').trim(),
        matchMode: String(feifei.matchMode || 'kuaishou_feifei_name').trim(),
      },
      notes: '91卡券商品名自动匹配 kuaishou-feifei 商品映射',
    },
  }
}

async function resolveDynamicAffiliateDashProfile(
  item: OrderItemRow,
  getProfileByKey: FulfillmentProfileResolver,
): Promise<FulfillmentBindingLike | null> {
  const snapshot = parseJsonObject(item.item_snapshot_json)
  const affiliateDash = parseJsonObject(snapshot.affiliateDash)
  const sku = String(affiliateDash.sku || '').trim()
  if (!sku) {
    return null
  }

  const profile = await getProfileByKey(FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH)
  if (!profile) {
    return null
  }

  return {
    ...profile,
    profile_id: Number(profile.id || profile.profile_id || 0),
    profile_key: FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH,
    profile_name: String(profile.profile_name || profile.name || 'affiliate-dash 履约').trim(),
    executor_key: FULFILLMENT_EXECUTOR_KEYS.AFFILIATE_DASH,
    requires_claim: true,
    auto_dispatch: false,
    config_json: {
      flowType: 'affiliate_dash',
      configId: `affiliate_dash:${sku}`,
      affiliateDash: {
        sku,
        productName: String(
          affiliateDash.skuName || affiliateDash.productName || item.sku_name || '',
        ).trim(),
        matchMode: String(affiliateDash.matchMode || 'affiliate_dash_sku_mapping').trim(),
      },
      notes: '91卡券商品自动匹配 affiliate-dash sku 映射',
    },
  }
}

async function resolveDynamicManualDispatchProfile(
  item: OrderItemRow,
  getProfileByKey: FulfillmentProfileResolver,
): Promise<FulfillmentBindingLike | null> {
  const profile = await getProfileByKey('manual_review')
  if (!profile) {
    return null
  }

  return {
    ...profile,
    profile_id: Number(profile.id || profile.profile_id || 0),
    profile_key: 'manual_review',
    profile_name: String(profile.profile_name || profile.name || '人工发货').trim(),
    executor_key: FULFILLMENT_EXECUTOR_KEYS.MANUAL_DISPATCH,
    requires_claim: false,
    auto_dispatch: false,
    config_json: {
      flowType: 'manual_dispatch',
      configId: `manual_dispatch:${item.sku_code || item.id}`,
      manualDispatch: {
        source: 'fulfillment_routing',
        skuCode: item.sku_code,
        skuName: item.sku_name,
      },
      notes: '履约路由规则指定人工履约',
    },
  }
}

function resolveSelectedFulfillmentExecutorKey(item: OrderItemRow) {
  const snapshot = parseJsonObject(item.item_snapshot_json)
  const route = parseJsonObject(snapshot.fulfillmentRoute)
  return String(route.selectedExecutorKey || '').trim()
}

function parseJsonObject(value: unknown): JsonObject {
  if (!value) {
    return {}
  }

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

  try {
    const parsed = JSON.parse(String(value || '{}'))
    return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
      ? (parsed as JsonObject)
      : {}
  } catch {
    return {}
  }
}

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

  return Array.from(new Set(value.map((item) => String(item || '').trim()).filter(Boolean)))
}

function normalizeCloudDeliveryItems(value: JsonObject): Array<{
  cloudSkuId: number
  cloudSkuName: string
  quantity: number
}> {
  const rawItems = Array.isArray(value.deliveryItems) ? value.deliveryItems : []
  const items = rawItems
    .map((item) => normalizeCloudDeliveryItem(item))
    .filter((item): item is { cloudSkuId: number; cloudSkuName: string; quantity: number } =>
      Boolean(item),
    )

  if (items.length > 0) {
    return mergeCloudDeliveryItems(items)
  }

  const cloudSkuId = Number(value.skuId || 0) || 0
  if (!cloudSkuId) {
    return []
  }

  return [
    {
      cloudSkuId,
      cloudSkuName: String(value.skuName || '').trim(),
      quantity: 1,
    },
  ]
}

function normalizeCloudDeliveryItem(value: unknown) {
  const source =
    value && typeof value === 'object' && !Array.isArray(value) ? (value as JsonObject) : {}
  const cloudSkuId = Number(source.cloudSkuId || source.skuId || 0) || 0
  if (!Number.isInteger(cloudSkuId) || cloudSkuId <= 0) {
    return null
  }

  const quantity = Number(source.quantity || 1) || 1
  return {
    cloudSkuId,
    cloudSkuName: String(source.cloudSkuName || source.skuName || '').trim(),
    quantity: Number.isInteger(quantity) && quantity > 0 ? quantity : 1,
  }
}

function mergeCloudDeliveryItems(
  items: Array<{ cloudSkuId: number; cloudSkuName: string; quantity: number }>,
) {
  const merged = new Map<number, { cloudSkuId: number; cloudSkuName: string; quantity: number }>()

  for (const item of items) {
    const existing = merged.get(item.cloudSkuId)
    if (existing) {
      existing.quantity += item.quantity
      existing.cloudSkuName = existing.cloudSkuName || item.cloudSkuName
      continue
    }

    merged.set(item.cloudSkuId, { ...item })
  }

  return Array.from(merged.values())
}
