<template>
  <div class="jobs-page dflex">
    <SideNav />
    <div class="jobs-page__content">

      <div v-if="false" class="fs18 p20 bgeee">
        支付
        <iframe
            v-if="paymentFormHtml"
            :srcdoc="paymentFormHtml"
            frameborder="0"
            style="width: 100%; height: 600px;"
            scrolling="auto"
        ></iframe>
      </div>

      <!-- 页面标题 + Tab 切换 -->
      <JobPageHeader v-model:activeTab="activeTab" :favoriteCount="favoriteTotal" :applyCount="applyTotal" />
      <!-- 收藏统计栏 -->
      <div v-if="activeTab === 'collected'" class="jobs-page__filters-bar">
        <div class="jobs-page__fav-stats">
          <span class="jobs-page__fav-stats-item">有效（{{ favoriteValidCount }}）</span>
          <span class="jobs-page__fav-stats-item">失效（{{ favoriteInvalidCount }}）</span>
        </div>
      </div>
      <!-- 投递状态筛选栏 -->
      <div v-if="activeTab === 'applied'" class="jobs-page__filters-bar">
        <div class="jobs-page__fav-stats">
          <span
            v-for="tab in applyStatusTabs"
            :key="tab.status"
            class="jobs-page__fav-stats-item"
            :class="{ 'jobs-page__fav-stats-item--active': applyStatusFilter === tab.status }"
            @click="switchApplyStatus(tab.status)"
          >{{ tab.label }}（{{ tab.count }}）</span>
        </div>
      </div>
      <!-- 筛选条件 -->
      <div v-if="isRecommendTab" class="jobs-page__filters-bar">
        <div class="jobs-page__filters">
          <div class="jobs-page__filter-group">
            <!-- 筛选条件按钮列表（行业单独用组件） -->
            <template v-for="filter in filters" :key="filter.label">
              <!-- 城市筛选：使用地区选择组件（选到市级） -->
              <RegionSelector
                v-if="filter.key === 'city'"
                :regionCodes="selectedRegionCodes"
                :level="2"
                :maxSelect="3"
                @update:regionCodes="onRegionChange"
              />
              <!-- 岗位筛选：使用岗位选择组件 -->
              <JobCategorySelector
                v-else-if="filter.key === 'position'"
                :categoryIds="selectedCategoryIds"
                :maxSelect="3"
                :level="3"
                :allowParentSelect="true"
                @update:categoryIds="onCategoryChange"
              />
              <!-- 行业筛选：使用行业选择组件 -->
              <IndustrySelector
                v-else-if="filter.key === 'industry'"
                :industryIds="selectedIndustryIds"
                :maxSelect="3"
                :level="2"
                :allowParentSelect="true"
                @update:industryIds="onIndustryChange"
              />
              <!-- 其他筛选条件 -->
              <div
                v-else
                class="jobs-page__filter-item"
                @click="handleFilterClick(filter)"
              >
                <span>{{ filter.selected || filter.label }}</span>
                <svg class="jobs-page__filter-arrow-icon" viewBox="0 0 12 12" fill="none">
                  <path d="M3 4.5L6 7.5L9 4.5" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
                </svg>
                <!-- 工作类型下拉菜单 -->
                <div
                  v-if="filter.key === 'jobType' && showJobTypeDropdown"
                  class="jobs-page__filter-dropdown"
                  @click.stop
                >
                  <div
                    class="jobs-page__filter-dropdown-item"
                    v-for="option in jobTypeOptions"
                    :key="option.value"
                    :class="{ 'jobs-page__filter-dropdown-item--active': filter.selected === option.label }"
                    @click.stop="selectJobType(filter, option)"
                  >
                    {{ option.label }}
                  </div>
                </div>
              </div>
            </template>
          </div>
          <div class="jobs-page__search-box">
            <svg class="jobs-page__search-svg" viewBox="0 0 16 16" fill="none" @click="reloadFirstPage">
              <circle cx="7" cy="7" r="5.5" stroke="currentColor" stroke-width="1.2"/>
              <path d="M11 11L14 14" stroke="currentColor" stroke-width="1.2" stroke-linecap="round"/>
            </svg>
            <input
              v-model="keyword"
              class="jobs-page__search-input"
              placeholder="搜索职位、公司或关键词"
              @keyup.enter="reloadFirstPage"
            />
          </div>
        </div>
      </div>

      <!-- 职位列表 -->
      <div ref="jobListRef" v-loading="loading" class="jobs-page__list pr5" :style="restoring ? { visibility: 'hidden' } : {}" @scroll="onListScroll">
        <div
          v-for="(job, index) in jobList"
          :key="index"
          class="jobs-page__job-card"
          :class="{ 'jobs-page__job-card--selected--none': selectedIndex === index }"
          @click="goToDetail(job)"
        >
          <div class="jobs-page__job-main">
            <!-- 左侧：公司图标(后面一定要换成正式的公司logo) + 职位信息 -->
            <div class="jobs-page__job-left">
              <div class="dflex ">
                <div class="jobs-page__job-icon mr16">
                  <svg viewBox="0 0 24 24" fill="none" class="jobs-page__company-svg">
                    <rect x="3" y="7" width="18" height="14" rx="2" stroke="currentColor" stroke-width="1.5"/>
                    <path d="M7 7V5a2 2 0 012-2h6a2 2 0 012 2v2" stroke="currentColor" stroke-width="1.5"/>
                    <path d="M3 13h18" stroke="currentColor" stroke-width="1.5"/>
                    <rect x="10" y="11" width="4" height="4" rx="0.5" stroke="currentColor" stroke-width="1"/>
                  </svg>
                </div>
                <div class="jobs-page__job-info">
                  <div class="jobs-page__job-title-row">
                    <span class="jobs-page__job-name">{{ job.title }}</span>
                    <button v-if="isRecommendTab" class="jobs-page__job-more" aria-label="更多操作" @click.stop="toggleMenu(index)">
                      <svg viewBox="0 0 16 16" fill="currentColor" class="jobs-page__more-svg">
                        <circle cx="3" cy="8" r="1.5"/><circle cx="8" cy="8" r="1.5"/><circle cx="13" cy="8" r="1.5"/>
                      </svg>
                    </button>
                    <button v-if="activeTab === 'collected'" class="jobs-page__job-remove" aria-label="取消收藏" @click.stop="removeFavoriteFromList(job, index)">
                      <svg viewBox="0 0 16 16" fill="none" class="jobs-page__remove-svg">
                        <path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
                      </svg>
                    </button>
                  </div>
                  <div class="jobs-page__job-meta pt5">
                    <span>{{ job.regionName }}</span>
                    <span class="jobs-page__job-dot">·</span>
                    <span>{{ job.companyShortName || job.companyName }}</span>
                    <span class="jobs-page__job-dot">·</span>
                    <span>{{ job.categoryName }}</span>
                  </div>
                  <!-- 提示信息 -->
                  <div v-if="(job as any).tip" class="jobs-page__job-tip">
                    <svg viewBox="0 0 14 14" fill="none" class="jobs-page__tip-svg">
                      <circle cx="7" cy="7" r="6" stroke="currentColor" stroke-width="1"/>
                      <path d="M7 6.5V10" stroke="currentColor" stroke-width="1" stroke-linecap="round"/>
                      <circle cx="7" cy="4.5" r="0.5" fill="currentColor"/>
                    </svg>
                    {{ (job as any).tip }}
                  </div>


                </div>
              </div>
              <!-- 底部操作栏 -->
              <div class="jobs-page__job-actions pt20">
                <div class="dflex fgrow2 aliite-c flex-warp" >
                  <!-- 标签 -->
                  <div class="jobs-page__job-tags mt10">
                    <span v-for="(tag, ti) in job.tags" :key="ti" class="jobs-page__job-tag">{{ tag }}</span>
                  </div>
                  <div class="dflex-end mt10">
                    <div v-if="isRecommendTab" class="jobs-page__job-action-left">
                      <button class="jobs-page__action-icon-btn" aria-label="不感兴趣" @click.stop="openDislikeDialog(job)">
                        <svg viewBox="0 0 16 16" fill="none" class="jobs-page__action-svg">
                          <path d="M11.5 2.5l2 2L5 13H3v-2l8.5-8.5z" stroke="currentColor" stroke-width="1.2" stroke-linejoin="round"/>
                        </svg>
                      </button>
                      <button class="jobs-page__action-icon-btn" :class="{ 'jobs-page__action-icon-btn--liked': job.isFavorite }" aria-label="收藏" @click.stop="toggleFavorite(job)">
                        <svg viewBox="0 0 16 16" :fill="job.isFavorite ? 'currentColor' : 'none'" class="jobs-page__action-svg">
                          <path d="M8 13.7l-1.1-1C3.6 9.8 1.5 7.9 1.5 5.7 1.5 3.9 2.9 2.5 4.7 2.5c1 0 2 .5 2.6 1.2h1.4c.6-.7 1.6-1.2 2.6-1.2 1.8 0 3.2 1.4 3.2 3.2 0 2.2-2.1 4.1-5.4 6.9L8 13.7z" stroke="currentColor" stroke-width="1"/>
                        </svg>
                      </button>
                    </div>

                    <div class="jobs-page__job-action-right ">
                      <button class="jobs-page__job-helper ml5" @click.stop="askAssistant(job)">
                        <svg viewBox="0 0 14 14" fill="none" class="jobs-page__helper-svg">
                          <circle cx="7" cy="7" r="6" stroke="currentColor" stroke-width="1"/>
                          <path d="M5.5 5.5a1.5 1.5 0 113 0c0 .8-.7 1-1.5 1.5V9" stroke="currentColor" stroke-width="1" stroke-linecap="round"/>
                          <circle cx="7" cy="11" r="0.5" fill="currentColor"/>
                        </svg>
                        问助手
                      </button>
                      <button @click="handleReport(job.sourceUrl)" class="jobs-page__job-apply-btn" :class="{ 'jobs-page__job-apply-btn--active': job.applied }">
                        去投递
                      </button>
                    </div>
                  </div>
                </div>
                <!-- 弹出菜单 -->
                <div v-if="isRecommendTab && job.showMenu" class="jobs-page__job-popup" @click.stop>
                  <div
                      class="jobs-page__job-popup-item"
                      v-for="action in popupActions"
                      :key="action"
                      @click="handlePopupAction(action, job)"
                  >{{ action }}</div>
                </div>
              </div>


            </div>
            <!-- 右侧：匹配度 -->
            <div class="jobs-page__job-match" :class="isAuthenticated ? matchClass(job.matchScore) : 'jobs-page__job-match--locked'">
              <template v-if="isAuthenticated">
                <div class="jobs-page__match-ring">
                  <svg viewBox="0 0 80 80" class="jobs-page__ring-svg">
                    <circle cx="40" cy="40" r="34" stroke-width="5" stroke="#E8E8E8" fill="none" opacity="0.3"/>
                    <circle cx="40" cy="40" r="34" stroke-width="5" fill="none"
                      :stroke="job.matchScore >= 80 ? '#4FC2C9' : '#BFBFBF'"
                      stroke-linecap="round"
                      :stroke-dasharray="2 * Math.PI * 34"
                      :stroke-dashoffset="2 * Math.PI * 34 * (1 - job.matchScore / 100)"
                      transform="rotate(-90 40 40)"
                    />
                  </svg>
                  <div class="jobs-page__match-score">{{ job.matchScore }}%</div>
                </div>
                <div class="jobs-page__match-label">匹配值</div>
                <div class="jobs-page__match-level">{{ matchLevelText(job.matchScore) }}</div>
              </template>
              <template v-else>
                <svg class="jobs-page__lock-icon" viewBox="0 0 24 24" fill="none">
                  <rect x="5" y="11" width="14" height="10" rx="2" stroke="currentColor" stroke-width="1.5"/>
                  <path d="M8 11V7a4 4 0 118 0v4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
                </svg>
                <div class="jobs-page__match-lock-text">登录查看匹配值</div>
              </template>
            </div>
          </div>
        </div>
        <!-- 暂无数据提示 -->
        <div v-if="!loading && jobList.length === 0" class="jobs-page__empty">暂无数据</div>
        <!-- 加载更多提示 -->
        <div v-if="loadingMore" class="jobs-page__loading-more">加载中...</div>
        <div v-else-if="noMore && jobList.length > 0" class="jobs-page__loading-more">没有更多符合的职位了</div>
      </div>
    </div>
    <AiChat :jobId="currentAskJobId" />

    <!-- 职位不感兴趣反馈弹窗 -->
    <JobDislikeDialog ref="dislikeDialogRef" v-model="showDislikeDialog" :job-id="dislikeJobId" @disliked="removeDislikedJob" />

    <!-- 职位问题反馈弹窗 -->
    <JobFeedbackDialog ref="feedbackDialogRef" v-model="showFeedbackDialog" :job-id="feedbackJobId"  />

    <!-- 欢迎上传简历弹窗 -->
    <ProfileWelcomeDialog v-model="showWelcomeDialog" />
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onBeforeUnmount, nextTick, computed } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useStore } from 'vuex'
import SideNav from '@/components/SideNav.vue'
import AiChat from '@/components/AiChat.vue'
import JobPageHeader from '@/components/JobPageHeader.vue'
import JobDislikeDialog from '@/components/JobDislikeDialog.vue'
import JobFeedbackDialog from '@/components/JobFeedbackDialog.vue'
import IndustrySelector from '@/components/tools/IndustrySelector.vue'
import JobCategorySelector from '@/components/tools/JobCategorySelector.vue'
import RegionSelector from '@/components/tools/RegionSelector.vue'
import ProfileWelcomeDialog from '@/components/ProfileWelcomeDialog.vue'
import { fetchProfile } from '@/api/profile'
import { fetchJobList, fetchFavoriteList, toggleJobFavorite, removeJobFavorite, fetchFavoriteCount, fetchApplyList, fetchApplyCount, removeJobFromList } from '@/api/jobs'
import type { JobListItem, JobListParams, FavoriteListParams, ApplyListParams, ApplyCountData } from '@/api/jobs'


