<script setup lang="ts">
import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { Search, Service, ShoppingCart, Tickets } from '@element-plus/icons-vue'
import MohongCartPanel from '@/features/mohong/components/MohongCartPanel.vue'
import MohongProductCard from '@/features/mohong/components/MohongProductCard.vue'
import { useMohongCart } from '@/features/mohong/composables/useMohongCart'
import { ensureSupportChat } from '@/features/chats/api/chats'
import PayWaySelectDialog from '@/features/orders/components/PayWaySelectDialog.vue'
import type { PaymentPayWay } from '@/features/orders/api/orders'
import { useOrderPaymentCashier } from '@/features/orders/composables/useOrderPaymentCashier'
import { queryMohongPayment } from '@/features/mohong/api/mohong'
import {
  fetchMohongCategories,
  fetchMohongProducts,
  type MohongCategory,
  type MohongProduct,
} from '@/features/mohong/api/mohong'
import { useSessionStore } from '@/stores/session'
import { readError } from '@/shared/utils/error'

const router = useRouter()
const route = useRoute()
const session = useSessionStore()
const { totalCount: cartCount, openCart } = useMohongCart()
const supportLoading = ref(false)
const loading = ref(false)
const payWayDialogVisible = ref(false)
let payWayResolver: ((value: PaymentPayWay | null) => void) | null = null

const cashier = useOrderPaymentCashier({
  notifySuccess: msg => ElMessage.success(msg),
  notifyError: msg => ElMessage.error(msg),
  notifyInfo: msg => ElMessage.info(msg),
  notifyFallback: msg => ElMessage.warning(msg),
  paidMessage: '支付成功',
  pollIntervalMs: 3000,
  qrWidth: 240,
  queryPayment: queryMohongPayment,
})

function selectPayWay(): Promise<PaymentPayWay | null> {
  payWayDialogVisible.value = true
  return new Promise(resolve => {
    payWayResolver = resolve
  })
}
function choosePayWay(payWay: PaymentPayWay) {
  payWayResolver?.(payWay)
  payWayResolver = null
  payWayDialogVisible.value = false
}
function handlePayWayDialogClosed() {
  payWayResolver?.(null)
  payWayResolver = null
}
const loadingMore = ref(false)
const products = ref<MohongProduct[]>([])
const categories = ref<MohongCategory[]>([])
const total = ref(0)
const page = ref(1)
const hasMore = ref(true)
const keyword = ref('')
const activeCategoryId = ref<number | null>(null)
const loadMoreSentinel = ref<HTMLElement | null>(null)
let searchTimer: ReturnType<typeof setTimeout> | null = null
let loadMoreObserver: IntersectionObserver | null = null

onMounted(async () => {
  await loadCategories()
  applyRouteQuery()
  await loadProducts(true)
  setupLoadMoreObserver()
})

onBeforeUnmount(() => {
  loadMoreObserver?.disconnect()
  loadMoreObserver = null
  if (searchTimer) clearTimeout(searchTimer)
})

watch(
  () => route.query,
  () => {
    applyRouteQuery()
    loadProducts(true)
  }
)

function applyRouteQuery() {
  const q = route.query
  keyword.value = typeof q.keyword === 'string' ? q.keyword : ''
  const cat = Number(q.category_id || 0)
  activeCategoryId.value = cat > 0 ? cat : null
}

async function loadCategories() {
  try {
    categories.value = await fetchMohongCategories()
    // 默认选中「大红」或第一个有商品的分类
    if (!activeCategoryId.value && categories.value.length) {
      const dahong = categories.value.find(c => c.name === '大红')
      const first = categories.value.find(c => c.product_count > 0) || categories.value[0]
      if (dahong || first) {
        activeCategoryId.value = (dahong || first)!.id
        syncQuery()
      }
    }
  } catch (error) {
    ElMessage.error(readError(error, '加载分类失败'))
  }
}

async function loadProducts(reset = true) {
  if (reset) {
    if (loading.value) return
    loading.value = true
    page.value = 1
    hasMore.value = true
  } else {
    if (loading.value || loadingMore.value || !hasMore.value) return
    loadingMore.value = true
  }
  try {
    const result = await fetchMohongProducts({
      page: page.value,
      page_size: 24,
      keyword: keyword.value.trim() || undefined,
      category_id: activeCategoryId.value || undefined,
    })
    const items = result.items || []
    products.value = reset ? items : [...products.value, ...items]
    total.value = result.total || 0
    hasMore.value = products.value.length < total.value
    page.value += 1
  } catch (error) {
    ElMessage.error(readError(error, '加载商品失败'))
  } finally {
    loading.value = false
    loadingMore.value = false
  }
}

