/* AI_CHANGELOG
| 日期 | Prompt | 变更 |
|------|--------|------|
| 2026-03-23 | 角色路由+页面权限守卫 | onShow 添加 checkPageAccess 权限守卫 |
*/
import { checkPageAccess, getVisibleBoardTabs } from '../../utils/auth-guard'
// CHANGE 2026-03-28 | P5 联调：Mock → 真实 API
import { fetchBoardCustomers } from '../../services/api'
import { initPageAiColor } from '../../utils/ai-color-manager'
import { nameToAvatarColor } from '../../utils/avatar-color'

export {}

/** 维度类型 → 卡片模板映射 */
type DimType = 'recall' | 'potential' | 'balance' | 'recharge' | 'recent' | 'spend60' | 'freq60' | 'loyal'

const DIMENSION_TO_DIM: Record<string, DimType> = {
  recall: 'recall',
  potential: 'potential',
  balance: 'balance',
  recharge: 'recharge',
  recent: 'recent',
  spend60: 'spend60',
  freq60: 'freq60',
  loyal: 'loyal',
}

const DIMENSION_OPTIONS = [
  { value: 'recall', text: '最应召回' },
  { value: 'potential', text: '最大消费潜力' },
  { value: 'balance', text: '最高余额' },
  { value: 'recharge', text: '最近充值' },
  { value: 'recent', text: '最近到店' },
  { value: 'spend60', text: '最高消费 近60天' },
  { value: 'freq60', text: '最频繁 近60天' },
  { value: 'loyal', text: '最专一 近90天' },
]

// CHANGE 2026-03-28 | P9 修复：value 改为数据库 category_code，与后端枚举一致。
// 与 board-coach SKILL_OPTIONS 保持同步（2026-03-20 已修正）。
const PROJECT_OPTIONS = [
  { value: 'ALL', text: '全部' },
  { value: 'BILLIARD', text: '🎱 中式/追分' },
  { value: 'SNOOKER', text: '斯诺克' },
  { value: 'MAHJONG', text: '🀄 麻将/棋牌' },
  { value: 'KTV', text: '🎤 团建/K歌' },
]

interface AssistantInfo {
  name: string
  cls: string       // assistant--assignee / assistant--abandoned / assistant--normal
  heartScore: number // 0-10，heart-icon 组件用
  badge?: string    // 跟 / 弃
  badgeCls?: string // assistant-badge--follow / assistant-badge--drop
}

interface CustomerItem {
  id: string
  name: string
  initial: string
  avatarCls: string
  // 召回维度
  idealDays: number
  elapsedDays: number
  overdueDays: number
  visits30d: number
  balance: string
  recallIndex: string
  // 消费潜力维度
  potentialTags: Array<{ text: string; theme: string }>
  spend30d: string
  avgVisits: string
  avgSpend: string
  // 余额维度
  lastVisit: string
  monthlyConsume: string
  availableMonths: string
  // 充值维度
  lastRecharge: string
  rechargeAmount: string
  recharges60d: string
  currentBalance: string
  // 消费60天
  spend60d: string
  visits60d: string
  highSpendTag: boolean
  // 频率60天
  avgInterval: string
  weeklyVisits: Array<{ val: number; pct: number }>
  // 专一度
  intimacy: string
  coachName: string
  coachRatio: string
  topCoachName: string
  topCoachHeart: number
  topCoachScore: string
  coachDetails: Array<{
    name: string
    cls: string
    heartScore: number
    badge?: string
    avgDuration: string
    serviceCount: string
    coachSpend: string
    relationIdx: number
  }>
  // 最近到店
  visitFreq: string
  daysAgo: number
  // 助教
  assistants: AssistantInfo[]
}

