﻿<template>
  <div class="smart-classification">
    <van-nav-bar
      title="智能分类"
      left-text="返回"
      left-arrow
      @click-left="onClickLeft"
    />
    
    <div class="container" style="padding-top: 5px;">
      <!-- 统计信息 -->
      <div class="stats-info">
        <span class="stats-label">未分类账单：</span>
        <span class="stats-value">{{ records.length }} / {{ unclassifiedCount }}</span>
      </div>

      <!-- 账单列表 -->
      <TransactionList
        :transactions="records"
        :loading="false"
        :show-delete="false"
        :show-checkbox="true"
        :selected-ids="selectedIds"
        @click="viewDetail"
        @update:selected-ids="selectedIds = $event"
      />
    </div>

    <!-- 详情/编辑弹出层 -->
    <TransactionDetail
      v-model:show="detailVisible"
      :transaction="currentTransaction"
      @save="onDetailSave"
    />

    <!-- 底部操作按钮 -->
    <div class="action-bar">
      <van-button 
        type="primary" 
        :loading="classifying"
        :disabled="selectedIds.size === 0"
        @click="startClassify"
        class="action-btn"
      >
        {{ classifying ? '分类中...' : `开始分类 (${selectedIds.size}/${records.length})` }}
      </van-button>
      
      <van-button 
        type="success" 
        :disabled="!hasChanges || classifying"
        @click="saveClassifications"
        class="action-btn"
      >
        保存分类
      </van-button>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { showToast, showLoadingToast, closeToast, showConfirmDialog } from 'vant'
import { 
  getUnclassifiedCount, 
  getUnclassified, 
  smartClassify,
  batchUpdateClassify,
  getTransactionDetail
} from '@/api/transactionRecord'
import TransactionList from '@/components/TransactionList.vue'
import TransactionDetail from '@/components/TransactionDetail.vue'

const router = useRouter()
const unclassifiedCount = ref(0)
const records = ref([])
const selectedIds = ref(new Set()) // 选中的账单ID集合
const classifying = ref(false)
const hasChanges = ref(false)
const detailVisible = ref(false)
const currentTransaction = ref(null)
const classifyBuffer = ref('') // SSE数据缓冲区

const onClickLeft = () => {
  if (hasChanges.value) {
    showConfirmDialog({
      title: '提示',
      message: '有未保存的分类结果，确定要离开吗？',
    }).then(() => {
      router.back()
    }).catch(() => {})
  } else {
    router.back()
  }
}

// 加载未分类账单数量
const loadUnclassifiedCount = async () => {
  try {
    const res = await getUnclassifiedCount()
    if (res.success) {
      unclassifiedCount.value = res.data
    }
  } catch (error) {
    console.error('获取未分类数量失败', error)
  }
}

// 加载未分类账单列表
const loadUnclassified = async () => {
  showLoadingToast({
    message: '加载中...',
    forbidClick: true,
    duration: 0
  })
  
  try {
    const res = await getUnclassified(10)
    if (res.success) {
      records.value = res.data
      // 默认全选所有账单
      selectedIds.value = new Set(res.data.map(r => r.id))
    } else {
      showToast(res.message || '加载失败')
    }
  } catch (error) {
    console.error('加载账单失败', error)
    showToast('加载失败')
  } finally {
    closeToast()
  }
}

// 开始智能分类
const startClassify = async () => {
  const idsToClassify = Array.from(selectedIds.value)
  
  if (idsToClassify.length === 0) {
    showToast('请先选择要分类的账单')
    return
  }

  const toast = showLoadingToast({
    message: '智能分类中...',
    forbidClick: true,
    duration: 0
  })

  classifying.value = true
  classifyBuffer.value = '' // 重置缓冲区
  
  try {
    const response = await smartClassify(idsToClassify)
    
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }

    const reader = response.body.getReader()
    const decoder = new TextDecoder()
    let buffer = ''

    while (true) {
      const { done, value } = await reader.read()
      
      if (done) break
      
      buffer += decoder.decode(value, { stream: true })
      const lines = buffer.split('\n\n')
      buffer = lines.pop() || ''

      for (const line of lines) {
        if (!line.trim()) continue
        
        const eventMatch = line.match(/^event: (.+)$/m)
        const dataMatch = line.match(/^data: (.+)$/m)
        
        if (eventMatch && dataMatch) {
          const eventType = eventMatch[1]
          const data = dataMatch[1]
          
          handleSSEEvent(eventType, data)
        }
      }
    }
  } catch (error) {
    console.error('智能分类失败', error)
    showToast(`分类失败: ${error.message}`)
  } finally {
    classifying.value = false
    classifyBuffer.value = ''
    closeToast()
  }
}

