<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { GRADE_ORDER, parseStrategies, gradeRank } from '../types/demand'

type GradeFilter = 'all' | (typeof GRADE_ORDER)[number]

export type DemandGradeListCategoryOption = {
  categoryId: number
  categoryName: string
}

export type DemandGradeListCard = {
  id: number
  demand_name: string
  grade: string
  score: number | null
  reason: string | null
  strategies: string | null
  biz_dt: string
  categoryOptions: DemandGradeListCategoryOption[]
}

const props = defineProps<{
  demandCards: DemandGradeListCard[]
  selectedDemandId: number | null
  selectedCategoryId: number | null
}>()

const emit = defineEmits<{
  'select-demand': [payload: { demandId: number; defaultCategoryId: number | null }]
  'select-demand-category': [payload: { demandId: number; categoryId: number }]
}>()

const pageSizeOptions = [10, 20, 50, 100, 200]
const pageSize = ref<number>(10)
const page = ref<number>(1)
const gradeFilter = ref<GradeFilter>('all')

const gradeTabs = computed(() => [
  { key: 'all' as GradeFilter, label: '全部', count: props.demandCards.length },
  ...GRADE_ORDER.map((grade) => ({
    key: grade as GradeFilter,
    label: grade,
    count: gradeCounts.value[grade] ?? 0,
  })),
])

const gradeCounts = computed(() => {
  const counts = Object.fromEntries(GRADE_ORDER.map((g) => [g, 0])) as Record<
    (typeof GRADE_ORDER)[number],
    number
  >
  for (const card of props.demandCards) {
    const g = (card.grade || '').toUpperCase()
    if (g in counts) counts[g as (typeof GRADE_ORDER)[number]] += 1
  }
  return counts
})

const filteredCards = computed(() => {
  if (gradeFilter.value === 'all') return props.demandCards
  return props.demandCards.filter(
    (card) => (card.grade || '').toUpperCase() === gradeFilter.value,
  )
})

const sortedCards = computed(() => {
  const cards = [...filteredCards.value]
  cards.sort((a, b) => {
    const gr = gradeRank(a.grade) - gradeRank(b.grade)
    if (gr !== 0) return gr
    const sa = a.score ?? -Infinity
    const sb = b.score ?? -Infinity
    // Same grade: higher score first.
    if (sa !== sb) return sb - sa
    return a.demand_name.localeCompare(b.demand_name)
  })
  return cards
})

const total = computed(() => sortedCards.value.length)
const totalPages = computed(() => Math.max(1, Math.ceil(total.value / pageSize.value)))

const pagedCards = computed(() => {
  const p = Math.max(1, page.value)
  const start = (p - 1) * pageSize.value
  return sortedCards.value.slice(start, start + pageSize.value)
})

watch([total, pageSize, gradeFilter], () => {
  page.value = 1
})

function gradeClass(grade: string | null | undefined): string {
  const g = (grade || '').toUpperCase()
  return g ? `grade-${g}` : 'grade-none'
}

function onSelectDemand(card: DemandGradeListCard) {
  const defaultCategoryId = card.categoryOptions[0]?.categoryId ?? null
  emit('select-demand', { demandId: card.id, defaultCategoryId })
}

function onSelectCategory(card: DemandGradeListCard, categoryId: number) {
  emit('select-demand-category', { demandId: card.id, categoryId })
}

function isActiveDemand(cardId: number): boolean {
  return props.selectedDemandId === cardId
}

function isActiveCategory(cardId: number, categoryId: number): boolean {
  return props.selectedDemandId === cardId && props.selectedCategoryId === categoryId
}

const strategiesMax = 3
function slicedStrategies(card: DemandGradeListCard): string[] {
  const s = parseStrategies(card.strategies)
  return s.slice(0, strategiesMax)
}
</script>

