import { computed, ref } from 'vue'

import {
  batchApproveApprovalTasks,
  fetchApprovalTaskDetail,
  fetchApprovalTasks
} from '../services/approvalTasks.js'
import { resolveApprovalTaskRetryKey } from '../views/scripts/approvalTaskRetry.js'
import {
  createApprovalTaskSelectionState,
  reconcileApprovalTaskSelectionAfterBatch,
  reconcileApprovalTaskSelectionWithPage,
  resolveCurrentPageApprovalSelection,
  syncApprovalTaskSelectionFilters,
  toggleApprovalTaskSelection,
  toggleCurrentPageApprovalSelection
} from '../views/scripts/approvalTaskQueueState.js'

const DEFAULT_FILTERS = Object.freeze({
  status: 'pending',
  nodeKey: '',
  taskKind: '',
  riskLevel: '',
  slaState: '',
  keyword: '',
  sort: 'priority_desc',
  batchEligible: null
})
const MAX_BATCH_SELECTION = 20

function toText(value) {
  return String(value ?? '').trim()
}

function toPositiveInteger(value, fallback = 1) {
  const number = Math.trunc(Number(value))
  return Number.isFinite(number) && number > 0 ? number : fallback
}

function taskIdOf(item = {}) {
  return toText(item?.task?.id ?? item?.id ?? item?.task_id ?? item?.taskId)
}

export function normalizeApprovalTaskQueueFilters(filters = {}) {
  return {
    ...DEFAULT_FILTERS,
    ...filters,
    status: filters.status ?? DEFAULT_FILTERS.status,
    nodeKey: filters.nodeKey ?? filters.node_key ?? DEFAULT_FILTERS.nodeKey,
    taskKind: filters.taskKind ?? filters.task_kind ?? DEFAULT_FILTERS.taskKind,
    riskLevel: filters.riskLevel ?? filters.risk_level ?? DEFAULT_FILTERS.riskLevel,
    slaState: filters.slaState ?? filters.sla_state ?? DEFAULT_FILTERS.slaState,
    keyword: toText(filters.keyword),
    sort: filters.sort ?? DEFAULT_FILTERS.sort,
    batchEligible: typeof (filters.batchEligible ?? filters.batch_eligible) === 'boolean'
      ? Boolean(filters.batchEligible ?? filters.batch_eligible)
      : null
  }
}