// 2. 注意：这里的字符串不需要再手动转义双引号了
const paymentFormHtml = ref(`
  <form name="punchout_form" method="post" action="https://openapi-sandbox.dl.alipaydev.com/gateway.do?charset=UTF-8&method=alipay.trade.page.pay&sign=o8MQ7cEAh4yrf6ri5iT9gXbtR%2BTncX36p9JNZf8nmXxEp1WKO6dF1HDC6DPF8nxJbus6OG9E5UPSoiHgqrEiu3aeOs4LMcYzXXZP0UQzG%2F6pXyZrvlL70G8uwpnV6MgQojzhKheG0vYIJgSPaGsHKjwcp%2BT8yOZg3eEDIgFYEBf2a3c7kANc7%2FuOOGCSD9Ip9zqwX9LQ3b433NPH3AbGQkFSLsdGOTY62I7yI8hEF7EM7nNm%2BYryieqju21yN76JrV4k%2BgIGHn83I5oT3y7zurzdTqHLD4UawpPWdJ5B7p6wnJ4cN4uzO8JgRpNqogYqqKBPcHIlB9o4uax3bcRqhg%3D%3D&notify_url=http%3A%2F%2F39.108.134.218%3A10106%2Fapi%2F%2Fpublic%2FalipayNotify%2Fpay&version=1.0&app_id=2018062160374941&sign_type=RSA2&timestamp=2026-05-20+15%3A29%3A21&alipay_sdk=alipay-sdk-java-4.40.791.ALL&format=json">
    <input type="hidden" name="biz_content" value='{"out_trade_no":"OP2057000709638877186","product_code":"FAST_INSTANT_TRADE_PAY","qr_pay_mode":"4","qrcode_width":200,"subject":"周会员","total_amount":"0.10"}'>
    <input type="submit" value="立即支付" style="display:none">
  </form>
  <script>document.forms[0].submit();<\/script>
`)

