<template>
  <view class="bill-list">
    <ErpSearchBar
      v-model="keyword"
      :placeholder="`搜索${module?.title || ''}`"
      @search="onSearch"
    />

    <!-- 单据状态筛选 -->
    <view v-if="module?.shape === 'bill'" class="status-filter">
      <view
        v-for="s in statusOptions"
        :key="String(s.value)"
        class="status-filter__item"
        :class="{ 'status-filter__item--active': statusFilter === s.value }"
        @click="onStatusChange(s.value)"
      >
        <text>{{ s.label }}</text>
      </view>
    </view>

    <!-- 列表 -->
    <ErpEmpty
      v-if="!state.loading && !state.records.length"
      :show-retry="state.error"
      @retry="refresh"
    />
    <ErpListItem
      v-for="(row, idx) in state.records"
      :key="(row as any).id ?? idx"
      :title="rowTitle(row)"
      :rows="rowRows(row)"
      :status-text="statusText(row)"
      :status-type="statusType(row)"
      @click="openDetail(row)"
    />
    <ErpLoadMore
      v-if="state.records.length"
      :status="moreStatus"
      @retry="loadMore"
    />
  </view>
</template>

<script setup lang="ts">
/**
 * 通用列表模板（props 驱动）：搜索 + 状态筛选 + 卡片列表 + 触底加载
 * 页面壳通过 ref 调用 refresh()/loadMore() 挂接 onPullDownRefresh/onReachBottom
 */
import { ref, reactive, computed, watch } from 'vue'
import { getModule, BILL_STATUS_TEXT, BILL_STATUS_TYPE, type ModuleConfig } from '@/modules/registry'
import { usePagedList } from '@/composables/usePagedList'
import { formatMoney, formatDateTime } from '@/utils/format'
import ErpSearchBar from '@/components/common/ErpSearchBar.vue'
import ErpEmpty from '@/components/common/ErpEmpty.vue'
import ErpListItem from '@/components/common/ErpListItem.vue'
import ErpLoadMore from '@/components/common/ErpLoadMore.vue'
import { moduleDetailPage } from '@/constants/routes'

const props = defineProps<{ moduleKey: string; initialStatus?: string }>()

const module = ref<ModuleConfig | null>(null)
const keyword = ref('')
const statusFilter = ref<number | null>(null)
let paged: ReturnType<typeof usePagedList> | null = null

// 模板渲染用响应式状态（initPaged 内与 usePagedList 同步）
const state = reactive({ records: [] as any[], loading: false, finished: false, error: false })

const statusOptions = [
  { label: '全部', value: null },
  { label: '未审核', value: 0 },
  { label: '已审核', value: 1 },
  { label: '已完成', value: 2 }
] as { label: string; value: number | null }[]

const moreStatus = computed(() => {
  if (state.error) return 'error'
  if (state.loading) return 'loading'
  if (state.finished) return 'nomore'
  return 'more'
})

watch(
  () => props.moduleKey,
  (key) => {
    if (!key) return
    const m = getModule(key)
    if (!m) {
      uni.showToast({ title: '未知模块', icon: 'none' })
      return
    }
    module.value = m
    uni.setNavigationBarTitle({ title: m.title })
    // 深链状态筛选（如工作台待办直达 ?status=0 → 未审核）
    const s = props.initialStatus
    statusFilter.value = s === undefined || s === '' ? null : Number(s)
    initPaged(m)
  },
  { immediate: true }
)

function initPaged(m: ModuleConfig) {
  paged = usePagedList({
    apiPrefix: m.apiPrefix,
    searchKey: m.searchKey,
    fixedQuery: statusFilter.value === null ? {} : { status: statusFilter.value }
  })
  // 同步响应式状态到模板
  watch(
    [paged.records, paged.loading, paged.finished, paged.error],
    ([records, loading, finished, error]) => {
      state.records = [...records]
      state.loading = loading
      state.finished = finished
      state.error = error
    },
    { immediate: true }
  )
  refresh()
}

function refresh() {
  return paged?.refresh()
}