function setupLoadMoreObserver() {
  loadMoreObserver?.disconnect()
  loadMoreObserver = new IntersectionObserver(
    entries => {
      if (!entries.some(item => item.isIntersecting)) return
      if (loading.value || loadingMore.value || !hasMore.value) return
      loadProducts(false)
    },
    { root: null, rootMargin: '200px 0px', threshold: 0 }
  )
  nextTick(() => {
    if (loadMoreSentinel.value) loadMoreObserver?.observe(loadMoreSentinel.value)
  })
}

watch(loadMoreSentinel, el => {
  loadMoreObserver?.disconnect()
  if (el) loadMoreObserver?.observe(el)
})

function selectCategory(id: number | null) {
  activeCategoryId.value = id
  syncQuery()
  loadProducts(true)
}

function onKeywordInput() {
  if (searchTimer) clearTimeout(searchTimer)
  searchTimer = setTimeout(() => {
    syncQuery()
    loadProducts(true)
  }, 280)
}

function syncQuery() {
  const query: Record<string, string> = {}
  if (keyword.value.trim()) query.keyword = keyword.value.trim()
  if (activeCategoryId.value) query.category_id = String(activeCategoryId.value)
  router.replace({ path: '/crash', query })
}

const activeCategoryName = () => {
  if (!activeCategoryId.value) return '全部'
  return categories.value.find(c => c.id === activeCategoryId.value)?.name || '全部'
}

async function handleSupportClick() {
  if (!session.isLoggedIn) {
    router.push({ path: '/login', query: { redirect: route.fullPath } })
    return
  }
  if (supportLoading.value) return
  supportLoading.value = true
  try {
    const chat = await ensureSupportChat('crash')
    router.push(`/messages/${chat.id}`)
  } catch {
    ElMessage.error('联系客服失败，请稍后重试')
  } finally {
    supportLoading.value = false
  }
}
</script>

<template>
  <section class="mohong-pc-page">
    <header class="toolbar">
      <div class="title-block">
        <h1>撞车</h1>
        <span class="count">{{ total }} 件</span>
        <span class="tip">{{ activeCategoryName() }} · 支付后扫码联系客服</span>
      </div>
      <div class="actions">
        <div class="search-box">
          <el-icon><Search /></el-icon>
          <input
            v-model="keyword"
            type="search"
            placeholder="搜索商品名称"
            @input="onKeywordInput"
          />
        </div>
        <button type="button" class="toolbar-btn outline" @click="openCart">
          <el-icon><ShoppingCart /></el-icon>
          <span>购物车{{ cartCount > 0 ? `(${cartCount})` : '' }}</span>
        </button>
        <button type="button" class="toolbar-btn outline" @click="router.push('/orders')">
          <el-icon><Tickets /></el-icon>
          <span>我的订单</span>
        </button>
        <button
          type="button"
          class="toolbar-btn outline"
          :disabled="supportLoading"
          @click="handleSupportClick"
        >
          <el-icon><Service /></el-icon>
          <span>{{ supportLoading ? '接入中' : '联系客服' }}</span>
        </button>
        <button type="button" class="toolbar-btn outline" @click="router.push('/')">
          租号大厅
        </button>
      </div>
    </header>

    <div class="shop-layout">
      <aside class="cat-sidebar">
        <button
          type="button"
          class="cat-item"
          :class="{ active: !activeCategoryId }"
          @click="selectCategory(null)"
        >
          全部
        </button>
        <button
          v-for="cat in categories"
          :key="cat.id"
          type="button"
          class="cat-item"
          :class="{ active: activeCategoryId === cat.id }"
          @click="selectCategory(cat.id)"
        >
          <span>{{ cat.name }}</span>
          <em v-if="cat.product_count">{{ cat.product_count }}</em>
        </button>
      </aside>

      <div class="shop-main">
        <div v-if="!loading && products.length === 0" class="empty-state">
          <strong>暂无商品</strong>
          <span>试试切换分类或清空搜索关键词。</span>
        </div>
        <div v-else v-loading="loading" class="product-grid">
          <MohongProductCard v-for="item in products" :key="item.id" :product="item" />
        </div>
        <div
          v-if="products.length"
          ref="loadMoreSentinel"
          class="load-sentinel"
          aria-hidden="true"
        />
        <div v-if="loadingMore" class="load-state">
          <span class="loading-more">加载中...</span>
        </div>
        <div v-else-if="!loading && products.length && !hasMore" class="load-state">
          <span class="end">已经到底了</span>
        </div>
      </div>
    </div>

    <MohongCartPanel
      :select-pay-way="selectPayWay"
      :start-cashier="(payment, onPaid) => cashier.openPaymentCashier(payment, onPaid)"
    />
    <PayWaySelectDialog
      v-model="payWayDialogVisible"
      @choose="choosePayWay"
      @closed="handlePayWayDialogClosed"
    />
  </section>