// ==================== 路由相关 ====================

const router = useRouter()
const route = useRoute()
const store = useStore()

/** 登录状态 — 从 store 读取 */
const isAuthenticated = computed(() => store.state.isAuthenticated)

/** 用户昵称 — 从全局 store 读取 */
const nickName = computed(() => store.state.userInfo?.nick || '')

// ==================== 页面状态 ====================

/** 当前激活的 Tab，从 URL query 参数读取，默认"推荐" */
const activeTab = ref((route.query.tab as string) || 'recommend')

/** 是否为推荐列表 Tab */
const isRecommendTab = computed(() => activeTab.value === 'recommend')

/** 搜索框输入内容 */
const keyword = ref('')

/** 当前选中的职位卡片索引 */
const selectedIndex = ref(0)

/** 不感兴趣弹窗的显示状态 */
const showDislikeDialog = ref(false)

/** 当前操作的职位 ID（用于提交不感兴趣反馈） */
const dislikeJobId = ref<string | null>(null)

/** 问题反馈弹窗的显示状态 */
const showFeedbackDialog = ref(false)

/** 当前操作的职位 ID（用于提交问题反馈） */
const feedbackJobId = ref<string | null>(null)

/** 当前问助手的岗位 ID（传给 AiChat 组件） */
const currentAskJobId = ref<string>('')

