<template>
  <view class="page">
    <!-- 固定顶部导航栏 -->
    <AnalyticsTopBar 
      :title="'数据分析中心'"
      :lastUpdateTime="lastUpdateTime"
      :sidebarVisible="showSidebarMenu"
      @menu-click="handleMenu"
      @refresh="refreshAll"
      @search="handleSearch"
      @notification="handleNotification"
      @fullscreen="handleFullscreen"
      @mobile="handleMobile"
      @dropdown="handleDropdown"
      @settings="handleSettings"
    />
    
    <view class="page-layout">
      <!-- 侧边栏菜单组件 -->
      <AnalyticsSidebarMenu 
        :visible="showSidebarMenu" 
        :currentPath="currentPath"
        @visible-change="handleSidebarUpdate"
      />
      
      <!-- 主内容区域 -->
      <view class="main-content">
        <view class="container">
      <!-- KPI：宽屏 4列，窄屏 2列（增强版：渐变背景 + sparkline） -->
      <view class="kpi-grid">
        <view class="kpi-card kpi-card-gmv" @click="goToSalesReport">
          <view class="kpi-header">
            <text class="kpi-label">实时 GMV</text>
          </view>
          <text class="kpi-value">¥{{ formatMoney(realTime.gmv) }}</text>
          <view class="kpi-footer">
            <text class="kpi-meta">较昨日同刻</text>
            <text class="kpi-chip" :class="realTime.gmv_growth >= 0 ? 'pos' : 'neg'">
              {{ formatPct(realTime.gmv_growth) }}
            </text>
				</view>
        </view>
        <view class="kpi-card kpi-card-orders" @click="goToSalesReport">
          <view class="kpi-header">
            <text class="kpi-label">实时订单</text>
          </view>
          <text class="kpi-value">{{ formatInt(realTime.orders) }}</text>
          <view class="kpi-footer">
            <text class="kpi-meta">较昨日同刻</text>
            <text class="kpi-chip" :class="realTime.order_growth >= 0 ? 'pos' : 'neg'">
              {{ formatPct(realTime.order_growth) }}
            </text>
				</view>
        </view>
        <view class="kpi-card kpi-card-users" @click="goToUserAnalysis">
          <view class="kpi-header">
            <text class="kpi-label">在线用户</text>
          </view>
          <text class="kpi-value">{{ formatInt(realTime.online_users) }}</text>
          <view class="kpi-footer">
            <text class="kpi-meta">最近 5 分钟</text>
            <text class="kpi-chip neutral">实时</text>
				</view>
        </view>
        <view class="kpi-card kpi-card-conversion" @click="goToSalesReport">
          <view class="kpi-header">
            <text class="kpi-label">转化率</text>
          </view>
          <text class="kpi-value">{{ formatPct(realTime.conversion_rate) }}</text>
          <view class="kpi-footer">
            <text class="kpi-meta">较昨日同刻</text>
            <text class="kpi-chip" :class="realTime.conversion_growth >= 0 ? 'pos' : 'neg'">
              {{ formatPct(realTime.conversion_growth) }}
            </text>
				</view>
        </view>
		</view>

      <!-- 时间维度筛选（快捷 + 自定义） -->
      <view class="tabs">
        <view
          v-for="p in timePeriods"
          :key="p.value"
          class="tab"
          :class="{ active: selectedPeriod === p.value && !customRangeEnabled }"
          @click="selectPeriod(p.value)"
        >
          {{ p.label }}
			</view>
        <view
          class="tab"
          :class="{ active: customRangeEnabled }"
          @click="toggleCustomRange"
        >
          自定义
        </view>
		</view>

      <AnalyticsDateRangePicker
        v-if="customRangeEnabled"
        :initialStartDate="selectedStartDate"
        :initialEndDate="selectedEndDate"
        @apply="onDateRangeApply"
        @clear="onDateRangeClear"
      />

      <!-- 核心趋势：占满横向（柱+折 组合图） -->
      <view class="card card-full">
        <view class="card-head">
          <text class="card-title">核心趋势（GMV / 订单数）</text>
          <text class="card-desc">{{ selectedPeriodText }} · 柱：GMV（元） · 线：订单数</text>
				</view>
				
        <view v-if="loading || !trend.x || trend.x.length === 0" class="chart-loading">
          <text>{{ loading ? '加载中...' : '暂无数据' }}</text>
        </view>
        <view v-else style="width: 100%; height: 320px; position: relative; overflow: hidden; min-height: 320px;">
          <AnalyticsComboChart
            :xLabels="trend.x"
            :gmv="trend.gmv"
            :orders="trend.orders"
            :height="320"
            :key="'trend-' + trend.x.length + '-' + trend.gmv.length"
          />
        </view>
		</view>

      <!-- 用户结构和流量来源：横排显示 -->
      <view class="charts-row">
        <!-- 左侧：用户结构 -->
        <view class="charts-left card">
          <view class="card-head">
            <text class="card-title">用户结构（环形图）</text>
            <text class="card-desc">未消费 / 首购 / 复购 / 回流</text>
          </view>
          <view v-if="loading || !userSegmentOption || !userSegmentOption.series || (userSegmentOption.series && userSegmentOption.series.length === 0)" class="chart-loading">
            <text>{{ loading ? '加载中...' : '暂无数据' }}</text>
          </view>
          <view v-else class="chart-box">
            <EChartsView 
              :option="userSegmentOption" 
              :key="'user-segment-' + userSegments.length + '-' + (userSegmentOption?.series?.[0]?.data?.length || 0)" 
            />
          </view>
        </view>
        
        <!-- 右侧：流量来源 -->
        <view class="charts-right card">
          <view class="card-head">
            <text class="card-title">流量来源（条形）</text>
            <text class="card-desc">占比%</text>
          </view>
          <view v-if="loading || !trafficBarOption || !trafficBarOption.series || trafficBarOption.series.length === 0" class="chart-loading">
            <text>{{ loading ? '加载中...' : '暂无数据' }}</text>
          </view>
          <view v-else class="chart-box">
            <EChartsView 
              :option="trafficBarOption" 
              :key="'traffic-' + trafficSources.length + '-' + Date.now()" 
            />
          </view>
        </view>
      </view>

      <!-- 两个TOP排行：横排显示 -->
      <view class="tops-row">
        <!-- 左侧：热销商品TOP -->
        <view class="tops-left card">
          <view class="card-head">
            <text class="card-title">热销商品 TOP</text>
            <text class="card-desc">按销量</text>
          </view>
          <view class="rank-scroll-container">
            <view class="rank-scroll-wrapper" :class="{ 'has-scroll': topProducts.length >= 6 }">
              <view class="rank-list">
                <view v-for="p in topProducts" :key="p.id" class="rank-item">
                  <text class="rank-no">{{ p.rank }}</text>
                  <text class="rank-name">{{ p.name }}</text>
                  <text class="rank-val">{{ p.sales }} 件</text>
                </view>
                <!-- 循环播放：复制一份数据用于无缝滚动 -->
                <view v-if="topProducts.length >= 6" v-for="p in topProducts" :key="'copy-' + p.id" class="rank-item">
                  <text class="rank-no">{{ p.rank }}</text>
                  <text class="rank-name">{{ p.name }}</text>
                  <text class="rank-val">{{ p.sales }} 件</text>
                </view>
              </view>
            </view>
          </view>
        </view>

        <!-- 右侧：商家排行TOP -->
        <view class="tops-right card">
          <view class="card-head">
            <text class="card-title">商家排行 TOP</text>
            <text class="card-desc">按 GMV</text>
          </view>
          <view class="rank-scroll-container">
            <view class="rank-scroll-wrapper" :class="{ 'has-scroll': topMerchants.length >= 6 }">
              <view class="rank-list">
                <view v-for="m in topMerchants" :key="m.id" class="rank-item">
                  <text class="rank-no">{{ m.rank }}</text>
                  <text class="rank-name">{{ m.name }}</text>
                  <view class="rank-right">
                    <text class="rank-val">¥{{ formatMoney(m.sales) }}</text>
                    <text class="chip" :class="m.growth >= 0 ? 'pos' : 'neg'">
                      {{ m.growth >= 0 ? '+' : '' }}{{ m.growth }}%
                    </text>
                  </view>
                </view>
                <!-- 循环播放：复制一份数据用于无缝滚动 -->
                <view v-if="topMerchants.length >= 6" v-for="m in topMerchants" :key="'copy-' + m.id" class="rank-item">
                  <text class="rank-no">{{ m.rank }}</text>
                  <text class="rank-name">{{ m.name }}</text>
                  <view class="rank-right">
                    <text class="rank-val">¥{{ formatMoney(m.sales) }}</text>
                    <text class="chip" :class="m.growth >= 0 ? 'pos' : 'neg'">
                      {{ m.growth >= 0 ? '+' : '' }}{{ m.growth }}%
                    </text>
                  </view>
                </view>
              </view>
            </view>
          </view>
        </view>
      </view>

      <!-- 快速工具卡片区（6个工具入口） -->
      <view class="tools-section">
        <view class="section-header">
          <text class="section-title">快速分析工具</text>
          <text class="section-desc">点击进入详细分析</text>
        </view>
        <view class="tools-grid">
          <view class="tool-card" @click="goToSalesReport">
            <view class="tool-icon sales">📊</view>
            <text class="tool-title">销售报表</text>
            <text class="tool-desc">GMV、订单、转化率</text>
          </view>
          <view class="tool-card" @click="goToUserAnalysis">
            <view class="tool-icon users">👥</view>
            <text class="tool-title">用户分析</text>
            <text class="tool-desc">增长、活跃、留存</text>
          </view>
          <view class="tool-card" @click="goToProductInsights">
            <view class="tool-icon products">📦</view>
            <text class="tool-title">商品洞察</text>
            <text class="tool-desc">销量、库存、价格</text>
          </view>
          <view class="tool-card" @click="goToMarketTrends">
            <view class="tool-icon market">📈</view>
            <text class="tool-title">市场趋势</text>
            <text class="tool-desc">整体趋势、行业对比</text>
          </view>
          <view class="tool-card" @click="goToCouponAnalysis">
            <view class="tool-icon coupon">🎫</view>
            <text class="tool-title">优惠券分析</text>
            <text class="tool-desc">发放、使用、ROI</text>
          </view>
          <view class="tool-card" @click="goToCustomReport">
            <view class="tool-icon custom">⚙️</view>
            <text class="tool-title">自定义报表</text>
            <text class="tool-desc">创建专属报表</text>
				</view>
			</view>
		</view>

      <!-- 留白 -->
      <view style="height: 24px;"></view>
        </view>
      </view>
    </view>
  </view>
