import { reactive, ref, type Ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  generateDataProcess,
  getDataProcessProgress,
  getDataProcessResults,
  restoreDataProcessResult,
  stopDataProcess,
  updateDataProcessResult,
  type DataProcessProgress,
  type DataProcessResult,
} from '@/api/modules/dataProcess'
import type { 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

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,
    status: item.status,
    error: item.error || undefined,
    split: item.split || undefined,
    qualityScore: item.quality_score?.overall,
    qualityFlags: item.quality_score?.flags || [],
    updatedAt: item.updated_at,
  }
}

export function useDataProcessGeneration(bindings: GenerationBindings) {
  const results = ref<ResultItem[]>([])
  const selectedResultId = ref<string | null>(null)
  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
  }

  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) {
    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()} 条数据处理，可进入结果页检查。`
      bindings.dirty.value = true
      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
    const taskId = bindings.taskId.value
    if (!taskId) {
      ElMessage.error('任务尚未创建，请返回上一步重试')
      return
    }

    generationStarting = true
    let runId: number | null = null
    try {
      const canStart = await bindings.beforeGenerate?.()
      if (canStart === false) return
      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
      if (progress.status === 'completed' || progress.status === 'failed' || progress.status === 'stopped') {
        await finishFromProgress(progress)
        return
      }
      applyProgress(progress)
      generationTimer = setTimeout(() => void pollGeneration(activeRunId), POLL_INTERVAL_MS)
    } catch (error) {
      if (runId !== null && runId !== generationRun) return
      generation.status = 'failed'
      generation.message = error instanceof Error ? error.message : '启动数据处理失败，请重试。'
    } finally {
      generationStarting = false
    }
  }

  async function stopGeneration() {
    const taskId = bindings.taskId.value
    if (!taskId) return
    stopGenerationTimer()
    try {
      const progress = await stopDataProcess(taskId)
      applyProgress(progress)
    } catch {
      generation.status = 'running'
      generation.message = '停止请求失败，继续查询后端任务状态。'
      const runId = generationRun
      generationTimer = setTimeout(() => void pollGeneration(runId), POLL_INTERVAL_MS)
      return
    }
    generation.status = 'failed'
    generation.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 restoreResult(id: string) {
    const taskId = bindings.taskId.value
    const item = results.value.find((entry) => entry.id === id)
    if (!taskId || !item) return
    const restored = await restoreDataProcessResult(taskId, id)
    const index = results.value.indexOf(item)
    results.value[index] = mapResult(restored)
    bindings.dirty.value = true
  }

  async function persistResultChanges() {
    const taskId = bindings.taskId.value
    if (!taskId) throw new Error('任务尚未创建')
    const changed = results.value.filter((item) => (
      item.instruction !== item.originalInstruction
      || item.input !== item.originalInput
      || item.output !== item.originalOutput
    ))
    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 {
    generation,
    results,
    selectedResultId,
    persistResultChanges,
    resetDownstream,
    restoreResult,
    startGeneration,
    stopGeneration,
    stopGenerationTimer,
    updateResultField,
    validateResults,
  }
}