/** 欢迎弹窗的显示状态 */
const showWelcomeDialog = ref(false)

/** 点击"问助手"按钮，传入岗位 ID 给 AiChat */
function askAssistant(job: JobItem) {
  currentAskJobId.value = job.id
}

// ==================== 收藏统计 ====================

/** 收藏总数（用于 Tab 标签显示） */
const favoriteTotal = ref(0)

/** 有效收藏数 */
const favoriteValidCount = ref(0)

/** 失效收藏数 */
const favoriteInvalidCount = ref(0)

/** 加载收藏统计 */
async function loadFavoriteCount() {
  try {
    const res = await fetchFavoriteCount()
    if (res.code === '0' && res.data) {
      favoriteTotal.value = res.data.totalCount
      favoriteValidCount.value = res.data.validCount
      favoriteInvalidCount.value = res.data.invalidCount
    }
  } catch (e) {
    console.error('加载收藏统计失败', e)
  }
}

// ==================== 投递统计 ====================

/** 投递总数（用于 Tab 标签显示） */
const applyTotal = ref(0)

/** 投递统计详情 */
const applyCountData = ref<ApplyCountData>({
  totalCount: 0,
  appliedCount: 0,
  interviewingCount: 0,
  offerCount: 0,
  rejectedCount: 0,
  closedCount: 0,
})

/** 当前投递状态筛选（null=全部） */
const applyStatusFilter = ref<number | null>(null)

/** 投递状态 Tab 列表 */
const applyStatusTabs = computed(() => [
  { status: 0, label: '已投递', count: applyCountData.value.appliedCount },
  { status: 1, label: '面试中', count: applyCountData.value.interviewingCount },
  { status: 2, label: '有Offer', count: applyCountData.value.offerCount },
  { status: 3, label: '未通过', count: applyCountData.value.rejectedCount },
  { status: 4, label: '已结束', count: applyCountData.value.closedCount },
])

/** 切换投递状态筛选 */
function switchApplyStatus(status: number) {
  applyStatusFilter.value = applyStatusFilter.value === status ? null : status
  pageNum.value = 1
  hasNoMoreData.value = false
  jobList.value = []
  total.value = 0
  loadApplyList()
}

/** 加载投递统计 */
async function loadApplyCount() {
  try {
    const res = await fetchApplyCount()
    if (res.code === '0' && res.data) {
      applyCountData.value = res.data
      applyTotal.value = res.data.totalCount
    }
  } catch (e) {
    console.error('加载投递统计失败', e)
  }
}

// ==================== 常量数据 ====================

/** 筛选条件项类型 */
interface FilterItem {
  label: string
  key: string
  selected: string
}

