<template>
  <div class="app-container live-statistics-panel-root">
    <el-alert
      v-if="trainingPeriodId"
      title="仅可选择当前营期下的直播间进行统计查询。"
      type="info"
      :closable="false"
      show-icon
      class="mb8"
    />
    <!-- 左上角：选择直播间（多选，最多展示8个，多余折叠）+ 查询按钮 -->
    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <div
          class="live-select-input"
          @click="openLiveSelectDialog">
          <div class="live-select-content">
            <template v-if="selectedLiveList.length === 0">
              <span class="placeholder">请选择直播间</span>
            </template>
            <template v-else>
              <template v-for="(item, idx) in displayedLives">
                <span :key="item.liveId" class="live-tag">{{ item.liveName }}（{{ item.liveId }}）</span>
                <span v-if="idx < displayedLives.length - 1 || selectedLiveList.length > 7" class="tag-sep">、</span>
              </template>
              <span v-if="selectedLiveList.length > 7" class="fold-text">等{{ selectedLiveList.length }}个</span>
            </template>
          </div>
          <div class="live-select-suffix">
            <i v-if="selectedLiveList.length > 0" class="el-icon-circle-close" @click.stop="handleClearLive"></i>
            <i class="el-icon-arrow-down"></i>
          </div>
        </div>
      </el-col>
      <el-col :span="1">
        <el-button
          type="primary"
          icon="el-icon-search"
          size="small"
          :loading="overviewLoading"
          :disabled="selectedLiveList.length === 0"
          @click="fetchOverview">
          查询
        </el-button>
      </el-col>
    </el-row>

    <el-card ref="statsCard" class="box-card" shadow="never">
      <div class="stats-main">
        <!-- 固定导航栏：滚动时固定在顶部 -->
        <div class="stats-nav-wrapper">
          <div v-if="navFixed" ref="statsNavSpacer" class="stats-nav-spacer" :style="{ height: navHeight + 'px' }"/>
          <div
            ref="statsNavBar"
            :class="['stats-nav-bar', { 'is-fixed': navFixed }]"
            :style="navFixed ? navFixedStyle : {}">
            <span
              v-for="item in navItems"
              :key="item.key"
              :class="['nav-item', { active: activeNav === item.key }]"
              @click="scrollToSection(item.key)">
              {{ item.label }}
            </span>
          </div>
        </div>
        <!-- 四个板块竖排展示，每个板块独立卡片样式 -->
        <el-card ref="sectionOverview" class="stats-section-card" shadow="never" data-section="overview">
          <div slot="header" class="section-title">数据概览</div>
          <div v-loading="overviewLoading" class="overview-content">
            <template >
              <!-- 直播数据 -->
              <div class="overview-block">
                <div class="overview-block-title">直播数据</div>
                <el-row :gutter="16" class="overview-grid">
                  <el-col :xs="24" :sm="12" :md="8" :lg="6" v-for="item in overviewItems" :key="item.key">
                    <div class="overview-item">
                      <div class="overview-label">{{ item.label }}</div>
                      <div class="overview-value">{{ formatOverviewValue(overviewData[item.key]) }}</div>
                    </div>
                  </el-col>
                </el-row>
              </div>
              <!-- 互动带货数据 -->
              <div class="overview-block">
                <div class="overview-block-title">互动带货数据</div>
                <el-row :gutter="16" class="overview-grid">
                  <el-col :xs="24" :sm="12" :md="8" :lg="6" v-for="item in interactionItems" :key="item.key">
                    <div class="overview-item">
                      <div class="overview-label">{{ item.label }}</div>
                      <div class="overview-value">{{ formatOverviewValue(overviewData[item.key]) }}</div>
                    </div>
                  </el-col>
                </el-row>
              </div>
            </template>
          </div>
        </el-card>
        <el-card ref="sectionTrend" class="stats-section-card" shadow="never" data-section="trend">
          <div slot="header" class="section-title">直播趋势</div>
          <div v-loading="trendLoading" class="trend-chart-wrap">
            <div  ref="trendChartRef" class="trend-chart"></div>
          </div>
        </el-card>
        <el-card ref="sectionStudent" class="stats-section-card" shadow="never" data-section="student">
          <div slot="header" class="section-title">直播间学员</div>
          <div class="student-section">
            <el-form :model="studentQueryParams" :inline="true" class="filter-form student-filter">
              <el-form-item label="直播名称">
                <el-select
                  v-model="studentQueryParams.liveIds"
                  multiple
                  collapse-tags
                  placeholder="不选则展示全部已选直播间"
                  size="small"
                  clearable
                  style="width: 280px;">
                  <el-option
                    v-for="item in selectedLiveList"
                    :key="item.liveId"
                    :label="item.liveName + '（' + item.liveId + '）'"
                    :value="item.liveId"/>
                </el-select>
              </el-form-item>
              <el-form-item label="首次访问时间">
                <el-date-picker
                  v-model="studentFirstEntryRange"
                  type="datetimerange"
                  range-separator="至"
                  start-placeholder="开始时间"
                  end-placeholder="结束时间"
                  value-format="yyyy-MM-dd HH:mm:ss"
                  size="small"
                  style="width: 340px;">
                </el-date-picker>
              </el-form-item>
              <el-form-item>
                <el-button type="primary" icon="el-icon-search" size="small" :loading="studentLoading" @click="fetchStudentList">查询</el-button>
                <el-button icon="el-icon-refresh" size="small" @click="resetStudentQuery">重置</el-button>
              </el-form-item>
            </el-form>
            <el-table
              v-loading="studentLoading"
              :data="studentList"
              border
              style="width: 100%">
              <el-table-column label="用户名" align="center" min-width="160">
                <template slot-scope="scope">
                  <div class="user-name-cell">
                    <el-avatar :size="28" :src="scope.row.avatar" icon="el-icon-user-solid"/>
                    <el-tooltip :content="scope.row.userName" placement="top">
                      <span class="user-name-text">{{ scope.row.userName && scope.row.userName.length > 8 ? scope.row.userName.substring(0, 8) + '...' : scope.row.userName }}</span>
                    </el-tooltip>
                  </div>
                </template>
              </el-table-column>
              <el-table-column label="直播间名称" align="center" prop="liveName" min-width="150" show-overflow-tooltip/>
              <el-table-column label="销售名称" align="center" prop="salesName" min-width="100" show-overflow-tooltip/>
              <el-table-column label="用户创建时间" align="center" prop="userCreateTime" width="170"/>
              <el-table-column label="联系方式" align="center" prop="contact" width="140"/>
            </el-table>
            <pagination
              v-show="studentTotal > 0"
              :total="studentTotal"
              :page.sync="studentQueryParams.pageNum"
              :limit.sync="studentQueryParams.pageSize"
              :auto-scroll="false"
              @pagination="fetchStudentList"
            />
          </div>
        </el-card>
        <el-card ref="sectionCompare" class="stats-section-card" shadow="never" data-section="compare">
          <div slot="header" class="section-title">数据对比</div>
          <div class="compare-tabs-wrap">
            <el-radio-group v-model="compareTab" size="small" class="compare-tabs">
              <el-radio-button label="invite">邀课对比</el-radio-button>
              <el-radio-button label="product">商品对比</el-radio-button>
            </el-radio-group>
            <!-- 邀课对比 -->
            <div v-show="compareTab === 'invite'" class="compare-panel">
              <el-form :model="inviteCompareQueryParams" :inline="true" class="filter-form">
                <el-form-item label="分享人">
                  <el-select
                    v-model="inviteCompareQueryParams.companyUserIds"
                    multiple
                    collapse-tags
                    placeholder="请选择分享人（需先选择直播间并查询）"
                    size="small"
                    clearable
                    style="width: 400px;">
                    <el-option
                      v-for="item in inviteSalesOptions"
                      :key="(item.companyId || '') + '_' + (item.companyUserId || '')"
                      :label="item.salesName + (item.companyName ? '（' + item.companyName + '）' : '')"
                      :value="(item.companyId || '') + '_' + (item.companyUserId || '')"/>
                  </el-select>
                </el-form-item>
                <el-form-item>
                  <el-button type="primary" icon="el-icon-search" size="small" :loading="inviteCompareLoading" @click="fetchInviteCompareList">查询</el-button>
                  <el-button icon="el-icon-refresh" size="small" @click="resetInviteCompareQuery">重置</el-button>
                </el-form-item>
              </el-form>
              <el-table
                v-loading="inviteCompareLoading"
                :data="inviteCompareList"
                border
                style="width: 100%">
                <el-table-column label="归属公司" align="center" prop="companyName" min-width="140" show-overflow-tooltip/>
                <el-table-column label="销售名称" align="center" prop="salesName" min-width="120" show-overflow-tooltip/>
                <el-table-column label="邀请人数" align="center" prop="inviteCount" width="120"/>
                <el-table-column label="已支付订单数" align="center" prop="paidOrderCount" width="140"/>
                <el-table-column label="订单总金额" align="center" prop="totalGmv" width="140">
                  <template slot-scope="scope">
                    {{ formatProductMoney(scope.row.totalGmv) }}
                  </template>
                </el-table-column>
              </el-table>
              <pagination
                v-show="inviteCompareTotal > 0"
                :total="inviteCompareTotal"
                :page.sync="inviteCompareQueryParams.pageNum"
                :limit.sync="inviteCompareQueryParams.pageSize"
                :auto-scroll="false"
                @pagination="fetchInviteCompareList"
              />
            </div>
            <!-- 商品对比 -->
            <div v-show="compareTab === 'product'" class="compare-panel">
              <el-form :model="productCompareQueryParams" :inline="true" class="filter-form">
                <el-form-item label="直播间带货的产品">
                  <el-select
                    v-model="productCompareQueryParams.productIds"
                    multiple
                    collapse-tags
                    placeholder="请选择商品（需先选择直播间并查询）"
                    size="small"
                    clearable
                    style="width: 400px;">
                    <el-option
                      v-for="item in liveProductOptions"
                      :key="item.productId"
                      :label="item.productName"
                      :value="item.productId"/>
                  </el-select>
                </el-form-item>
                <el-form-item>
                  <el-button type="primary" icon="el-icon-search" size="small" :loading="productCompareLoading" @click="fetchProductCompareList">查询</el-button>
                  <el-button icon="el-icon-refresh" size="small" @click="resetProductCompareQuery">重置</el-button>
                </el-form-item>
              </el-form>
              <el-table
                v-loading="productCompareLoading"
                :data="productCompareList"
                border
                style="width: 100%">
                <el-table-column label="商品名称" align="center" prop="productName" min-width="180" show-overflow-tooltip/>
                <el-table-column label="下单未支付人数" align="center" prop="unpaidUserCount" width="140"/>
                <el-table-column label="成交人数" align="center" prop="paidUserCount" width="120"/>
                <el-table-column label="成交金额" align="center" prop="totalGmv" width="140">
                  <template slot-scope="scope">
                    {{ formatProductMoney(scope.row.totalGmv) }}
                  </template>
                </el-table-column>
              </el-table>
              <pagination
                v-show="productCompareTotal > 0"
                :total="productCompareTotal"
                :page.sync="productCompareQueryParams.pageNum"
                :limit.sync="productCompareQueryParams.pageSize"
                :auto-scroll="false"
                @pagination="fetchProductCompareList"
              />
            </div>
          </div>
        </el-card>
      </div>
    </el-card>

    <!-- 选择直播间弹窗 -->
    <el-dialog
      title="选择直播间"
      :visible.sync="liveSelectDialogVisible"
      width="900px"
      append-to-body
      :close-on-click-modal="false"
      @open="handleDialogOpen"
      @close="handleDialogClose">
      <!-- 上面：筛选条件 -->
      <el-form :model="liveQueryParams" ref="liveQueryForm" :inline="true" label-width="100px" class="filter-form">
        <el-form-item label="直播名称" prop="liveName">
          <el-input
            v-model="liveQueryParams.liveName"
            placeholder="请输入直播名称"
            clearable
            size="small"
            style="width: 160px;"
            @keyup.enter.native="handleLiveSearch"/>
        </el-form-item>
        <el-form-item label="直播时间" prop="createTimeRange">
          <el-date-picker
            v-model="createTimeRange"
            type="datetimerange"
            range-separator="至"
            start-placeholder="开始时间"
            end-placeholder="结束时间"
            value-format="yyyy-MM-dd HH:mm:ss"
            size="small"
            style="width: 340px;">
          </el-date-picker>
        </el-form-item>
        <el-form-item v-if="!trainingPeriodId" label="公司名称" prop="companyName">
          <el-input
            v-model="liveQueryParams.companyName"
            placeholder="请输入公司名称"
            clearable
            size="small"
            style="width: 160px;"
            @keyup.enter.native="handleLiveSearch"/>
        </el-form-item>
        <el-form-item label="直播状态" prop="status">
          <el-select v-model="liveQueryParams.status" placeholder="请选择" clearable size="small" style="width: 120px;">
            <el-option label="待直播" :value="1"></el-option>
            <el-option label="直播中" :value="2"></el-option>
            <el-option label="已结束" :value="3"></el-option>
            <el-option label="直播回放中" :value="4"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="el-icon-search" size="small" @click="handleLiveSearch">搜索</el-button>
          <el-button icon="el-icon-refresh" size="small" @click="resetLiveQuery">重置</el-button>
        </el-form-item>
      </el-form>

      <!-- 下面：展示列表（多选，支持翻页继续选择） -->
      <el-table
        ref="liveTable"
        v-loading="liveListLoading"
        :data="liveList"
        row-key="liveId"
        @selection-change="handleSelectionChange"
        border
        max-height="400">
        <el-table-column type="selection" width="55" align="center" reserve-selection />
        <el-table-column label="直播ID" align="center" prop="liveId" width="100"/>
        <el-table-column label="直播名称" align="center" prop="liveName" min-width="150" show-overflow-tooltip/>
        <el-table-column label="直播状态" align="center" prop="status" width="120">
          <template slot-scope="scope">
            <el-tag v-if="scope.row.status === 1" size="small">待直播</el-tag>
            <el-tag v-else-if="scope.row.status === 2" type="success" size="small">直播中</el-tag>
            <el-tag v-else-if="scope.row.status === 3" type="info" size="small">已结束</el-tag>
            <el-tag v-else-if="scope.row.status === 4" type="warning" size="small">直播回放中</el-tag>
            <span v-else>---</span>
          </template>
        </el-table-column>
        <el-table-column label="直播公司" align="center" prop="companyName" min-width="120" show-overflow-tooltip>
          <template slot-scope="scope">
            {{ scope.row.companyName || '总台' }}
          </template>
        </el-table-column>
      </el-table>

      <pagination
        v-show="liveTotal > 0"
        :total="liveTotal"
        :page.sync="liveQueryParams.pageNum"
        :limit.sync="liveQueryParams.pageSize"
        @pagination="getLiveList"
      />

      <div slot="footer" class="dialog-footer">
        <span class="selected-count">已选 {{ selectedLiveList.length }}/15 个</span>
        <el-button @click="liveSelectDialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="confirmSelectLive">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import * as echarts from 'echarts'
