<template>
  <div class="bill-list-component">
    <!-- 4.1 筛选栏 UI -->
    <div
      v-if="enableFilter"
      class="filter-bar"
    >
      <van-dropdown-menu active-color="#1989fa">
        <!-- 4.2 类型筛选 -->
        <van-dropdown-item
          v-model="selectedType"
          :options="typeOptions"
        />

        <!-- 4.3 分类筛选 -->
        <van-dropdown-item
          v-model="selectedCategory"
          :options="categoryOptions"
        />

        <!-- 4.4 日期范围筛选 -->
        <van-dropdown-item
          ref="dateDropdown"
          title="日期"
        >
          <van-cell-group inset>
            <van-cell
              :title="dateRangeText"
              is-link
              @click="showCalendar = true"
            />
          </van-cell-group>
          <div style="padding: 16px">
            <van-button
              block
              type="primary"
              @click="closeDateDropdown"
            >
              确定
            </van-button>
          </div>
        </van-dropdown-item>

        <!-- 4.5 排序功能 -->
        <van-dropdown-item
          v-model="sortBy"
          :options="sortOptions"
        />
      </van-dropdown-menu>

      <!-- 4.6 重置按钮 -->
      <van-button
        size="small"
        type="default"
        style="margin-top: 8px"
        @click="resetFilters"
      >
        重置筛选
      </van-button>
    </div>

    <!-- 4.4 日期选择弹出层 -->
    <van-calendar
      v-model:show="showCalendar"
      type="range"
      :min-date="new Date(2020, 0, 1)"
      :max-date="new Date(2030, 11, 31)"
      @confirm="onDateConfirm"
    />

    <!-- 账单列表 -->
    <van-list
      :loading="loading"
      :finished="finished"
      finished-text="没有更多了"
      @load="onLoad"
    >
      <van-cell-group
        v-if="displayTransactions && displayTransactions.length"
        inset
        style="margin-top: 10px"
      >
        <van-swipe-cell
          v-for="transaction in displayTransactions"
          :key="transaction.id"
          class="bill-item"
        >
          <div class="bill-row">
            <!-- 多选框 -->
            <van-checkbox
              v-if="showCheckbox"
              :model-value="isSelected(transaction.id)"
              class="checkbox-col"
              @update:model-value="toggleSelection(transaction)"
            />

            <!-- 账单卡片 -->
            <div
              class="bill-card"
              @click="handleClick(transaction)"
            >
              <!-- 5.1 左侧图标 -->
              <div
                class="card-icon"
                :style="{ backgroundColor: getIconBg(transaction.type) }"
              >
                <!-- 使用 Iconify 图标（格式：collection:name） -->
                <Icon
                  v-if="isIconifyFormat(getIconByClassify(transaction.classify))"
                  :icon-identifier="getIconByClassify(transaction.classify)"
                  :color="getIconColor(transaction.type)"
                  size="20"
                />
                <!-- 降级使用 Vant 图标 -->
                <van-icon
                  v-else
                  :name="getIconByClassify(transaction.classify)"
                  :color="getIconColor(transaction.type)"
                  size="20"
                />
              </div>

              <!-- 5.1 中间内容 -->
              <div class="card-content">
                <div class="card-title">
                  <span class="reason">{{ transaction.reason || '(无摘要)' }}</span>
                </div>
                <div class="card-info">
                  <!-- 5.6 时间格式化 -->
                  <span class="time">{{ formatTime(transaction.occurredAt) }}</span>
                  <!-- 5.5 分类标签 -->
                  <span
                    v-if="transaction.classify"
                    class="classify-tag"
                    :class="getClassifyTagClass(transaction.type)"
                  >
                    {{ transaction.classify }}
                  </span>
                </div>
              </div>

              <!-- 5.1 右侧金额 -->
              <div class="card-right">
                <div
                  class="amount"
                  :class="getAmountClass(transaction.type)"
                >
                  {{ formatAmount(transaction.amount, transaction.type) }}
                </div>
                <!-- 5.5 类型标签 -->
                <van-tag
                  :type="getTypeTagType(transaction.type)"
                  size="small"
                  class="type-tag"
                >
                  {{ getTypeName(transaction.type) }}
                </van-tag>
              </div>
            </div>
          </div>

          <!-- 删除按钮 -->
          <template
            v-if="showDelete"
            #right
          >
            <van-button
              square
              type="danger"
              text="删除"
              class="delete-button"
              @click="handleDeleteClick(transaction)"
            />
          </template>
        </van-swipe-cell>
      </van-cell-group>

      <!-- 空状态 -->
      <van-empty
        v-if="!loading && !(displayTransactions && displayTransactions.length)"
        description="暂无交易记录"
      />
    </van-list>
  </div>