<template>
  <aside class="demand-list">
    <header class="head">
      <div class="head-left">
        <h2 class="title">全部需求</h2>
        <span class="count" :title="`共 ${total} 条`">{{ total }}</span>
      </div>
      <div class="head-right" />
    </header>

    <div class="body">
      <div class="grade-bar">
        <div class="grade-tabs" role="tablist" aria-label="等级筛选">
          <button
            v-for="tab in gradeTabs"
            :key="tab.key"
            type="button"
            role="tab"
            class="grade-tab"
            :class="{ active: gradeFilter === tab.key }"
            :aria-selected="gradeFilter === tab.key"
            @click="gradeFilter = tab.key"
          >
            {{ tab.label }}
            <span class="grade-tab-count">{{ tab.count }}</span>
          </button>
        </div>
      </div>

      <div class="subbar">
        <label class="page-size">
          每页
          <select v-model.number="pageSize">
            <option v-for="n in pageSizeOptions" :key="n" :value="n">{{ n }}</option>
          </select>
          条
        </label>
      </div>

      <div v-if="!pagedCards.length" class="empty">
        {{ gradeFilter === 'all' ? '暂无需求数据' : `暂无 ${gradeFilter} 级需求` }}
      </div>

      <div v-else class="cards">
        <button
          v-for="card in pagedCards"
          :key="card.id"
          type="button"
          class="demand-card"
          :class="{ active: isActiveDemand(card.id) }"
          @click="onSelectDemand(card)"
        >
          <div class="demand-card-top">
            <span class="grade-badge" :class="gradeClass(card.grade)">{{ card.grade || '—' }}</span>
          </div>

          <div class="demand-name" :title="card.demand_name">{{ card.demand_name }}</div>

          <div v-if="card.reason" class="reason" :title="card.reason">
            {{ card.reason }}
          </div>

          <div v-if="slicedStrategies(card).length" class="strategies">
            <span class="strategies-label">策略</span>
            <span v-for="s in slicedStrategies(card)" :key="s" class="strategy-tag">
              {{ s }}
            </span>
          </div>

          <div v-if="card.categoryOptions.length" class="category-options">
            <span class="category-label">所属分类</span>
            <div class="category-tags">
              <button
                v-for="opt in card.categoryOptions"
                :key="opt.categoryId"
                type="button"
                class="category-tag"
                :class="{ active: isActiveCategory(card.id, opt.categoryId) }"
                @click.stop="onSelectCategory(card, opt.categoryId)"
                :title="opt.categoryName"
              >
                {{ opt.categoryName }}
              </button>
            </div>
          </div>
        </button>
      </div>

      <footer class="pager">
        <button type="button" class="pager-btn" :disabled="page <= 1" @click="page = page - 1">
          上一页
        </button>
        <span class="pager-info">
          第 {{ page }} / {{ totalPages }} 页
        </span>
        <button
          type="button"
          class="pager-btn"
          :disabled="page >= totalPages"
          @click="page = page + 1"
        >
          下一页
        </button>
      </footer>
    </div>
  </aside>
</template>

<style scoped>
.demand-list {
  height: 100%;
  min-height: 0;
  border: 1px solid #e2e8f0;
  border-radius: 10px;
  background: #fff;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-shrink: 0;
  padding: 10px 14px;
  border-bottom: 1px solid #e2e8f0;
  background: #f8fafc;
}

.head-left {
  display: flex;
  align-items: baseline;
  gap: 10px;
  min-width: 0;
}

.title {
  margin: 0;
  font-size: 14px;
  font-weight: 800;
  color: #0f172a;
}

.count {
  font-size: 14px;
  font-weight: 800;
  color: #1d4ed8;
  font-variant-numeric: tabular-nums;
}

.head-right {
  display: flex;
  align-items: center;
  gap: 8px;
}

.body {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.grade-bar {
  flex-shrink: 0;
  padding: 10px 14px;
  border-bottom: 1px solid #edf1f5;
  overflow-x: auto;
}

.grade-tabs {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 6px;
  min-width: min-content;
}

.grade-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 30px;
  padding: 0 10px;
  border: 1px solid #e2e8f0;
  border-radius: 999px;
  background: #fff;
  color: #475569;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
}