</template>

<script setup lang="uts">
import { computed, reactive, ref, watch } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { ensureAnalyticsLogin } from '@/services/analytics/authGuard.uts'

import AnalyticsComboChart from '@/components/analytics/AnalyticsComboChart.uvue'
import AnalyticsSidebarMenu from '@/components/analytics/AnalyticsSidebarMenu.uvue'
import AnalyticsTopBar from '@/components/analytics/AnalyticsTopBar.uvue'
import AnalyticsDateRangePicker from '@/components/analytics/AnalyticsDateRangePicker.uvue'
import EChartsView from '@/uni_modules/charts/EChartsView.vue'
import { fetchDashboardRealtime, fetchDashboardTrend, fetchDashboardUserSegments, fetchDashboardTrafficSources, fetchDashboardTopProducts, fetchDashboardTopMerchants } from '@/services/analytics/dashboardService.uts'
import { mapAnalyticsError } from '@/services/analytics/errorMapper.uts'
import type { TrendData, SegmentItem, TrafficItem, TopProductItem, TopMerchantItem } from '@/types/analytics/dashboard.uts'

const lastUpdateTime = ref('')
const selectedPeriod = ref('7d')

const customRangeEnabled = ref(false)
const selectedStartDate = ref('')
const selectedEndDate = ref('')
const showMoreMenu = ref(false)
const showSidebarMenu = ref(false)
const currentPath = ref('/pages/mall/analytics/index')
const loading = ref(true)
const autoRefreshEnabled = ref(true)
const autoRefreshInterval = ref(60000)
const autoRefreshTimer = ref<any>(null)

