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

const router = Router()

// ============ Tab1: 费用总览 ============

// 费用总览指标
router.get('/overview', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    const result = await query(`
      WITH bill_discount AS (
        SELECT store_code,
          round(sum(discount_total)::numeric, 2) AS discount
        FROM analytics.bill_fact
        WHERE closed_at >= $1::date AND closed_at < ($1::date + interval '1 month')
        GROUP BY store_code
      ),
      full_scope AS (
        SELECT
          r.store_code,
          r.store_name,
          r.received,
          e.consumption,
          COALESCE(bd.discount, e.consumption - e.received) AS discount,
          r.bill_count,
          r.theoretical_margin_pct,
          e.operating_expense,
          e.wage_expense,
          e.rent_expense,
          e.utility_expense,
          e.dorm_expense,
          e.delivery_commission_expense,
          e.card_fee_expense,
          e.repair_clean_expense,
          e.actual_food_cost,
          COALESCE(e.theoretical_cost, r.received * (1 - COALESCE(r.theoretical_margin_pct, 0) / 100)) AS theoretical_cost,
          CASE WHEN e.operating_expense IS NOT NULL THEN (r.received - e.actual_food_cost - e.operating_expense) ELSE NULL END AS actual_store_contribution,
          CASE WHEN e.operating_expense IS NOT NULL THEN (r.received - r.received * (1 - COALESCE(r.theoretical_margin_pct, 0) / 100) - e.operating_expense) ELSE NULL END AS theoretical_store_contribution,
          e.area_sqm
        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::date
        LEFT JOIN bill_discount bd ON bd.store_code = r.store_code
        WHERE r.month_start = $1 AND r.received IS NOT NULL
      )
      SELECT
        count(*) AS total_stores,
        count(*) FILTER (WHERE actual_store_contribution > 0) AS profitable_stores,
        count(*) FILTER (WHERE actual_store_contribution <= 0 AND received > 0 AND actual_store_contribution IS NOT NULL) AS loss_stores,
        count(*) FILTER (WHERE operating_expense IS NULL) AS no_expense_stores,
        sum(bill_count)::bigint AS total_bills,
        round(sum(consumption)::numeric, 2) AS total_consumption,
        round(sum(discount)::numeric, 2) AS total_discount,
        round(sum(received)::numeric, 2) AS total_received,
        round(sum(received) / nullif(sum(bill_count), 0), 2) AS avg_bill_value,
        round(sum(operating_expense)::numeric, 2) AS total_expense,
        round(sum(wage_expense)::numeric, 2) AS total_wage,
        round(sum(rent_expense)::numeric, 2) AS total_rent,
        round(sum(utility_expense)::numeric, 2) AS total_utility,
        round(sum(dorm_expense)::numeric, 2) AS total_dorm,
        round(sum(delivery_commission_expense)::numeric, 2) AS total_commission,
        round(sum(card_fee_expense)::numeric, 2) AS total_card_fee,
        round(sum(repair_clean_expense)::numeric, 2) AS total_repair,
        round(sum(actual_food_cost)::numeric, 2) AS total_food_cost,
        round(sum(theoretical_cost)::numeric, 2) AS total_theoretical_cost,
        round(sum(actual_store_contribution)::numeric, 2) AS total_contribution,
        round(sum(theoretical_store_contribution)::numeric, 2) AS total_theoretical_contribution,
        round(sum(received) - sum(theoretical_cost) - sum(operating_expense), 2) AS theoretical_net_profit,
        round(sum(received) - sum(actual_food_cost) - sum(operating_expense), 2) AS actual_net_profit,
        round(sum(area_sqm)::numeric, 2) AS total_area,
        round((1 - sum(operating_expense) / nullif(sum(received), 0)) * 100, 2) AS overall_expense_rate_pct,
        round((1 - (sum(actual_food_cost) + sum(operating_expense)) / nullif(sum(received), 0)) * 100, 2) AS overall_contribution_rate_pct,
        round((sum(received) - sum(theoretical_cost) - sum(operating_expense)) / nullif(sum(received), 0) * 100, 2) AS theoretical_net_margin_pct,
        round((sum(received) - sum(actual_food_cost) - sum(operating_expense)) / nullif(sum(received), 0) * 100, 2) AS actual_net_margin_pct,
        round(sum(theoretical_cost) / nullif(sum(received), 0) * 100, 2) AS theoretical_food_cost_rate_pct,
        round(sum(actual_food_cost) / nullif(sum(received), 0) * 100, 2) AS actual_food_cost_rate_pct,
        round(sum(wage_expense) / nullif(sum(received), 0) * 100, 2) AS overall_wage_rate_pct,
        round(sum(rent_expense) / nullif(sum(received), 0) * 100, 2) AS overall_rent_rate_pct,
        round(sum(utility_expense) / nullif(sum(received), 0) * 100, 2) AS overall_utility_rate_pct
      FROM full_scope
    `, [month])
    sendSuccess(res, result.rows[0])
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// 费用结构分析
router.get('/expense-structure', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    const result = await query(`
      SELECT account_name,
        round(amount::numeric, 2) AS amount,
        round(expense_share_pct::numeric, 2) AS expense_share_pct,
        nonzero_cost_unit_count
      FROM analytics.v_operating_expense_account_monthly
      WHERE report_month = $1::date
      ORDER BY amount DESC
    `, [month])
    sendSuccess(res, result.rows)
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============ Tab2: 门店费用率排名 ============

// 门店费用率排名
router.get('/store-ranking', async (req: AuthRequest, res) => {
  try {
    const { page, pageSize, offset } = parsePagination(req)
    const sort = (req.query.sort as string) || 'operating_expense_rate_pct'
    const order = (req.query.order as string) === 'asc' ? 'ASC' : 'DESC'
    const filter = (req.query.filter as string) || ''
    const month = parseMonth(req)

    let where = `WHERE report_month = $1::date`
    const params: any[] = [month]
    if (filter === 'loss') {
      where += ` AND actual_store_contribution <= 0 AND received > 0`
    } else if (filter === 'profitable') {
      where += ` AND actual_store_contribution > 0`
    } else if (filter === 'zero_sales') {
      where += ` AND received = 0`
    }

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

    const validSorts = ['operating_expense_rate_pct', 'wage_rate_pct', 'rent_rate_pct', 'utility_rate_pct', 'received', 'operating_expense', 'actual_store_contribution', 'actual_store_contribution_rate_pct', 'received_per_sqm']
    const sortCol = validSorts.includes(sort) ? sort : 'operating_expense_rate_pct'

    const result = await query(`
      SELECT sales_store_code, sales_store_name,
        round(received::numeric, 2) AS received,
        round(operating_expense::numeric, 2) AS operating_expense,
        round(operating_expense_rate_pct::numeric, 2) AS operating_expense_rate_pct,
        round(wage_expense::numeric, 2) AS wage_expense,
        round(wage_rate_pct::numeric, 2) AS wage_rate_pct,
        round(rent_expense::numeric, 2) AS rent_expense,
        round(rent_rate_pct::numeric, 2) AS rent_rate_pct,
        round(utility_expense::numeric, 2) AS utility_expense,
        round(utility_rate_pct::numeric, 2) AS utility_rate_pct,
        round(actual_food_cost::numeric, 2) AS actual_food_cost,
        round(actual_store_contribution::numeric, 2) AS actual_store_contribution,
        round(actual_store_contribution_rate_pct::numeric, 2) AS actual_store_contribution_rate_pct,
        round(area_sqm::numeric, 2) AS area_sqm,
        round(received_per_sqm::numeric, 2) AS received_per_sqm,
        lease_expiry_date
      FROM analytics.mv_store_operating_expense_monthly
      ${where}
      ORDER BY ${sortCol} ${order} NULLS LAST LIMIT $${params.length + 1} OFFSET $${params.length + 2}
    `, [...params, pageSize, offset])

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

// ============ Tab3: 门店贡献利润 ============

// 门店贡献利润分析
router.get('/store-contribution', async (req: AuthRequest, res) => {
  try {
    const { page, pageSize, offset } = parsePagination(req)
    const sort = (req.query.sort as string) || 'actual_store_contribution_rate_pct'
    const order = (req.query.order as string) === 'desc' ? 'DESC' : 'ASC'
    const filter = (req.query.filter as string) || ''
    const month = parseMonth(req)

    let where = `WHERE report_month = $1::date`
    const params: any[] = [month]
    if (filter === 'loss') {
      where += ` AND actual_store_contribution <= 0 AND received > 0`
    } else if (filter === 'profitable') {
      where += ` AND actual_store_contribution > 0`
    } else if (filter === 'zero_sales') {
      where += ` AND received = 0`
    } else {
      where += ` AND received > 0`
    }

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

    const validSorts = ['received', 'actual_store_contribution', 'actual_store_contribution_rate_pct', 'theoretical_store_contribution', 'theoretical_store_contribution_rate_pct', 'contribution_variance', 'operating_expense_rate_pct', 'wage_rate_pct', 'rent_rate_pct', 'received_per_sqm']
    const sortCol = validSorts.includes(sort) ? sort : 'actual_store_contribution_rate_pct'

    const result = await query(`
      SELECT sales_store_code, sales_store_name,
        round(received::numeric, 2) AS received,
        round(theoretical_cost::numeric, 2) AS theoretical_cost,
        round(actual_food_cost::numeric, 2) AS actual_food_cost,
        round(operating_expense::numeric, 2) AS operating_expense,
        round(theoretical_store_contribution::numeric, 2) AS theoretical_store_contribution,
        round(theoretical_store_contribution_rate_pct::numeric, 2) AS theoretical_store_contribution_rate_pct,
        round(actual_store_contribution::numeric, 2) AS actual_store_contribution,
        round(actual_store_contribution_rate_pct::numeric, 2) AS actual_store_contribution_rate_pct,
        round((actual_store_contribution - theoretical_store_contribution)::numeric, 2) AS contribution_variance
      FROM analytics.mv_store_operating_expense_monthly
      ${where}
      ORDER BY ${sortCol} ${order} NULLS LAST LIMIT $${params.length + 1} OFFSET $${params.length + 2}
    `, [...params, pageSize, offset])

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

// ============ Tab4: 房租及租约风险 ============

// 房租及租约风险
router.get('/rent-risk', async (req: AuthRequest, res) => {
  try {
    const { page, pageSize, offset } = parsePagination(req)
    const sort = (req.query.sort as string) || 'rent_rate_pct'
    const order = (req.query.order as string) === 'asc' ? 'ASC' : 'DESC'
    const filter = (req.query.filter as string) || ''
    const riskOnly = req.query.risk_only === 'true'
    const month = parseMonth(req)

    let where = `WHERE report_month = $1::date AND rent_expense IS NOT NULL`
    const params: any[] = [month]
    if (filter === 'loss') {
      where += ` AND actual_store_contribution <= 0 AND received > 0`
    } else if (filter === 'profitable') {
      where += ` AND actual_store_contribution > 0`
    } else if (filter === 'zero_sales') {
      where += ` AND received = 0`
    }
    if (riskOnly) {
      where += ` AND (lease_expiry_date <= $1::date + interval '12 months' OR rent_rate_pct > 20)`
    }

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

    const validSorts = ['rent_rate_pct', 'rent_expense', 'received', 'received_per_sqm', 'lease_expiry_date', 'operating_expense_rate_pct', 'actual_store_contribution']
    const sortCol = validSorts.includes(sort) ? sort : 'rent_rate_pct'
    const orderBy = sortCol === 'lease_expiry_date'
      ? `CASE WHEN lease_expiry_date IS NULL THEN 1 ELSE 0 END, lease_expiry_date ASC NULLS LAST`
      : `${sortCol} ${order} NULLS LAST`

    const result = await query(`
      SELECT sales_store_code, sales_store_name,
        round(received::numeric, 2) AS received,
        round(rent_expense::numeric, 2) AS rent_expense,
        round(rent_rate_pct::numeric, 2) AS rent_rate_pct,
        round(area_sqm::numeric, 2) AS area_sqm,
        round(received_per_sqm::numeric, 2) AS received_per_sqm,
        lease_expiry_date,
        CASE
          WHEN lease_expiry_date <= $1::date + interval '3 months' THEN '即将到期'
          WHEN lease_expiry_date <= $1::date + interval '12 months' THEN '年内到期'
          WHEN lease_expiry_date <= $1::date + interval '18 months' THEN '明年上半年到期'
          WHEN rent_rate_pct > 20 THEN '租金占比偏高'
          ELSE '正常'
        END AS risk_level,
        CASE
          WHEN lease_expiry_date <= $1::date + interval '3 months' THEN '需立即启动续租谈判或关停评估'
          WHEN lease_expiry_date <= $1::date + interval '12 months' THEN '需提前规划续租或迁址方案'
          WHEN rent_rate_pct > 25 THEN '租金严重偏高，建议谈判降租或迁址'
          WHEN rent_rate_pct > 20 THEN '租金占比偏高，关注续租条件'
          ELSE '保持关注'
        END AS suggestion
      FROM analytics.mv_store_operating_expense_monthly
      ${where}
      ORDER BY ${orderBy}
      LIMIT $${params.length + 1} OFFSET $${params.length + 2}
    `, [...params, pageSize, offset])

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

// ============ Tab5: 外卖佣金分析 ============

// 外卖佣金分析
router.get('/delivery-commission', async (req: AuthRequest, res) => {
  try {
    const { page, pageSize, offset } = parsePagination(req)
    const sort = (req.query.sort as string) || 'commission_to_delivery_sales_pct'
    const order = (req.query.order as string) === 'asc' ? 'ASC' : 'DESC'
    const filter = (req.query.filter as string) || ''
    const month = parseMonth(req)

    let where = `WHERE report_month = $1::date AND delivery_received > 0`
    const params: any[] = [month]
    if (filter === 'loss') {
      where += ` AND actual_store_contribution <= 0`
    } else if (filter === 'profitable') {
      where += ` AND actual_store_contribution > 0`
    }

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

    const validSorts = ['commission_to_delivery_sales_pct', 'delivery_sales_share_pct', 'delivery_received', 'delivery_commission_expense', 'combined_platform_cost_rate_pct', 'received', 'actual_store_contribution']
    const sortCol = validSorts.includes(sort) ? sort : 'commission_to_delivery_sales_pct'

    const result = await query(`
      SELECT sales_store_code, sales_store_name,
        round(received::numeric, 2) AS received,
        round(delivery_received::numeric, 2) AS delivery_received,
        round(delivery_sales_share_pct::numeric, 2) AS delivery_sales_share_pct,
        round(delivery_commission_expense::numeric, 2) AS delivery_commission_expense,
        round(commission_to_delivery_sales_pct::numeric, 2) AS commission_to_delivery_sales_pct,
        round(combined_platform_cost_rate_pct::numeric, 2) AS combined_platform_cost_rate_pct,
        CASE
          WHEN delivery_sales_share_pct > 40 THEN '重度依赖外卖'
          WHEN delivery_sales_share_pct > 25 THEN '外卖占比较高'
          WHEN delivery_sales_share_pct > 10 THEN '外卖占比正常'
          ELSE '以堂食为主'
        END AS delivery_type,
        CASE
          WHEN commission_to_delivery_sales_pct > 25 THEN '佣金率偏高，建议优化平台策略'
          WHEN delivery_sales_share_pct > 40 THEN '外卖依赖度高，建议提升堂食客流'
          WHEN combined_platform_cost_rate_pct > 30 THEN '综合平台成本率高，需评估外卖盈利性'
          ELSE '外卖运营正常'
        END AS suggestion
      FROM analytics.mv_store_operating_expense_monthly
      ${where}
      ORDER BY ${sortCol} ${order} NULLS LAST LIMIT $${params.length + 1} OFFSET $${params.length + 2}
    `, [...params, pageSize, offset])

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

// ============ Tab6: 人效坪效 ============

// 人效坪效分析
router.get('/efficiency', async (req: AuthRequest, res) => {
  try {
    const { page, pageSize, offset } = parsePagination(req)
    const sort = (req.query.sort as string) || 'received_per_sqm'
    const order = (req.query.order as string) === 'asc' ? 'ASC' : 'DESC'
    const filter = (req.query.filter as string) || ''
    const month = parseMonth(req)

    let where = `WHERE report_month = $1::date AND received > 0 AND area_sqm IS NOT NULL`
    const params: any[] = [month]
    if (filter === 'loss') {
      where += ` AND actual_store_contribution <= 0`
    } else if (filter === 'profitable') {
      where += ` AND actual_store_contribution > 0`
    }

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

    const validSorts = ['received_per_sqm', 'wage_rate_pct', 'received', 'wage_expense', 'bill_count', 'avg_ticket_size', 'actual_store_contribution', 'operating_expense_rate_pct']
    const sortCol = validSorts.includes(sort) ? sort : 'received_per_sqm'

    const result = await query(`
      SELECT sales_store_code, sales_store_name,
        round(received::numeric, 2) AS received,
        round(area_sqm::numeric, 2) AS area_sqm,
        round(received_per_sqm::numeric, 2) AS received_per_sqm,
        round(wage_expense::numeric, 2) AS wage_expense,
        round(wage_rate_pct::numeric, 2) AS wage_rate_pct,
        round(received / nullif(wage_expense, 0)::numeric, 2) AS revenue_per_wage,
        round(bill_count::numeric, 0) AS bill_count,
        round(received / nullif(bill_count, 0)::numeric, 2) AS avg_ticket_size,
        CASE
          WHEN received_per_sqm < 1000 THEN '坪效偏低'
          WHEN received_per_sqm < 2000 THEN '坪效一般'
          WHEN received_per_sqm < 4000 THEN '坪效良好'
          ELSE '坪效优秀'
        END AS efficiency_level,
        CASE
          WHEN wage_rate_pct > 35 THEN '人工成本率偏高，需优化排班或提升营业额'
          WHEN received_per_sqm < 1000 AND area_sqm > 400 THEN '面积大产出低，考虑缩减面积或改造'
          WHEN wage_rate_pct > 25 AND wage_rate_pct <= 35 THEN '人工成本率中等偏高，关注人效'
          ELSE '运营效率正常'
        END AS suggestion
      FROM analytics.mv_store_operating_expense_monthly
      ${where}
      ORDER BY ${sortCol} ${order} NULLS LAST LIMIT $${params.length + 1} OFFSET $${params.length + 2}
    `, [...params, pageSize, offset])

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

// ============ Tab7: 固定/变动费用拆分 ============

// 固定/变动费用拆分
router.get('/fixed-variable', async (req: AuthRequest, res) => {
  try {
    const { page, pageSize, offset } = parsePagination(req)
    const sort = (req.query.sort as string) || 'fixed_rate_pct'
    const order = (req.query.order as string) === 'asc' ? 'ASC' : 'DESC'
    const filter = (req.query.filter as string) || ''
    const month = parseMonth(req)

    let where = `WHERE report_month = $1::date AND received > 0`
    const params: any[] = [month]
    if (filter === 'loss') {
      where += ` AND actual_store_contribution <= 0`
    } else if (filter === 'profitable') {
      where += ` AND actual_store_contribution > 0`
    }

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

    const validSorts = ['fixed_rate_pct', 'variable_rate_pct', 'received', 'fixed_expense', 'variable_expense', 'contribution_after_variable', 'break_even_sales', 'actual_store_contribution', 'operating_expense_rate_pct']
    const sortCol = validSorts.includes(sort) ? sort : 'fixed_rate_pct'

    const result = await query(`
      SELECT sales_store_code, sales_store_name,
        round(received::numeric, 2) AS received,
        round((rent_expense + dorm_expense + repair_clean_expense * 0.5)::numeric, 2) AS fixed_expense,
        round((wage_expense + utility_expense + delivery_commission_expense + card_fee_expense + repair_clean_expense * 0.5)::numeric, 2) AS variable_expense,
        round(rent_expense::numeric, 2) AS rent_expense,
        round(dorm_expense::numeric, 2) AS dorm_expense,
        round(wage_expense::numeric, 2) AS wage_expense,
        round(utility_expense::numeric, 2) AS utility_expense,
        round(delivery_commission_expense::numeric, 2) AS delivery_commission_expense,
        round(card_fee_expense::numeric, 2) AS card_fee_expense,
        round(repair_clean_expense::numeric, 2) AS repair_clean_expense,
        round((rent_expense + dorm_expense + repair_clean_expense * 0.5) / nullif(received, 0) * 100::numeric, 2) AS fixed_rate_pct,
        round((wage_expense + utility_expense + delivery_commission_expense + card_fee_expense + repair_clean_expense * 0.5) / nullif(received, 0) * 100::numeric, 2) AS variable_rate_pct,
        round((received - actual_food_cost - wage_expense - utility_expense - delivery_commission_expense - card_fee_expense - repair_clean_expense * 0.5)::numeric, 2) AS contribution_after_variable,
        round((rent_expense + dorm_expense + repair_clean_expense * 0.5)::numeric, 2) AS break_even_sales
      FROM analytics.mv_store_operating_expense_monthly
      ${where}
      ORDER BY ${sortCol} ${order} NULLS LAST LIMIT $${params.length + 1} OFFSET $${params.length + 2}
    `, [...params, pageSize, offset])

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

// ============ Tab8: 盈亏平衡分析 ============

// 盈亏平衡分析
router.get('/break-even', async (req: AuthRequest, res) => {
  try {
    const { page, pageSize, offset } = parsePagination(req)
    const sort = (req.query.sort as string) || 'safety_margin_pct'
    const order = (req.query.order as string) === 'desc' ? 'DESC' : 'ASC'
    const filter = (req.query.filter as string) || ''
    const month = parseMonth(req)

    let where = `WHERE report_month = $1::date AND received > 0`
    const params: any[] = [month]
    if (filter === 'loss') {
      where += ` AND actual_store_contribution <= 0`
    } else if (filter === 'profitable') {
      where += ` AND actual_store_contribution > 0`
    }

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

    const validSorts = ['safety_margin_pct', 'break_even_sales', 'sales_gap', 'food_cost_rate_pct', 'expense_rate_pct', 'received', 'actual_store_contribution', 'operating_expense_rate_pct']
    const sortCol = validSorts.includes(sort) ? sort : 'safety_margin_pct'

    const result = await query(`
      WITH base AS (
        SELECT sales_store_code, sales_store_name,
          received, actual_food_cost, operating_expense,
          actual_food_cost / nullif(received, 0) AS food_cost_ratio,
          operating_expense / nullif(received, 0) AS expense_ratio,
          1 - actual_food_cost / nullif(received, 0) AS contribution_margin_ratio,
          CASE
            WHEN 1 - actual_food_cost / nullif(received, 0) <= 0 THEN NULL
            ELSE operating_expense / nullif(1 - actual_food_cost / nullif(received, 0), 0)
          END AS break_even_sales
        FROM analytics.mv_store_operating_expense_monthly
        ${where}
      )
      SELECT sales_store_code, sales_store_name,
        round(received::numeric, 2) AS received,
        round(actual_food_cost::numeric, 2) AS actual_food_cost,
        round(operating_expense::numeric, 2) AS operating_expense,
        round((food_cost_ratio * 100)::numeric, 2) AS food_cost_rate_pct,
        round((expense_ratio * 100)::numeric, 2) AS expense_rate_pct,
        round(break_even_sales::numeric, 2) AS break_even_sales,
        round((received - break_even_sales)::numeric, 2) AS sales_gap,
        round(((received - break_even_sales) / nullif(break_even_sales, 0) * 100)::numeric, 2) AS safety_margin_pct,
        CASE
          WHEN contribution_margin_ratio <= 0 THEN '无法盈利'
          WHEN received < break_even_sales THEN '未达盈亏平衡'
          WHEN (received - break_even_sales) / nullif(break_even_sales, 0) * 100 < 15 THEN '接近盈亏平衡'
          WHEN (received - break_even_sales) / nullif(break_even_sales, 0) * 100 < 30 THEN '安全边际较低'
          ELSE '安全边际充足'
        END AS safety_status
      FROM base
      ORDER BY ${sortCol} ${order} NULLS LAST LIMIT $${params.length + 1} OFFSET $${params.length + 2}
    `, [...params, pageSize, offset])

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

// ============ Tab9: 亏损门店诊断 ============

// 亏损门店诊断 - 自动分析亏损原因并给出建议
router.get('/loss-diagnosis', async (req: AuthRequest, res) => {
  try {
    const { page, pageSize, offset } = parsePagination(req)
    const sort = (req.query.sort as string) || 'actual_store_contribution'
    const order = (req.query.order as string) === 'desc' ? 'DESC' : 'ASC'
    const filter = (req.query.filter as string) || ''
    const month = parseMonth(req)

    let where = `WHERE report_month = $1::date AND actual_store_contribution <= 0 AND received > 0`
    const params: any[] = [month]
    if (filter === 'P0') {
      where += ` AND actual_store_contribution_rate_pct < -20`
    } else if (filter === 'P1') {
      where += ` AND actual_store_contribution_rate_pct >= -20 AND actual_store_contribution_rate_pct < -5`
    } else if (filter === 'P2') {
      where += ` AND actual_store_contribution_rate_pct >= -5 AND actual_store_contribution_rate_pct <= 0`
    }

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

    const validSorts = ['actual_store_contribution', 'actual_store_contribution_rate_pct', 'received', 'wage_rate_pct', 'rent_rate_pct', 'utility_rate_pct', 'received_per_sqm', 'operating_expense_rate_pct']
    const sortCol = validSorts.includes(sort) ? sort : 'actual_store_contribution'

    const result = await query(`
      SELECT sales_store_code, sales_store_name,
        round(received::numeric, 2) AS received,
        round(actual_food_cost::numeric, 2) AS actual_food_cost,
        round(operating_expense::numeric, 2) AS operating_expense,
        round(actual_store_contribution::numeric, 2) AS actual_store_contribution,
        round(actual_store_contribution_rate_pct::numeric, 2) AS actual_store_contribution_rate_pct,
        round(wage_expense::numeric, 2) AS wage_expense,
        round(wage_rate_pct::numeric, 2) AS wage_rate_pct,
        round(rent_expense::numeric, 2) AS rent_expense,
        round(rent_rate_pct::numeric, 2) AS rent_rate_pct,
        round(utility_expense::numeric, 2) AS utility_expense,
        round(utility_rate_pct::numeric, 2) AS utility_rate_pct,
        round(dorm_expense::numeric, 2) AS dorm_expense,
        round(delivery_commission_expense::numeric, 2) AS delivery_commission_expense,
        round(delivery_received::numeric, 2) AS delivery_received,
        round(delivery_sales_share_pct::numeric, 2) AS delivery_sales_share_pct,
        round(area_sqm::numeric, 2) AS area_sqm,
        round(received_per_sqm::numeric, 2) AS received_per_sqm,
        round(bill_count::numeric, 0) AS bill_count,
        lease_expiry_date,
        round(theoretical_cost::numeric, 2) AS theoretical_cost,
        round(theoretical_store_contribution::numeric, 2) AS theoretical_store_contribution,
        round(theoretical_store_contribution_rate_pct::numeric, 2) AS theoretical_store_contribution_rate_pct,
        CASE
          WHEN received < 10000 THEN '收入极低'
          WHEN received < 50000 THEN '收入偏低'
          ELSE '收入正常'
        END AS revenue_status,
        CASE
          WHEN actual_food_cost / nullif(received, 0) * 100 > 50 THEN '食材成本率过高'
          WHEN actual_food_cost / nullif(received, 0) * 100 > 40 THEN '食材成本率偏高'
          ELSE '食材成本率正常'
        END AS food_cost_status,
        CASE
          WHEN wage_rate_pct > 50 THEN '人工成本率严重过高'
          WHEN wage_rate_pct > 35 THEN '人工成本率过高'
          WHEN wage_rate_pct > 25 THEN '人工成本率偏高'
          ELSE '人工成本率正常'
        END AS wage_status,
        CASE
          WHEN rent_rate_pct > 25 THEN '租金占比严重过高'
          WHEN rent_rate_pct > 20 THEN '租金占比过高'
          WHEN rent_rate_pct > 15 THEN '租金占比偏高'
          ELSE '租金占比正常'
        END AS rent_status,
        CASE
          WHEN utility_rate_pct > 15 THEN '水电燃气率过高'
          WHEN utility_rate_pct > 10 THEN '水电燃气率偏高'
          ELSE '水电燃气率正常'
        END AS utility_status,
        CASE
          WHEN delivery_sales_share_pct > 40 THEN '外卖依赖度过高'
          WHEN delivery_sales_share_pct > 25 THEN '外卖占比较高'
          ELSE '外卖占比正常'
        END AS delivery_status,
        CASE
          WHEN received_per_sqm < 500 THEN '坪效极低'
          WHEN received_per_sqm < 1000 THEN '坪效偏低'
          ELSE '坪效正常'
        END AS efficiency_status,
        CASE
          WHEN lease_expiry_date IS NOT NULL AND lease_expiry_date <= $1::date + interval '12 months' THEN '租约即将到期'
          ELSE '租约正常'
        END AS lease_status,
        CASE
          WHEN theoretical_store_contribution <= 0 THEN '理论即亏损'
          WHEN theoretical_store_contribution > 0 AND actual_store_contribution <= 0 THEN '实际超耗导致亏损'
          ELSE '费用过高导致亏损'
        END AS loss_type
      FROM analytics.mv_store_operating_expense_monthly
      ${where}
      ORDER BY ${sortCol} ${order} NULLS LAST LIMIT $${params.length + 1} OFFSET $${params.length + 2}
    `, [...params, pageSize, offset])

    // 为每个亏损门店生成诊断原因和建议
    const rows = result.rows.map((r: any) => {
      const reasons: string[] = []
      const suggestions: string[] = []
      const actions: string[] = []

      // 收入问题
      if (r.revenue_status === '收入极低') {
        reasons.push('门店收入极低，可能处于停业或半停业状态')
        suggestions.push('核查门店是否正常营业，评估是否值得继续经营')
        actions.push('核查营业状态')
      } else if (r.revenue_status === '收入偏低') {
        reasons.push('门店收入偏低，无法覆盖固定费用')
        suggestions.push('提升客流和客单价，开展营销活动拉动销售')
        actions.push('提升营业额')
      }

      // 食材成本问题
      if (r.food_cost_status === '食材成本率过高') {
        reasons.push(`食材成本率高达${Math.round(r.actual_food_cost / r.received * 100)}%，远超行业标杆`)
        suggestions.push('核查BOM配方准确性、物料损耗和采购成本，优化高成本菜品')
        actions.push('优化食材成本')
      } else if (r.food_cost_status === '食材成本率偏高') {
        reasons.push(`食材成本率${Math.round(r.actual_food_cost / r.received * 100)}%偏高`)
        suggestions.push('关注物料损耗和超耗菜品，优化配方和份量')
        actions.push('控制食材成本')
      }

      // 人工成本问题
      if (r.wage_status === '人工成本率严重过高') {
        reasons.push(`人工成本率${r.wage_rate_pct}%严重过高`)
        suggestions.push('大幅优化排班、减少冗余人员，考虑合并岗位或引入兼职')
        actions.push('优化人工配置')
      } else if (r.wage_status === '人工成本率过高') {
        reasons.push(`人工成本率${r.wage_rate_pct}%过高`)
        suggestions.push('优化排班效率，评估人员配置是否合理')
        actions.push('优化排班')
      } else if (r.wage_status === '人工成本率偏高') {
        reasons.push(`人工成本率${r.wage_rate_pct}%偏高`)
        suggestions.push('关注人效指标，适度优化排班')
        actions.push('关注人效')
      }

      // 租金问题
      if (r.rent_status === '租金占比严重过高') {
        reasons.push(`租金占比${r.rent_rate_pct}%严重过高`)
        suggestions.push('与房东谈判降租，或评估迁址/关停方案')
        actions.push('谈判降租或迁址')
      } else if (r.rent_status === '租金占比过高') {
        reasons.push(`租金占比${r.rent_rate_pct}%过高`)
        suggestions.push('关注续租条件，争取降低租金')
        actions.push('关注租金')
      }

      // 水电燃气问题
      if (r.utility_status === '水电燃气率过高') {
        reasons.push(`水电燃气率${r.utility_rate_pct}%过高`)
        suggestions.push('排查是否有漏水漏气，优化能源使用')
        actions.push('排查能源浪费')
      }

      // 外卖依赖问题
      if (r.delivery_status === '外卖依赖度过高') {
        reasons.push(`外卖占比${r.delivery_sales_share_pct}%过高，佣金侵蚀利润`)
        suggestions.push('提升堂食客流，优化外卖平台策略，减少佣金支出')
        actions.push('降低外卖依赖')
      } else if (r.delivery_status === '外卖占比较高') {
        reasons.push(`外卖占比${r.delivery_sales_share_pct}%较高`)
        suggestions.push('关注外卖佣金成本，提升堂食比例')
        actions.push('优化外卖结构')
      }

      // 坪效问题
      if (r.efficiency_status === '坪效极低') {
        reasons.push(`坪效仅${r.received_per_sqm}元/㎡，面积利用率极低`)
        suggestions.push('考虑缩减面积、改造布局或迁址至更小店面')
        actions.push('缩减面积或迁址')
      } else if (r.efficiency_status === '坪效偏低') {
        reasons.push(`坪效${r.received_per_sqm}元/㎡偏低`)
        suggestions.push('优化空间利用，提升单位面积产出')
        actions.push('提升坪效')
      }

      // 租约到期问题
      if (r.lease_status === '租约即将到期') {
        reasons.push(`租约将于${r.lease_expiry_date}到期`)
        suggestions.push('立即启动续租谈判或关停评估，把握决策窗口')
        actions.push('启动续租评估')
      }

      // 亏损类型综合判断
      if (r.loss_type === '理论即亏损') {
        reasons.unshift('按理论成本计算已亏损，定价或成本结构存在根本问题')
        suggestions.unshift('重新评估菜品定价策略和成本结构，必要时调整菜单价格')
        actions.unshift('调整定价策略')
      } else if (r.loss_type === '实际超耗导致亏损') {
        reasons.unshift('理论贡献为正但实际亏损，超耗是主要亏损原因')
        suggestions.unshift('重点排查物料超耗、损耗和浪费，参考菜品成本分析模块')
        actions.unshift('治理物料超耗')
      } else if (r.loss_type === '费用过高导致亏损') {
        reasons.unshift('食材成本正常但费用过高导致亏损')
        suggestions.unshift('重点削减人工、租金等费用支出')
        actions.unshift('削减费用')
      }

      // 优先级判断
      let priority = 'P3'
      if (r.actual_store_contribution_rate_pct < -20) priority = 'P0'
      else if (r.actual_store_contribution_rate_pct < -5) priority = 'P1'
      else if (r.actual_store_contribution_rate_pct < 0) priority = 'P2'

      return {
        ...r,
        diagnosis_reasons: reasons.join('；'),
        diagnosis_suggestions: suggestions.join('；'),
        suggested_actions: actions.join('、'),
        priority
      }
    })

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

// ============ Tab10: 门店关停/续租/改造评估 ============

// 门店关停/续租/改造评估
router.get('/store-evaluation', async (req: AuthRequest, res) => {
  try {
    const { page, pageSize, offset } = parsePagination(req)
    const sort = (req.query.sort as string) || 'actual_store_contribution_rate_pct'
    const order = (req.query.order as string) === 'desc' ? 'DESC' : 'ASC'
    const filter = (req.query.filter as string) || ''
    const month = parseMonth(req)

    let where = `WHERE report_month = $1::date AND received > 0`
    const params: any[] = [month]
    if (filter === 'loss') {
      where += ` AND actual_store_contribution <= 0`
    } else if (filter === 'profitable') {
      where += ` AND actual_store_contribution > 0`
    }

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

    const validSorts = ['actual_store_contribution_rate_pct', 'received', 'actual_store_contribution', 'received_per_sqm', 'wage_rate_pct', 'rent_rate_pct', 'operating_expense_rate_pct']
    const sortCol = validSorts.includes(sort) ? sort : 'actual_store_contribution_rate_pct'

    const result = await query(`
      SELECT sales_store_code, sales_store_name,
        round(received::numeric, 2) AS received,
        round(actual_food_cost::numeric, 2) AS actual_food_cost,
        round(operating_expense::numeric, 2) AS operating_expense,
        round(actual_store_contribution::numeric, 2) AS actual_store_contribution,
        round(actual_store_contribution_rate_pct::numeric, 2) AS actual_store_contribution_rate_pct,
        round(wage_rate_pct::numeric, 2) AS wage_rate_pct,
        round(rent_rate_pct::numeric, 2) AS rent_rate_pct,
        round(received_per_sqm::numeric, 2) AS received_per_sqm,
        round(area_sqm::numeric, 2) AS area_sqm,
        lease_expiry_date,
        round(theoretical_store_contribution::numeric, 2) AS theoretical_store_contribution,
        CASE
          WHEN received = 0 OR received < 5000 THEN '关停评估'
          WHEN actual_store_contribution_rate_pct < -20 AND lease_expiry_date <= $1::date + interval '12 months' THEN '关停评估'
          WHEN actual_store_contribution_rate_pct < -10 AND received_per_sqm < 1000 THEN '关停评估'
          WHEN actual_store_contribution_rate_pct < 0 AND lease_expiry_date <= $1::date + interval '12 months' THEN '关停或迁址评估'
          WHEN actual_store_contribution_rate_pct < 0 AND received_per_sqm < 1000 AND area_sqm > 400 THEN '改造评估'
          WHEN actual_store_contribution_rate_pct < 0 AND wage_rate_pct > 35 THEN '改造评估'
          WHEN actual_store_contribution_rate_pct < 0 THEN '关注观察'
          WHEN lease_expiry_date <= $1::date + interval '3 months' THEN '续租评估'
          WHEN actual_store_contribution_rate_pct > 0 AND actual_store_contribution_rate_pct < 10 THEN '关注观察'
          ELSE '正常经营'
        END AS evaluation_type,
        CASE
          WHEN received = 0 OR received < 5000 THEN 'P0'
          WHEN actual_store_contribution_rate_pct < -20 THEN 'P0'
          WHEN actual_store_contribution_rate_pct < -10 THEN 'P1'
          WHEN actual_store_contribution_rate_pct < 0 THEN 'P2'
          WHEN actual_store_contribution_rate_pct < 10 THEN 'P3'
          ELSE 'P4'
        END AS priority
      FROM analytics.mv_store_operating_expense_monthly
      ${where}
      ORDER BY 
        CASE
          WHEN received = 0 OR received < 5000 THEN 0
          WHEN actual_store_contribution_rate_pct < -20 THEN 1
          WHEN actual_store_contribution_rate_pct < -10 THEN 2
          WHEN actual_store_contribution_rate_pct < 0 THEN 3
          WHEN actual_store_contribution_rate_pct < 10 THEN 4
          ELSE 5
        END,
        ${sortCol} ${order} NULLS LAST
      LIMIT $${params.length + 1} OFFSET $${params.length + 2}
    `, [...params, pageSize, offset])

    // 格式化日期
    const fmtDate = (d: any) => d ? new Date(d).toLocaleDateString('zh-CN') : '-'

    // 为每个门店生成评估详情和建议
    const rows = result.rows.map((r: any) => {
      let detail = ''
      let suggestion = ''

      switch (r.evaluation_type) {
        case '关停评估':
          detail = r.received < 5000 
            ? `月收入仅${r.received}元，基本无营业活动，继续经营只会增加亏损`
            : `贡献利润率${r.actual_store_contribution_rate_pct}%，严重亏损且租约即将到期，关停可止损`
          suggestion = r.received < 5000
            ? '建议立即关停，减少固定费用支出；若为新店筹备期则明确开业时间表'
            : '建议到期不再续租，提前制定关停计划（人员分流、设备调拨、会员退款）'
          break
        case '关停或迁址评估':
          detail = `贡献利润率${r.actual_store_contribution_rate_pct}%，亏损运营且租约${fmtDate(r.lease_expiry_date)}到期`
          suggestion = '评估周边市场潜力：若商圈有潜力则谈判降租续营，否则到期关停并寻找更低租金位置迁址'
          break
        case '改造评估':
          if (r.received_per_sqm < 1000 && r.area_sqm > 400) {
            detail = `坪效${r.received_per_sqm}元/㎡偏低，面积${r.area_sqm}㎡过大，空间利用率不足`
            suggestion = '考虑缩减营业面积（退租部分区域），或改造空间布局增加外卖/零售功能'
          } else {
            detail = `人工成本率${r.wage_rate_pct}%偏高且持续亏损，运营效率需提升`
            suggestion = '优化人员配置和排班制度，引入数字化点餐减少人工依赖，必要时进行门店改造'
          }
          break
        case '续租评估':
          detail = `租约${fmtDate(r.lease_expiry_date)}即将到期，当前贡献利润率${r.actual_store_contribution_rate_pct}%`
          suggestion = '若盈利则尽快启动续租谈判锁定租金，若微利则谈判降租条件，设定续租租金上限'
          break
        case '关注观察':
          detail = r.actual_store_contribution_rate_pct < 0
            ? `贡献利润率${r.actual_store_contribution_rate_pct}%，持续亏损需关注`
            : `贡献利润率仅${r.actual_store_contribution_rate_pct}%，盈利能力薄弱`
          suggestion = r.actual_store_contribution_rate_pct < 0
            ? '分析亏损原因，制定改善计划提升营业额或降低费用，避免亏损扩大'
            : '持续监控经营状况，制定改善计划提升营业额或降低费用，避免滑入亏损'
          break
        default:
          detail = '经营状况正常'
          suggestion = '保持现有运营水平，持续优化费用结构'
      }

      return { ...r, lease_expiry_date: r.lease_expiry_date ? new Date(r.lease_expiry_date).toISOString().split('T')[0] : null, evaluation_detail: detail, evaluation_suggestion: suggestion }
    })

    // 全量统计各评估类型数量
    const statsResult = await query(`
      SELECT 
        count(*) FILTER (WHERE received = 0 OR received < 5000 OR (actual_store_contribution_rate_pct < -20 AND lease_expiry_date <= $1::date + interval '12 months') OR (actual_store_contribution_rate_pct < -10 AND received_per_sqm < 1000)) AS "关停评估",
        count(*) FILTER (WHERE actual_store_contribution_rate_pct < 0 AND received_per_sqm < 1000 AND area_sqm > 400) + count(*) FILTER (WHERE actual_store_contribution_rate_pct < 0 AND wage_rate_pct > 35) AS "改造评估",
        count(*) FILTER (WHERE lease_expiry_date <= $1::date + interval '3 months' AND actual_store_contribution_rate_pct >= 0) AS "续租评估",
        count(*) FILTER (WHERE actual_store_contribution_rate_pct < 0 AND lease_expiry_date > $1::date + interval '12 months' AND NOT (received_per_sqm < 1000 AND area_sqm > 400) AND wage_rate_pct <= 35) + count(*) FILTER (WHERE actual_store_contribution_rate_pct > 0 AND actual_store_contribution_rate_pct < 10) AS "关注观察"
      FROM analytics.mv_store_operating_expense_monthly
      ${where}
    `, params)
    const evalStats = statsResult.rows[0]

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

// ============ 数据质量 ============

// 费用数据质量
router.get('/data-quality', async (req: AuthRequest, res) => {
  try {
    const result = await query(`
      SELECT * FROM analytics.v_operating_expense_data_quality
    `)
    sendSuccess(res, result.rows)
  } catch (err: any) {
    sendError(res, err.message)
  }
})

export default router