// 处理SSE事件
const handleSSEEvent = (eventType, data) => {
  if (eventType === 'data') {
    try {
      // 累积AI输出的JSON片段
      classifyBuffer.value += data

      // 尝试查找并提取完整的JSON对象
      // 使用更精确的方式：查找 { 和匹配的 }
      let startIndex = 0
      while (startIndex < classifyBuffer.value.length) {
        const openBrace = classifyBuffer.value.indexOf('{', startIndex)
        if (openBrace === -1) {
          // 没有找到开始的 {，清理前面的无用字符
          classifyBuffer.value = ''
          break
        }

        // 尝试找到匹配的闭合括号
        let braceCount = 0
        let closeBrace = -1
        for (let i = openBrace; i < classifyBuffer.value.length; i++) {
          if (classifyBuffer.value[i] === '{') braceCount++
          else if (classifyBuffer.value[i] === '}') {
            braceCount--
            if (braceCount === 0) {
              closeBrace = i
              break
            }
          }
        }

        if (closeBrace !== -1) {
          // 找到了完整的JSON
          const jsonStr = classifyBuffer.value.substring(openBrace, closeBrace + 1)
          
          try {
            const result = JSON.parse(jsonStr)
            
            if (result.id) {
              const record = records.value.find(r => r.id === result.id)
              if (record) {
                record.classify = result.classify || ''
                // 如果AI返回了type字段，也更新type
                if (result.type !== undefined && result.type !== null) {
                  record.type = result.type
                }
                hasChanges.value = true
              }
            }
          } catch (e) {
            console.error('JSON解析失败:', e)
          }
          
          // 移除已处理的部分
          classifyBuffer.value = classifyBuffer.value.substring(closeBrace + 1)
          startIndex = 0 // 从头开始查找下一个JSON
        } else {
          // 没有找到闭合括号，说明JSON还不完整，等待更多数据
          break
        }
      }
    } catch (error) {
      console.error('解析分类结果失败', error)
    }
  } else if (eventType === 'start') {
    showToast(data)
  } else if (eventType === 'end') {
    classifyBuffer.value = ''
    showToast('分类完成')
  } else if (eventType === 'error') {
    classifyBuffer.value = ''
    showToast(data)
  }
}

// 保存分类
const saveClassifications = async () => {
  const itemsToUpdate = records.value
    .filter(r => r.classify)
    .map(r => ({
      id: r.id,
      classify: r.classify,
      type: r.type
    }))

  if (itemsToUpdate.length === 0) {
    showToast('没有需要保存的分类')
    return
  }

  const toast = showLoadingToast({
    message: '保存中...',
    forbidClick: true,
    duration: 0
  })

  try {
    const res = await batchUpdateClassify(itemsToUpdate)
    if (res.success) {
      showToast('保存成功')
      hasChanges.value = false
      // 重新加载数据
      await loadUnclassifiedCount()
      await loadUnclassified()
    } else {
      showToast(res.message || '保存失败')
    }
  } catch (error) {
    console.error('保存失败', error)
    showToast('保存失败')
  } finally {
    closeToast()
  }
}

// 查看详情
const viewDetail = async (transaction) => {
  try {
    const response = await getTransactionDetail(transaction.id)
    if (response.success) {
      currentTransaction.value = response.data
      detailVisible.value = true
    } else {
      showToast(response.message || '获取详情失败')
    }
  } catch (error) {
    console.error('获取详情出错:', error)
    showToast('获取详情失败')
  }
}

// 详情保存后的回调
const onDetailSave = async () => {
  // 重新加载数据
  await loadUnclassifiedCount()
  await loadUnclassified()
}

onMounted(() => {
  loadUnclassifiedCount()
  loadUnclassified()
})
</script>

<style scoped>
.smart-classification {
  min-height: var(--vh, 100vh);
  padding-bottom: calc(60px + env(safe-area-inset-bottom, 0px));
}

/* 统计信息 */
.stats-info {
  padding: 12px 16px;
  font-size: 14px;
  color: #969799;
}

.stats-value {
  font-weight: 500;
}

/* 底部操作栏 */
.action-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  gap: 12px;
  padding: 12px;
  background-color: var(--van-background-2, #fff);
  box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.08);
  z-index: 100;
}

@media (prefers-color-scheme: dark) {
  .action-bar {
    background-color: var(--van-background-2, #2c2c2c);
    box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.3);
  }
}

.action-btn {
  flex: 1;
  height: 44px;
}
</style>