const timePeriods = ref<Array<{ value: string; label: string }>>([
  { value: '7d', label: '7天' },
  { value: '30d', label: '30天' },
  { value: '90d', label: '90天' },
  { value: '1y', label: '1年' }
])

const realTime = reactive({
  gmv: 0,
  gmv_growth: 0,
  orders: 0,
  order_growth: 0,
  online_users: 0,
  conversion_rate: 0,
  conversion_growth: 0
})

const trend = reactive<TrendData>({ x: [], gmv: [], orders: [] })
const userSegments = reactive<Array<SegmentItem>>([])
const trafficSources = reactive<Array<TrafficItem>>([])
const topProducts = reactive<Array<TopProductItem>>([])
const topMerchants = reactive<Array<TopMerchantItem>>([])

const trafficBarOption = ref<any>({})
const userSegmentOption = ref<any>({})

const selectedPeriodText = computed((): string => {
  const p = timePeriods.value.find((t) => t.value === selectedPeriod.value)
  return p ? p.label : '7天'
})

function updateTime() {
  const now = new Date()
  const hh = now.getHours().toString().padStart(2, '0')
  const mm = now.getMinutes().toString().padStart(2, '0')
  lastUpdateTime.value = `${hh}:${mm}`
}

function startAutoRefresh() {
  stopAutoRefresh()
  autoRefreshTimer.value = setInterval(() => {
    refreshAll()
  }, autoRefreshInterval.value)
}

function stopAutoRefresh() {
  if (autoRefreshTimer.value != null) {
    clearInterval(autoRefreshTimer.value)
    autoRefreshTimer.value = null
  }
}

async function loadTrend() {
  try {
    const range = selectedStartDate.value && selectedEndDate.value
      ? { start: selectedStartDate.value, end: selectedEndDate.value }
      : null

    const data = await fetchDashboardTrend(selectedPeriod.value, range)
    trend.x = data.x
    trend.gmv = data.gmv
    trend.orders = data.orders
  } catch (e) {
    console.error('❌ loadTrend failed', e)
    trend.x = []
    trend.gmv = []
    trend.orders = []
  }
}

async function loadRealTime() {
  try {
    const data = await fetchDashboardRealtime()
    realTime.gmv = data.gmv
    realTime.gmv_growth = data.gmv_growth
    realTime.orders = data.orders
    realTime.order_growth = data.order_growth
    realTime.online_users = data.online_users
    realTime.conversion_rate = data.conversion_rate
    realTime.conversion_growth = data.conversion_growth
  } catch (e) {
    console.error('❌ loadRealTime failed', e)
  }
}

async function loadTopProducts() {
  try {
    const range = selectedStartDate.value && selectedEndDate.value
      ? { start: selectedStartDate.value, end: selectedEndDate.value }
      : null
    const list = await fetchDashboardTopProducts(selectedPeriod.value, 50, range)
    topProducts.splice(0, topProducts.length, ...list)
  } catch (e) {
    console.error('❌ loadTopProducts failed', e)
    topProducts.splice(0, topProducts.length)
  }
}

async function loadTopMerchants() {
  try {
    const range = selectedStartDate.value && selectedEndDate.value
      ? { start: selectedStartDate.value, end: selectedEndDate.value }
      : null
    const list = await fetchDashboardTopMerchants(selectedPeriod.value, 50, range)
    topMerchants.splice(0, topMerchants.length, ...list)
  } catch (e) {
    console.error('❌ loadTopMerchants failed', e)
    topMerchants.splice(0, topMerchants.length)
  }
}

async function loadUserSegments() {
  try {
    const range = selectedStartDate.value && selectedEndDate.value
      ? { start: selectedStartDate.value, end: selectedEndDate.value }
      : null
    const list = await fetchDashboardUserSegments(selectedPeriod.value, range)
    userSegments.splice(0, userSegments.length, ...list)
  } catch (e) {
    console.error('❌ loadUserSegments failed', e)
    userSegments.splice(0, userSegments.length)
  }
}

async function loadTrafficSources() {
  try {
    const range = selectedStartDate.value && selectedEndDate.value
      ? { start: selectedStartDate.value, end: selectedEndDate.value }
      : null
    const list = await fetchDashboardTrafficSources(selectedPeriod.value, range)
    trafficSources.splice(0, trafficSources.length, ...list)
  } catch (e) {
    console.error('❌ loadTrafficSources failed', e)
    trafficSources.splice(0, trafficSources.length)
  }
}