/** 筛选条件列表 */
const filters = ref<FilterItem[]>([
  { label: '城市', key: 'city', selected: '' },
  { label: '岗位', key: 'position', selected: '' },
  { label: '行业', key: 'industry', selected: '' },
  { label: '工作类型', key: 'jobType', selected: '' },
])

/** 工作类型选项映射：label → 接口参数 employmentType（0=全职 1=实习） */
const jobTypeOptions: { label: string; value: number }[] = [
  { label: '全职', value: 0 },
  { label: '实习', value: 1 },
]

/** 工作类型下拉菜单是否显示 */
const showJobTypeDropdown = ref(false)

/** 当前选中的工作类型 — 直接读 store.jobIntention.employmentType */
const selectedEmploymentType = computed<number | null>(
  () => store.state.jobIntention.employmentType ?? null,
)

/** 选中的行业 id 数组 — 直接读 store.jobIntention.industryIds */
const selectedIndustryIds = computed<number[]>(
  () => store.state.jobIntention.industryIds || [],
)

/** 选中的岗位 id 数组 — 直接读 store.jobIntention.categoryIds */
const selectedCategoryIds = computed<number[]>(
  () => store.state.jobIntention.categoryIds || [],
)

/** 选中的地区编码数组 — 直接读 store.jobIntention.regionCodes */
const selectedRegionCodes = computed<string[]>(
  () => store.state.jobIntention.regionCodes || [],
)

/** 行业选择变更回调 */
function onIndustryChange(ids: number[]) {
  store.dispatch('saveJobIntention', {
    ...store.state.jobIntention,
    industryIds: ids,
  })
}

/** 岗位选择变更回调 */
function onCategoryChange(ids: number[]) {
  store.dispatch('saveJobIntention', {
    ...store.state.jobIntention,
    categoryIds: ids,
  })
}

/** 地区选择变更回调 */
function onRegionChange(codes: string[]) {
  store.dispatch('saveJobIntention', {
    ...store.state.jobIntention,
    regionCodes: codes,
  })
}

/** 点击筛选条件按钮 — 仅工作类型展开下拉 */
function handleFilterClick(filter: FilterItem) {
  if (filter.key === 'jobType') {
    showJobTypeDropdown.value = !showJobTypeDropdown.value
  }
}

/** 选中工作类型选项 */
function selectJobType(filter: FilterItem, option: { label: string; value: number }) {
  filter.selected = option.label
  showJobTypeDropdown.value = false
  store.dispatch('saveJobIntention', {
    ...store.state.jobIntention,
    employmentType: option.value,
  })
}

/** 监听 store 中 employmentType 变化，同步工作类型筛选按钮的显示文字 */
watch(selectedEmploymentType, (val) => {
  const jobTypeFilter = filters.value.find(f => f.key === 'jobType')
  if (jobTypeFilter && val !== null) {
    const matched = jobTypeOptions.find(o => o.value === val)
    if (matched) jobTypeFilter.selected = matched.label
  }
}, { immediate: true })

/** 点击页面其他区域时关闭下拉菜单 */
function closeDropdownOnClickOutside(e: MouseEvent) {
  const target = e.target as HTMLElement
  if (!target.closest('.jobs-page__filter-item')) {
    showJobTypeDropdown.value = false
  }
}

/** 跳转到原链接 */
function handleReport( url:string ) {
  if (url) {
    window.open(url, '_blank')
  }
}

onMounted(async () => {
  document.addEventListener('click', closeDropdownOnClickOutside)

  // 先判断是否有缓存（从详情页返回），在任何异步操作之前取出
  const cache = store.state.jobListCache
  const hasCache = !!(cache && cache.list.length > 0)

  if (hasCache) {
    // 立即恢复缓存数据，隐藏列表避免闪烁
    restoring.value = true
    jobList.value = cache!.list
    pageNum.value = cache!.pageNum
    total.value = cache!.total
    savedScrollTop = cache!.scrollTop
    // 清除缓存，避免下次非详情页返回时误用
    store.commit('SET_JOB_LIST_CACHE', null)
  }

  // 进入 Jobs 页时加载公共工具数据（行业分类等）
  store.dispatch('loadCommonData')

  // 仅登录状态下才加载需要鉴权的数据
  if (isAuthenticated.value) {
    // 加载用户个人信息到全局 store
    store.dispatch('loadUserInfo')

    // 检查个人资料是否存在，不存在则弹出欢迎弹窗
    // try {
    //   const profileRes = await fetchProfile()
    //   if (profileRes.code === '0' && (!profileRes.data || profileRes.data === null)) {
    //     showWelcomeDialog.value = true
    //   }
    // } catch {
    //   // 接口异常不阻塞页面加载
    // }

    // 加载收藏统计（用于 Tab 标签显示）
    loadFavoriteCount()

    // 加载投递统计（用于 Tab 标签显示）
    loadApplyCount()

    // 加载求职意向数据，computed 会自动反映到筛选条件
    await store.dispatch('loadJobIntention')
  }

  if (hasCache) {
    // 从详情页返回，恢复滚动位置后再显示列表
    nextTick(() => {
      if (jobListRef.value) {
        jobListRef.value.scrollTop = savedScrollTop
      }
      restoring.value = false
    })
  } else {
    // 没有缓存，正常加载
    loadCurrentTab()
  }

  // 初始化完成，允许 watcher 正常工作
  // 使用双重 nextTick 确保 loadJobIntention 引起的所有响应式更新都已 flush
  nextTick(() => {
    nextTick(() => {
      initializing = false
    })
  })
})

