import { computed, reactive, ref, type Ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  generateDataProcess,
  getDataProcessProgress,
  getDataProcessResults,
  regenerateDataProcessResult,
  regenerateDataProcessResults,
  restoreDataProcessResult,
  updateDataProcessResult,
  type DataProcessProgress,
  type DataProcessResult,
} from '@/api/modules/dataProcess'
import type { BulkResultRegenerationState, GenerationState, ResultItem } from './types'

interface GenerationBindings {
  taskId: Ref<string | null>
  dirty: Ref<boolean>
  beforeGenerate?: () => Promise<boolean | void>
}

const RESULT_PAGE_SIZE = 500
const POLL_INTERVAL_MS = 1500
// 4 个后端 worker 可连续消费三轮，减少每 4 条等待最慢项造成的空闲；
// 单条重生成最长 60 秒，因此 12 条仍处于批量接口 240 秒超时预算内。
const BULK_REGENERATION_CHUNK_SIZE = 12

function mapResult(item: DataProcessResult): ResultItem {
  return {
    id: String(item.id),
    previewItemId: item.preview_item_id == null ? null : String(item.preview_item_id),
    instruction: item.instruction,
    input: item.input || '',
    output: item.output,
    originalInstruction: item.original_instruction ?? item.instruction,
    originalInput: item.original_input ?? item.input ?? '',
    originalOutput: item.original_output ?? item.output,
    savedInstruction: item.instruction,
    savedInput: item.input || '',
    savedOutput: item.output,
    savedStatus: item.status,
    status: item.status,
    error: item.error || undefined,
    split: item.split || undefined,
    qualityScore: item.quality_score?.overall,
    updatedAt: item.updated_at,
  }
}