</template>

<!--
/**
 * BillListComponent - 统一的账单列表组件
 *
 * @component
 * @description
 * 高内聚的账单列表组件，基于 v2 风格设计，支持筛选、排序、分页、左滑删除、多选等功能。
 * 可用于替代项目中的旧版 TransactionList 组件。
 *
 * @example
 * ```vue
 * <BillListComponent
 *   dataSource="api"
 *   :apiParams="{ type: 0, dateRange: ['2026-01-01', '2026-01-31'] }"
 *   :showDelete="true"
 *   :enableFilter="true"
 *   @click="handleBillClick"
 *   @delete="handleBillDelete"
 * />
 * ```
 *
 * @props
 * - dataSource?: 'api' | 'custom' - 数据源模式，默认 'api'
 * - apiParams?: { dateRange?, category?, type? } - API 模式的筛选参数
 * - transactions?: Array - 自定义数据源（dataSource='custom' 时使用）
 * - showDelete?: Boolean - 是否显示左滑删除，默认 true
 * - showCheckbox?: Boolean - 是否显示多选框，默认 false
 * - enableFilter?: Boolean - 是否启用筛选栏，默认 true
 * - enableSort?: Boolean - 是否启用排序，默认 true
 * - compact?: Boolean - 是否使用紧凑模式，默认 true
 * - selectedIds?: Set - 已选中的账单 ID 集合
 *
 * @emits
 * - load - 触发分页加载
 * - click - 点击账单卡片，参数: transaction
 * - delete - 删除账单成功，参数: id
 * - update:selectedIds - 多选状态变更，参数: Set<id>
 *
 * @author AI Assistant
 * @since 2026-02-15
 */
-->

<script setup>
import { ref, computed, watch, onMounted } from 'vue'
import { showConfirmDialog, showToast } from 'vant'
import { getTransactionList, deleteTransaction } from '@/api/transactionRecord'
import { getCategoryList } from '@/api/transactionCategory'
import Icon from '@/components/Icon.vue'

/**
 * @typedef {Object} Transaction
 * @property {number|string} id - 账单 ID
 * @property {string} reason - 摘要
 * @property {number} amount - 金额
 * @property {0|1|2} type - 类型：0=支出, 1=收入, 2=不计入
 * @property {string} [classify] - 分类
 * @property {string} occurredAt - 交易时间
 * @property {number} [balance] - 余额
 * @property {string} [importFrom] - 导入来源
 * @property {number} [upsetedType] - 修改后类型
 * @property {string} [upsetedClassify] - 修改后分类
 */

// Props 定义
const props = defineProps({
  dataSource: {
    type: String,
    default: 'api',
    validator: (value) => ['api', 'custom'].includes(value)
  },
  apiParams: {
    type: Object,
    default: () => ({})
  },
  transactions: {
    type: Array,
    default: () => []
  },
  showDelete: {
    type: Boolean,
    default: true
  },
  showCheckbox: {
    type: Boolean,
    default: false
  },
  enableFilter: {
    type: Boolean,
    default: true
  },
  enableSort: {
    type: Boolean,
    default: true
  },
  compact: {
    type: Boolean,
    default: true
  },
  selectedIds: {
    type: Set,
    default: () => new Set()
  }
})

// Emits 定义
const emit = defineEmits(['load', 'click', 'delete', 'update:selectedIds'])

// 响应式数据状态
const rawTransactions = ref([]) // API 或 custom 数据的原始数据
const loading = ref(false)
const finished = ref(false)
const page = ref(1)
const pageSize = ref(20)

// 分类列表及图标映射
const categories = ref([]) // 所有分类列表
const categoryIconMap = ref({}) // 分类名称 -> 图标的映射

// 筛选状态管理
const selectedType = ref(null) // null=全部, 0=支出, 1=收入, 2=不计入
const selectedCategory = ref(null) // null=全部
const dateRange = ref(null)
const sortBy = ref('time-desc')

