import {
  createInventoryItems,
  invalidateInventoryItem,
  listInventoryItems,
  releaseReservedInventoryItem,
} from '../../../repositories/inventory-repo.js'
import { createHttpError } from '../../../utils/http.js'
import { nowIso } from '../../../utils/time.js'
import {
  getRequiredInventoryItem,
  mapAdminInventoryListItem,
} from '../admin-inventory-read-helpers.js'

import type { AdminEntityIdInput } from '../../../types/admin-read-inputs.js'
import type {
  AdminInventoryCreateInput,
  AdminInventoryImportInput,
  AdminInventoryImportRowInput,
  AdminInventoryInvalidateInput,
} from '../../../types/admin-write-inputs.js'
import type {
  AdminInventoryImportResponse,
  AdminInventoryMutationResponse,
} from '../../../types/admin-write-models.js'
import type { InventoryItemRow } from '../../../types/repository-rows.js'

type NormalizedInventoryImportRow = Required<Pick<
  AdminInventoryImportRowInput,
  'skuCode' | 'displayValue' | 'batchNo' | 'credentialType' | 'inventoryGroupCode'
>>

export async function createAdminInventoryItem(
  payload: AdminInventoryCreateInput = {},
): Promise<AdminInventoryMutationResponse> {
  const skuCode = String(payload.skuCode || '').trim()
  const displayValue = String(payload.displayValue || '').trim()
  const batchNo = String(payload.batchNo || '').trim()
  const credentialType = String(payload.credentialType || 'tencent_code').trim() || 'tencent_code'
  const inventoryGroupCode = String(payload.inventoryGroupCode || '').trim()

  if (!skuCode || !displayValue) {
    throw createHttpError('缺少 skuCode 或 displayValue', {
      statusCode: 400,
      errorCode: 'admin_inventory_create_invalid',
    })
  }

  const now = nowIso()
  const created = await createInventoryItems([
    {
      skuCode,
      displayValue,
      batchNo,
      credentialType,
      inventoryGroupCode,
      createdAt: now,
      updatedAt: now,
    },
  ])

  if (created === 0) {
    throw createHttpError('库存凭据已存在，不能重复新增', {
      statusCode: 409,
      errorCode: 'admin_inventory_duplicate',
    })
  }

  const { items } = await listInventoryItems({
    page: 1,
    pageSize: 20,
    skuCode,
    inventoryGroupCode,
  })
  const createdItem = items.find((item) => item.display_value === displayValue && item.inventory_group_code === inventoryGroupCode) || null

  return {
    inventoryItem: createdItem ? await mapAdminInventoryListItem(createdItem) : null,
  }
}

export async function importAdminInventoryItems(
  payload: AdminInventoryImportInput = {},
): Promise<AdminInventoryImportResponse> {
  const rows = normalizeInventoryImportRows(payload)

  if (rows.length === 0) {
    throw createHttpError('没有可导入的库存凭据数据', {
      statusCode: 400,
      errorCode: 'admin_inventory_import_empty',
    })
  }

  const now = nowIso()
  const normalizedRows = rows.map((row) => ({
    skuCode: row.skuCode,
    batchNo: row.batchNo,
    displayValue: row.displayValue,
    credentialType: row.credentialType,
    inventoryGroupCode: row.inventoryGroupCode,
    createdAt: now,
    updatedAt: now,
  }))

  const created = await createInventoryItems(normalizedRows)

  return {
    total: normalizedRows.length,
    created,
    duplicated: normalizedRows.length - created,
  }
}

export async function releaseAdminInventoryItem(
  inventoryItemId: AdminEntityIdInput,
): Promise<AdminInventoryMutationResponse> {
  const inventoryItem = await getRequiredInventoryItem(inventoryItemId)

  if (inventoryItem.status !== 'reserved') {
    throw createHttpError('当前库存项不是预占状态，不能释放', {
      statusCode: 409,
      errorCode: 'admin_inventory_release_not_allowed',
    })
  }

  const updated = await releaseReservedInventoryItem(inventoryItem.id, nowIso())

  return {
    inventoryItem: await mapAdminInventoryListItem(updated as InventoryItemRow),
  }
}

export async function invalidateAdminInventoryItem(
  inventoryItemId: AdminEntityIdInput,
  payload: AdminInventoryInvalidateInput = {},
): Promise<AdminInventoryMutationResponse> {
  const inventoryItem = await getRequiredInventoryItem(inventoryItemId)

  if (inventoryItem.status !== 'available') {
    throw createHttpError('只有可用库存项才能作废，请先释放预占', {
      statusCode: 409,
      errorCode: 'admin_inventory_invalidate_not_allowed',
    })
  }

  const reason = String(payload.reason || '').trim() || '后台手动作废'
  const updated = await invalidateInventoryItem(inventoryItem.id, reason, nowIso())

  return {
    inventoryItem: await mapAdminInventoryListItem(updated as InventoryItemRow),
  }
}

function normalizeInventoryImportRows(payload: AdminInventoryImportInput): NormalizedInventoryImportRow[] {
  const rows: NormalizedInventoryImportRow[] = []
  const directRows = Array.isArray(payload.rows) ? payload.rows : []
  const bulkCodes = Array.isArray(payload.codes) ? payload.codes : []

  if (directRows.length > 0) {
    for (const row of directRows) {
      const skuCode = String(row?.skuCode || '').trim()
      const displayValue = String(row?.displayValue || '').trim()
      const batchNo = String(row?.batchNo || '').trim()
      const credentialType = String(row?.credentialType || payload.credentialType || 'tencent_code').trim() || 'tencent_code'
      const inventoryGroupCode = String(row?.inventoryGroupCode || payload.inventoryGroupCode || '').trim()

      if (!skuCode || !displayValue) {
        continue
      }

      rows.push({ skuCode, displayValue, batchNo, credentialType, inventoryGroupCode })
    }
  }

  if (bulkCodes.length > 0) {
    const skuCode = String(payload.skuCode || '').trim()
    const batchNo = String(payload.batchNo || '').trim()
    const credentialType = String(payload.credentialType || 'tencent_code').trim() || 'tencent_code'
    const inventoryGroupCode = String(payload.inventoryGroupCode || '').trim()

    if (!skuCode) {
      throw createHttpError('批量导入时缺少 skuCode', {
        statusCode: 400,
        errorCode: 'admin_inventory_import_missing_sku',
      })
    }

    for (const rawValue of bulkCodes) {
      const displayValue = String(rawValue || '').trim()
      if (!displayValue) {
        continue
      }
      rows.push({ skuCode, displayValue, batchNo, credentialType, inventoryGroupCode })
    }
  }

  return dedupeRows(rows)
}

function dedupeRows(rows: NormalizedInventoryImportRow[]): NormalizedInventoryImportRow[] {
  const seen = new Set<string>()
  const output: NormalizedInventoryImportRow[] = []

  for (const row of rows) {
    const key = `${row.skuCode}::${row.credentialType || 'tencent_code'}::${row.displayValue}`
    if (seen.has(key)) {
      continue
    }
    seen.add(key)
    output.push(row)
  }

  return output
}
