import { Router } from 'express'
import { query } from '../config/database.js'
import { sendSuccess, sendError, parseMonth, parsePagination } from '../middleware/error.js'
import type { AuthRequest } from '../middleware/auth.js'
import { getDataScope } from '../middleware/data-scope.js'

const router = Router()

// ============================================================
// 1. 会员LTV与分层
// ============================================================
router.get('/member/ltv', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    const { page, pageSize, offset } = parsePagination(req)
    const status = (req.query.status as string) || ''
    const level = (req.query.level as string) || ''

    let whereClause = 'WHERE 1=1'
    const params: any[] = []
    if (status) {
      params.push(status)
      whereClause += ` AND dm.status = $${params.length}`
    }
    if (level) {
      params.push(level)
      whereClause += ` AND dm.member_level = $${params.length}`
    }

    const countResult = await query(`SELECT count(*) as total FROM analytics.dim_member dm ${whereClause}`, params)
    const total = Number(countResult.rows[0].total)

    params.push(pageSize, offset)
    const result = await query(`
      SELECT dm.member_id, dm.register_channel, dm.register_store, ds.store_name as register_store_name,
             dm.register_date, dm.member_level, dm.total_orders, round(dm.total_revenue::numeric, 2) as total_revenue,
             dm.last_order_date, dm.status, dm.tags
      FROM analytics.dim_member dm
      LEFT JOIN analytics.dim_store ds ON dm.register_store = ds.store_code
      ${whereClause}
      ORDER BY dm.total_revenue DESC NULLS LAST
      LIMIT $${params.length - 1} OFFSET $${params.length}
    `, params)

    // 汇总统计
    const summaryResult = await query(`
      SELECT 
        count(*) as total_members,
        count(*) FILTER (WHERE status = '活跃') as active_count,
        count(*) FILTER (WHERE status = '沉睡') as dormant_count,
        count(*) FILTER (WHERE status = '流失') as churned_count,
        round(avg(total_revenue)::numeric, 2) as avg_ltv,
        round(sum(total_revenue)::numeric, 2) as total_revenue,
        round(avg(total_orders)::numeric, 1) as avg_orders
      FROM analytics.dim_member
    `)

    // 等级分布
    const levelDist = await query(`
      SELECT member_level, count(*) as count, 
             round(avg(total_revenue)::numeric, 2) as avg_revenue,
             round(avg(total_orders)::numeric, 1) as avg_orders
      FROM analytics.dim_member GROUP BY member_level ORDER BY 
      CASE member_level WHEN '钻石' THEN 1 WHEN '金卡' THEN 2 WHEN '银卡' THEN 3 WHEN '普通' THEN 4 ELSE 5 END
    `)

    sendSuccess(res, {
      summary: summaryResult.rows[0],
      level_distribution: levelDist.rows,
      members: result.rows,
    }, { page, pageSize, total })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============================================================
// 2. 菜单工程行动清单
// ============================================================
router.get('/menu-engineering/actions', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)

    const result = await query(`
      SELECT 
        dish_name,
        abc_class,
        received_amount as revenue,
        bill_count as order_count,
        realized_unit_price as avg_price,
        category_level1 as category_l1,
        category_level2 as category_l2,
        CASE 
          WHEN abc_class LIKE 'A%' AND bill_count > 0 THEN '保留并推广'
          WHEN abc_class LIKE 'A%' AND bill_count <= 0 THEN '调查停售原因'
          WHEN abc_class LIKE 'B%' THEN '优化提升'
          WHEN abc_class LIKE 'C%' AND received_amount < 1000 THEN '考虑淘汰'
          WHEN abc_class LIKE 'C%' THEN '降本或提价'
          ELSE '观察'
        END as action,
        CASE 
          WHEN abc_class LIKE 'A%' AND realized_unit_price > 0 THEN '高人气高收入，维持品质，可考虑提价测试'
          WHEN abc_class LIKE 'B%' AND bill_count > 50 THEN '有潜力，优化呈现和推荐话术'
          WHEN abc_class LIKE 'C%' AND received_amount < 500 THEN '长尾SKU，建议下架或季节性供应'
          WHEN abc_class LIKE 'C%' THEN '收入偏低，尝试降本或搭配套餐'
          ELSE '持续观察'
        END as suggestion
      FROM analytics.mv_dish_sku_abc_monthly
      WHERE month_start = $1
      ORDER BY 
        CASE WHEN abc_class LIKE 'A%' THEN 1 WHEN abc_class LIKE 'B%' THEN 2 WHEN abc_class LIKE 'C%' THEN 3 ELSE 4 END,
        received_amount DESC NULLS LAST
    `, [month])

    // 汇总
    const summary = {
      total_skus: result.rows.length,
      class_a: result.rows.filter((r: any) => r.abc_class?.startsWith('A')).length,
      class_b: result.rows.filter((r: any) => r.abc_class?.startsWith('B')).length,
      class_c: result.rows.filter((r: any) => r.abc_class?.startsWith('C')).length,
      recommend_eliminate: result.rows.filter((r: any) => r.action === '考虑淘汰').length,
      recommend_promote: result.rows.filter((r: any) => r.action === '保留并推广').length,
    }

    sendSuccess(res, { summary, actions: result.rows })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============================================================
// 3. 菜品搭配分析（套餐推荐）
// ============================================================
router.get('/dish-pair/recommendations', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    const { page, pageSize, offset } = parsePagination(req)
    const minPairCount = parseInt((req.query.min_count as string) || '10')

    const countResult = await query(`
      SELECT count(*) as total FROM analytics.mv_dish_pair_summary_monthly 
      WHERE month_start = $1 AND pair_count >= $2
    `, [month, minPairCount])
    const total = Number(countResult.rows[0].total)

    const result = await query(`
      SELECT 
        dish_a, dish_b, pair_count, 
        dish_a_revenue, dish_b_revenue,
        combined_revenue,
        round(pair_count::numeric / NULLIF((SELECT max(pair_count) FROM analytics.mv_dish_pair_summary_monthly WHERE month_start = $1), 0) * 100, 1) as affinity_pct
      FROM analytics.mv_dish_pair_summary_monthly
      WHERE month_start = $1 AND pair_count >= $2
      ORDER BY pair_count DESC
      LIMIT $3 OFFSET $4
    `, [month, minPairCount, pageSize, offset])

    sendSuccess(res, result.rows, { page, pageSize, total })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============================================================
// 4. 区域间对比排名
// ============================================================
router.get('/region/comparison', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)

    const result = await query(`
      WITH bill_region AS (
        SELECT COALESCE(ds.region, '未知区域') AS region,
          round(sum(b.consumption)::numeric, 2) AS total_consumption,
          round(sum(b.discount_total)::numeric, 2) AS total_discount
        FROM analytics.bill_fact b
        JOIN analytics.dim_store ds ON b.store_code = ds.store_code
        WHERE b.closed_at >= $1::date AND b.closed_at < ($1::date + interval '1 month')
          AND ds.region IS NOT NULL
        GROUP BY COALESCE(ds.region, '未知区域')
      ),
      store_metrics AS (
        SELECT 
          COALESCE(ds.region, '未知区域') AS region,
          count(DISTINCT r.store_code) as store_count,
          sum(r.received) as total_revenue,
          round(avg(r.avg_bill_value)::numeric, 2) as avg_bill_value,
          sum(r.bill_count) as bill_count,
          round(avg(r.theoretical_margin_pct)::numeric, 2) as avg_margin,
          round(sum(r.bill_count * r.member_bill_share_pct / 100)::numeric, 0) as member_count
        FROM analytics.mv_store_risk_rating_monthly r
        JOIN analytics.dim_store ds ON r.store_code = ds.store_code
        WHERE r.month_start = $1
          AND ds.region IS NOT NULL
        GROUP BY COALESCE(ds.region, '未知区域')
      ),
      expense_metrics AS (
        SELECT 
          COALESCE(ds.region, '未知区域') AS region,
          avg(oe.operating_expense_rate_pct) as avg_expense_rate,
          avg(oe.rent_rate_pct) as avg_rent_rate,
          avg(oe.wage_rate_pct) as avg_wage_rate
        FROM analytics.mv_store_operating_expense_monthly oe
        JOIN analytics.dim_store ds ON oe.sales_store_code = ds.store_code
        WHERE oe.report_month = $1
          AND ds.region IS NOT NULL
        GROUP BY COALESCE(ds.region, '未知区域')
      )
      SELECT 
        sm.region,
        sm.store_count,
        br.total_consumption,
        br.total_discount,
        round(sm.total_revenue::numeric, 2) as total_revenue,
        round((sm.total_revenue / sm.store_count)::numeric, 2) as revenue_per_store,
        round(sm.avg_bill_value::numeric, 2) as avg_bill_value,
        sm.bill_count,
        round(sm.avg_margin::numeric, 2) as avg_margin_pct,
        sm.member_count,
        round((sm.member_count::numeric / NULLIF(sm.bill_count, 0) * 100)::numeric, 1) as member_penetration_pct,
        round(em.avg_expense_rate::numeric, 2) as avg_expense_rate,
        round(em.avg_rent_rate::numeric, 2) as avg_rent_rate,
        round(em.avg_wage_rate::numeric, 2) as avg_wage_rate
      FROM store_metrics sm
      LEFT JOIN bill_region br ON sm.region = br.region
      LEFT JOIN expense_metrics em ON sm.region = em.region
      ORDER BY sm.total_revenue DESC
    `, [month])

    sendSuccess(res, result.rows)
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============================================================
// 5. 区域KPI达成预测
// ============================================================
router.get('/region/kpi-forecast', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)

    const result = await query(`
      WITH region_actual AS (
        SELECT 
          ds.region,
          round(sum(r.received)::numeric, 2) as actual_revenue,
          sum(r.bill_count) as actual_bills,
          max(r.active_days) as elapsed_days,
          round(sum(r.received) / NULLIF(max(r.active_days), 0)::numeric, 2) as avg_daily_revenue
        FROM analytics.mv_store_risk_rating_monthly r
        JOIN analytics.dim_store ds ON r.store_code = ds.store_code
        WHERE r.month_start = $1
          AND ds.region IS NOT NULL AND ds.region != '未知区域'
        GROUP BY ds.region
      ),
      region_target AS (
        SELECT 
          ds.region,
          round(sum(t.revenue_target)::numeric, 2) as target_revenue,
          round(sum(t.bill_count_target)::numeric, 0) as target_bills
        FROM analytics.dim_store_target t
        JOIN analytics.dim_store ds ON t.store_code = ds.store_code
        WHERE t.target_month = $1
          AND ds.region IS NOT NULL AND ds.region != '未知区域'
        GROUP BY ds.region
      ),
      calendar AS (
        SELECT count(*) as total_days 
        FROM analytics.dim_calendar 
        WHERE date_value >= $1::date AND date_value < $1::date + interval '1 month'
          AND is_operating_day = true
      )
      SELECT 
        ra.region,
        ra.actual_revenue,
        rt.target_revenue,
        ra.actual_bills,
        rt.target_bills,
        ra.elapsed_days,
        c.total_days as working_days,
        ra.avg_daily_revenue,
        round((ra.avg_daily_revenue * c.total_days)::numeric, 2) as forecast_revenue,
        round((ra.actual_revenue / NULLIF(rt.target_revenue, 0) * 100)::numeric, 1) as achievement_pct,
        round((ra.actual_bills / NULLIF(rt.target_bills, 0) * 100)::numeric, 1) as bill_achievement_pct
      FROM region_actual ra
      LEFT JOIN region_target rt ON ra.region = rt.region
      CROSS JOIN calendar c
      ORDER BY ra.actual_revenue DESC
    `, [month])

    sendSuccess(res, result.rows)
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============================================================
// 6. 每日销售目标分解
// ============================================================
router.get('/store/daily-target', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    const storeCode = (req.query.store_code as string) || ''

    if (!storeCode) {
      return sendError(res, 'store_code is required')
    }

    // 该门店历史日均收入（按餐段）
    const mealPeriodStats = await query(`
      SELECT 
        meal_period,
        round(avg(daily_revenue)::numeric, 2) as avg_revenue,
        round(avg(bill_count)::numeric, 0) as avg_bills,
        round(avg(avg_bill_value)::numeric, 2) as avg_bill_value
      FROM (
        SELECT 
          meal_period,
          date_trunc('day', opened_at)::date as day,
          sum(received_total) as daily_revenue,
          count(*) as bill_count,
          round(avg(received_total)::numeric, 2) as avg_bill_value
        FROM analytics.bill_fact
        WHERE store_code = $1
          AND opened_at >= $2 AND opened_at < $2::date + interval '1 month'
        GROUP BY meal_period, date_trunc('day', opened_at)::date
      ) t
      GROUP BY meal_period
      ORDER BY 
        CASE meal_period WHEN '早市' THEN 1 WHEN '午市' THEN 2 WHEN '下午茶' THEN 3 WHEN '晚市' THEN 4 WHEN '夜宵' THEN 5 ELSE 6 END
    `, [storeCode, month])

    // 该门店历史日均收入（按星期）
    const weekdayStats = await query(`
      SELECT 
        extract(dow from opened_at)::int as weekday,
        round(avg(daily_revenue)::numeric, 2) as avg_revenue,
        round(avg(bill_count)::numeric, 0) as avg_bills
      FROM (
        SELECT 
          date_trunc('day', opened_at)::date as day,
          extract(dow from opened_at)::int as weekday,
          sum(received_total) as daily_revenue,
          count(*) as bill_count
        FROM analytics.bill_fact
        WHERE store_code = $1
          AND opened_at >= $2 AND opened_at < $2::date + interval '1 month'
        GROUP BY date_trunc('day', opened_at)::date, extract(dow from opened_at)::int
      ) t
      GROUP by weekday
      ORDER BY weekday
    `, [storeCode, month])

    // 月度总目标（基于历史日均 * 当月天数）
    const totalAvg = await query(`
      SELECT 
        round(avg(daily_revenue)::numeric, 2) as avg_daily_revenue,
        count(DISTINCT date_trunc('day', opened_at)::date) as active_days,
        round(sum(daily_revenue)::numeric, 2) as total_revenue
      FROM (
        SELECT date_trunc('day', opened_at)::date as day, sum(received_total) as daily_revenue
        FROM analytics.bill_fact
        WHERE store_code = $1 AND opened_at >= $2 AND opened_at < $2::date + interval '1 month'
        GROUP BY date_trunc('day', opened_at)::date
      ) t
    `, [storeCode, month])

    const workingDays = await query(`
      SELECT count(*) as total_days FROM analytics.dim_calendar 
      WHERE date_value >= $1::date AND date_value < $1::date + interval '1 month' AND is_operating_day = true
    `, [month])

    const avgDaily = Number(totalAvg.rows[0]?.avg_daily_revenue || 0)
    const forecastTotal = avgDaily * Number(workingDays.rows[0]?.total_days || 30)

    sendSuccess(res, {
      monthly_target: Math.round(forecastTotal),
      avg_daily_revenue: avgDaily,
      meal_period_breakdown: mealPeriodStats.rows,
      weekday_breakdown: weekdayStats.rows,
    })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============================================================
// 7. 门店会员活跃度面板
// ============================================================
router.get('/store/member-activity', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    const storeCode = (req.query.store_code as string) || ''

    if (!storeCode) {
      return sendError(res, 'store_code is required')
    }

    // 该门店会员活跃度
    const memberStats = await query(`
      WITH store_members AS (
        SELECT 
          bf.member_id,
          count(DISTINCT bf.bill_no) as orders,
          sum(bf.received_total) as revenue,
          max(bf.opened_at) as last_visit,
          min(bf.opened_at) as first_visit
        FROM analytics.bill_fact bf
        WHERE bf.store_code = $1
          AND bf.opened_at >= $2 AND bf.opened_at < $2::date + interval '1 month'
          AND bf.member_id IS NOT NULL AND bf.member_id != ''
        GROUP BY bf.member_id
      )
      SELECT 
        count(*) as total_members,
        count(*) FILTER (WHERE orders >= 3) as frequent_members,
        count(*) FILTER (WHERE orders = 1) as one_time_members,
        round(avg(orders)::numeric, 1) as avg_orders,
        round(avg(revenue)::numeric, 2) as avg_revenue,
        round(sum(revenue)::numeric, 2) as total_revenue
      FROM store_members
    `, [storeCode, month])

    // 会员等级分布
    const levelDist = await query(`
      SELECT 
        CASE 
          WHEN bf.member_level IN ('1') THEN '普通'
          WHEN bf.member_level IN ('2','3') THEN '银卡'
          WHEN bf.member_level IN ('4','5') THEN '金卡'
          WHEN bf.member_level IN ('6','7','LV6','LV7') THEN '钻石'
          ELSE '普通'
        END as standard_level,
        count(DISTINCT bf.member_id) as count,
        round(sum(bf.received_total)::numeric, 2) as revenue
      FROM analytics.bill_fact bf
      WHERE bf.store_code = $1
        AND bf.opened_at >= $2 AND bf.opened_at < $2::date + interval '1 month'
        AND bf.member_id IS NOT NULL AND bf.member_id != ''
      GROUP BY 1
      ORDER BY 
        CASE standard_level WHEN '钻石' THEN 1 WHEN '金卡' THEN 2 WHEN '银卡' THEN 3 WHEN '普通' THEN 4 ELSE 5 END
    `, [storeCode, month])

    // 会员 vs 非会员
    const comparison = await query(`
      SELECT 
        CASE WHEN member_id IS NOT NULL AND member_id != '' THEN '会员' ELSE '非会员' END as customer_type,
        count(*) as bill_count,
        round(sum(received_total)::numeric, 2) as revenue,
        round(avg(received_total)::numeric, 2) as avg_bill_value
      FROM analytics.bill_fact
      WHERE store_code = $1
        AND opened_at >= $2 AND opened_at < $2::date + interval '1 month'
      GROUP BY 1
    `, [storeCode, month])

    sendSuccess(res, {
      stats: memberStats.rows[0],
      level_distribution: levelDist.rows,
      comparison: comparison.rows,
    })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============================================================
// 8. 员工绩效分析
// ============================================================
router.get('/employee/performance', async (req: AuthRequest, res) => {
  try {
    const { page, pageSize, offset } = parsePagination(req)
    const position = (req.query.position as string) || ''
    const status = (req.query.status as string) || ''

    let whereClause = 'WHERE 1=1'
    const params: any[] = []
    if (position) {
      params.push(position)
      whereClause += ` AND de.position = $${params.length}`
    }
    if (status) {
      params.push(status)
      whereClause += ` AND de.status = $${params.length}`
    }

    const countResult = await query(`SELECT count(*) as total FROM analytics.dim_employee ${whereClause}`, params)
    const total = Number(countResult.rows[0].total)

    params.push(pageSize, offset)
    const result = await query(`
      SELECT 
        de.employee_id,
        de.position,
        de.hire_date,
        de.leave_date,
        de.status,
        s.salary_period,
        round(s.gross_pay::numeric, 2) as gross_pay,
        round(s.net_pay::numeric, 2) as net_pay,
        round(s.perf_score::numeric, 2) as perf_score,
        round(s.actual_attend::numeric, 0) as actual_attend,
        round(s.expected_attend::numeric, 0) as expected_attend,
        round(s.overtime_pay::numeric, 2) as overtime_pay,
        round(s.bonus::numeric, 2) as bonus,
        s.org_level2,
        s.org_level3
      FROM analytics.dim_employee de
      LEFT JOIN public.salary_detail_records s ON de.employee_id = s.employee_code
      ${whereClause}
      ORDER BY s.gross_pay DESC NULLS LAST
      LIMIT $${params.length - 1} OFFSET $${params.length}
    `, params)

    // 岗位汇总
    const positionSummary = await query(`
      SELECT 
        de.position,
        count(*) as headcount,
        count(*) FILTER (WHERE de.status = '在职') as active_count,
        round(avg(s.gross_pay)::numeric, 2) as avg_gross_pay,
        round(avg(s.perf_score)::numeric, 2) as avg_perf_score,
        round(avg(s.actual_attend::numeric / NULLIF(s.expected_attend, 0) * 100)::numeric, 1) as avg_attendance_rate
      FROM analytics.dim_employee de
      LEFT JOIN public.salary_detail_records s ON de.employee_id = s.employee_code
      GROUP BY de.position
      ORDER BY count(*) DESC
    `)

    sendSuccess(res, {
      position_summary: positionSummary.rows,
      employees: result.rows,
    }, { page, pageSize, total })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============================================================
// 9. 库存周转与损耗趋势
// ============================================================
router.get('/inventory/turnover', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    const storeCode = (req.query.store_code as string) || ''

    let storeFilter = ''
    const params: any[] = [month]
    if (storeCode) {
      params.push(storeCode)
      storeFilter = `AND fis.store_code = $${params.length}`
    }

    // 库存周转概览
    const turnoverResult = await query(`
      SELECT 
        fis.store_code,
        ds.store_name,
        round(sum(fis.opening_amount)::numeric, 2) as opening_value,
        round(sum(fis.purchase_amount)::numeric, 2) as purchase_value,
        round(sum(fis.consumption_amount)::numeric, 2) as consumption_value,
        round(sum(fis.ending_amount)::numeric, 2) as ending_value,
        round(sum(fis.waste_amount)::numeric, 2) as waste_value,
        round(avg(fis.ending_amount)::numeric, 2) as avg_ending,
        round(sum(fis.consumption_amount)::numeric / NULLIF(avg(fis.ending_amount) * count(*), 0) * 30, 1) as turnover_days
      FROM analytics.fact_inventory_snapshot fis
      LEFT JOIN analytics.dim_store ds ON fis.store_code = ds.store_code
      WHERE fis.snapshot_date >= $1 AND fis.snapshot_date < $1::date + interval '1 month'
      ${storeFilter}
      GROUP BY fis.store_code, ds.store_name
      ORDER BY turnover_days ASC
    `, params)

    // 损耗TOP
    const wasteTop = await query(`
      SELECT 
        dm.material_name,
        round(sum(fis.waste_quantity)::numeric, 2) as waste_qty,
        round(sum(fis.waste_amount)::numeric, 2) as waste_value,
        count(DISTINCT fis.store_code) as affected_stores
      FROM analytics.fact_inventory_snapshot fis
      LEFT JOIN analytics.dim_material dm ON fis.material_code = dm.material_code
      WHERE fis.snapshot_date >= $1 AND fis.snapshot_date < $1::date + interval '1 month'
        AND fis.waste_amount > 0
      ${storeFilter}
      GROUP BY dm.material_name
      ORDER BY waste_value DESC
      LIMIT 20
    `, params)

    sendSuccess(res, {
      turnover: turnoverResult.rows,
      waste_top: wasteTop.rows,
    })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============================================================
// 10. 营销ROI基础版
// ============================================================
router.get('/marketing/roi', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)

    // 各营销方案的效果对比
    const result = await query(`
      WITH plan_stats AS (
        SELECT 
          marketing_plan,
          count(*) as bill_count,
          round(sum(received_total)::numeric, 2) as total_revenue,
          round(avg(received_total)::numeric, 2) as avg_bill_value,
          round(avg(theoretical_margin) * 100, 2) as avg_margin,
          round(avg(discount_total)::numeric, 2) as avg_discount,
          round(sum(discount_total)::numeric, 2) as total_discount,
          count(DISTINCT member_id) FILTER (WHERE member_id IS NOT NULL AND member_id != '') as member_bills
        FROM analytics.bill_fact
        WHERE opened_at >= $1 AND opened_at < $1::date + interval '1 month'
          AND marketing_plan IS NOT NULL AND marketing_plan != ''
        GROUP BY marketing_plan
      ),
      no_plan_stats AS (
        SELECT 
          count(*) as bill_count,
          round(avg(received_total)::numeric, 2) as avg_bill_value,
          round(avg(theoretical_margin) * 100, 2) as avg_margin,
          round(avg(discount_total)::numeric, 2) as avg_discount
        FROM analytics.bill_fact
        WHERE opened_at >= $1 AND opened_at < $1::date + interval '1 month'
          AND (marketing_plan IS NULL OR marketing_plan = '')
      )
      SELECT 
        ps.marketing_plan,
        ps.bill_count,
        ps.total_revenue,
        ps.avg_bill_value,
        ps.avg_margin,
        ps.total_discount,
        ps.avg_discount,
        ps.member_bills,
        round((ps.member_bills::numeric / NULLIF(ps.bill_count, 0) * 100)::numeric, 1) as member_share_pct,
        round(((ps.avg_bill_value - nps.avg_bill_value) / NULLIF(nps.avg_bill_value, 0) * 100)::numeric, 1) as bill_value_uplift_pct,
        round((ps.avg_margin - nps.avg_margin)::numeric, 2) as margin_delta
      FROM plan_stats ps
      CROSS JOIN no_plan_stats nps
      ORDER BY ps.total_revenue DESC
    `, [month])

    // 无营销方案基准
    const baseline = await query(`
      SELECT 
        count(*) as bill_count,
        round(avg(received_total)::numeric, 2) as avg_bill_value,
        round(avg(theoretical_margin) * 100, 2) as avg_margin,
        round(avg(discount_total)::numeric, 2) as avg_discount
      FROM analytics.bill_fact
      WHERE opened_at >= $1 AND opened_at < $1::date + interval '1 month'
        AND (marketing_plan IS NULL OR marketing_plan = '')
    `, [month])

    sendSuccess(res, {
      baseline: baseline.rows[0],
      campaigns: result.rows,
    })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============================================================
// 11. 辖区巡检计划生成
// ============================================================
router.get('/region/inspection-plan', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)

    const result = await query(`
      SELECT 
        rr.store_code,
        rr.store_name,
        rr.risk_level,
        rr.primary_issue,
        rr.bill_count,
        round(rr.received::numeric, 2) as received,
        rr.anomaly_rate_pct,
        rr.discount_rate_pct,
        rr.member_bill_share_pct,
        ds.region,
        CASE rr.risk_level
          WHEN '高风险' THEN 1
          WHEN '中风险' THEN 2
          WHEN '低风险' THEN 3
          ELSE 4
        END as priority,
        CASE rr.risk_level
          WHEN '高风险' THEN '本周必须巡检'
          WHEN '中风险' THEN '两周内巡检'
          WHEN '低风险' THEN '月度例行巡检'
          ELSE '季度巡检'
        END as inspection_frequency,
        CASE rr.risk_level
          WHEN '高风险' THEN '重点检查: ' || COALESCE(rr.primary_issue, '综合风险')
          WHEN '中风险' THEN '关注: ' || COALESCE(rr.primary_issue, '常规指标')
          ELSE '常规检查'
        END as focus_area
      FROM analytics.mv_store_risk_rating_monthly rr
      LEFT JOIN analytics.dim_store ds ON rr.store_code = ds.store_code
      WHERE rr.month_start = $1
      ORDER BY priority, rr.received ASC
    `, [month])

    const summary = {
      total_stores: result.rows.length,
      high_risk: result.rows.filter((r: any) => r.risk_level === '高风险').length,
      medium_risk: result.rows.filter((r: any) => r.risk_level === '中风险').length,
      low_risk: result.rows.filter((r: any) => r.risk_level === '低风险').length,
      this_week: result.rows.filter((r: any) => r.priority === 1).length,
    }

    sendSuccess(res, { summary, plan: result.rows })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============================================================
// 12. 统一KPI达成率（支持门店/区域/总部三个维度）
// ============================================================
router.get('/kpi', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    const level = (req.query.level as string) || 'hq' // hq | region | store
    const region = (req.query.region as string) || ''
    const storeCode = (req.query.store_code as string) || ''

    if (level === 'store' && storeCode) {
      // 单门店KPI
      const result = await query(`
        SELECT 
          r.store_code,
          r.store_name,
          round(r.received::numeric, 2) as actual_revenue,
          round(r.bill_count::numeric, 0) as actual_bills,
          t.revenue_target,
          t.bill_count_target,
          t.profit_target,
          e.actual_store_contribution as actual_profit,
          round((r.received / NULLIF(t.revenue_target, 0) * 100)::numeric, 1) as revenue_achievement_pct,
          round(CASE 
            WHEN t.profit_target > 0 THEN e.actual_store_contribution / t.profit_target * 100
            WHEN t.profit_target < 0 THEN (2 * ABS(t.profit_target) - ABS(e.actual_store_contribution)) / ABS(t.profit_target) * 100
            ELSE NULL
          END::numeric, 1) as profit_achievement_pct,
          round((e.actual_store_contribution / NULLIF(r.received, 0) * 100)::numeric, 2) as profit_margin_pct
        FROM analytics.mv_store_risk_rating_monthly r
        LEFT JOIN analytics.dim_store_target t ON r.store_code = t.store_code AND t.target_month = $1
        LEFT JOIN analytics.mv_store_operating_expense_monthly e ON r.store_code = e.sales_store_code AND e.report_month = $1
        WHERE r.month_start = $1 AND r.store_code = $2
      `, [month, storeCode])
      sendSuccess(res, result.rows[0] || {})
    } else if (level === 'region') {
      // 按区域汇总KPI
      const scope = getDataScope(req)
      const scopeCodes = scope?.role === 'store' || scope?.role === 'regional'
        ? (scope.storeCode || scope.region || '').split(',').map(s => s.trim()).filter(Boolean)
        : []
      const hasScope = scopeCodes.length > 0
      const scopeParamIdx = hasScope ? 2 : 0
      const scopeParams = hasScope ? [month, scopeCodes] : [month]
      const scopeFilter = hasScope ? ` AND r.store_code = ANY($${scopeParamIdx})` : ''
      const scopeFilterTarget = hasScope ? ` AND t.store_code = ANY($${scopeParamIdx})` : ''
      const result = await query(`
        WITH actual AS (
          SELECT 
            ds.region,
            round(sum(r.received)::numeric, 2) as actual_revenue,
            sum(r.bill_count) as actual_bills,
            round(sum(e.actual_store_contribution)::numeric, 2) as actual_profit
          FROM analytics.mv_store_risk_rating_monthly r
          JOIN analytics.dim_store ds ON r.store_code = ds.store_code
          LEFT JOIN analytics.mv_store_operating_expense_monthly e ON r.store_code = e.sales_store_code AND e.report_month = $1
          WHERE r.month_start = $1
            AND ds.region IS NOT NULL AND ds.region != '未知区域'${scopeFilter}
          GROUP BY ds.region
        ),
        target AS (
          SELECT 
            ds.region,
            round(sum(t.revenue_target)::numeric, 2) as revenue_target,
            round(sum(t.bill_count_target)::numeric, 0) as bill_count_target,
            round(sum(t.profit_target)::numeric, 2) as profit_target
          FROM analytics.dim_store_target t
          JOIN analytics.dim_store ds ON t.store_code = ds.store_code
          WHERE t.target_month = $1
            AND ds.region IS NOT NULL AND ds.region != '未知区域'${scopeFilterTarget}
          GROUP BY ds.region
        )
        SELECT 
          a.region,
          a.actual_revenue,
          a.actual_bills,
          a.actual_profit,
          t.revenue_target,
          t.bill_count_target,
          t.profit_target,
          round((a.actual_revenue / NULLIF(t.revenue_target, 0) * 100)::numeric, 1) as revenue_achievement_pct,
          round(CASE 
            WHEN t.profit_target > 0 THEN a.actual_profit / t.profit_target * 100
            WHEN t.profit_target < 0 THEN (2 * ABS(t.profit_target) - ABS(a.actual_profit)) / ABS(t.profit_target) * 100
            ELSE NULL
          END::numeric, 1) as profit_achievement_pct,
          round((a.actual_profit / NULLIF(a.actual_revenue, 0) * 100)::numeric, 2) as profit_margin_pct
        FROM actual a
        LEFT JOIN target t ON a.region = t.region
        ORDER BY a.actual_revenue DESC
      `, scopeParams, { skipScope: true })
      sendSuccess(res, result.rows)
    } else {
      // 总部汇总KPI
      const result = await query(`
        WITH actual AS (
          SELECT 
            round(sum(r.received)::numeric, 2) as actual_revenue,
            sum(r.bill_count) as actual_bills,
            round(sum(e.actual_store_contribution)::numeric, 2) as actual_profit
          FROM analytics.mv_store_risk_rating_monthly r
          LEFT JOIN analytics.mv_store_operating_expense_monthly e ON r.store_code = e.sales_store_code AND e.report_month = $1
          WHERE r.month_start = $1
        ),
        target AS (
          SELECT 
            round(sum(t.revenue_target)::numeric, 2) as revenue_target,
            round(sum(t.bill_count_target)::numeric, 0) as bill_count_target,
            round(sum(t.profit_target)::numeric, 2) as profit_target
          FROM analytics.dim_store_target t
          WHERE t.target_month = $1
        )
        SELECT 
          a.actual_revenue,
          a.actual_bills,
          a.actual_profit,
          t.revenue_target,
          t.bill_count_target,
          t.profit_target,
          round((a.actual_revenue / NULLIF(t.revenue_target, 0) * 100)::numeric, 1) as revenue_achievement_pct,
          round(CASE 
            WHEN t.profit_target > 0 THEN a.actual_profit / t.profit_target * 100
            WHEN t.profit_target < 0 THEN (2 * ABS(t.profit_target) - ABS(a.actual_profit)) / ABS(t.profit_target) * 100
            ELSE NULL
          END::numeric, 1) as profit_achievement_pct,
          round((a.actual_profit / NULLIF(a.actual_revenue, 0) * 100)::numeric, 2) as profit_margin_pct
        FROM actual a
        CROSS JOIN target t
      `, [month])
      sendSuccess(res, result.rows[0] || {})
    }
  } catch (err: any) {
    sendError(res, err.message)
  }
})

export default router