// 4.1-4.5 筛选选项数据
const typeOptions = [
  { text: '全部类型', value: null },
  { text: '支出', value: 0 },
  { text: '收入', value: 1 },
  { text: '不计入收支', value: 2 }
]

const categoryOptions = ref([
  { text: '全部分类', value: null },
  { text: '餐饮', value: '餐饮' },
  { text: '购物', value: '购物' },
  { text: '交通', value: '交通' },
  { text: '娱乐', value: '娱乐' },
  { text: '医疗', value: '医疗' },
  { text: '工资', value: '工资' },
  { text: '红包', value: '红包' },
  { text: '其他', value: '其他' }
])

const sortOptions = [
  { text: '时间降序', value: 'time-desc' },
  { text: '时间升序', value: 'time-asc' },
  { text: '金额降序', value: 'amount-desc' },
  { text: '金额升序', value: 'amount-asc' }
]

// 4.4 日期选择相关
const showCalendar = ref(false)
const dateDropdown = ref(null)

const dateRangeText = computed(() => {
  if (!dateRange.value) {
    return '选择日期范围'
  }
  return `${dateRange.value[0]} 至 ${dateRange.value[1]}`
})

const onDateConfirm = (values) => {
  const [start, end] = values
  dateRange.value = [formatDateKey(start), formatDateKey(end)]
  showCalendar.value = false
}

const closeDateDropdown = () => {
  dateDropdown.value?.toggle()
}

const formatDateKey = (date) => {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  return `${year}-${month}-${day}`
}

// 4.6 重置筛选
const resetFilters = () => {
  selectedType.value = null
  selectedCategory.value = null
  dateRange.value = null
  sortBy.value = 'time-desc'
}

// 多选状态管理（本地状态，与 prop 同步）
const localSelectedIds = ref(new Set())

// 监听 props.selectedIds 变化，同步到本地状态
watch(
  () => props.selectedIds,
  (newIds) => {
    localSelectedIds.value = new Set(newIds)
  },
  { immediate: true }
)

// 数据源模式切换逻辑
const displayTransactions = computed(() => {
  let data = []

  // 2.1 根据 dataSource 选择数据源
  if (props.dataSource === 'custom') {
    data = props.transactions || []
  } else {
    data = rawTransactions.value
  }

  // 2.5 应用筛选逻辑
  let filtered = data

  // 类型筛选
  if (selectedType.value !== null) {
    filtered = filtered.filter((t) => t.type === selectedType.value)
  }

  // 分类筛选
  if (selectedCategory.value) {
    filtered = filtered.filter((t) => t.classify === selectedCategory.value)
  }

  // 日期范围筛选
  if (dateRange.value) {
    const [start, end] = dateRange.value
    filtered = filtered.filter((t) => {
      const date = new Date(t.occurredAt).toISOString().split('T')[0]
      return date >= start && date <= end
    })
  }

  // 2.5 应用排序逻辑
  const sorted = [...filtered]
  switch (sortBy.value) {
    case 'amount-desc':
      sorted.sort((a, b) => b.amount - a.amount)
      break
    case 'amount-asc':
      sorted.sort((a, b) => a.amount - b.amount)
      break
    case 'time-desc':
      sorted.sort((a, b) => new Date(b.occurredAt).getTime() - new Date(a.occurredAt).getTime())
      break
    case 'time-asc':
      sorted.sort((a, b) => new Date(a.occurredAt).getTime() - new Date(b.occurredAt).getTime())
      break
  }

  return sorted
})

// ========== 格式化和样式方法 ==========

// 5.3 根据分类获取图标
const getIconByClassify = (classify) => {
  // 优先使用从API加载的分类图标
  if (categoryIconMap.value[classify]) {
    return categoryIconMap.value[classify]
  }
  
  // 降级：使用本地映射（向后兼容）
  const iconMap = {
    餐饮: 'food-o',
    购物: 'shopping-cart-o',
    交通: 'logistics',
    娱乐: 'music-o',
    医疗: 'hospital-o',
    工资: 'balance-o',
    红包: 'envelop-o',
    其他: 'star-o'
  }
  return iconMap[classify || ''] || 'star-o'
}

// 判断是否为 Iconify 格式（collection:name）
const isIconifyFormat = (icon) => {
  return icon && icon.includes(':')
}