function toPlainObject(obj: any): any {
  if (obj == null) return null
  if (typeof obj !== 'object') return obj
  if (Array.isArray(obj)) {
    return obj.map((item) => toPlainObject(item))
  }
  const plain: any = {}
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      const value = obj[key]
      if (typeof value === 'function' || key.startsWith('_') || key === 'toJSON') {
        continue
      }
      if (value != null && typeof value === 'object' && !Array.isArray(value)) {
        let isSimple = true
        for (const k in value) {
          if (typeof value[k] === 'object' && value[k] !== null) {
            isSimple = false
            break
          }
        }
        plain[key] = isSimple ? { ...value } : toPlainObject(value)
      } else {
        plain[key] = value
      }
    }
  }
  return plain
}

function buildChartOptions() {
  console.log('📊 buildChartOptions: 开始构建图表配置')
  console.log('📊 buildChartOptions: trafficSources', trafficSources, '数量:', trafficSources.length)
  console.log('📊 buildChartOptions: userSegments', userSegments, '数量:', userSegments.length)

  if (!trafficSources || !userSegments) {
    console.warn('⚠️ buildChartOptions: 数据未准备好，跳过构建')
    return
  }

  const trafficX = trafficSources.map((it) => String(it.name))
  const trafficY = trafficSources.map((it) => {
    const n = Number(it.value)
    return isFinite(n) ? n : 0
  })
  const total = trafficY.reduce((sum, v) => sum + v, 0)

  console.log('📊 buildChartOptions: 流量来源数据', { trafficX, trafficY, total, count: trafficX.length })

  if (trafficX.length === 0 || total === 0) {
    console.warn('⚠️ buildChartOptions: 流量来源数据为空，使用占位数据')
    trafficBarOption.value = toPlainObject({
      grid: { left: 80, right: 24, top: 18, bottom: 18 },
      tooltip: { trigger: 'axis' },
      xAxis: { type: 'value', axisLabel: { color: 'rgba(0,0,0,0.55)' } },
      yAxis: { type: 'category', data: ['暂无数据'], axisTick: { show: false } },
      series: [{ type: 'bar', data: [0], barWidth: 14 }]
    })
  } else {
    const newTrafficOption = {
      grid: { left: 80, right: 24, top: 18, bottom: 18 },
      tooltip: {
        trigger: 'axis',
        axisPointer: { type: 'shadow' },
        formatter: (params: any) => {
          const p = params[0]
          const percent = total > 0 ? ((p.value / total) * 100).toFixed(1) : '0'
          return `${p.name}<br/>${p.marker} ${p.value} 次 (${percent}%)`
        }
      },
      xAxis: {
        type: 'value',
        axisLabel: { color: 'rgba(0,0,0,0.55)' },
        splitLine: { lineStyle: { color: 'rgba(0,0,0,0.06)' } }
      },
      yAxis: {
        type: 'category',
        data: trafficX,
        axisTick: { show: false },
        axisLabel: { color: 'rgba(0,0,0,0.65)' }
      },
      series: [
        {
          type: 'bar',
          data: trafficY,
          barWidth: 14,
          itemStyle: {
            borderRadius: 6,
            color: {
              type: 'linear',
              x: 0,
              y: 0,
              x2: 1,
              y2: 0,
              colorStops: [
                { offset: 0, color: '#FF4D4F' },
                { offset: 1, color: '#FF7A45' }
              ]
            }
          },
          animationDuration: 800,
          animationEasing: 'cubicOut'
        }
      ]
    }

    trafficBarOption.value = toPlainObject(newTrafficOption)
  }

  console.log('📊 buildChartOptions: trafficBarOption 构建完成', trafficBarOption.value)

  const segmentData = userSegments.map((it) => ({
    name: String(it.name),
    value: (() => {
      const n = Number(it.value)
      return isFinite(n) ? n : 0
    })()
  }))

  console.log('📊 buildChartOptions: 用户结构数据', segmentData, '数量:', segmentData.length)

  if (segmentData.length === 0) {
    console.warn('⚠️ buildChartOptions: 用户结构数据为空，使用占位数据')
    userSegmentOption.value = toPlainObject({
      tooltip: { trigger: 'item' },
      legend: { left: 0, bottom: 0, itemWidth: 10, itemHeight: 10, textStyle: { fontSize: 12 } },
      color: ['#95A5A6'],
      series: [
        {
          type: 'pie',
          radius: ['55%', '75%'],
          center: ['50%', '45%'],
          data: [{ name: '暂无数据', value: 1 }],
          label: { show: true, formatter: '{b}\n{d}%' }
        }
      ]
    })
  } else {
    const colors = ['#FF6B6B', '#4ECDC4', '#A8E6CF', '#FFD93D', '#95A5A6']

    const newUserSegmentOption = {
      tooltip: {
        trigger: 'item',
        formatter: '{b}: {c} ({d}%)'
      },
      legend: {
        left: 0,
        bottom: 0,
        itemWidth: 10,
        itemHeight: 10,
        textStyle: { fontSize: 12 }
      },
      color: colors,
      series: [
        {
          type: 'pie',
          radius: ['55%', '75%'],
          center: ['50%', '45%'],
          avoidLabelOverlap: true,
          label: { show: true, formatter: '{b}\n{d}%' },
          labelLine: { length: 10, length2: 10 },
          data: segmentData,
          animationType: 'scale',
          animationEasing: 'elasticOut',
          animationDelay: (idx: number) => idx * 100
        }
      ]
    }

    userSegmentOption.value = toPlainObject(newUserSegmentOption)
  }

  console.log('📊 buildChartOptions: userSegmentOption 构建完成', userSegmentOption.value)
  console.log('📊 buildChartOptions: 图表配置构建完成')
}