onBeforeUnmount(() => {
  document.removeEventListener('click', closeDropdownOnClickOutside)
})

/** 弹出菜单操作项 */
const popupActions = ['从列表中移除', '已投递', '复制链接']

// ==================== 职位列表项（扩展接口字段，增加前端交互状态） ====================

/** 职位列表项类型（在接口返回基础上扩展前端交互字段） */
interface JobItem extends JobListItem {
  /** 是否已投递 */
  applied: boolean
  /** 是否显示弹出菜单 */
  showMenu: boolean
}

// ==================== 分页与加载状态 ====================

/** 当前页码 */
const pageNum = ref(1)

/** 每页条数 */
const pageSize = ref(15)

/** 总记录数 */
const total = ref(0)

/** 是否正在加载（首次加载） */
const loading = ref(false)

/** 是否正在加载下一页 */
const loadingMore = ref(false)

/** 接口返回空列表时标记为无更多数据 */
const hasNoMoreData = ref(false)

/** 是否已加载全部数据 */
const noMore = computed(() => hasNoMoreData.value || (jobList.value.length >= total.value && total.value > 0))

/** 职位列表数据 */
const jobList = ref<JobItem[]>([])

/** 列表容器 ref，用于监听滚动和恢复滚动位置 */
const jobListRef = ref<HTMLElement | null>(null)

/** 记录离开页面前的滚动位置 */
let savedScrollTop = 0

/** 初始化标志 — onMounted 期间为 true，防止 watcher 误触发 reloadFirstPage */
let initializing = true

/** 恢复缓存中 — 为 true 时列表容器 visibility:hidden，避免滚动位置闪烁 */
const restoring = ref(false)
// ==================== 加载岗位列表 ====================

/** 组装请求参数 */
function buildParams(): JobListParams {
  const params: JobListParams = {
    pageNum: pageNum.value,
    pageSize: pageSize.value,
  }
  // 地区筛选
  if (selectedRegionCodes.value.length) {
    params.regionCodes = selectedRegionCodes.value
  }
  // 岗位类型筛选
  if (selectedCategoryIds.value.length) {
    params.categoryIds = selectedCategoryIds.value
  }
  // 行业筛选
  if (selectedIndustryIds.value.length) {
    params.industryIds = selectedIndustryIds.value
  }
  // 工作类型筛选
  if (selectedEmploymentType.value !== null) {
    params.employmentType = selectedEmploymentType.value
  }
  // 搜索关键词
  if (keyword.value.trim()) {
    params.keyword = keyword.value.trim()
  }
  return params
}

/** 加载岗位列表数据（首次加载，替换列表） */
async function loadJobList() {
  loading.value = true
  try {
    const res = await fetchJobList(buildParams())
    if (res.code === '0' && res.data) {
      // 将接口数据映射为前端 JobItem，补充交互状态字段
      jobList.value = res.data.list.map((item) => ({
        ...item,
        applied: false,
        showMenu: false,
      }))
      total.value = Number(res.data.total)
    }
  } catch (e) {
    console.error('加载岗位列表失败', e)
  } finally {
    loading.value = false
  }
}

/** 加载下一页数据（追加到列表末尾） */
async function loadNextPage() {
  if (loadingMore.value || noMore.value) return
  loadingMore.value = true
  pageNum.value++
  try {
    const res = await fetchJobList(buildParams())
    if (res.code === '0' && res.data) {
      const newItems = res.data.list.map((item) => ({
        ...item,
        applied: false,
        showMenu: false,
      }))
      // 返回空列表时标记无更多数据，停止滚动加载
      if (newItems.length === 0) {
        hasNoMoreData.value = true
        pageNum.value--
      } else {
        jobList.value.push(...newItems)
        total.value = Number(res.data.total)
      }
    }
  } catch (e) {
    // 加载失败时回退页码
    pageNum.value--
    console.error('加载下一页失败', e)
  } finally {
    loadingMore.value = false
  }
}

/** 列表滚动事件 — 滚动到底部时自动加载下一页 */
function onListScroll() {
  const el = jobListRef.value
  if (!el) return
  // 距离底部小于 100px 时触发加载
  const threshold = 100
  if (el.scrollHeight - el.scrollTop - el.clientHeight < threshold) {
    if (isRecommendTab.value) {
      loadNextPage()
    } else if (activeTab.value === 'collected') {
      loadFavoriteNextPage()
    } else if (activeTab.value === 'applied') {
      loadApplyNextPage()
    }
  }
}