// 5.3 根据类型获取图标背景色
const getIconBg = (type) => {
  if (type === 0) {
    return '#FEE2E2'
  } // 支出 - 浅红色
  if (type === 1) {
    return '#D1FAE5'
  } // 收入 - 浅绿色
  return '#E5E7EB' // 不计入 - 灰色
}

// 5.3 根据类型获取图标颜色
const getIconColor = (type) => {
  if (type === 0) {
    return '#EF4444'
  } // 支出 - 红色
  if (type === 1) {
    return '#10B981'
  } // 收入 - 绿色
  return '#6B7280' // 不计入 - 灰色
}

// 5.4 格式化金额
const formatAmount = (amount, type) => {
  const formatted = `¥${Number(amount).toFixed(2)}`
  if (type === 0) {
    return `- ${formatted}`
  }
  if (type === 1) {
    return `+ ${formatted}`
  }
  return formatted
}

// 5.4 获取金额样式类
const getAmountClass = (type) => {
  if (type === 0) {
    return 'amount-expense'
  }
  if (type === 1) {
    return 'amount-income'
  }
  return 'amount-neutral'
}

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

// 5.5 获取类型标签类型
const getTypeTagType = (type) => {
  if (type === 0) {
    return 'danger'
  }
  if (type === 1) {
    return 'success'
  }
  return 'default'
}

// 5.5 获取分类标签样式类
const getClassifyTagClass = (type) => {
  if (type === 0) {
    return 'tag-expense'
  }
  if (type === 1) {
    return 'tag-income'
  }
  return 'tag-neutral'
}

// 5.6 格式化时间
const formatTime = (dateString) => {
  if (!dateString) {
    return ''
  }
  const date = new Date(dateString)
  const month = String(date.getMonth() + 1).padStart(2, '0')
  const day = String(date.getDate()).padStart(2, '0')
  const hours = String(date.getHours()).padStart(2, '0')
  const minutes = String(date.getMinutes()).padStart(2, '0')
  return `${month}-${day} ${hours}:${minutes}`
}

// ========== API 数据加载 ==========

// 3.2 初始加载逻辑
const fetchTransactions = async () => {
  if (props.dataSource !== 'api') {
    return
  }

  try {
    loading.value = true
    const params = {
      latestId:
        page.value === 1 ? undefined : rawTransactions.value[rawTransactions.value.length - 1]?.id
    }

    // 应用 apiParams 筛选
    if (props.apiParams?.type !== undefined) {
      selectedType.value = props.apiParams.type
    }
    if (props.apiParams?.category) {
      selectedCategory.value = props.apiParams.category
    }
    if (props.apiParams?.dateRange) {
      dateRange.value = props.apiParams.dateRange
    }

    const response = await getTransactionList(params)

    if (response && response.success) {
      const newData = response.data || []

      if (page.value === 1) {
        rawTransactions.value = newData
      } else {
        rawTransactions.value = [...rawTransactions.value, ...newData]
      }

      // 判断是否加载完成
      finished.value = newData.length < pageSize.value
    } else {
      showToast(response?.message || '加载失败')
      finished.value = true
    }
  } catch (error) {
    console.error('加载交易记录失败:', error)
    showToast('加载失败，请稍后重试')
    finished.value = true
  } finally {
    loading.value = false
  }
}

// 3.3 分页加载逻辑
const onLoad = () => {
  if (props.dataSource === 'api') {
    page.value++
    fetchTransactions()
  }
  emit('load')
}

// 3.4 筛选条件变更时的数据重载逻辑
const resetAndReload = () => {
  if (props.dataSource !== 'api') {
    return
  }

  page.value = 1
  rawTransactions.value = []
  finished.value = false
  fetchTransactions()
}

// 监听筛选条件变化
watch([selectedType, selectedCategory, dateRange, sortBy], () => {
  resetAndReload()
})

// 监听 apiParams 变化
watch(
  () => props.apiParams,
  () => {
    resetAndReload()
  },
  { deep: true }
)

// 加载分类列表及图标映射
const loadCategories = async () => {
  try {
    const response = await getCategoryList()
    if (response && response.success) {
      categories.value = response.data || []
      
      // 构建分类名称 -> 图标的映射
      const iconMap = {}
      categories.value.forEach(category => {
        if (category.name && category.icon) {
          iconMap[category.name] = category.icon
        }
      })
      categoryIconMap.value = iconMap
    }
  } catch (error) {
    console.error('加载分类列表失败:', error)
    // 静默失败，使用降级图标
  }
}