export function useDataProcessGeneration(bindings: GenerationBindings) {
  const results = ref<ResultItem[]>([])
  const selectedResultId = ref<string | null>(null)
  const regeneratingResultId = ref<string | null>(null)
  const bulkRegeneration = reactive<BulkResultRegenerationState>({
    status: 'idle',
    total: 0,
    completed: 0,
    succeeded: 0,
    failed: 0,
    targetIds: [],
    failedIds: [],
  })
  const resultRegenerationBusy = computed(() => (
    Boolean(regeneratingResultId.value) || bulkRegeneration.status === 'running'
  ))
  const generation = reactive<GenerationState>({
    status: 'idle',
    progress: 0,
    message: '确认摘要后即可开始生成，过程中可查看实时进度。',
  })
  let generationTimer: ReturnType<typeof setTimeout> | null = null
  let generationRun = 0
  let pollFailureCount = 0
  let generationStarting = false

  function stopGenerationTimer() {
    generationRun += 1
    if (generationTimer) clearTimeout(generationTimer)
    generationTimer = null
  }

  function resetDownstream() {
    stopGenerationTimer()
    generation.status = 'idle'
    generation.progress = 0
    generation.message = '确认摘要后即可开始生成，过程中可查看实时进度。'
    results.value = []
    selectedResultId.value = null
    regeneratingResultId.value = null
    Object.assign(bulkRegeneration, {
      status: 'idle',
      total: 0,
      completed: 0,
      succeeded: 0,
      failed: 0,
      targetIds: [],
      failedIds: [],
    })
  }

  function applyProgress(progress: DataProcessProgress) {
    generation.progress = Math.max(0, Math.min(100, Number(progress.progress) || 0))
    generation.message = progress.message || (
      progress.status === 'running'
        ? '后端正在生成标准化结果并进行质量评分。'
        : progress.status === 'completed'
          ? '数据处理已完成。'
          : progress.failure_reason || '任务已停止。'
    )
  }

  async function loadAllResults(taskId: string) {
    const first = await getDataProcessResults(taskId, { page: 1, page_size: RESULT_PAGE_SIZE })
    const items = [...first.items]
    const pages = Math.ceil(first.total / first.page_size)
    for (let page = 2; page <= pages; page += 1) {
      const next = await getDataProcessResults(taskId, { page, page_size: RESULT_PAGE_SIZE })
      items.push(...next.items)
    }
    results.value = items.map(mapResult)
    selectedResultId.value = results.value[0]?.id ?? null
  }

  async function finishFromProgress(progress: DataProcessProgress, notify = true) {
    pollFailureCount = 0
    applyProgress(progress)
    if (progress.status === 'completed') {
      const taskId = bindings.taskId.value
      if (!taskId) return
      await loadAllResults(taskId)
      generation.status = 'success'
      generation.progress = 100
      generation.message = `已完成 ${results.value.length.toLocaleString()} 条数据处理，可进入结果页检查。`
      if (notify) ElMessage.success('数据处理完成')
      return
    }
    if (progress.status === 'failed' || progress.status === 'stopped') {
      generation.status = 'failed'
      generation.message = progress.failure_reason || progress.message || (
        progress.status === 'stopped' ? '任务已停止，可以重新生成。' : '数据处理失败，请检查配置后重试。'
      )
    }
  }

  async function pollGeneration(runId: number) {
    const taskId = bindings.taskId.value
    if (!taskId || runId !== generationRun || generation.status !== 'running') return

    try {
      const progress = await getDataProcessProgress(taskId)
      if (runId !== generationRun) return
      pollFailureCount = 0
      if (progress.status === 'running' || progress.status === 'pending') {
        applyProgress(progress)
        generationTimer = setTimeout(() => void pollGeneration(runId), POLL_INTERVAL_MS)
        return
      }
      await finishFromProgress(progress)
    } catch (error) {
      if (runId !== generationRun) return
      pollFailureCount += 1
      if (pollFailureCount <= 3) {
        generation.message = `进度查询暂时失败，正在重试（${pollFailureCount}/3）…`
        generationTimer = setTimeout(() => void pollGeneration(runId), POLL_INTERVAL_MS)
        return
      }
      generation.status = 'failed'
      generation.message = error instanceof Error ? error.message : '查询任务进度失败，请重试。'
    }
  }

  async function startGeneration() {
    if (generationStarting || generation.status === 'running') return false
    const taskId = bindings.taskId.value
    if (!taskId) {
      ElMessage.error('任务尚未创建，请返回上一步重试')
      return false
    }

    generationStarting = true
    let runId: number | null = null
    try {
      const canStart = await bindings.beforeGenerate?.()
      if (canStart === false) return false
      stopGenerationTimer()
      const activeRunId = generationRun
      runId = activeRunId
      generation.status = 'running'
      pollFailureCount = 0
      generation.progress = 0
      generation.message = '正在同步预览修改并启动后端处理，请稍候。'
      const progress = await generateDataProcess(taskId)
      if (activeRunId !== generationRun) return false
      if (progress.status === 'completed' || progress.status === 'failed' || progress.status === 'stopped') {
        await finishFromProgress(progress)
        return true
      }
      applyProgress(progress)
      generationTimer = setTimeout(() => void pollGeneration(activeRunId), POLL_INTERVAL_MS)
      return true
    } catch (error) {
      if (runId !== null && runId !== generationRun) return
      generation.status = 'failed'
      generation.message = error instanceof Error ? error.message : '启动数据处理失败，请重试。'
      return false
    } finally {
      generationStarting = false
    }
  }

  async function resumeGeneration() {
    const taskId = bindings.taskId.value
    if (!taskId) return
    stopGenerationTimer()
    const activeRunId = generationRun
    pollFailureCount = 0
    try {
      const progress = await getDataProcessProgress(taskId)
      if (activeRunId !== generationRun) return
      if (progress.status === 'running') {
        generation.status = 'running'
        applyProgress(progress)
        generationTimer = setTimeout(() => void pollGeneration(activeRunId), POLL_INTERVAL_MS)
        return
      }
      if (progress.status === 'completed') {
        await finishFromProgress(progress, false)
        return
      }
      if (progress.status === 'failed' || progress.status === 'stopped') {
        await finishFromProgress(progress, false)
        return
      }
      generation.status = 'idle'
      applyProgress(progress)
    } catch (error) {
      generation.status = 'failed'
      generation.message = error instanceof Error ? error.message : '查询任务进度失败，请重试。'
    }
  }

  function updateResultField(id: string, field: 'instruction' | 'input' | 'output', value: string) {
    const item = results.value.find((entry) => entry.id === id)
    if (!item) return
    item[field] = value
    const valid = item.instruction.trim() && item.output.trim()
    item.error = valid ? undefined : 'Instruction 和 Output 不能为空'
    const changed = item.instruction !== item.originalInstruction
      || item.input !== item.originalInput
      || item.output !== item.originalOutput
    item.status = item.error ? 'invalid' : changed ? 'modified' : 'valid'
    bindings.dirty.value = true
  }



  async function regenerateResult(id: string) {
    const taskId = bindings.taskId.value
    const item = results.value.find((entry) => entry.id === id)
    if (!taskId || !item) return false
    if (resultRegenerationBusy.value) {
      ElMessage.warning('请等待当前失败结果重新生成完成')
      return false
    }
    if (item.savedStatus !== 'invalid') {
      ElMessage.warning('只有生成失败的结果可以重新生成')
      return false
    }
    if (!item.updatedAt) {
      ElMessage.error('结果版本信息缺失，请刷新页面后重试')
      return false
    }

    regeneratingResultId.value = id
    try {
      const regenerated = await regenerateDataProcessResult(taskId, id, {
        expected_updated_at: item.updatedAt,
      })
      const index = results.value.findIndex((entry) => entry.id === id)
      if (index >= 0) results.value[index] = mapResult(regenerated)
      ElMessage.success('当前结果已重新生成')
      return true
    } catch {
      return false
    } finally {
      regeneratingResultId.value = null
    }
  }

  async function regenerateAllResults() {
    const taskId = bindings.taskId.value
    if (!taskId) return false
    if (resultRegenerationBusy.value) {
      ElMessage.warning('请等待当前失败结果重新生成完成')
      return false
    }

    const candidates = results.value.filter((item) => item.savedStatus === 'invalid')
    if (!candidates.length) {
      ElMessage.info('当前没有需要重新生成的失败结果')
      return false
    }
    const unsaved = candidates.find((item) => (
      item.instruction !== item.savedInstruction
      || item.input !== item.savedInput
      || item.output !== item.savedOutput
    ))
    if (unsaved) {
      selectedResultId.value = unsaved.id
      ElMessage.warning('失败结果存在未保存修改，请先保存或恢复后再全部重新生成')
      return false
    }
    const missingVersion = candidates.find((item) => !item.updatedAt)
    if (missingVersion) {
      selectedResultId.value = missingVersion.id
      ElMessage.error('失败结果版本信息缺失，请刷新页面后重试')
      return false
    }

    Object.assign(bulkRegeneration, {
      status: 'running',
      total: candidates.length,
      completed: 0,
      succeeded: 0,
      failed: 0,
      targetIds: candidates.map((item) => item.id),
      failedIds: [],
    })

    try {
      for (let offset = 0; offset < candidates.length; offset += BULK_REGENERATION_CHUNK_SIZE) {
        const chunk = candidates.slice(offset, offset + BULK_REGENERATION_CHUNK_SIZE)
        try {
          const regenerated = await regenerateDataProcessResults(taskId, {
            items: chunk.map((item) => ({
              result_id: item.id,
              expected_updated_at: item.updatedAt as string,
            })),
          })
          for (const item of regenerated.items) {
            const index = results.value.findIndex((entry) => entry.id === String(item.id))
            if (index >= 0) results.value[index] = mapResult(item)
          }
          bulkRegeneration.completed += regenerated.total
          bulkRegeneration.succeeded += regenerated.succeeded
          bulkRegeneration.failed += regenerated.failed
          bulkRegeneration.failedIds.push(
            ...regenerated.failures.map((failure) => failure.result_id),
          )
        } catch {
          const remaining = candidates.slice(offset)
          bulkRegeneration.completed = bulkRegeneration.total
          bulkRegeneration.failed += remaining.length
          bulkRegeneration.failedIds.push(...remaining.map((item) => item.id))
          break
        }
      }

      if (bulkRegeneration.failed === 0) {
        bulkRegeneration.status = 'completed'
        ElMessage.success(`已重新生成 ${bulkRegeneration.succeeded} 条失败结果`)
      } else if (bulkRegeneration.succeeded > 0) {
        bulkRegeneration.status = 'partial'
        ElMessage.warning(
          `重新生成完成：成功 ${bulkRegeneration.succeeded} 条，仍失败 ${bulkRegeneration.failed} 条`,
        )
      } else {
        bulkRegeneration.status = 'failed'
        ElMessage.error(`重新生成失败：${bulkRegeneration.failed} 条结果仍需重试`)
      }
      const firstFailed = bulkRegeneration.failedIds.find((id) => (
        results.value.find((item) => item.id === id)?.savedStatus === 'invalid'
      ))
      if (firstFailed) selectedResultId.value = firstFailed
      return bulkRegeneration.failed === 0
    } catch {
      const remaining = Math.max(0, bulkRegeneration.total - bulkRegeneration.completed)
      const remainingIds = candidates
        .filter((candidate) => (
          results.value.find((item) => item.id === candidate.id)?.savedStatus === 'invalid'
        ))
        .map((item) => item.id)
      bulkRegeneration.completed = bulkRegeneration.total
      bulkRegeneration.failed += remaining
      bulkRegeneration.failedIds = [...new Set([
        ...bulkRegeneration.failedIds,
        ...remainingIds,
      ])]
      bulkRegeneration.status = 'failed'
      if (bulkRegeneration.failedIds[0]) selectedResultId.value = bulkRegeneration.failedIds[0]
      ElMessage.error('批量重新生成意外中断，尚未成功的结果保持原状')
      return false
    } finally {
      bulkRegeneration.targetIds = []
    }
  }

  async function persistResultChanges() {
    const taskId = bindings.taskId.value
    if (!taskId) throw new Error('任务尚未创建')
    const changed = results.value.filter((item) => (
      item.instruction !== item.savedInstruction
      || item.input !== item.savedInput
      || item.output !== item.savedOutput
    ))
    for (const item of changed) {
      const saved = await updateDataProcessResult(taskId, item.id, {
        instruction: item.instruction,
        input: item.input,
        output: item.output,
        expected_updated_at: item.updatedAt,
      })
      const index = results.value.findIndex((entry) => entry.id === item.id)
      if (index >= 0) results.value[index] = mapResult(saved)
    }
  }

  function validateResults() {
    let firstInvalidId: string | null = null
    for (const item of results.value) {
      if (!item.instruction.trim() || !item.output.trim() || item.status === 'invalid') {
        item.error ||= '结果未通过后端质量校验，请修改后重新保存'
        item.status = 'invalid'
        firstInvalidId ??= item.id
      }
    }
    if (firstInvalidId) selectedResultId.value = firstInvalidId
    return firstInvalidId == null
  }

  return {
    bulkRegeneration,
    generation,
    regeneratingResultId,
    resultRegenerationBusy,
    results,
    selectedResultId,
    persistResultChanges,
    resetDownstream,
    regenerateAllResults,
    regenerateResult,
    resumeGeneration,
    startGeneration,
    stopGenerationTimer,
    updateResultField,
    validateResults,
  }
}