/** Mock 数据 — 2 个空字段骨架项，用于排查字段为空时的渲染表现 */
const MOCK_CUSTOMERS: CustomerItem[] = [
  {
    id: '', name: '', initial: '', avatarCls: '',
    idealDays: 0, elapsedDays: 0, overdueDays: 0,
    visits30d: 0, balance: '', recallIndex: '',
    potentialTags: [
      { text: '', theme: '' },
    ],
    spend30d: '', avgVisits: '', avgSpend: '',
    lastVisit: '', monthlyConsume: '', availableMonths: '',
    lastRecharge: '', rechargeAmount: '', recharges60d: '', currentBalance: '',
    spend60d: '', visits60d: '', highSpendTag: false,
    avgInterval: '', intimacy: '',
    topCoachName: '', topCoachHeart: 0, topCoachScore: '',
    coachDetails: [
      { name: '', cls: '', heartScore: 0, badge: '', avgDuration: '', serviceCount: '', coachSpend: '', relationIdx: 0 },
    ],
    weeklyVisits: [
      { val: 0, pct: 0 }, { val: 0, pct: 0 }, { val: 0, pct: 0 }, { val: 0, pct: 0 },
      { val: 0, pct: 0 }, { val: 0, pct: 0 }, { val: 0, pct: 0 }, { val: 0, pct: 0 },
    ], coachName: '', coachRatio: '',
    visitFreq: '',
    daysAgo: 0,
    assistants: [
      { name: '', cls: '', heartScore: 0, badge: '', badgeCls: '' },
    ],
  },
  {
    id: '', name: '', initial: '', avatarCls: '',
    idealDays: 0, elapsedDays: 0, overdueDays: 0,
    visits30d: 0, balance: '', recallIndex: '',
    potentialTags: [
      { text: '', theme: '' },
    ],
    spend30d: '', avgVisits: '', avgSpend: '',
    lastVisit: '', monthlyConsume: '', availableMonths: '',
    lastRecharge: '', rechargeAmount: '', recharges60d: '', currentBalance: '',
    spend60d: '', visits60d: '', highSpendTag: false,
    avgInterval: '', intimacy: '',
    topCoachName: '', topCoachHeart: 0, topCoachScore: '',
    coachDetails: [
      { name: '', cls: '', heartScore: 0, badge: '', avgDuration: '', serviceCount: '', coachSpend: '', relationIdx: 0 },
    ],
    weeklyVisits: [
      { val: 0, pct: 0 }, { val: 0, pct: 0 }, { val: 0, pct: 0 }, { val: 0, pct: 0 },
      { val: 0, pct: 0 }, { val: 0, pct: 0 }, { val: 0, pct: 0 }, { val: 0, pct: 0 },
    ], coachName: '', coachRatio: '',
    visitFreq: '',
    daysAgo: 0,
    assistants: [
      { name: '', cls: '', heartScore: 0, badge: '', badgeCls: '' },
    ],
  },
]