// 组件挂载时初始加载
onMounted(() => {
  // 加载分类列表（用于图标映射）
  loadCategories()
  
  if (props.dataSource === 'api') {
    fetchTransactions()
  }
})

// 临时实现：点击处理
const handleClick = (transaction) => {
  emit('click', transaction)
}

// 6.3-6.8 删除处理（完整实现）
const handleDeleteClick = async (transaction) => {
  try {
    await showConfirmDialog({
      title: '提示',
      message: '确定要删除这条交易记录吗？'
    })

    loading.value = true
    const response = await deleteTransaction(transaction.id)

    if (response && response.success) {
      showToast('删除成功')

      // 6.5 删除成功后更新本地列表
      rawTransactions.value = rawTransactions.value.filter((t) => t.id !== transaction.id)

      // 6.7 派发全局事件
      try {
        window.dispatchEvent(new CustomEvent('transaction-deleted', { detail: transaction.id }))
      } catch (e) {
        console.log('非浏览器环境，跳过派发 transaction-deleted 事件', e)
      }

      // 6.8 触发父组件事件
      emit('delete', transaction.id)
    } else {
      showToast(response?.message || '删除失败')
    }
  } catch (err) {
    if (err !== 'cancel') {
      console.error('删除出错:', err)
      showToast('删除失败')
    }
  } finally {
    loading.value = false
  }
}

// 临时实现：多选相关
const isSelected = (id) => {
  return localSelectedIds.value.has(id)
}

const toggleSelection = (transaction) => {
  const newSelectedIds = new Set(localSelectedIds.value)
  if (newSelectedIds.has(transaction.id)) {
    newSelectedIds.delete(transaction.id)
  } else {
    newSelectedIds.add(transaction.id)
  }
  localSelectedIds.value = newSelectedIds
  emit('update:selectedIds', newSelectedIds)
}
</script>

<style scoped lang="scss">
.bill-list-component {
  width: 100%;
}

.filter-bar {
  padding: 12px 16px;
  background-color: var(--van-background-2);
}

.bill-row {
  display: flex;
  align-items: center;
  width: 100%;
  overflow: hidden;
}

.checkbox-col {
  padding: 12px 8px;
  flex-shrink: 0;
}

// 5.1-5.2 账单卡片布局（紧凑模式）
.bill-card {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  cursor: pointer;
  transition: background-color 0.3s;
  flex: 1;
  min-width: 0;
  overflow: hidden;
  margin-top: 6px; // 5.2 紧凑间距
}

.bill-card:active {
  background-color: var(--van-active-color);
}

// 5.3 左侧图标
.card-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  flex-shrink: 0;
}

// 5.1 中间内容
.card-content {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
  min-width: 0;
  overflow: hidden;
}

.card-title {
  display: flex;
  align-items: center;
  gap: 8px;
}

.reason {
  font-size: 15px;
  font-weight: 500;
  color: var(--van-text-color);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.card-info {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  color: var(--van-text-color-2);
}

.time {
  flex-shrink: 0;
}

// 5.5 分类标签
.classify-tag {
  padding: 2px 8px;
  font-size: 11px;
  border-radius: 12px;
  flex-shrink: 0;
}

.tag-expense {
  background-color: rgba(239, 68, 68, 0.1);
  color: #ef4444;
}

.tag-income {
  background-color: rgba(16, 185, 129, 0.1);
  color: #10b981;
}

.tag-neutral {
  background-color: rgba(107, 114, 128, 0.1);
  color: #6b7280;
}

// 5.1 右侧金额区域
.card-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  flex-shrink: 0;
  min-width: 90px;
}

// 5.4 金额样式
.amount {
  font-size: 16px;
  font-weight: bold;
  white-space: nowrap;
}

.amount-expense {
  color: var(--van-danger-color);
}

.amount-income {
  color: var(--van-success-color);
}

.amount-neutral {
  color: var(--van-text-color-2);
}

// 5.5 类型标签
.type-tag {
  font-size: 11px;
}

.delete-button {
  height: 100%;
}

// 9.4 根据 compact prop 调整样式
.bill-list-component.comfortable {
  .bill-card {
    padding: 16px;
    margin-top: 10px;
  }

  .card-icon {
    width: 44px;
    height: 44px;
  }
}
</style>
