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

      <!-- 分组列表 -->
      <van-empty v-if="reasonGroups.length === 0 && !loading" description="暂无未分类账单" />
      
      <van-cell-group v-else inset>
        <van-cell 
          v-for="group in reasonGroups" 
          :key="group.reason"
          clickable
        >
          <template #title>
            <div class="group-header">
              <van-checkbox 
                :model-value="selectedReasons.has(group.reason)"
                @click.stop="toggleGroupSelection(group.reason)"
              />
              <div class="group-title">
                {{ group.reason }}
              </div>
            </div>
          </template>
          <template #label>
            <div class="group-info">
              <van-tag 
                :type="getTypeColor(group.sampleType)" 
                size="medium"
                style="margin-right: 8px;"
              >
                {{ getTypeName(group.sampleType) }}
              </van-tag>
              <van-tag 
                v-if="group.sampleClassify" 
                type="primary" 
                size="medium"
                style="margin-right: 8px;"
              >
                {{ group.sampleClassify }}
              </van-tag>
              <span class="count-text">{{ group.count }} 条</span>
              <span class="amount-text" v-if="group.totalAmount">
                ¥{{ Math.abs(group.totalAmount).toFixed(2) }}
              </span>
            </div>
          </template>
        </van-cell>
      </van-cell-group>

      <!-- 底部安全距离 -->
      <div style="height: calc(50px + env(safe-area-inset-bottom, 0px))"></div>
    </div>

    <!-- 底部操作按钮 -->
    <div class="action-bar">
      <van-button 
        type="primary" 
        :loading="classifying"
        :disabled="selectedReasons.size === 0"
        @click="startClassify"
        class="action-btn"
      >
        {{ classifying ? '分类中...' : `开始分类 (${selectedReasons.size}组)` }}
      </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, 
  getReasonGroups,
  smartClassify,
  batchUpdateClassify
} from '@/api/transactionRecord'

const router = useRouter()
const unclassifiedCount = ref(0)
const reasonGroups = ref([]) // 改为分组数据
const selectedReasons = ref(new Set()) // 选中的分组摘要集合
const loading = ref(false)
const classifying = ref(false)
const hasChanges = ref(false)
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 loadReasonGroups = async () => {
  showLoadingToast({
    message: '加载中...',
    forbidClick: true,
    duration: 0
  })
  
  loading.value = true
  
  try {
    // 获取所有未分类的分组，设置较大的pageSize以获取所有数据
    const res = await getReasonGroups(1, 20)
    if (res.success) {
      // 后端已经按数量排序，我们需要计算每个分组的总金额并重新排序
      // 但是后端DTO没有返回总金额，我们先按数量排序即可
      reasonGroups.value = res.data || []
      // 默认全选所有分组
      selectedReasons.value = new Set(reasonGroups.value.map(g => g.reason))
    } else {
      showToast(res.message || '加载失败')
    }
  } catch (error) {
    console.error('加载分组失败', error)
    showToast('加载失败')
  } finally {
    loading.value = false
    closeToast()
  }
}

// 切换分组选择状态
const toggleGroupSelection = (reason) => {
  if (selectedReasons.value.has(reason)) {
    selectedReasons.value.delete(reason)
  } else {
    selectedReasons.value.add(reason)
  }
  // 触发响应式更新
  selectedReasons.value = new Set(selectedReasons.value)
}

// 获取类型名称
const getTypeName = (type) => {
  const typeMap = {
    0: '支出',
    1: '收入',
    2: '不计收支'
  }
  return typeMap[type] || '未知'
}

// 获取类型对应的标签颜色
const getTypeColor = (type) => {
  const colorMap = {
    0: 'danger',    // 支出 - 红色
    1: 'success',   // 收入 - 绿色
    2: 'default'    // 不计收支 - 灰色
  }
  return colorMap[type] || 'default'
}

// 开始智能分类
const startClassify = async () => {
  // 获取所有选中分组的账单ID
  const idsToClassify = []
  for (const group of reasonGroups.value) {
    if (selectedReasons.value.has(group.reason)) {
      idsToClassify.push(...group.transactionIds)
    }
  }
  
  if (idsToClassify.length === 0) {
    showToast('请先选择要分类的账单组')
    return
  }

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

  classifying.value = true
  classifyBuffer.value = '' // 重置缓冲区
  
  // 用于存储分类结果的临时对象
  const classifyResults = new Map() // id -> {classify, type}
  
  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, classifyResults)
        }
      }
    }
  } catch (error) {
    console.error('智能分类失败', error)
    showToast(`分类失败: ${error.message}`)
  } finally {
    classifying.value = false
    classifyBuffer.value = ''
    closeToast()
  }
}

// 处理SSE事件
const handleSSEEvent = (eventType, data, classifyResults) => {
  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) {
          const jsonStr = classifyBuffer.value.substring(openBrace, closeBrace + 1)
          
          try {
            const result = JSON.parse(jsonStr)
            
            if (result.id) {
              // 存储分类结果
              classifyResults.set(result.id, {
                classify: result.classify || '',
                type: result.type !== undefined ? result.type : null
              })
              
              // 更新对应分组的显示状态
              for (const group of reasonGroups.value) {
                if (group.transactionIds.includes(result.id)) {
                  group.sampleClassify = result.classify || ''
                  if (result.type !== undefined && result.type !== null) {
                    group.sampleType = result.type
                  }
                  hasChanges.value = true
                  break
                }
              }
            }
          } catch (e) {
            console.error('JSON解析失败:', e)
          }
          
          classifyBuffer.value = classifyBuffer.value.substring(closeBrace + 1)
          startIndex = 0
        } else {
          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 = []
  for (const group of reasonGroups.value) {
    if (group.sampleClassify) {
      // 为该分组的所有账单添加分类
      for (const id of group.transactionIds) {
        itemsToUpdate.push({
          id: id,
          classify: group.sampleClassify,
          type: group.sampleType
        })
      }
    }
  }

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

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

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

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

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

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

/* 分组头部 */
.group-header {
  display: flex;
  align-items: center;
  gap: 8px;
}

.group-title {
  flex: 1;
  font-size: 15px;
  font-weight: 500;
  line-height: 1.4;
}

.group-info {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 4px;
  flex-wrap: wrap;
}

.count-text {
  font-size: 13px;
  color: #969799;
}

.amount-text {
  font-size: 14px;
  font-weight: 500;
  color: #ff976a;
}

/* 底部操作栏 */
.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;
}

/* 设置页面容器背景色 */
:deep(.van-nav-bar) {
  background: transparent !important;
}
</style>