watch(
  trafficSources,
  (newVal) => {
    console.log('👀 watch trafficSources 触发', newVal)
    if (newVal && newVal.length > 0) {
      buildChartOptions()
    }
  },
  { deep: true, immediate: false }
)

watch(
  userSegments,
  (newVal) => {
    console.log('👀 watch userSegments 触发', newVal)
    if (newVal && newVal.length > 0) {
      buildChartOptions()
    }
  },
  { deep: true, immediate: false }
)

async function refreshAll() {
  updateTime()
  try {
    await Promise.all([
      loadRealTime(),
      loadTrend(),
      loadUserSegments(),
      loadTrafficSources(),
      loadTopProducts(),
      loadTopMerchants()
    ])
    updateTime()

    console.log('✅ refreshAll: 所有数据加载完成，开始构建图表')

    await new Promise((resolve) => {
      if (typeof requestAnimationFrame !== 'undefined') {
        requestAnimationFrame(() => {
          buildChartOptions()
          console.log('✅ refreshAll: 图表配置构建完成')
          resolve(null)
        })
      } else {
        setTimeout(() => {
          buildChartOptions()
          console.log('✅ refreshAll: 图表配置构建完成')
          resolve(null)
        }, 50)
      }
    })
  } catch (e) {
    console.error('❌ refreshAll failed', e)
    uni.showToast({ title: mapAnalyticsError(e, { fallbackMessage: '数据加载失败' }), icon: 'none' })
  }
}

async function initDashboard() {
  loading.value = true
  try {
    await refreshAll()
    if (autoRefreshEnabled.value) {
      startAutoRefresh()
    }
  } finally {
    loading.value = false
  }
}

async function selectPeriod(p: string) {
  selectedPeriod.value = p

  // 切换到快捷时间段时，退出自定义范围
  customRangeEnabled.value = false
  selectedStartDate.value = ''
  selectedEndDate.value = ''

  loading.value = true
  try {
    await Promise.all([loadTrend(), loadUserSegments(), loadTrafficSources(), loadTopProducts(), loadTopMerchants()])

    await new Promise((resolve) => {
      if (typeof requestAnimationFrame !== 'undefined') {
        requestAnimationFrame(() => {
          buildChartOptions()
          console.log('✅ selectPeriod: 图表配置构建完成')
          resolve(null)
        })
      } else {
        setTimeout(() => {
          buildChartOptions()
          console.log('✅ selectPeriod: 图表配置构建完成')
          resolve(null)
        }, 50)
      }
    })
  } catch (e) {
    console.error('❌ selectPeriod failed', e)
  } finally {
    loading.value = false
  }
}

function handleMenu() {
  showSidebarMenu.value = true
}

function handleSidebarUpdate(visible: boolean) {
  showSidebarMenu.value = visible
}

function closeMoreMenu() {
  showMoreMenu.value = false
}

function handleSearch() {
  uni.showToast({ title: '搜索功能', icon: 'none' })
}

function handleNotification() {
  uni.showToast({ title: '通知中心', icon: 'none' })
}

function handleFullscreen() {
  uni.showToast({ title: '全屏模式', icon: 'none' })
}

function handleMobile() {
  uni.showToast({ title: '移动端预览', icon: 'none' })
}

function handleDropdown() {
  uni.showActionSheet({
    itemList: ['crmeb demo', '切换项目', '项目设置'],
    success: () => {}
  })
}

function handleSettings() {
  uni.showToast({ title: '设置', icon: 'none' })
}

function toggleCustomRange() {
  customRangeEnabled.value = !customRangeEnabled.value
}

function onDateRangeApply(range: { start: string; end: string }) {
  selectedStartDate.value = range.start
  selectedEndDate.value = range.end
  customRangeEnabled.value = true
  refreshAll()
}

function onDateRangeClear() {
  selectedStartDate.value = ''
  selectedEndDate.value = ''
  customRangeEnabled.value = false
  refreshAll()
}

function formatInt(n: number): string {
  const v = isFinite(n) ? Math.round(n) : 0
  if (v >= 10000) return (v / 10000).toFixed(1) + '万'
  return v.toString()
}

function formatMoney(n: number): string {
  const v = isFinite(n) ? n : 0
  if (v >= 10000) return (v / 10000).toFixed(1) + '万'
  return v.toFixed(0)
}

function formatPct(n: number): string {
  const v = isFinite(n) ? n : 0
  const sign = v > 0 ? '+' : ''
  return `${sign}${v.toFixed(1)}%`
}

function goToSalesReport() {
  uni.navigateTo({ url: '/pages/mall/analytics/sales-report' })
}

function goToUserAnalysis() {
  uni.navigateTo({ url: '/pages/mall/analytics/user-analysis' })
}

function goToProductInsights() {
  uni.navigateTo({ url: '/pages/mall/analytics/product-insights' })
}

function goToMarketTrends() {
  uni.navigateTo({ url: '/pages/mall/analytics/market-trends' })
}

function goToCouponAnalysis() {
  uni.navigateTo({ url: '/pages/mall/analytics/coupon-analysis' })
}

function goToCustomReport() {
  uni.navigateTo({ url: '/pages/mall/analytics/custom-report' })
}