/** 筛选条件变化时重置到第一页并重新加载 */
function reloadFirstPage() {
  pageNum.value = 1
  hasNoMoreData.value = false
  jobList.value = []
  total.value = 0
  // 筛选条件变化时清除缓存
  store.commit('SET_JOB_LIST_CACHE', null)
  loadCurrentTab()
}

/** 根据当前 Tab 加载对应列表 */
function loadCurrentTab() {
  if (isRecommendTab.value) {
    loadJobList()
  } else if (activeTab.value === 'collected') {
    loadFavoriteList()
  } else if (activeTab.value === 'applied') {
    loadApplyList()
  }
}

/** 加载收藏列表 */
async function loadFavoriteList() {
  loading.value = true
  try {
    const params: FavoriteListParams = {
      pageNum: pageNum.value,
      pageSize: pageSize.value,
      valid: true,
    }
    const res = await fetchFavoriteList(params)
    if (res.code === '0' && res.data) {
      jobList.value = res.data.list.map((item) => ({
        ...item,
        applied: false,
        showMenu: false,
      }))
      total.value = Number(res.data.total)
    }
  } catch (e) {
    console.error('加载收藏列表失败', e)
  } finally {
    loading.value = false
  }
}

/** 加载收藏列表下一页 */
async function loadFavoriteNextPage() {
  if (loadingMore.value || noMore.value) return
  loadingMore.value = true
  pageNum.value++
  try {
    const params: FavoriteListParams = {
      pageNum: pageNum.value,
      pageSize: pageSize.value,
      valid: true,
    }
    const res = await fetchFavoriteList(params)
    if (res.code === '0' && res.data) {
      const newItems = res.data.list.map((item) => ({
        ...item,
        applied: false,
        showMenu: false,
      }))
      // 返回空列表时标记无更多数据，停止滚动加载
      if (newItems.length === 0) {
        hasNoMoreData.value = true
        pageNum.value--
      } else {
        jobList.value.push(...newItems)
        total.value = Number(res.data.total)
      }
    }
  } catch (e) {
    pageNum.value--
    console.error('加载收藏列表下一页失败', e)
  } finally {
    loadingMore.value = false
  }
}

// ==================== 投递列表加载 ====================

/** 加载投递列表 */
async function loadApplyList() {
  loading.value = true
  try {
    const params: ApplyListParams = {
      pageNum: pageNum.value,
      pageSize: pageSize.value,
    }
    if (applyStatusFilter.value !== null) {
      params.status = applyStatusFilter.value
    }
    const res = await fetchApplyList(params)
    if (res.code === '0' && res.data) {
      jobList.value = res.data.list.map((item) => ({
        ...item,
        applied: true,
        showMenu: false,
      }))
      total.value = Number(res.data.total)
    }
  } catch (e) {
    console.error('加载投递列表失败', e)
  } finally {
    loading.value = false
  }
}

/** 加载投递列表下一页 */
async function loadApplyNextPage() {
  if (loadingMore.value || noMore.value) return
  loadingMore.value = true
  pageNum.value++
  try {
    const params: ApplyListParams = {
      pageNum: pageNum.value,
      pageSize: pageSize.value,
    }
    if (applyStatusFilter.value !== null) {
      params.status = applyStatusFilter.value
    }
    const res = await fetchApplyList(params)
    if (res.code === '0' && res.data) {
      const newItems = res.data.list.map((item) => ({
        ...item,
        applied: true,
        showMenu: false,
      }))
      // 返回空列表时标记无更多数据，停止滚动加载
      if (newItems.length === 0) {
        hasNoMoreData.value = true
        pageNum.value--
      } else {
        jobList.value.push(...newItems)
        total.value = Number(res.data.total)
      }
    }
  } catch (e) {
    pageNum.value--
    console.error('加载投递列表下一页失败', e)
  } finally {
    loadingMore.value = false
  }
}

// 监听筛选条件变化，自动重新加载
watch(
  [selectedRegionCodes, selectedCategoryIds, selectedIndustryIds, selectedEmploymentType],
  () => {
    // 初始化阶段（loadJobIntention 导致的变化）跳过，避免清掉缓存
    if (initializing) return
    reloadFirstPage()
  },
  { deep: true },
)

// 监听登录状态变化 — 登录成功后检查个人资料是否存在
watch(isAuthenticated, async (newVal, oldVal) => {
  if (newVal && !oldVal) {
    // 从未登录变为已登录，检查个人资料
    try {
      const profileRes = await fetchProfile()
      if (profileRes.code === '0' && (!profileRes.data || profileRes.data === null)) {
        showWelcomeDialog.value = true
      }
    } catch {
      // 接口异常不阻塞
    }
  }
})

// 监听 Tab 切换，重置列表状态并加载对应数据
watch(activeTab, (newTab, oldTab) => {
  if (initializing) return

  // 收藏和投递 Tab 需要登录
  if ((newTab === 'collected' || newTab === 'applied') && !isAuthenticated.value) {
    // 回退到之前的 Tab，弹登录框
    nextTick(() => { activeTab.value = oldTab })
    store.dispatch('openLogin')
    return
  }

  jobList.value = []
  keyword.value = ''
  pageNum.value = 1
  total.value = 0
  hasNoMoreData.value = false
  loadCurrentTab()
  // 切换到收藏 Tab 时刷新统计
  if (newTab === 'collected') {
    loadFavoriteCount()
  }
  // 切换到投递 Tab 时刷新统计并重置筛选
  if (newTab === 'applied') {
    applyStatusFilter.value = null
    loadApplyCount()
  }
})