export function useApprovalTaskQueue(options = {}) {
  const services = {
    fetchApprovalTasks,
    fetchApprovalTaskDetail,
    batchApproveApprovalTasks,
    ...(options.services || {})
  }
  const page = ref(toPositiveInteger(options.initialPage, 1))
  const pageSize = ref(toPositiveInteger(options.initialPageSize, 20))
  const filters = ref(normalizeApprovalTaskQueueFilters(options.initialFilters))
  const items = ref([])
  const total = ref(0)
  const totalPages = ref(0)
  const generatedAt = ref('')
  const loading = ref(false)
  const batchBusy = ref(false)
  const errorMessage = ref('')
  const lastBatchResult = ref(null)
  const pendingBatchRequestId = ref('')
  const pendingBatchFingerprint = ref('')
  const selectionState = ref(createApprovalTaskSelectionState({ filters: filters.value }))
  const selectedSnapshots = new Map()
  const taskRefreshSequences = new Map()
  let listRequestSequence = 0

  const selectedTaskIds = computed(() => selectionState.value.selectedTaskIds)
  const pageSelection = computed(() =>
    resolveCurrentPageApprovalSelection(items.value, selectedTaskIds.value)
  )
  const selectedCount = computed(() => selectedTaskIds.value.length)

  function updateSelection(nextTaskIds) {
    const selectedSet = new Set(nextTaskIds)
    selectionState.value = {
      ...selectionState.value,
      selectedTaskIds: [...selectedSet]
    }
    for (const taskId of [...selectedSnapshots.keys()]) {
      if (!selectedSet.has(taskId)) {
        selectedSnapshots.delete(taskId)
      }
    }
    for (const item of items.value) {
      const taskId = taskIdOf(item)
      if (taskId && selectedSet.has(taskId)) {
        selectedSnapshots.set(taskId, item)
      }
    }
  }

  function applyListResult(result) {
    items.value = Array.isArray(result?.items) ? result.items : []
    total.value = Math.max(0, Number(result?.total) || 0)
    totalPages.value = Math.max(0, Number(result?.totalPages) || 0)
    generatedAt.value = toText(result?.generatedAt)
    page.value = toPositiveInteger(result?.page, page.value)
    pageSize.value = toPositiveInteger(result?.pageSize, pageSize.value)
    updateSelection(reconcileApprovalTaskSelectionWithPage(
      selectedTaskIds.value,
      items.value
    ))
  }

  async function loadQueue(loadOptions = {}) {
    const requestSequence = ++listRequestSequence
    if (!loadOptions.silent) {
      loading.value = true
    }
    errorMessage.value = ''
    try {
      const result = await services.fetchApprovalTasks({
        ...filters.value,
        page: page.value,
        pageSize: pageSize.value
      }, loadOptions.requestOptions)
      if (requestSequence !== listRequestSequence) {
        return { ignored: true, result }
      }
      applyListResult(result)
      return { ignored: false, result }
    } catch (error) {
      if (requestSequence !== listRequestSequence) {
        return { ignored: true, error }
      }
      errorMessage.value = error?.message || '审批任务列表加载失败。'
      throw error
    } finally {
      if (requestSequence === listRequestSequence) {
        loading.value = false
      }
    }
  }

  function setFilters(nextFilters = {}, setOptions = {}) {
    const normalized = normalizeApprovalTaskQueueFilters({
      ...filters.value,
      ...nextFilters
    })
    selectionState.value = syncApprovalTaskSelectionFilters(
      selectionState.value,
      normalized
    )
    if (!selectionState.value.selectedTaskIds.length) {
      selectedSnapshots.clear()
    }
    filters.value = normalized
    page.value = 1
    return setOptions.reload === false ? Promise.resolve(null) : loadQueue()
  }

  function setPage(nextPage, setOptions = {}) {
    page.value = toPositiveInteger(nextPage, 1)
    return setOptions.reload === false ? Promise.resolve(null) : loadQueue()
  }

  function setPageSize(nextPageSize, setOptions = {}) {
    pageSize.value = toPositiveInteger(nextPageSize, pageSize.value)
    page.value = 1
    return setOptions.reload === false ? Promise.resolve(null) : loadQueue()
  }

  function toggleTask(item, selected) {
    const nextSelection = toggleApprovalTaskSelection(selectedTaskIds.value, item, selected)
    if (nextSelection.length > MAX_BATCH_SELECTION) {
      errorMessage.value = `批量审批每次最多选择 ${MAX_BATCH_SELECTION} 项任务。`
      return
    }
    updateSelection(nextSelection)
  }

  function toggleCurrentPage(selected) {
    const nextSelection = toggleCurrentPageApprovalSelection(
      selectedTaskIds.value,
      items.value,
      selected
    )
    if (nextSelection.length > MAX_BATCH_SELECTION) {
      errorMessage.value = `批量审批每次最多选择 ${MAX_BATCH_SELECTION} 项，已保留当前结果中的前 ${MAX_BATCH_SELECTION} 项。`
      updateSelection(nextSelection.slice(0, MAX_BATCH_SELECTION))
      return
    }
    updateSelection(nextSelection)
  }

  function clearSelection() {
    updateSelection([])
  }

  function replaceTaskItem(taskId, nextItem) {
    const index = items.value.findIndex((item) => taskIdOf(item) === taskId)
    if (index < 0) {
      return
    }
    if (!nextItem) {
      items.value = items.value.filter((_, itemIndex) => itemIndex !== index)
      total.value = Math.max(0, total.value - 1)
    } else {
      items.value = items.value.map((item, itemIndex) => itemIndex === index ? nextItem : item)
    }
    updateSelection(reconcileApprovalTaskSelectionWithPage(
      selectedTaskIds.value,
      items.value
    ))
  }

  async function refreshTask(taskId, refreshOptions = {}) {
    const normalizedTaskId = toText(taskId)
    if (!normalizedTaskId) {
      return null
    }
    const sequence = (taskRefreshSequences.get(normalizedTaskId) || 0) + 1
    taskRefreshSequences.set(normalizedTaskId, sequence)
    try {
      const nextItem = await services.fetchApprovalTaskDetail(
        normalizedTaskId,
        refreshOptions.requestOptions
      )
      if (taskRefreshSequences.get(normalizedTaskId) !== sequence) {
        return null
      }
      replaceTaskItem(normalizedTaskId, nextItem)
      return nextItem
    } catch (error) {
      if (taskRefreshSequences.get(normalizedTaskId) !== sequence) {
        return null
      }
      if (Number(error?.status) === 404) {
        replaceTaskItem(normalizedTaskId, null)
        return null
      }
      errorMessage.value = error?.message || '审批任务刷新失败。'
      throw error
    }
  }

  async function batchApprove(batchOptions = {}) {
    if (batchBusy.value) {
      return null
    }
    const selectedItems = selectedTaskIds.value.map((taskId) => selectedSnapshots.get(taskId))
    if (!selectedItems.length || selectedItems.some((item) => !item)) {
      throw new Error('所选审批任务快照已失效，请刷新列表后重新选择。')
    }
    const opinion = toText(batchOptions.opinion)
    const payloadItems = selectedItems.map((item) => opinion ? { ...item, opinion } : item)
    const retryKey = resolveApprovalTaskRetryKey({
      action: 'batch-approve',
      scopeId: 'queue',
      payload: { items: payloadItems },
      previousFingerprint: pendingBatchFingerprint.value,
      previousRequestId: pendingBatchRequestId.value
    })
    pendingBatchRequestId.value = retryKey.requestId.slice(0, 80)
    pendingBatchFingerprint.value = retryKey.fingerprint
    batchBusy.value = true
    errorMessage.value = ''
    try {
      const result = await services.batchApproveApprovalTasks({
        batchRequestId: pendingBatchRequestId.value,
        items: payloadItems
      }, batchOptions.requestOptions)
      lastBatchResult.value = result
      pendingBatchRequestId.value = ''
      pendingBatchFingerprint.value = ''
      updateSelection(reconcileApprovalTaskSelectionAfterBatch(
        selectedTaskIds.value,
        result
      ))
      try {
        await loadQueue({ silent: true })
      } catch {
        // 批量结果已经落定，列表刷新失败由 errorMessage 明确展示，不覆盖真实结果。
      }
      return result
    } catch (error) {
      errorMessage.value = error?.message || '批量审批失败，请刷新任务状态后重试。'
      throw error
    } finally {
      batchBusy.value = false
    }
  }

  function clearBatchResult() {
    lastBatchResult.value = null
  }

  function clearError() {
    errorMessage.value = ''
  }

  return {
    batchApprove,
    batchBusy,
    clearBatchResult,
    clearError,
    clearSelection,
    errorMessage,
    filters,
    generatedAt,
    items,
    lastBatchResult,
    loadQueue,
    loading,
    page,
    pageSelection,
    pageSize,
    pendingBatchRequestId,
    refreshTask,
    selectedCount,
    selectedTaskIds,
    setFilters,
    setPage,
    setPageSize,
    toggleCurrentPage,
    toggleTask,
    total,
    totalPages
  }
}