function handleMoreAction(action: string) {
  showMoreMenu.value = false
  switch (action) {
    case 'refresh':
      refreshAll()
      break
    case 'search':
      handleSearch()
      break
    case 'notification':
      handleNotification()
      break
    case 'fullscreen':
      handleFullscreen()
      break
    case 'mobile':
      handleMobile()
      break
    case 'settings':
      handleSettings()
      break
  }
}

function toggleAutoRefresh() {
  autoRefreshEnabled.value = !autoRefreshEnabled.value
  if (autoRefreshEnabled.value) {
    startAutoRefresh()
    uni.showToast({ title: '已开启自动刷新', icon: 'success' })
  } else {
    stopAutoRefresh()
    uni.showToast({ title: '已关闭自动刷新', icon: 'none' })
  }
}

function exportReport() {
  uni.showActionSheet({
    itemList: ['导出Excel', '导出PDF', '导出图片'],
    success: () => uni.showToast({ title: '导出成功', icon: 'success' })
  })
}

onLoad(() => {
	if (!ensureAnalyticsLogin({ toastTitle: '请先登录后查看数据分析' })) return
	initDashboard()
})

onUnload(() => {
  showMoreMenu.value = false
  stopAutoRefresh()
})

onShow(() => {
  if (autoRefreshEnabled.value) {
    startAutoRefresh()
  }
})

onHide(() => {
  stopAutoRefresh()
})
</script>

<style>
/* 页面：白底 + 宽屏居中 + 自适应 */
/* 说明：uni-app 的 rpx 会随屏宽缩放，宽屏 H5 建议用 max-width 控制内容宽度。 */

.page {
		min-height: 100vh;
  background: #f6f7fb;
	}
	
/* 页面布局：宽屏时侧边栏+内容，窄屏时全屏内容 */
.page-layout {
		display: flex;
  flex-direction: row !important;
  min-height: 100vh;
	}
	
.main-content {
  flex: 1;
  min-width: 0;
		display: flex;
		flex-direction: column;
  padding-top: 64px; /* 为固定顶部导航栏留出空间 */
}

.container {
  width: 100%;
  max-width: 1280px;
  margin: 0 auto;
  padding: 16px 16px 28px;
  box-sizing: border-box;
  flex: 1;
}

/* 响应式：窄屏时全屏显示 */
@media screen and (max-width: 959px) {
  .page-layout {
    flex-direction: column !important;
  }
  
  .main-content {
    width: 100%;
  }
}

/* 顶部 */
/* ✅ 强制：顶部必须横排（避免被全局 view:flex-direction:column 影响） */
.topbar {
		display: flex;
  flex-direction: row !important;
		justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  background: #fff;
  border-radius: 14px;
  border: 1px solid rgba(0,0,0,0.06);
  width: 100%;
  box-sizing: border-box;
  overflow: hidden;
}

.topbar-left {
  display: flex;
  flex-direction: row !important;
  align-items: center;
  gap: 12px;
  flex: 1;
  min-width: 0;
}

.menu-icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: #f3f4f6;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: all 0.2s;
}

.menu-icon:active {
  background: #e5e7eb;
  transform: scale(0.95);
}

.menu-icon .icon {
  font-size: 18px;
  color: #111;
  line-height: 1;
}

/* 左侧标题组仍然是纵向 */
.title-group {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  min-width: 0; /* 允许内部 text 做省略 */
}