function loadMore() {
  return paged?.loadMore()
}

function onSearch() {
  paged?.onSearchInput(keyword.value)
}

// 输入即搜（300ms 防抖在 usePagedList 内）
watch(keyword, (v) => {
  paged?.onSearchInput(v)
})

function onStatusChange(value: number | null) {
  statusFilter.value = value
  if (!paged) return
  paged.setFixedQuery(value === null ? { status: undefined } : { status: value })
}

function rowTitle(row: any): string {
  const m = module.value!
  if (m.shape === 'bill') return row.billNo || `${m.title} #${row.id}`
  if (m.shape === 'entity') return row.name || row.attributeName || row.nativeName || `${row.id}`
  return row.materialName || row.billNo || row.name || String(row.id ?? m.title)
}

function rowRows(row: any): { label: string; value?: string | number | null; strong?: boolean }[] {
  const m = module.value!
  if (m.shape === 'bill') {
    return [
      { label: '往来单位', value: row.organName || row.memberName || '-' },
      { label: '单据日期', value: row.operTime ? formatDateTime(row.operTime) : row.createTime ? formatDateTime(row.createTime) : '-' },
      {
        label: '金额',
        value:
          row.discountLastMoney != null
            ? formatMoney(row.discountLastMoney)
            : row.totalPrice != null
              ? formatMoney(row.totalPrice)
              : row.changeAmount != null
                ? formatMoney(row.changeAmount)
                : '-',
        strong: true
      }
    ]
  }
  if (m.shape === 'entity') {
    const rows: { label: string; value?: string | number | null }[] = []
    if (row.contacts || row.principal) rows.push({ label: '联系人', value: row.contacts || row.principal })
    if (row.phoneNum || row.telephone) rows.push({ label: '电话', value: row.phoneNum || row.telephone })
    if (row.depotType) rows.push({ label: '类型', value: row.depotType })
    if (row.address) rows.push({ label: '地址', value: row.address })
    if (row.remark) rows.push({ label: '备注', value: row.remark })
    if (!rows.length && row.enabled !== undefined) rows.push({ label: '状态', value: row.enabled === 1 ? '启用' : '停用' })
    return rows
  }
  // 报表：宽松展示前 3 个标量字段
  const rows: { label: string; value?: string | number | null; strong?: boolean }[] = []
  for (const [key, value] of Object.entries(row)) {
    if (rows.length >= 3) break
    if (['id', 'createTime', 'updateTime', 'pageNo', 'pageSize'].includes(key)) continue
    if (value === null || value === undefined || typeof value === 'object') continue
    const strong = /amount|money|price/i.test(key)
    rows.push({
      label: key,
      value: typeof value === 'number' && strong ? formatMoney(value) : String(value),
      strong
    })
  }
  return rows
}

function statusText(row: any): string {
  if (module.value?.shape !== 'bill' || row.status === undefined || row.status === null) return ''
  return BILL_STATUS_TEXT[row.status] ?? ''
}

function statusType(row: any): 'warning' | 'success' | 'primary' | undefined {
  if (module.value?.shape !== 'bill' || row.status === undefined || row.status === null) return undefined
  return BILL_STATUS_TYPE[row.status]
}

function openDetail(row: any) {
  const m = module.value!
  if (m.listOnly) return
  uni.navigateTo({ url: `${moduleDetailPage(m.pkg)}?module=${m.key}&id=${row.id}` })
}

defineExpose({ refresh, loadMore })
</script>

<style lang="scss" scoped>
.bill-list {
  min-height: 100vh;
  background: #f2f5fa;
  padding-bottom: 40rpx;
}

.status-filter {
  display: flex;
  padding: 12rpx 24rpx;
  background: #fff;
  gap: 16rpx;

  &__item {
    padding: 8rpx 24rpx;
    border-radius: 24rpx;
    font-size: 24rpx;
    color: #606266;
    background: #f4f5f7;

    &--active {
      color: #fff;
      background: #2979ff;
    }
  }
}
</style>