</template>

<style scoped>
.mohong-pc-page {
  display: grid;
  gap: 14px;
  width: 100%;
}

.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  padding: 8px 0;
}

.title-block {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px 12px;
  min-width: 0;
}

.title-block h1 {
  margin: 0;
  color: #17233d;
  font-size: 20px;
  font-weight: 800;
}

.count {
  padding: 1px 8px;
  border-radius: 999px;
  background: #fff4ea;
  color: #ff6a00;
  font-size: 12px;
  font-weight: 700;
}

.tip {
  color: #8a94a6;
  font-size: 12px;
}

.actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.search-box {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 220px;
  height: 36px;
  padding: 0 12px;
  border: 1px solid #eef1f5;
  border-radius: 10px;
  background: #fff;
  color: #94a3b8;
  transition:
    border-color 0.2s,
    box-shadow 0.2s;
}

.search-box:focus-within {
  border-color: rgba(255, 106, 0, 0.45);
  box-shadow: 0 0 0 3px rgba(255, 106, 0, 0.08);
}

.search-box input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: #17233d;
  font-size: 13px;
}

/* 对齐顶栏客服/发布账号的主题按钮风格 */
.toolbar-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px;
  border-radius: 10px;
  border: 1px solid transparent;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.2s;
}

.toolbar-btn.outline {
  border-color: rgba(255, 106, 0, 0.32);
  background: #fff8f2;
  color: #ff6a00;
}

.toolbar-btn.outline:hover {
  border-color: #ff6a00;
  background: #fff3e8;
  box-shadow: 0 4px 12px rgba(255, 106, 0, 0.1);
  transform: translateY(-1px);
}

.shop-layout {
  display: grid;
  grid-template-columns: 140px minmax(0, 1fr);
  gap: 16px;
  align-items: start;
  min-height: 480px;
}

.cat-sidebar {
  position: sticky;
  top: 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 0;
  border-radius: 12px;
  background: #fff;
  border: 1px solid #eef1f5;
  overflow: hidden;
}

.cat-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  padding: 12px 14px;
  border: 0;
  border-left: 3px solid transparent;
  background: transparent;
  color: #52616f;
  font-size: 14px;
  text-align: left;
  cursor: pointer;
  transition:
    background 0.15s,
    color 0.15s,
    border-color 0.15s;
}

.cat-item:hover {
  background: #f8fafc;
  color: #17233d;
}

.cat-item.active {
  background: #fff7ed;
  border-left-color: #ff6a00;
  color: #ff6a00;
  font-weight: 700;
}

.cat-item em {
  font-style: normal;
  color: #b0b8c4;
  font-size: 12px;
  font-weight: 600;
}

.cat-item.active em {
  color: #ff9a4d;
}

.shop-main {
  min-width: 0;
}

.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 14px;
  width: 100%;
}

.product-grid :deep(.mohong-card) {
  justify-self: center;
}

.empty-state {
  display: grid;
  gap: 6px;
  justify-items: center;
  width: 100%;
  padding: 64px 20px;
  border-radius: 14px;
  border: 1px dashed #dbe3ee;
  background: #fff;
  color: #8a94a6;
}

.empty-state strong {
  color: #17233d;
}

.load-sentinel {
  width: 100%;
  height: 1px;
}

.load-state {
  display: flex;
  justify-content: center;
  width: 100%;
  padding: 12px 0 8px;
}

.loading-more,
.end {
  color: #b0b8c4;
  font-size: 12px;
}



@media (max-width: 900px) {
  .shop-layout {
    grid-template-columns: 1fr;
  }

  .cat-sidebar {
    position: static;
    flex-direction: row;
    overflow-x: auto;
    padding: 6px;
    gap: 4px;
  }

  .cat-item {
    flex: 0 0 auto;
    border-left: 0;
    border-radius: 8px;
    padding: 8px 12px;
    white-space: nowrap;
  }

  .cat-item.active {
    border-left-color: transparent;
  }

  .toolbar {
    flex-direction: column;
    align-items: stretch;
  }

  .search-box {
    width: 100%;
  }
}
</style>
