import { computed, onMounted, ref, watch } from 'vue'

import { showConfirm, showError, showSuccess } from '@/lib/feedback'
import {
  createAdminInventoryItem,
  fetchAdminInventoryItems,
  fetchAdminInventorySkuSuggestions,
  importAdminInventoryItems,
} from '@/services/admin'
import type {
  AdminInventoryItemListItem,
  AdminInventorySkuSuggestion,
  AdminPagination,
} from '@/types/admin'
import { formatAdminDateTime } from '@/utils/admin-time'
import {
  adminInventoryCredentialTypeOptions,
  adminInventoryStatusOptions,
} from '@/utils/admin-options'

import type { InventoryImportRow, InventoryPoolGroup } from './types'

export function useAdminInventory() {
  const loading = ref(true)
  const importing = ref(false)
  const creating = ref(false)
  const actionLoadingId = ref<number | null>(null)
  const errorMessage = ref('')

  const filterSkuCode = ref('')
  const filterCredentialType = ref('')
  const filterStatus = ref('')
  const filterBatchNo = ref('')
  const filterInventoryGroupCode = ref('')

  const entrySkuCode = ref('')
  const entryCredentialType = ref('tencent_code')
  const entryBatchNo = ref('')
  const entryInventoryGroupCode = ref('')
  const singleDisplayValue = ref('')
  const bulkText = ref('')
  const skuSuggestionsLoading = ref(false)
  const inventorySkuSuggestions = ref<AdminInventorySkuSuggestion[]>([])

  const items = ref<AdminInventoryItemListItem[]>([])
  const pagination = ref<AdminPagination>({
    page: 1,
    pageSize: 20,
    total: 0,
  })

  const pageSummary = computed(() => {
    const availableCount = items.value.filter((item) => item.status === 'available').length
    const reservedCount = items.value.filter((item) => item.status === 'reserved').length
    const deliveredCount = items.value.filter((item) => item.status === 'consumed').length
    const invalidCount = items.value.filter((item) => item.status === 'invalid').length
    return { availableCount, reservedCount, deliveredCount, invalidCount }
  })

  const inventoryGroups = computed<InventoryPoolGroup[]>(() => {
    const groupMap = new Map<
      string,
      {
        skuCode: string
        credentialType: string
        inventoryGroupCode: string
        totalCount: number
        availableCount: number
        reservedCount: number
        deliveredCount: number
        invalidCount: number
        latestUpdatedAt: string
        batches: Set<string>
      }
    >()

    for (const item of items.value) {
      const key = `${item.skuCode}::${item.credentialType || 'tencent_code'}::${item.inventoryGroupCode || ''}`
      const current = groupMap.get(key) || {
        skuCode: item.skuCode,
        credentialType: item.credentialType || 'tencent_code',
        inventoryGroupCode: item.inventoryGroupCode || '',
        totalCount: 0,
        availableCount: 0,
        reservedCount: 0,
        deliveredCount: 0,
        invalidCount: 0,
        latestUpdatedAt: item.updatedAt,
        batches: new Set<string>(),
      }

      current.totalCount += 1
      if (item.status === 'available') current.availableCount += 1
      else if (item.status === 'reserved') current.reservedCount += 1
      else if (item.status === 'consumed') current.deliveredCount += 1
      else if (item.status === 'invalid') current.invalidCount += 1

      if (item.batchNo) current.batches.add(item.batchNo)
      if (String(item.updatedAt || '') > String(current.latestUpdatedAt || ''))
        current.latestUpdatedAt = item.updatedAt
      groupMap.set(key, current)
    }

    return Array.from(groupMap.entries())
      .map(([key, value]) => ({
        key,
        skuCode: value.skuCode,
        credentialType: value.credentialType,
        inventoryGroupCode: value.inventoryGroupCode,
        totalCount: value.totalCount,
        availableCount: value.availableCount,
        reservedCount: value.reservedCount,
        deliveredCount: value.deliveredCount,
        invalidCount: value.invalidCount,
        latestUpdatedAt: value.latestUpdatedAt,
        batchSummary:
          value.batches.size > 0 ? Array.from(value.batches).slice(0, 3).join(' / ') : '未分批',
      }))
      .sort((left, right) => {
        if (right.availableCount !== left.availableCount)
          return right.availableCount - left.availableCount
        if (right.reservedCount !== left.reservedCount)
          return right.reservedCount - left.reservedCount
        return left.skuCode.localeCompare(right.skuCode)
      })
  })

  const pageOverview = computed(() => ({
    skuCount: new Set(items.value.map((item) => item.skuCode)).size,
    groupCount: inventoryGroups.value.length,
  }))

  const entrySkuSuggestions = computed(() => {
    const keyword = entrySkuCode.value.trim().toLowerCase()
    const suggestions = inventorySkuSuggestions.value.filter(
      (item) => item.credentialType === entryCredentialType.value,
    )
    if (!keyword) return suggestions.slice(0, 12)
    return suggestions.filter((item) => item.skuCode.toLowerCase().includes(keyword)).slice(0, 12)
  })

  function getCredentialTypeLabel(value: string) {
    const normalized = String(value || '').trim()
    const option = adminInventoryCredentialTypeOptions.find((item) => item.value === normalized)
    return option?.label || normalized || '-'
  }

  function getCredentialTypeHint(value: string) {
    const normalized = String(value || '').trim()
    if (normalized === 'tencent_code')
      return '当前腾讯自动领取链路会优先预占这一类兑换码，三角洲行动这类场景就使用这个类型。内部 SKU 支持中文、英文和数字混用。'
    if (normalized === 'card_password') return '适合卡号 / 卡密一体的库存项。'
    if (normalized === 'account_password') return '适合账号密码、账号令牌等组合凭据。'
    if (normalized === 'activation_link') return '适合直接发链接的激活类库存。'
    if (normalized === 'text_credential') return '适合任意纯文本凭据。'
    return '库存预占时会按凭据类型与内部履约 SKU 一起匹配。'
  }

  function getSkuNamingHint() {
    if (entrySkuSuggestions.value.length > 0)
      return `当前凭据类型下已有 ${entrySkuSuggestions.value.length} 个可复用的内部 SKU，也可以直接输入新的中文或英文名称。`
    return '内部 SKU 支持中文、英文、数字和常见连接符。建议同一类商品长期使用同一个命名，方便共用库存池。'
  }

  function formatInventoryStatus(item: AdminInventoryItemListItem) {
    if (item.status === 'consumed') return '已完成发放'
    if (item.status === 'reserved') return '已被任务预占'
    if (item.status === 'invalid') return '已手动作废'
    return '可参与后续自动分配'
  }

  function getGroupSuggestion(group: InventoryPoolGroup) {
    if (group.availableCount > 0)
      return `当前还有 ${group.availableCount} 条可直接分配的库存，可以继续承接订单。`
    if (group.reservedCount > 0)
      return `当前没有可用库存，但有 ${group.reservedCount} 条正在被任务预占，建议优先检查任务进度。`
    if (group.deliveredCount > 0 && group.invalidCount === 0)
      return '当前页看到的库存都已经发放完成，若继续售卖需要补新的库存项。'
    if (group.invalidCount > 0 && group.totalCount === group.invalidCount)
      return '当前页这组库存都已作废，建议重新补充可用库存。'
    return '当前页没有可立即分配的库存，建议补库存或检查对应履约任务。'
  }

  function useGroupAsFilter(group: InventoryPoolGroup) {
    filterSkuCode.value = group.skuCode
    filterCredentialType.value = group.credentialType
    filterInventoryGroupCode.value = group.inventoryGroupCode
    void loadInventoryItems(1)
  }

  function useGroupAsEntry(group: InventoryPoolGroup) {
    entrySkuCode.value = group.skuCode
    entryCredentialType.value = group.credentialType
    entryInventoryGroupCode.value = group.inventoryGroupCode
    if (group.batchSummary !== '未分批' && !group.batchSummary.includes(' / '))
      entryBatchNo.value = group.batchSummary
    showSuccess(
      `已把 ${group.skuCode} / ${group.credentialType} / ${group.inventoryGroupCode || '未分组'} 填入入库表单`,
    )
  }

  function applySkuSuggestion(skuCode: string) {
    entrySkuCode.value = String(skuCode || '').trim()
  }

  function buildImportRows() {
    const lines = bulkText.value
      .split('\n')
      .map((line) => line.trim())
      .filter(Boolean)
    const rows: InventoryImportRow[] = []
    const defaultSkuCode = entrySkuCode.value.trim()
    const defaultCredentialType = entryCredentialType.value.trim() || 'tencent_code'
    const defaultBatchNo = entryBatchNo.value.trim()

    for (let index = 0; index < lines.length; index += 1) {
      const line = lines[index]
      if (line.includes('|')) {
        const parts = line.split('|').map((part) => part.trim())
        if (parts.length !== 4 && parts.length !== 5)
          throw new Error(
            `第 ${index + 1} 行格式不正确，请使用 内部SKU|凭据类型|批次号|库存组|凭据内容`,
          )
        const [skuCode, credentialType, batchNo, inventoryGroupCode, displayValue] =
          parts.length === 5 ? parts : [parts[0], parts[1], parts[2], '', parts[3]]
        if (!skuCode || !displayValue) throw new Error(`第 ${index + 1} 行缺少内部 SKU 或凭据内容`)
        rows.push({
          skuCode,
          credentialType: credentialType || defaultCredentialType,
          batchNo,
          inventoryGroupCode: inventoryGroupCode || entryInventoryGroupCode.value.trim(),
          displayValue,
        })
        continue
      }
      if (!defaultSkuCode)
        throw new Error('存在未带内部 SKU 的行，请先填写默认内部履约 SKU，或改用四列导入格式')
      rows.push({
        skuCode: defaultSkuCode,
        credentialType: defaultCredentialType,
        batchNo: defaultBatchNo,
        inventoryGroupCode: entryInventoryGroupCode.value.trim(),
        displayValue: line,
      })
    }
    return rows
  }

  async function loadInventoryItems(page = pagination.value.page) {
    loading.value = true
    errorMessage.value = ''
    try {
      const response = await fetchAdminInventoryItems({
        page,
        pageSize: pagination.value.pageSize,
        skuCode: filterSkuCode.value.trim(),
        credentialType: filterCredentialType.value.trim(),
        status: filterStatus.value.trim(),
        batchNo: filterBatchNo.value.trim(),
        inventoryGroupCode: filterInventoryGroupCode.value.trim(),
      })
      items.value = response.data.items
      pagination.value = response.data.pagination
    } catch (error) {
      errorMessage.value = error instanceof Error ? error.message : '读取库存列表失败'
    } finally {
      loading.value = false
    }
  }

  async function loadInventorySkuSuggestions() {
    skuSuggestionsLoading.value = true
    try {
      const response = await fetchAdminInventorySkuSuggestions({
        credentialType: entryCredentialType.value.trim() || 'tencent_code',
        inventoryGroupCode: entryInventoryGroupCode.value.trim(),
        limit: 50,
      })
      inventorySkuSuggestions.value = response.data.items
    } catch (error) {
      showError(error instanceof Error ? error.message : '读取内部 SKU 建议失败')
    } finally {
      skuSuggestionsLoading.value = false
    }
  }

  function resetFilters() {
    filterSkuCode.value = ''
    filterCredentialType.value = ''
    filterStatus.value = ''
    filterBatchNo.value = ''
    filterInventoryGroupCode.value = ''
    void loadInventoryItems(1)
  }

  async function submitCreate() {
    if (!entrySkuCode.value.trim() || !singleDisplayValue.value.trim()) {
      showError('请先填写内部履约 SKU 和凭据内容')
      return
    }
    creating.value = true
    try {
      await createAdminInventoryItem({
        skuCode: entrySkuCode.value.trim(),
        credentialType: entryCredentialType.value.trim() || 'tencent_code',
        batchNo: entryBatchNo.value.trim(),
        inventoryGroupCode: entryInventoryGroupCode.value.trim(),
        displayValue: singleDisplayValue.value.trim(),
      })
      showSuccess('库存项已新增')
      singleDisplayValue.value = ''
      await loadInventoryItems(1)
    } catch (error) {
      showError(error instanceof Error ? error.message : '新增库存项失败')
    } finally {
      creating.value = false
    }
  }

  async function submitImport() {
    const rawLines = bulkText.value
      .split('\n')
      .map((line) => line.trim())
      .filter(Boolean)
    if (rawLines.length === 0) {
      showError('请至少输入一条待导入库存')
      return
    }
    importing.value = true
    try {
      const rows = buildImportRows()
      const response = await importAdminInventoryItems({ rows })
      showSuccess(`导入完成，新增 ${response.data.created} 条，重复 ${response.data.duplicated} 条`)
      bulkText.value = ''
      await loadInventoryItems(1)
    } catch (error) {
      showError(error instanceof Error ? error.message : '导入失败')
    } finally {
      importing.value = false
    }
  }

  async function runRowAction(
    inventoryItemId: number,
    action: () => Promise<unknown>,
    successMessage: string,
    confirmText: string,
  ) {
    try {
      await showConfirm(confirmText, '确认操作', {
        type: 'warning',
        confirmButtonText: '继续执行',
        cancelButtonText: '取消',
      })
    } catch {
      return
    }
    actionLoadingId.value = inventoryItemId
    try {
      await action()
      showSuccess(successMessage)
      await loadInventoryItems()
    } catch (error) {
      showError(error instanceof Error ? error.message : '操作失败')
    } finally {
      actionLoadingId.value = null
    }
  }

  watch(entryCredentialType, () => {
    void loadInventorySkuSuggestions()
  })
  watch(entryInventoryGroupCode, () => {
    void loadInventorySkuSuggestions()
  })

  onMounted(async () => {
    await Promise.all([loadInventoryItems(), loadInventorySkuSuggestions()])
  })

  return {
    // state
    loading,
    importing,
    creating,
    actionLoadingId,
    errorMessage,
    items,
    pagination,
    pageSummary,
    pageOverview,
    inventoryGroups,
    // filter
    filterSkuCode,
    filterCredentialType,
    filterStatus,
    filterBatchNo,
    filterInventoryGroupCode,
    // entry
    entrySkuCode,
    entryCredentialType,
    entryBatchNo,
    entryInventoryGroupCode,
    singleDisplayValue,
    bulkText,
    skuSuggestionsLoading,
    inventorySkuSuggestions,
    entrySkuSuggestions,
    // actions
    loadInventoryItems,
    resetFilters,
    submitCreate,
    submitImport,
    runRowAction,
    useGroupAsFilter,
    useGroupAsEntry,
    applySkuSuggestion,
    // formatters
    getCredentialTypeLabel,
    getCredentialTypeHint,
    getSkuNamingHint,
    formatInventoryStatus,
    getGroupSuggestion,
    // utils
    formatAdminDateTime,
    adminInventoryCredentialTypeOptions,
    adminInventoryStatusOptions,
  }
}