Page({
  data: {
    pageState: 'loading' as 'loading' | 'empty' | 'normal' | 'error',
    activeTab: 'customer' as 'finance' | 'customer' | 'coach',

    // CHANGE 2026-03-27 | 权限改造 W5：动态看板二级 tab
    boardTabs: [] as Array<{ key: string; label: string; active: boolean }>,

    selectedDimension: 'recall',
    dimensionOptions: DIMENSION_OPTIONS,
    selectedProject: 'ALL',
    projectOptions: PROJECT_OPTIONS,

    /** 当前维度类型，控制卡片模板 */
    dimType: 'recall' as DimType,

    customers: [] as CustomerItem[],
    allCustomers: [] as CustomerItem[],
    totalCount: 0,

    /** 分页状态 */
    currentPage: 1,
    pageSize: 20,
    hasMore: true,
    isLoadingMore: false,

    /** 筛选栏可见性 */
    filterBarVisible: true,
  },

  _lastScrollTop: 0,
  _scrollAcc: 0,
  _scrollDir: null as 'up' | 'down' | null,
  /** 请求代数计数器：切换维度/项目时递增，旧请求的响应到达后对比丢弃 */
  _loadGeneration: 0,

  onLoad() {
    this.loadData()
  },

  onShow() {
    // CHANGE 2026-03-27 | 权限改造 W5：checkPageAccess 完成后再刷新 boardTabs
    // checkPageAccess 内部会调用 /api/xcx/me 并同步 permissions 到 globalData
    checkPageAccess('pages/board-customer/board-customer').then((allowed) => {
      if (!allowed) return
      const TAB_LABELS: Record<string, string> = { finance: '财务', customer: '客户', coach: '助教' }
      const visibleKeys = getVisibleBoardTabs()
      this.setData({
        boardTabs: visibleKeys.map(k => ({ key: k, label: TAB_LABELS[k] || k, active: k === 'customer' })),
      })
    })
  },

  onPullDownRefresh() {
    this._loadGeneration++
    this.setData({ currentPage: 1, hasMore: true, customers: [], allCustomers: [] })
    this.loadData()
    setTimeout(() => wx.stopPullDownRefresh(), 500)
  },

  /** 滚动隐藏/显示筛选栏 */
  onPageScroll(e: { scrollTop: number }) {
    const y = e.scrollTop
    const delta = y - this._lastScrollTop
    this._lastScrollTop = y

    if (y <= 8) {
      if (!this.data.filterBarVisible) this.setData({ filterBarVisible: true })
      this._scrollAcc = 0
      this._scrollDir = null
      return
    }

    if (Math.abs(delta) <= 2) return
    const dir = delta > 0 ? 'down' : 'up'
    if (dir !== this._scrollDir) {
      this._scrollDir = dir
      this._scrollAcc = 0
    }
    this._scrollAcc += Math.abs(delta)

    const threshold = dir === 'up' ? 12 : 24
    if (this._scrollAcc < threshold) return

    const visible = dir === 'up'
    if (this.data.filterBarVisible !== visible) {
      this.setData({ filterBarVisible: visible })
    }
    this._scrollAcc = 0
  },

  // CHANGE 2026-03-28 | P5 联调：替换 Mock 为真实 API 调用
  // CHANGE 2026-03-29 | 懒加载：支持分页追加
  // CHANGE 2026-04-08 | 竞态修复：用 _loadGeneration 丢弃过时响应
  async loadData() {
    const gen = this._loadGeneration
    const page = this.data.currentPage
    const isFirstPage = page === 1

    if (isFirstPage) {
      this.setData({ pageState: 'loading' })
      wx.showLoading({ title: '加载中...', mask: true })
    } else {
      if (this.data.isLoadingMore) return
      this.setData({ isLoadingMore: true })
    }

    try {
      const res = await fetchBoardCustomers({
        dimension: this.data.selectedDimension,
        project: this.data.selectedProject,
        page,
        pageSize: this.data.pageSize,
      })
      // 竞态保护：响应到达时代数已变（用户切了维度/项目），丢弃本次结果
      if (gen !== this._loadGeneration) return
      const items = res.items
      if (isFirstPage && (!items || items.length === 0)) {
        this.setData({ pageState: 'empty', totalCount: 0, hasMore: false })
        return
      }
      // 非首页返回空数据，标记到底
      if (!isFirstPage && (!items || items.length === 0)) {
        this.setData({ hasMore: false })
        return
      }
      // 头像颜色 + 项目标签
      items.forEach((item: any) => {
        item.avatarCls = 'avatar-' + nameToAvatarColor(String(item.id))
        const PROJ_SHORT: Record<string, string> = { BILLIARD: '🎱', SNOOKER: '斯', MAHJONG: '🀄', KTV: '🎤' }
        const PROJ_CLS: Record<string, string> = { BILLIARD: 'skill--chinese', SNOOKER: 'skill--snooker', MAHJONG: 'skill--mahjong', KTV: 'skill--karaoke' }
        item.projectTags = (item.projects || []).map((p: string) => ({ text: PROJ_SHORT[p] || p, cls: PROJ_CLS[p] || '' }))
      })

      // 追加时按 id 去重，避免 wx:key 重复警告
      let merged: any[]
      if (isFirstPage) {
        merged = items
      } else {
        const existIds = new Set(this.data.customers.map((c: any) => c.id))
        const newItems = items.filter((c: any) => !existIds.has(c.id))
        merged = [...this.data.customers, ...newItems]
      }
      // items 不足一页 或 已达 total，标记到底
      const hasMore = items.length >= this.data.pageSize && merged.length < res.total

      this.setData({
        allCustomers: merged,
        customers: merged,
        totalCount: res.total,
        hasMore,
        pageState: 'normal',
      })
    } catch {
      if (isFirstPage) this.setData({ pageState: 'error' })
    } finally {
      if (isFirstPage) wx.hideLoading()
      this.setData({ isLoadingMore: false })
    }
  },

  /** 触底加载下一页 */
  onReachBottom() {
    if (!this.data.hasMore || this.data.isLoadingMore) return
    this.setData({ currentPage: this.data.currentPage + 1 })
    this.loadData()
  },

  onRetry() {
    this.loadData()
  },

  /** 看板 Tab 切换 — CHANGE 2026-03-29 | P1：redirectTo 替代 navigateTo */
  onTabChange(e: WechatMiniprogram.TouchEvent) {
    const tab = e.currentTarget.dataset.tab as string
    if (tab === 'customer') return
    const routes: Record<string, { url: string; isTab: boolean }> = {
      finance: { url: '/pages/board-finance/board-finance', isTab: true },
      customer: { url: '/pages/board-customer/board-customer', isTab: false },
      coach: { url: '/pages/board-coach/board-coach', isTab: false },
    }
    const route = routes[tab]
    if (!route) return
    if (route.isTab) { wx.switchTab({ url: route.url }) } else { wx.redirectTo({ url: route.url }) }
  },

  onDimensionChange(e: WechatMiniprogram.CustomEvent<{ value: string }>) {
    const val = e.detail.value
    this._loadGeneration++
    this.setData({
      selectedDimension: val,
      dimType: DIMENSION_TO_DIM[val] || 'recall',
      currentPage: 1, hasMore: true, customers: [], allCustomers: [],
    })
    this.loadData()
  },

  onProjectChange(e: WechatMiniprogram.CustomEvent<{ value: string }>) {
    this._loadGeneration++
    this.setData({ selectedProject: e.detail.value, currentPage: 1, hasMore: true, customers: [], allCustomers: [] })
    this.loadData()
  },

  onCustomerTap(e: WechatMiniprogram.TouchEvent) {
    const id = e.currentTarget.dataset.id as string
    wx.navigateTo({ url: '/pages/customer-detail/customer-detail?id=' + id })
  },
})