.title {
  font-size: 18px;
  font-weight: 700;
  color: #111;
  max-width: 420px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.subtitle {
  font-size: 12px;
  color: rgba(0,0,0,0.55);
  max-width: 420px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ✅ 右侧按钮永不换成竖列（必要时只裁切，不换行） */
.topbar-right {
		display: flex;
  flex-direction: row !important;
  gap: 8px;
  align-items: center;
  flex-wrap: nowrap;
  flex-shrink: 0;
  position: relative;
  white-space: nowrap;
}

.icon-btn {
  padding: 8px 12px;
  border-radius: 10px;
  background: #f3f4f6;
  color: #111;
  font-size: 13px;
}

.icon-btn.primary {
  background: #111;
		color: #fff;
	}
	
/* 图标按钮样式 */
.icon-btn-icon {
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: #f3f4f6;
		display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  position: relative;
  transition: all 0.2s;
}

.icon-btn-icon:active {
  background: #e5e7eb;
  transform: scale(0.95);
}

.icon-btn-icon .icon {
  font-size: 16px;
  line-height: 1;
}

/* 通知图标带红点 */
.icon-btn-icon.notification .badge {
  position: absolute;
  top: 4px;
  right: 4px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #ef4444;
  border: 1px solid #fff;
}

/* 下拉菜单 */
.dropdown {
		display: flex;
  flex-direction: row !important;
  align-items: center;
  gap: 4px;
  padding: 6px 10px;
  border-radius: 8px;
  background: #f3f4f6;
  cursor: pointer;
  transition: all 0.2s;
  white-space: nowrap;
  flex-shrink: 0;
}

/* 更多按钮（默认隐藏，窄屏时显示） */
.more-btn {
  display: none;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  background: #f3f4f6;
		align-items: center;
  justify-content: center;
  cursor: pointer;
  position: relative;
  transition: all 0.2s;
  flex-shrink: 0;
}

.more-btn.active {
  background: #e5e7eb;
}

.more-btn .icon {
  font-size: 18px;
  line-height: 1;
  color: #111;
}

/* 更多菜单下拉 */
.more-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  background: #fff;
  border-radius: 8px;
  border: 1px solid rgba(0,0,0,0.1);
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
  min-width: 140px;
  z-index: 1000;
  overflow: hidden;
		display: flex;
  flex-direction: column !important;
	}
	
.more-menu-item {
		display: flex;
  flex-direction: row !important;
		align-items: center;
  gap: 10px;
  padding: 10px 14px;
  cursor: pointer;
  transition: background 0.2s;
}

.more-menu-item:active {
  background: #f3f4f6;
}

.more-menu-item .icon {
  font-size: 16px;
  line-height: 1;
}

.more-menu-item .text {
  font-size: 13px;
  color: #111;
}

.dropdown:active {
  background: #e5e7eb;
}

.dropdown-text {
  font-size: 13px;
  color: #111;
}

.dropdown-arrow {
  font-size: 10px;
  color: #666;
  line-height: 1;
}

/* KPI：默认 2列，宽屏 4列 */
/* ✅ 核心修复：用 flex + calc(50%) 替代 width，避免 rpx + CSS var 失效 */
.kpi-grid {
  margin-top: 12px;
		display: flex;
  flex-direction: row !important;
  flex-wrap: wrap;
  gap: 12px;
}

.kpi-card {
  background: #fff;
  border-radius: 16px;
  border: 1px solid rgba(0,0,0,0.06);
  padding: 18px;
  box-sizing: border-box;
  flex: 1 1 calc(50% - 6px);
  min-width: 260px;
  position: relative;
  overflow: hidden;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}

.kpi-card:active {
  transform: scale(0.98);
  box-shadow: 0 1px 4px rgba(0,0,0,0.08);
}

/* KPI 卡片渐变背景 */
.kpi-card-gmv {
  background: linear-gradient(135deg, #FF6B6B 0%, #FF4D4F 100%);
  color: #fff;
}

.kpi-card-orders {
  background: linear-gradient(135deg, #4ECDC4 0%, #44A08D 100%);
  color: #fff;
}

.kpi-card-users {
  background: linear-gradient(135deg, #A8E6CF 0%, #7FCDBB 100%);
  color: #fff;
}

.kpi-card-conversion {
  background: linear-gradient(135deg, #FFD93D 0%, #FFA07A 100%);
  color: #fff;
}

.kpi-header {
  display: flex;
  flex-direction: row !important;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 12px;
  position: relative;
  width: 100%;
}

.kpi-label {
  font-size: 13px;
  color: rgba(255,255,255,0.9);
  font-weight: 500;
}


.kpi-value {
  font-size: 28px;
  font-weight: 800;
  color: #fff;
  margin-bottom: 12px;
  line-height: 1.2;
}

.kpi-footer {
  display: flex;
  flex-direction: row !important;
  justify-content: space-between;
  align-items: center;
}

.kpi-meta {
  font-size: 12px;
  color: rgba(255,255,255,0.75);
}

.kpi-chip {
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  background: rgba(255,255,255,0.2);
  backdrop-filter: blur(4px);
}

.kpi-chip.pos {
  background: rgba(34,197,94,0.25);
  color: #fff;
}

.kpi-chip.neg {
  background: rgba(239,68,68,0.25);
  color: #fff;
}

.kpi-chip.neutral {
  background: rgba(255,255,255,0.2);
  color: #fff;
}

/* 时间维度 tabs 横排 */
.tabs {
  margin-top: 12px;
		display: flex;
  flex-direction: row !important;
  gap: 8px;
  padding: 8px;
  background: #fff;
  border-radius: 14px;
  border: 1px solid rgba(0,0,0,0.06);
  overflow-x: auto;
  flex-wrap: wrap;
  justify-content: center;
}

.tab {
  padding: 8px 12px;
  border-radius: 999px;
  background: #f3f4f6;
  color: #111;
  font-size: 13px;
  white-space: nowrap;
  flex-shrink: 0;
}

.tab.active {
  background: #111;
  color: #fff;
}

/* 卡片 */
.card {
  margin-top: 12px;
  background: #fff;
  border-radius: 16px;
  border: 1px solid rgba(0,0,0,0.06);
  box-shadow: 0 2px 10px rgba(0,0,0,0.04);
  padding: 14px;
  box-sizing: border-box;
}

.card-full {
  width: 100%;
}

.fullwide {
  margin-top: 12px;
}

.card-head {
		display: flex;
  align-items: baseline;
		justify-content: space-between;
  margin-bottom: 16px;
}

.card-title {
  font-size: 14px;
  font-weight: 600;
  color: #111;
}

.card-desc {
  font-size: 12px;
  color: rgba(0,0,0,0.55);
}

/* 图表必须给高度（H5 否则可能 0 高） */
.chart-box {
  width: 100%;
  height: 360px; /* 建议用 px，H5 更稳 */
}

.fullwide .chart-box {
  height: 420px; /* 大图更高 */
}

/* 图表加载状态 */
.chart-loading {
  width: 100%;
  height: 360px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: rgba(0,0,0,0.45);
  font-size: 14px;
}

.fullwide .chart-loading {
  height: 420px;
}

/* 用户结构和流量来源：横排显示 */
.charts-row {
  display: flex;
  flex-direction: row !important;
  flex-wrap: wrap;
  gap: 12px;
  align-items: stretch;
  margin-top: 12px;
}

.charts-left,
.charts-right {
  flex: 1 1 calc(50% - 6px);
  min-width: 360px;
}

/* 两个TOP排行：横排显示 */
.tops-row {
  display: flex;
  flex-direction: row !important;
  flex-wrap: wrap;
  gap: 12px;
  align-items: stretch;
  margin-top: 12px;
}

.tops-left,
.tops-right {
  flex: 1 1 calc(50% - 6px);
  min-width: 360px;
}

/* 滚动容器 */
.rank-scroll-container {
  width: 100%;
  height: 300px;
  overflow: hidden;
  position: relative;
}

.rank-scroll-wrapper {
  width: 100%;
}

.rank-scroll-wrapper.has-scroll {
  animation: scrollRank 15s linear infinite;
}

/* 列表样式 */
.rank-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  width: 100%;
}

/* 滚动动画：当数据超过5条时自动滚动 */
@keyframes scrollRank {
  0% {
    transform: translateY(0);
  }
  100% {
    /* 滚动到第一份数据的末尾，实现无缝循环 */
    /* 每条 rank-item 高度约 50px（包括 padding 和 gap），滚动一半高度 */
    transform: translateY(calc(-50%));
  }
}

.rank-item {
  display: flex;
  flex-direction: row !important;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid rgba(0,0,0,0.06);
}

.rank-item:last-child {
  border-bottom: none;
}

.rank-no {
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: rgba(0,0,0,0.06);
  text-align: center;
  line-height: 28px;
  font-size: 12px;
  flex: 0 0 auto;
}

.rank-name {
  flex: 1;
  font-size: 13px;
  color: #111;
}

.rank-val {
  font-size: 13px;
  color: rgba(0,0,0,0.65);
}

.rank-right {
  display: flex;
  flex-direction: row !important;
  align-items: center;
  gap: 8px;
}

.chip {
  padding: 3px 8px;
  border-radius: 999px;
  font-size: 12px;
}

.chip.pos {
  background: rgba(34,197,94,0.12);
  color: #16a34a;
}

.chip.neg {
  background: rgba(239,68,68,0.12);
  color: #dc2626;
}

/* 宽屏：KPI 4列 */
@media screen and (min-width: 960px) {
  .kpi-card {
    flex: 1 1 calc(25% - 9px);
    min-width: 200px;
  }
  
  /* 宽屏时显示所有按钮，隐藏"更多"按钮 */
  .topbar-right .btn-hidden {
    display: flex !important;
  }
  
  .more-btn {
    display: none !important;
  }
  
  /* 宽屏时工具卡片 3列 */
  .tools-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* 自适应：窄屏自动变一列（断点用 px） */
@media screen and (max-width: 960px) {
  .charts-row,
  .tops-row {
    flex-direction: column;
  }
  .charts-left,
  .charts-right,
  .tops-left,
  .tops-right {
    flex: 1 1 100%;
    min-width: 100%;
  }
  .chart-box {
    height: 320px;
  }
  .fullwide .chart-box {
    height: 360px;
  }
  
  /* 顶部栏按钮在小屏幕上：隐藏部分按钮，显示"更多"按钮 */
  .topbar-right {
    gap: 6px;
  }
  
  /* 隐藏标记为 btn-hidden 的按钮 */
  .topbar-right .btn-hidden {
    display: none !important;
  }
  
  /* 显示"更多"按钮 */
  .more-btn {
    display: flex !important;
  }
  
  /* 标题在窄屏时允许省略号 */
  .title,
  .subtitle {
    max-width: 200px;
  }
  
  .icon-btn-icon {
    width: 28px;
    height: 28px;
    flex-shrink: 0;
  }
  
  .icon-btn-icon .icon {
    font-size: 14px;
  }
  
  .dropdown {
    padding: 4px 8px;
    flex-shrink: 0;
  }
  
  .dropdown-text {
    font-size: 12px;
  }
  
  /* 窄屏时 KPI 卡片单列 */
  .kpi-card {
    flex: 1 1 100%;
  }
  
  /* 窄屏时工具卡片 2列 */
  .tools-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

/* 快速工具卡片区 */
.tools-section {
  margin-top: 24px;
}

.section-header {
  display: flex;
  flex-direction: row !important;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 16px;
}

.section-title {
  font-size: 16px;
  font-weight: 700;
  color: #111;
}

.section-desc {
  font-size: 12px;
  color: rgba(0,0,0,0.55);
}

.tools-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
}

.tool-card {
  background: #fff;
  border-radius: 14px;
  border: 1px solid rgba(0,0,0,0.06);
  padding: 20px 16px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}

.tool-card:active {
  transform: scale(0.96);
  box-shadow: 0 1px 4px rgba(0,0,0,0.08);
}

.tool-icon {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 24px;
  margin-bottom: 12px;
  background: #f3f4f6;
}

.tool-icon.sales {
  background: linear-gradient(135deg, #FF6B6B 0%, #FF4D4F 100%);
}

.tool-icon.users {
  background: linear-gradient(135deg, #4ECDC4 0%, #44A08D 100%);
}

.tool-icon.products {
  background: linear-gradient(135deg, #A8E6CF 0%, #7FCDBB 100%);
}

.tool-icon.market {
  background: linear-gradient(135deg, #FFD93D 0%, #FFA07A 100%);
}

.tool-icon.coupon {
  background: linear-gradient(135deg, #FF9A9E 0%, #FECFEF 100%);
}

.tool-icon.custom {
  background: linear-gradient(135deg, #A8C0FF 0%, #3B82F6 100%);
}

.tool-title {
  font-size: 14px;
  font-weight: 600;
  color: #111;
  margin-bottom: 6px;
}

.tool-desc {
  font-size: 12px;
  color: rgba(0,0,0,0.55);
  line-height: 1.4;
}

</style>