.grade-tab:hover {
  border-color: #93c5fd;
  background: #f8fafc;
  color: #0f172a;
}

.grade-tab.active {
  border-color: #2563eb;
  background: #2563eb;
  color: #fff;
}

.grade-tab-count {
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 999px;
  background: rgba(15, 23, 42, 0.08);
  color: inherit;
  font-size: 10px;
  font-weight: 800;
  line-height: 18px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

.grade-tab.active .grade-tab-count {
  background: rgba(255, 255, 255, 0.22);
}

.subbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid #edf1f5;
}


.page-size {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: #334155;
  font-size: 12px;
  flex-shrink: 0;
}

.page-size select {
  height: 26px;
  padding: 0 8px;
  border: 1px solid #cbd5e1;
  border-radius: 6px;
  background: #fff;
  font-size: 12px;
}

.empty {
  padding: 24px 14px;
  color: #94a3b8;
  font-size: 13px;
  text-align: center;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.cards {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.demand-card {
  text-align: left;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  background: #fff;
  padding: 12px 12px;
  cursor: pointer;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.demand-card:hover {
  border-color: #93c5fd;
  box-shadow: 0 3px 10px rgba(15, 23, 42, 0.08);
}

.demand-card.active {
  border-color: #2563eb;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.16);
}

.demand-card-top {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: space-between;
  margin-bottom: 6px;
}

.grade-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 32px;
  height: 22px;
  padding: 0 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.02em;
}

.grade-badge.grade-S {
  background: #fee2e2;
  color: #b91c1c;
}
.grade-badge.grade-A {
  background: #ffedd5;
  color: #c2410c;
}
.grade-badge.grade-B {
  background: #fef9c3;
  color: #a16207;
}
.grade-badge.grade-C {
  background: #e0f2fe;
  color: #0369a1;
}
.grade-badge.grade-D {
  background: #f1f5f9;
  color: #64748b;
}
.grade-badge.grade-none {
  background: #f1f5f9;
  color: #94a3b8;
}

.demand-name {
  font-size: 14px;
  font-weight: 900;
  color: #0f172a;
  line-height: 1.3;
  margin-bottom: 6px;
}

.reason {
  font-size: 12px;
  color: #475569;
  line-height: 1.5;
  word-break: break-word;
  white-space: pre-wrap;
  margin-bottom: 6px;
}

.strategies {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-bottom: 8px;
}

.strategies-label {
  font-size: 11px;
  color: #64748b;
  font-weight: 700;
  margin-right: 2px;
}

.strategy-tag {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 8px;
  border-radius: 999px;
  background: rgba(99, 102, 241, 0.12);
  color: #4338ca;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}

.category-options {
  margin-top: 2px;
}

.category-label {
  display: inline-block;
  font-size: 11px;
  font-weight: 900;
  color: #64748b;
  margin-bottom: 6px;
}

.category-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.category-tag {
  border: 1px solid #cbd5e1;
  background: #fff;
  color: #334155;
  font-size: 11px;
  font-weight: 800;
  padding: 5px 8px;
  border-radius: 999px;
  cursor: pointer;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.category-tag:hover {
  border-color: #93c5fd;
  background: #eff6ff;
}

.category-tag.active {
  border-color: #2563eb;
  background: #dbeafe;
  color: #1d4ed8;
}

.pager {
  flex-shrink: 0;
  border-top: 1px solid #edf1f5;
  padding: 10px 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.pager-btn {
  height: 30px;
  padding: 0 10px;
  border: 1px solid #cbd5e1;
  border-radius: 8px;
  background: #fff;
  color: #334155;
  font-size: 13px;
  cursor: pointer;
}

.pager-btn:disabled {
  cursor: not-allowed;
  opacity: 0.6;
}

.pager-info {
  color: #64748b;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
</style>

