import { createHttpError } from '../../../utils/http.js'
import { normalizeProductName } from '../../order/product-match-service.js'
import { isPlainObject } from './context.js'

type JsonObject = Record<string, any>

export function assertAdminFulfillmentBindingsInput(bindings: unknown) {
  if (Array.isArray(bindings)) {
    return
  }

  throw createHttpError('履约配置格式不正确', {
    statusCode: 400,
    errorCode: 'admin_fulfillment_bindings_invalid_payload',
  })
}

export function normalizeAdminFulfillmentBindingItem(
  rawBinding: unknown,
  options: JsonObject = {},
) {
  const index = Number(options.index || 0)
  if (!isPlainObject(rawBinding)) {
    throw createHttpError(`第 ${index + 1} 条规则格式不正确`, {
      statusCode: 400,
      errorCode: 'admin_fulfillment_bindings_invalid_item',
    })
  }

  const provider = String(rawBinding.provider || 'agiso').trim() || 'agiso'
  const platform = String(rawBinding.platform || '').trim()
  const shopId = String(rawBinding.shopId || '').trim()
  const shopName = String(rawBinding.shopName || '').trim()
  const skuCode = String(rawBinding.skuCode || '').trim()
  const skuName = String(rawBinding.skuName || '').trim()
  const profileKey = String(rawBinding.profileKey || '').trim() || 'manual_review'
  const match = isPlainObject(rawBinding.match) ? rawBinding.match : {}
  const externalItemId = String(match.externalItemId || '').trim()
  const externalSkuCode = String(match.externalSkuCode || '').trim()
  const externalSkuName = String(match.externalSkuName || '').trim()
  const config = isPlainObject(rawBinding.config) ? { ...rawBinding.config } : {}

  if (!skuCode) {
    throw createHttpError(`第 ${index + 1} 条规则缺少内部履约 SKU`, {
      statusCode: 400,
      errorCode: 'admin_fulfillment_bindings_missing_sku_code',
    })
  }

  if (!externalItemId && !externalSkuCode && !externalSkuName) {
    throw createHttpError(`第 ${index + 1} 条规则至少需要一种外部匹配条件`, {
      statusCode: 400,
      errorCode: 'admin_fulfillment_bindings_missing_match_condition',
    })
  }

  return {
    provider,
    platform,
    shopId,
    shopName,
    skuCode,
    skuName,
    profileKey,
    enabled: rawBinding.enabled !== false,
    priority: rawBinding.priority,
    config,
    match: {
      externalSkuCode,
      externalItemId,
      externalSkuName,
      config: isPlainObject(match.config) ? match.config : {},
    },
  }
}

export function buildAdminFulfillmentBindingUniqueKey(binding) {
  return [
    String(binding?.provider || '').trim(),
    String(binding?.platform || '').trim(),
    String(binding?.shopId || '').trim(),
    String(binding?.match?.externalItemId || '').trim(),
    String(binding?.match?.externalSkuCode || '').trim(),
    normalizeProductName(String(binding?.match?.externalSkuName || '').trim()),
    String(binding?.skuCode || '').trim(),
  ].join('::')
}

export async function validateAdminFulfillmentBindingConfigs(
  bindings: JsonObject[],
  options: JsonObject = {},
) {
  assertAdminFulfillmentBindingsInput(bindings)

  const getFulfillmentProfileByKey = (
    options.getFulfillmentProfileByKey || (async () => null)
  ) as (profileKey: string) => Promise<unknown>
  const seenKeys = new Set()
  const normalizedBindings: JsonObject[] = []

  for (const [index, rawBinding] of bindings.entries()) {
    const normalized = normalizeAdminFulfillmentBindingItem(rawBinding, { index })

    const profile = await getFulfillmentProfileByKey(normalized.profileKey)
    if (!profile) {
      throw createHttpError(`第 ${index + 1} 条规则使用了不存在的履约方式: ${normalized.profileKey}`, {
        statusCode: 400,
        errorCode: 'admin_fulfillment_bindings_invalid_profile_key',
      })
    }

    const uniqueKey = buildAdminFulfillmentBindingUniqueKey(normalized)
    if (seenKeys.has(uniqueKey)) {
      throw createHttpError(`第 ${index + 1} 条规则与其它规则重复，请调整匹配条件或内部履约 SKU`, {
        statusCode: 409,
        errorCode: 'admin_fulfillment_bindings_duplicate_rule',
      })
    }

    seenKeys.add(uniqueKey)
    normalizedBindings.push(normalized)
  }

  return normalizedBindings
}