import { listLive } from '@/api/live/live'
import { listTrainingLive } from '@/api/live/trainingCampAdmin'
import { getLiveStatisticsOverview, getLiveEntryTrend, listLiveRoomStudents, listProductCompareStats, listInviteSalesOptions, listInviteCompareStats } from '@/api/live/liveData'
import { listLiveGoods } from '@/api/live/liveGoods'

export default {
  name: 'LiveStatisticsPanel',
  props: {
    /** 若传入，则直播间选择范围仅限该营期（训练营工作台） */
    trainingPeriodId: {
      type: [Number, String],
      default: null
    },
    /** 总后台营期统计必填：企业 ID（与 trainingCampAdmin 接口一致） */
    trainingCampCompanyId: {
      type: [Number, String],
      default: null
    }
  },
  data() {
    return {
      // 已选择的直播间（多选）
      selectedLiveList: [],
      // 选择弹窗
      liveSelectDialogVisible: false,
      liveListLoading: false,
      liveList: [],
      liveTotal: 0,
      // 直播间查询参数
      liveQueryParams: {
        pageNum: 1,
        pageSize: 10,
        liveName: null,
        companyName: null,
        status: null,
        beginTime: null,
        endTime: null
      },
      // 创建时间范围（用于日期选择器双向绑定）
      createTimeRange: null,
      // 当前激活的导航
      activeNav: 'overview',
      // 导航配置
      navItems: [
        { key: 'overview', label: '数据概览' },
        { key: 'trend', label: '直播趋势' },
        { key: 'student', label: '直播间学员' },
        { key: 'compare', label: '数据对比' }
      ],
      // 导航栏固定
      navFixed: false,
      navHeight: 48,
      navFixedStyle: {},
      // 数据概览
      overviewData: {},
      overviewLoading: false,
      // 直播趋势折线图
      trendLoading: false,
      trendChartData: { xAxis: [], series: [] },
      trendChart: null,
      // 直播间学员
      studentList: [],
      studentTotal: 0,
      studentLoading: false,
      studentQueryParams: {
        liveIds: [],
        pageNum: 1,
        pageSize: 10
      },
      studentFirstEntryRange: null,
      // 数据对比切换 tab：invite=邀课对比，product=商品对比
      compareTab: 'invite',
      // 商品对比（嵌入数据对比）
      liveProductOptions: [],
      productCompareList: [],
      productCompareTotal: 0,
      productCompareLoading: false,
      productCompareQueryParams: {
        productIds: [],
        liveIds: [],
        pageNum: 1,
        pageSize: 10
      },
      // 邀课对比（嵌入数据对比）
      inviteSalesOptions: [],
      inviteCompareList: [],
      inviteCompareTotal: 0,
      inviteCompareLoading: false,
      inviteCompareQueryParams: {
        companyUserIds: [],
        pageNum: 1,
        pageSize: 10
      }
    }
  },
  computed: {
    overviewItems() {
      return [
        { key: 'beforeLiveUv', label: '开播前访问人数（uv）' },
        { key: 'totalWatchUv', label: '累计观看人数（uv）' },
        { key: 'over10MinCount', label: '停留时长超过10分钟人数' },
        { key: 'totalWatchMinutes', label: '总观看时长（分钟）' },
        { key: 'avgWatchMinutes', label: '平均观看时长（分钟）' },
        { key: 'replayWatchUv', label: '累计回放观看人数（uv）' },
        { key: 'replayVisitPv', label: '累计回放访问人数（pv）' },
        { key: 'replayOnlyCount', label: '仅看过回放的人数' },
        { key: 'replayTotalMinutes', label: '回放总观看时长（分钟）' },
        { key: 'replayAvgMinutes', label: '回放平均观看时长（分钟）' },
        { key: 'completeCount', label: '完课人数' },
        { key: 'subscribeCount', label: '预约人数' }
      ]
    },
    interactionItems() {
      return [
        { key: 'lotteryCount', label: '抽奖次数' },
        { key: 'lotteryJoinCount', label: '参与抽奖人数' },
        { key: 'lotteryWinCount', label: '中奖人数' },
        { key: 'paidUserCount', label: '支付点击人数' },
        { key: 'unpaidUserCount', label: '未支付人数' },
        { key: 'totalGmv', label: '总成交金额' },
        { key: 'totalProductQty', label: '商品总销量' }
      ]
    },
    headerOffset() {
      const fixed = this.$store.state.settings.fixedHeader
      const tagsView = this.$store.state.settings.tagsView
      if (fixed && tagsView) return 84
      if (fixed) return 50
      return 0
    },
    displayedLives() {
      return this.selectedLiveList.slice(0, 7)
    },
    hasTrendData() {
      return this.trendChartData.xAxis && this.trendChartData.xAxis.length > 0
    }
  },
  watch: {
    trainingPeriodId() {
      this.handleClearLive()
      if (this.liveSelectDialogVisible) {
        this.liveQueryParams.pageNum = 1
        this.getLiveList()
      }
    },
    trainingCampCompanyId() {
      this.handleClearLive()
      if (this.liveSelectDialogVisible) {
        this.liveQueryParams.pageNum = 1
        this.getLiveList()
      }
    }
  },
  mounted() {
    this.$nextTick(() => this.measureNavHeight())
    window.addEventListener('scroll', this.handleNavScroll, { passive: true })
    window.addEventListener('resize', this.handleNavScroll)
    window.addEventListener('resize', this.handleTrendChartResize)
    this.trendChartData = this.getDefaultTrendData()
    this.$nextTick(() => setTimeout(() => this.renderTrendChart(), 100))
  },
  beforeDestroy() {
    window.removeEventListener('scroll', this.handleNavScroll)
    window.removeEventListener('resize', this.handleNavScroll)
    window.removeEventListener('resize', this.handleTrendChartResize)
    if (this.trendChart) {
      this.trendChart.dispose()
      this.trendChart = null
    }
  },
  methods: {
    openLiveSelectDialog() {
      this.liveSelectDialogVisible = true
    },
    handleClearLive() {
      this.selectedLiveList = []
      this.studentList = []
      this.studentTotal = 0
      this.studentQueryParams.liveIds = []
      this.studentFirstEntryRange = null
      this.liveProductOptions = []
      this.productCompareList = []
      this.productCompareTotal = 0
      this.productCompareQueryParams.productIds = []
      if (this.trendChart) {
        this.trendChart.dispose()
        this.trendChart = null
      }
      this.trendChartData = { xAxis: [], series: [] }
      this.overviewData = {}
      this.$nextTick(() => {
        const table = this.$refs.liveTable
        if (table && typeof table.clearSelection === 'function') {
          table.clearSelection()
        }
        this.handleTrendChartResize()
      })
    },
    handleDialogOpen() {
      this.getLiveList()
    },
    handleDialogClose() {
      this.resetLiveQuery()
    },
    handleLiveSearch() {
      this.liveQueryParams.pageNum = 1
      this.getLiveList()
    },
    resetLiveQuery() {
      this.liveQueryParams = {
        pageNum: 1,
        pageSize: 10,
        liveName: null,
        companyName: null,
        status: null,
        beginTime: null,
        endTime: null
      }
      this.createTimeRange = null
    },
    getLiveList() {
      const params = { ...this.liveQueryParams }
      if (this.createTimeRange && this.createTimeRange.length === 2) {
        params.beginTime = this.createTimeRange[0]
        params.endTime = this.createTimeRange[1]
      }
      this.liveListLoading = true
      let req
      if (this.trainingPeriodId != null && this.trainingPeriodId !== '') {
        const q = { ...params, trainingPeriodId: Number(this.trainingPeriodId) }
        if (this.trainingCampCompanyId != null && this.trainingCampCompanyId !== '') {
          q.companyId = Number(this.trainingCampCompanyId)
        }
        req = listTrainingLive(q)
      } else {
        req = listLive(params)
      }
      req.then(res => {
        this.liveList = res.rows || []
        this.liveTotal = res.total || 0
        this.liveListLoading = false
        this.$nextTick(() => this.setTableSelection())
      }).catch(() => {
        this.liveListLoading = false
      })
    },
    handleSelectionChange(selection) {
      if (selection && selection.length > 15) {
        this.$message.warning('最多只能选择15个直播间')
        this.$nextTick(() => this.setTableSelection())
      } else {
        this.selectedLiveList = selection || []
      }
    },
    setTableSelection() {
      this.$nextTick(() => {
        const table = this.$refs.liveTable
        if (!table || !this.liveList.length) return
        const selectedIds = new Set(this.selectedLiveList.map(l => l.liveId))
        this.liveList.forEach(row => {
          table.toggleRowSelection(row, selectedIds.has(row.liveId))
        })
      })
    },
    confirmSelectLive() {
      this.liveSelectDialogVisible = false
      // 默认不选直播名称=展示全部已选直播间的人数
    },
    formatProductMoney(val) {
      if (val === undefined || val === null) return '¥0.00'
      const num = typeof val === 'number' ? val : parseFloat(val)
      return '¥' + (isNaN(num) ? '0.00' : num.toFixed(2))
    },
    fetchLiveProductsForSelectedLives() {
      const liveIds = (this.selectedLiveList || []).map(l => l.liveId)
      if (!liveIds.length) {
        this.liveProductOptions = []
        return
      }
      const promises = liveIds.map(liveId => listLiveGoods({ liveId }).then(res => (res.rows || res.data?.rows || [])))
      Promise.all(promises).then(results => {
        const productMap = new Map()
        results.flat().forEach(item => {
          const pid = item.productId
          if (pid && !productMap.has(pid)) {
            productMap.set(pid, { productId: pid, productName: item.productName || item.name || '未知商品' })
          }
        })
        this.liveProductOptions = Array.from(productMap.values())
      }).catch(() => {
        this.liveProductOptions = []
      })
    },
    fetchProductCompareList() {
      const liveIds = (this.selectedLiveList || []).map(l => l.liveId)
      if (!liveIds.length) {
        this.$message.warning('请先选择直播间')
        return
      }
      const params = {
        liveIds,
        productIds: this.productCompareQueryParams.productIds,
        pageNum: this.productCompareQueryParams.pageNum,
        pageSize: this.productCompareQueryParams.pageSize
      }
      this.productCompareLoading = true
      listProductCompareStats(params).then(res => {
        this.productCompareList = res.rows || res.data?.rows || []
        this.productCompareTotal = res.total || res.data?.total || 0
        this.productCompareLoading = false
      }).catch(() => {
        this.productCompareLoading = false
      })
    },
    resetProductCompareQuery() {
      this.productCompareQueryParams.productIds = []
      this.productCompareQueryParams.pageNum = 1
      this.productCompareQueryParams.pageSize = 10
      this.fetchProductCompareList()
    },
    fetchInviteSalesOptions() {
      const liveIds = (this.selectedLiveList || []).map(l => l.liveId)
      if (!liveIds.length) {
        this.inviteSalesOptions = []
        return
      }
      listInviteSalesOptions(liveIds).then(res => {
        const data = res.data || res || []
        this.inviteSalesOptions = Array.isArray(data) ? data : []
      }).catch(() => {
        this.inviteSalesOptions = []
      })
    },
    fetchInviteCompareList() {
      const liveIds = (this.selectedLiveList || []).map(l => l.liveId)
      if (!liveIds.length) {
        this.$message.warning('请先选择直播间')
        return
      }
      const rawIds = this.inviteCompareQueryParams.companyUserIds || []
      const companyUserIds = rawIds.map(v => {
        if (typeof v === 'string' && v.includes('_')) {
          return parseInt(v.split('_')[1], 10)
        }
        return typeof v === 'number' ? v : parseInt(v, 10)
      }).filter(id => !isNaN(id))
      const params = {
        liveIds,
        companyUserIds: companyUserIds.length ? companyUserIds : undefined,
        pageNum: this.inviteCompareQueryParams.pageNum,
        pageSize: this.inviteCompareQueryParams.pageSize
      }
      this.inviteCompareLoading = true
      listInviteCompareStats(params).then(res => {
        this.inviteCompareList = res.rows || res.data?.rows || []
        this.inviteCompareTotal = res.total || res.data?.total || 0
        this.inviteCompareLoading = false
      }).catch(() => {
        this.inviteCompareLoading = false
      })
    },
    resetInviteCompareQuery() {
      this.inviteCompareQueryParams.companyUserIds = []
      this.inviteCompareQueryParams.pageNum = 1
      this.inviteCompareQueryParams.pageSize = 10
      this.fetchInviteCompareList()
    },
    fetchOverview() {
      const liveIds = (this.selectedLiveList || []).map(l => l.liveId)
      if (!liveIds.length) {
        this.overviewData = {}
        this.trendChartData = { xAxis: [], series: [] }
        if (this.trendChart) {
          this.trendChart.dispose()
          this.trendChart = null
        }
        return
      }
      this.overviewLoading = true
      getLiveStatisticsOverview(liveIds).then(res => {
        this.overviewData = res.data || res || {}
        this.overviewLoading = false
        this.fetchTrend()
        // 直播间学员：默认不选直播名称，自动查询全部已选直播间的用户
        this.studentQueryParams.liveIds = []
        this.studentFirstEntryRange = null
        this.studentQueryParams.pageNum = 1
        this.fetchStudentList()
        // 商品对比：加载已选直播间的带货产品
        this.fetchLiveProductsForSelectedLives()
        // 邀课对比：加载已选直播间的分享人选项
        this.fetchInviteSalesOptions()
      }).catch(() => {
        this.overviewLoading = false
      })
    },
    fetchTrend() {
      const liveIds = (this.selectedLiveList || []).map(l => l.liveId)
      if (!liveIds.length) {
        this.trendChartData = this.getDefaultTrendData()
        this.$nextTick(() => {
          setTimeout(() => this.renderTrendChart(), 150)
        })
        return
      }
      this.trendLoading = true
      getLiveEntryTrend(liveIds).then(res => {
        // 兼容多种返回格式: { code, msg, data: { xAxis, series } } 或 { data: [series] } 或 { xAxis, series }
        const body = res && typeof res === 'object' && res.data !== undefined ? res.data : res
        let xAxis = []
        let series = []
        const dataObj = body && typeof body === 'object' ? body : null
        if (Array.isArray(body) && body.length > 0) {
          series = body
        } else if (dataObj && Array.isArray(dataObj.series) && dataObj.series.length > 0) {
          xAxis = Array.isArray(dataObj.xAxis) ? dataObj.xAxis : []
          series = dataObj.series
        } else if (dataObj && Array.isArray(dataObj.data) && dataObj.data.length > 0) {
          series = dataObj.data
        } else if (dataObj && Array.isArray(dataObj.rows) && dataObj.rows.length > 0) {
          series = dataObj.rows
        }
        series = Array.isArray(series) ? series : []
        if (series.length && (!Array.isArray(xAxis) || !xAxis.length) && series[0] && Array.isArray(series[0].data)) {
          const len = series[0].data.length
          xAxis = ['开播前']
          for (let m = 0; m < len - 1; m++) xAxis.push((m * 5) + 'min')
        }
        if (!series.length) {
          this.trendChartData = this.getDefaultTrendData()
        } else {
          if (!xAxis.length) xAxis = this.getDefaultTrendData().xAxis
          this.trendChartData = { xAxis, series }
        }
        this.trendLoading = false
        this.$nextTick(() => {
          setTimeout(() => {
            this.renderTrendChart()
            this.$nextTick(() => { if (this.trendChart) this.trendChart.resize() })
          }, 80)
        })
      }).catch(() => {
        this.trendChartData = this.getDefaultTrendData()
        this.trendLoading = false
        this.$nextTick(() => {
          setTimeout(() => {
            this.renderTrendChart()
            this.$nextTick(() => {
              if (this.trendChart) this.trendChart.resize()
            })
          }, 150)
        })
      })
    },
    getDefaultTrendData() {
      const xAxis = ['开播前']
      for (let m = 0; m <= 240; m += 5) {
        xAxis.push(m + 'min')
      }
      const zeros = xAxis.map(() => 0)
      return {
        xAxis,
        series: [{ name: '进入人数', data: zeros }]
      }
    },
    renderTrendChart() {
      const el = this.$refs.trendChartRef
      if (!el) return
      let xAxis = this.trendChartData.xAxis && Array.isArray(this.trendChartData.xAxis) ? this.trendChartData.xAxis : []
      const series = this.trendChartData.series && Array.isArray(this.trendChartData.series) ? this.trendChartData.series : []
      if (!series.length) return
      if (!xAxis.length && series[0] && series[0].data) {
        const len = series[0].data.length
        xAxis = ['开播前']
        for (let m = 0; m < len - 1; m++) xAxis.push((m * 5) + 'min')
      }
      if (!xAxis.length) xAxis = this.getDefaultTrendData().xAxis
      if (this.trendChart) this.trendChart.dispose()
      this.trendChart = echarts.init(el)
      const option = {
        title: { text: '相对直播开始时间的累计进入人数', left: 'center' },
        tooltip: { trigger: 'axis' },
        legend: { bottom: 0, type: 'scroll' },
        grid: { left: '3%', right: '4%', bottom: '15%', top: 40, containLabel: true },
        xAxis: { type: 'category', boundaryGap: false, data: xAxis },
        yAxis: { type: 'value', name: '累计进入人数' },
        series: series.map((s, i) => ({
          name: s.name,
          type: 'line',
          smooth: true,
          data: s.data || []
        }))
      }
      this.trendChart.setOption(option)
      this.$nextTick(() => {
        if (this.trendChart) this.trendChart.resize()
      })
    },
    handleTrendChartResize() {
      if (this.trendChart) this.trendChart.resize()
    },
    fetchStudentList() {
      const liveIds = this.studentQueryParams.liveIds && this.studentQueryParams.liveIds.length > 0
        ? this.studentQueryParams.liveIds
        : (this.selectedLiveList || []).map(l => l.liveId)
      if (!liveIds.length) {
        this.studentList = []
        this.studentTotal = 0
        return
      }
      const params = {
        liveIds,
        pageNum: this.studentQueryParams.pageNum || 1,
        pageSize: this.studentQueryParams.pageSize || 10
      }
      if (this.studentFirstEntryRange && this.studentFirstEntryRange.length === 2) {
        params.firstEntryTimeBegin = this.studentFirstEntryRange[0]
        params.firstEntryTimeEnd = this.studentFirstEntryRange[1]
      }
      this.studentLoading = true
      listLiveRoomStudents(params).then(res => {
        this.studentList = res.rows || []
        this.studentTotal = res.total || 0
        this.studentLoading = false
      }).catch(() => {
        this.studentLoading = false
      })
    },
    resetStudentQuery() {
      this.studentQueryParams.liveIds = []
      this.studentQueryParams.pageNum = 1
      this.studentQueryParams.pageSize = 10
      this.studentFirstEntryRange = null
      this.fetchStudentList()
    },
    formatOverviewValue(val) {
      if (val === undefined || val === null) return '0'
      if (typeof val === 'number' && !Number.isInteger(val)) return Number(val).toFixed(2)
      return String(val)
    },
    measureNavHeight() {
      const nav = this.$refs.statsNavBar
      if (nav) {
        this.navHeight = nav.offsetHeight || 48
      }
    },
    handleNavScroll() {
      const nav = this.$refs.statsNavBar
      const card = this.$refs.statsCard
      if (!nav || !card) return

      if (this.navFixed) {
        const spacer = this.$refs.statsNavSpacer
        if (spacer) {
          const rect = spacer.getBoundingClientRect()
          if (rect.top >= this.headerOffset) {
            this.navFixed = false
            this.navFixedStyle = {}
          }
        }
      } else {
        const rect = nav.getBoundingClientRect()
        if (rect.top <= this.headerOffset) {
          const cardRect = card.$el ? card.$el.getBoundingClientRect() : card.getBoundingClientRect()
          this.navFixedStyle = {
            left: cardRect.left + 'px',
            top: this.headerOffset + 'px',
            width: cardRect.width + 'px'
          }
          this.navFixed = true
        }
      }
    },
    scrollToSection(key) {
      this.activeNav = key
      const refMap = {
        overview: 'sectionOverview',
        trend: 'sectionTrend',
        student: 'sectionStudent',
        compare: 'sectionCompare'
      }
      const el = this.$refs[refMap[key]]
      if (el && el.$el) {
        el.$el.scrollIntoView({ behavior: 'smooth', block: 'start' })
      } else if (el) {
        el.scrollIntoView({ behavior: 'smooth', block: 'start' })
      }
    }
  }
}
</script>