// ==================== 事件处理 ====================

/** 切换职位卡片的弹出菜单（同时关闭其他已打开的菜单） */
function toggleMenu(index: number) {
  jobList.value.forEach((j, i) => {
    j.showMenu = i === index ? !j.showMenu : false
  })
}

/** 处理弹出菜单操作项点击 */
function handlePopupAction(action: string, job: JobItem) {
  job.showMenu = false
  if (action === '从列表中移除') {
    handleRemoveFromList(job)
  } else if (action === '复制链接') {
    handleCopyLink(job)
  } else if (action === '问题反馈') {
    openFeedbackDialog(job)
  }
}

/** 复制职位原链接到剪贴板 */
async function handleCopyLink(job: JobItem) {
  try {
    await navigator.clipboard.writeText(job.sourceUrl)
    ElMessage.success('复制链接成功')
  } catch {
    ElMessage.error('复制链接失败')
  }
}

/** 从推荐列表中移除职位（前端移除 + 预留接口调用） */
async function handleRemoveFromList(job: JobItem) {
  try {
    // TODO: 接口对接后此处会真正调用后端，当前为模拟成功
    const res = await removeJobFromList(job.id)
    if (res.code === '0') {
      const index = jobList.value.findIndex(j => j.id === job.id)
      if (index !== -1) {
        jobList.value.splice(index, 1)
        total.value = Math.max(0, total.value - 1)
      }
      ElMessage.success('已从列表中移除')
    }
  } catch (e) {
    console.error('移除职位失败', e)
  }
}

/** 根据匹配分数返回对应的 CSS 类名 */
function matchClass(score: number) {
  return score >= 80 ? 'jobs-page__job-match--high' : 'jobs-page__job-match--low'
}

/** 根据匹配分数返回匹配等级文案 */
function matchLevelText(score: number) {
  if (score >= 80) return '匹配'
  if (score >= 60) return '一般匹配'
  return '匹配度偏低'
}

/** 跳转到岗位详情页 — 未登录弹登录框，登录后再跳转 */
function goToDetail(job: JobItem) {
  if (!isAuthenticated.value) {
    store.dispatch('openLogin', `/jobs/${job.id}`)
    return
  }
  // 保存当前列表状态到 store，返回时恢复
  store.commit('SET_JOB_LIST_CACHE', {
    list: jobList.value,
    pageNum: pageNum.value,
    total: total.value,
    scrollTop: jobListRef.value?.scrollTop ?? 0,
  })
  router.push(`/jobs/${job.id}`)
}

/** 不感兴趣弹窗和问题反馈弹窗的组件引用 */
const dislikeDialogRef = ref<InstanceType<typeof JobDislikeDialog> | null>(null)
const feedbackDialogRef = ref<InstanceType<typeof JobFeedbackDialog> | null>(null)

/** 收藏/取消收藏岗位 */
async function toggleFavorite(job: JobItem) {
  try {
    const res = job.isFavorite
      ? await removeJobFavorite(job.id)
      : await toggleJobFavorite(job.id)
    if (res.code === '0') {
      const wasFavorite = job.isFavorite
      job.isFavorite = !job.isFavorite
      ElMessage.success(wasFavorite ? '已取消收藏' : '收藏成功')
      // 刷新收藏统计
      loadFavoriteCount()
    }
  } catch (e) {
    console.error('收藏操作失败', e)
  }
}

/** 收藏列表中取消收藏并移除该项 */
async function removeFavoriteFromList(job: JobItem, index: number) {
  try {
    const res = await removeJobFavorite(job.id)
    if (res.code === '0') {
      jobList.value.splice(index, 1)
      total.value = Math.max(0, total.value - 1)
      ElMessage.success('已取消收藏')
      loadFavoriteCount()
    }
  } catch (e) {
    console.error('取消收藏失败', e)
  }
}

/** 打开不感兴趣弹窗 — 记录当前职位 ID 并重置表单 */
function openDislikeDialog(job: JobItem) {
  dislikeJobId.value = job.id
  dislikeDialogRef.value?.resetForm()
  showDislikeDialog.value = true
}

/** 不感兴趣提交成功后，从列表中移除该职位 */
function removeDislikedJob() {
  if (!dislikeJobId.value) return
  const index = jobList.value.findIndex(j => j.id === dislikeJobId.value)
  if (index !== -1) {
    jobList.value.splice(index, 1)
    total.value = Math.max(0, total.value - 1)
  }
}

/** 打开问题反馈弹窗 — 记录当前职位 ID 并重置表单 */
function openFeedbackDialog(job: JobItem) {
  feedbackJobId.value = job.id
  feedbackDialogRef.value?.resetForm()
  showFeedbackDialog.value = true
}
</script>