<style scoped>
.live-select-input {
  display: flex;
  align-items: flex-start;
  width: 100%;
  min-width: 200px;
  min-height: 32px;
  padding: 6px 12px;
  border: 1px solid #DCDFE6;
  border-radius: 4px;
  cursor: pointer;
  background: #fff;
  overflow: hidden;
}
.live-select-input:hover {
  border-color: #C0C4CC;
}
.live-select-content {
  flex: 1;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  align-items: center;
  gap: 6px 8px;
  min-height: 22px;
  min-width: 0;
  overflow: hidden;
}
.live-select-content .placeholder {
  color: #C0C4CC;
  font-size: 14px;
}
.live-tag {
  display: inline-block;
  padding: 0 8px;
  height: 22px;
  line-height: 22px;
  font-size: 12px;
  color: #606266;
  background: #f4f4f5;
  border-radius: 4px;
}
.tag-sep {
  color: #909399;
  margin: 0 2px;
}
.fold-text {
  font-size: 12px;
  color: #909399;
}
.live-select-suffix {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-left: 10px;
}
.live-select-suffix i {
  color: #C0C4CC;
  font-size: 14px;
  cursor: pointer;
}
.live-select-suffix i:hover {
  color: #909399;
}
.stats-main {
  padding-top: 0;
}
.stats-nav-wrapper {
  position: relative;
}
.stats-nav-spacer {
  flex-shrink: 0;
}
.stats-nav-bar {
  position: relative;
  z-index: 100;
  display: flex;
  width: 100%;
  flex: 1 1 auto;
  background: #fff;
  border-bottom: 1px solid #ebeef5;
  margin: 0 -20px 20px -20px;
  padding: 0;
  box-shadow: 0 1px 2px rgba(0,0,0,0.03);
}
.stats-nav-bar.is-fixed {
  position: fixed;
  margin: 0;
  left: 0;
  right: 0;
  box-shadow: 0 2px 8px rgba(0,0,0,0.08);
}
.stats-nav-bar .nav-item {
  flex: 1;
  text-align: center;
  padding: 14px 12px;
  font-size: 14px;
  color: #606266;
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: all 0.2s;
}
.stats-nav-bar .nav-item:hover {
  color: #409EFF;
}
.stats-nav-bar .nav-item.active {
  color: #409EFF;
  font-weight: 500;
  border-bottom-color: #409EFF;
}
.overview-content {
  min-height: 120px;
}
.overview-grid {
  margin-top: 8px;
}
.overview-item {
  padding: 12px 16px;
  margin-bottom: 12px;
  background: #fafafa;
  border-radius: 4px;
  border-left: 3px solid #409EFF;
  border: 1px solid #ebeef5;
}
.overview-label {
  font-size: 13px;
  color: #909399;
  margin-bottom: 6px;
  line-height: 1.4;
}
.overview-value {
  font-size: 18px;
  font-weight: 600;
  color: #303133;
}
.overview-block {
  margin-bottom: 24px;
}
.overview-block:last-child {
  margin-bottom: 0;
}
.overview-block-title {
  font-size: 14px;
  font-weight: 600;
  color: #303133;
  margin-bottom: 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid #ebeef5;
}
.stats-section-card {
  margin-bottom: 30px;
  /* 固定导航时：顶部 84px + 导航栏 ~48px ≈ 132，留足空间避免遮挡 */
  scroll-margin-top: 140px;
}
.stats-section-card:last-child {
  margin-bottom: 0;
}
.stats-section {
  min-height: 300px;
  padding: 20px 0;
}
.stats-section .section-title {
  font-size: 16px;
  font-weight: 500;
  color: #303133;
  margin-bottom: 16px;
  padding-bottom: 12px;
  padding-left: 10px;
  border-bottom: 1px solid #ebeef5;
  border-left: 3px solid #67C23A;
}
.box-card {
  margin-bottom: 20px;
}
.filter-form {
  margin-bottom: 16px;
  padding-bottom: 16px;
  border-bottom: 1px solid #ebeef5;
}
.dialog-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
}
.dialog-footer .selected-count {
  margin-right: auto;
  font-size: 13px;
  color: #606266;
}
.trend-chart-wrap {
  min-height: 320px;
}
.trend-chart {
  width: 100%;
  height: 360px;
}
.student-section {
  min-height: 200px;
}
.student-filter {
  margin-bottom: 16px;
}
.user-name-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
}
.user-name-cell .user-name-text {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.overview-content {
  min-height: 120px;
}
.overview-grid {
  margin-top: 0;
}
.overview-item {
  padding: 12px 16px;
  margin-bottom: 12px;
  background: #fafafa;
  border-radius: 4px;
  border: 1px solid #ebeef5;
}
.overview-label {
  font-size: 13px;
  color: #909399;
  margin-bottom: 8px;
  line-height: 1.4;
}
.overview-value {
  font-size: 18px;
  font-weight: 600;
  color: #303133;
}
.compare-tabs-wrap {
  padding-top: 4px;
}
.compare-tabs {
  margin-bottom: 16px;
}
.compare-panel {
  min-height: 200px;
}
</style>
