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

const router = Router()

// ============ P0: 门店健康度综合评分 ============

router.get('/health-score', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    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 scopeParams = hasScope ? [month, scopeCodes] : [month]
    const scopeFilter = hasScope ? ` AND store_code = ANY($2)` : ''
    const result = await query(`
      WITH base AS (
        SELECT store_code, store_name, received, bill_count,
               avg_bill_value, avg_daily_received, theoretical_margin_pct,
               member_bill_share_pct, risk_level
        FROM analytics.mv_store_risk_rating_monthly
        WHERE month_start = $1 AND received IS NOT NULL${scopeFilter}
      ),
      cost AS (
        SELECT store_code,
          round(avg(LEAST(variance_to_theoretical_pct, 50))::numeric, 1) AS avg_cost_variance_pct
        FROM analytics.mv_store_theoretical_actual_cost_monthly
        WHERE month_start = $1 AND variance_to_theoretical_pct IS NOT NULL
        GROUP BY store_code
      ),
      member AS (
        SELECT store_code, max(repeat_rate_pct) AS repeat_rate_pct
        FROM analytics.mv_store_repeat_summary_monthly
        WHERE month_start = $1::date
        GROUP BY store_code
      ),
      task AS (
        SELECT store_code,
          count(*) AS total_tasks,
          count(*) FILTER (WHERE status = '已验收' AND verification_result = '达标') AS passed_tasks,
          round(count(*) FILTER (WHERE status IN ('已验收', '已回滚'))::numeric / nullif(count(*), 0) * 100, 1) AS completion_rate
        FROM analytics.store_task
        WHERE is_simulated = false OR is_simulated IS NULL
        GROUP BY store_code
      ),
      scored AS (
        SELECT
          b.store_code, b.store_name, b.received, b.bill_count, b.avg_bill_value,
          b.risk_level, b.avg_daily_received,
          COALESCE(b.theoretical_margin_pct, 0) AS avg_margin,
          COALESCE(c.avg_cost_variance_pct, 20) AS avg_cost_variance_pct,
          COALESCE(m.repeat_rate_pct, 0) AS repeat_rate_pct,
          COALESCE(b.member_bill_share_pct, 0) AS member_share_pct,
          COALESCE(t.completion_rate, 0) AS task_completion_rate,
          -- 各维度得分
          (20 * LEAST(1.0, b.avg_daily_received / 30000))::numeric(5,1) AS score_revenue,
          (20 * GREATEST(0, 1 - LEAST(COALESCE(c.avg_cost_variance_pct, 20), 50) / 50))::numeric(5,1) AS score_cost,
          (15 * LEAST(1.0, GREATEST(0, COALESCE(b.theoretical_margin_pct, 0) - 60) / 15))::numeric(5,1) AS score_margin,
          (CASE b.risk_level WHEN '绿色' THEN 10 WHEN '黄色' THEN 6 WHEN '红色' THEN 2 ELSE 4 END)::numeric(5,1) AS score_risk,
          (10 * LEAST(1.0, COALESCE(m.repeat_rate_pct, 0) / 40))::numeric(5,1) AS score_repeat,
          (10 * LEAST(1.0, COALESCE(b.member_bill_share_pct, 0) / 20))::numeric(5,1) AS score_member,
          (10 * COALESCE(t.completion_rate, 0) / 100)::numeric(5,1) AS score_task,
          (5 * LEAST(1.0, COALESCE(b.avg_bill_value, 0) / 40))::numeric(5,1) AS score_bill,
          LEAST(100, GREATEST(0,
            -- 1. 营收规模 20分：30000=满分，中位18642≈12分
            20 * LEAST(1.0, b.avg_daily_received / 30000)
            -- 2. 成本控制 20分：差异率0%=满分，50%=0分，中位19%≈12分
            + 20 * GREATEST(0, 1 - LEAST(COALESCE(c.avg_cost_variance_pct, 20), 50) / 50)
            -- 3. 毛利率 15分：60%=0分，75%=满分，均值71.5%≈11.5分
            + 15 * LEAST(1.0, GREATEST(0, COALESCE(b.theoretical_margin_pct, 0) - 60) / 15)
            -- 4. 风险等级 10分
            + CASE b.risk_level WHEN '绿色' THEN 10 WHEN '黄色' THEN 6 WHEN '红色' THEN 2 ELSE 4 END
            -- 5. 复购率 10分：40%=满分，中位35%≈8.75分
            + 10 * LEAST(1.0, COALESCE(m.repeat_rate_pct, 0) / 40)
            -- 6. 会员占比 10分：20%=满分，中位12.5%≈6.25分
            + 10 * LEAST(1.0, COALESCE(b.member_bill_share_pct, 0) / 20)
            -- 7. 任务完成 10分
            + 10 * COALESCE(t.completion_rate, 0) / 100
            -- 8. 客单价 5分：40元=满分，中位33.4≈4.2分
            + 5 * LEAST(1.0, COALESCE(b.avg_bill_value, 0) / 40)
          ))::numeric(5,1) AS health_score
        FROM base b
        LEFT JOIN cost c ON b.store_code = c.store_code
        LEFT JOIN member m ON b.store_code = m.store_code
        LEFT JOIN task t ON b.store_code = t.store_code
      )
      SELECT store_code, store_name, received, bill_count, avg_bill_value,
             risk_level, avg_margin, avg_cost_variance_pct, repeat_rate_pct,
             member_share_pct, task_completion_rate, health_score,
             score_revenue, score_cost, score_margin, score_risk,
             score_repeat, score_member, score_task, score_bill,
             avg_daily_received,
             CASE WHEN health_score >= 75 THEN '健康'
                  WHEN health_score >= 55 THEN '亚健康'
                  ELSE '需干预'
             END AS health_status
      FROM scored
      ORDER BY health_score DESC
    `, scopeParams, { skipScope: true })
    sendSuccess(res, result.rows)
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============ P0: 自动化阈值预警 ============

router.get('/alerts', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    const alerts: any[] = []

    // 1. 营收异动预警：日营收连续低于月均70%
    const revenueAlerts = await query(`
      WITH daily_stats AS (
        SELECT closed_at::date AS business_date,
          count(*) AS bill_count,
          sum(received_total) AS received
        FROM analytics.bill_fact
        WHERE closed_at >= (SELECT max(closed_at)::date - interval '30 days' FROM analytics.bill_fact)
          AND closed_at IS NOT NULL
        GROUP BY closed_at::date
        ORDER BY business_date
      ),
      monthly_avg AS (
        SELECT avg(received) AS avg_received
        FROM daily_stats
      )
      SELECT d.business_date::text, d.received, m.avg_received,
        round(d.received / nullif(m.avg_received, 0) * 100, 1) AS ratio
      FROM daily_stats d, monthly_avg m
      WHERE d.received < m.avg_received * 0.7
      ORDER BY d.business_date DESC
      LIMIT 10
    `, [], { skipScope: true })
    revenueAlerts.rows.forEach((r: any) => {
      alerts.push({
        type: 'revenue',
        level: 'red',
        title: `营收异动 ${r.business_date}`,
        detail: `日营收 ¥${Number(r.received).toFixed(0)} 仅为月均的 ${r.ratio}%`,
        store: '全局',
        date: r.business_date,
      })
    })

    // 2. 成本异动预警：成本差异>30%的菜品
    const costAlerts = await query(`
      SELECT dish_name, dish_code, category_level1,
        round(cost_variance_amount::numeric, 2) AS variance,
        round((cost_variance_amount / nullif(theoretical_cost, 0) * 100)::numeric, 2) AS variance_pct,
        round(sales_amount::numeric, 2) AS sales_amount
      FROM public.dish_cost_analysis_summary
      WHERE cost_variance_amount > 0
        AND theoretical_cost > 0
        AND (cost_variance_amount / theoretical_cost) > 0.3
      ORDER BY variance_pct DESC
      LIMIT 10
    `, [], { skipScope: true })
    costAlerts.rows.forEach((r: any) => {
      alerts.push({
        type: 'cost',
        level: 'red',
        title: `成本异动 ${r.dish_name}`,
        detail: `成本差异率 ${r.variance_pct}%，差异金额 ¥${r.variance}`,
        store: '全局',
        date: null,
      })
    })

    // 3. 人力异动预警：考勤异常员工
    const hrAlerts = await query(`
      SELECT s.org_level5 AS store_name, count(*) AS alert_count,
        count(*) FILTER (WHERE s.absent_days > 0) AS absent_count,
        count(*) FILTER (WHERE s.late_deduction > 0 OR s.no_punch_deduction > 0) AS punch_issue_count
      FROM salary_detail_records s
      WHERE s.org_level2 = '西部马华品牌门店' AND s.org_level5 IS NOT NULL AND s.org_level5 != ''
        AND (s.absent_days > 0 OR s.late_deduction > 0 OR s.no_punch_deduction > 0)
      GROUP BY s.org_level5
      HAVING count(*) > 3
      ORDER BY alert_count DESC
      LIMIT 10
    `)
    hrAlerts.rows.forEach((r: any) => {
      alerts.push({
        type: 'hr',
        level: r.alert_count > 5 ? 'red' : 'orange',
        title: `考勤异常 ${r.store_name}`,
        detail: `异常员工 ${r.alert_count} 人（旷工 ${r.absent_count}，打卡问题 ${r.punch_issue_count}）`,
        store: r.store_name,
        date: null,
      })
    })

    // 4. 平台依赖预警：外卖佣金占比>40%
    const platformAlerts = await query(`
      SELECT p.store_code, p.store_name,
        round(p.meituan_cost_rate_pct::numeric, 1) AS meituan_rate,
        round(p.taobao_cost_rate_pct::numeric, 1) AS taobao_rate,
        round(p.jd_cost_rate_pct::numeric, 1) AS jd_rate,
        round((COALESCE(p.meituan_received, 0) + COALESCE(p.taobao_received, 0) + COALESCE(p.jd_received, 0)) / nullif(sc.received, 0) * 100, 1) AS platform_share
      FROM analytics.mv_store_platform_economics_monthly p
      JOIN analytics.v_store_scorecard sc ON p.store_code = sc.store_code
      WHERE p.month_start = $1 AND (COALESCE(p.meituan_received, 0) + COALESCE(p.taobao_received, 0) + COALESCE(p.jd_received, 0)) / nullif(sc.received, 0) > 0.4
      ORDER BY platform_share DESC
      LIMIT 10
    `, [month])
    platformAlerts.rows.forEach((r: any) => {
      alerts.push({
        type: 'platform',
        level: 'orange',
        title: `平台依赖 ${r.store_name}`,
        detail: `外卖占比 ${r.platform_share}%，美团 ${r.meituan_rate}%/淘宝 ${r.taobao_rate}%/京东 ${r.jd_rate}%`,
        store: r.store_name,
        date: null,
      })
    })

    // 5. 任务逾期预警
    const taskAlerts = await query(`
      SELECT store_code, store_name, priority, problem_indicator, deadline::text AS deadline,
        current_date - deadline::date AS overdue_days
      FROM analytics.store_task
      WHERE status NOT IN ('已验收', '已回滚')
        AND deadline < current_date
      ORDER BY overdue_days DESC
      LIMIT 10
    `)
    taskAlerts.rows.forEach((r: any) => {
      alerts.push({
        type: 'task',
        level: r.overdue_days > 14 ? 'red' : 'orange',
        title: `任务逾期 ${r.store_name}`,
        detail: `${r.priority} - ${r.problem_indicator}，逾期 ${r.overdue_days} 天`,
        store: r.store_name,
        date: r.deadline,
      })
    })

    // 按级别排序
    const levelOrder: Record<string, number> = { red: 0, orange: 1, yellow: 2 }
    alerts.sort((a, b) => (levelOrder[a.level] || 3) - (levelOrder[b.level] || 3))

    sendSuccess(res, {
      total: alerts.length,
      red: alerts.filter(a => a.level === 'red').length,
      orange: alerts.filter(a => a.level === 'orange').length,
      alerts,
    })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============ P1: 跨模块关联分析 ============

router.get('/correlation', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    // 客流-人力匹配度：每门店每小时"每人在岗产出账单数"
    // mv_store_hourly_staffing 可能不存在，容错处理
    let staffingRows: any[] = []
    try {
      const staffingEfficiency = await query(`
        WITH hourly_bills AS (
          SELECT store_name, hour, sum(bills) AS bills
          FROM mv_bill_hourly
          GROUP BY store_name, hour
        ),
        hourly_staff AS (
          SELECT store_name, hour, total_staff
          FROM mv_store_hourly_staffing
          WHERE total_staff > 0
        )
        SELECT
          COALESCE(b.store_name, s.store_name) AS store_name,
          COALESCE(b.hour, s.hour) AS hour,
          COALESCE(b.bills, 0) AS bills,
          COALESCE(s.total_staff, 0) AS staff,
          round(COALESCE(b.bills, 0)::numeric / nullif(COALESCE(s.total_staff, 0), 0), 1) AS bills_per_staff,
          CASE
            WHEN COALESCE(s.total_staff, 0) = 0 THEN '无在岗数据'
            WHEN COALESCE(b.bills, 0) > 0 AND COALESCE(b.bills, 0)::numeric / COALESCE(s.total_staff, 0) > 15 THEN '高峰人手不足'
            WHEN COALESCE(b.bills, 0) = 0 AND COALESCE(s.total_staff, 0) > 3 THEN '低谷人员冗余'
            ELSE '配置合理'
          END AS match_status
        FROM hourly_bills b
        FULL OUTER JOIN hourly_staff s ON b.store_name = s.store_name AND b.hour = s.hour
        WHERE COALESCE(b.bills, 0) > 0 OR COALESCE(s.total_staff, 0) > 0
        ORDER BY COALESCE(b.store_name, s.store_name), COALESCE(b.hour, s.hour)
      `)
      staffingRows = staffingEfficiency.rows
    } catch {
      staffingRows = []
    }

    // 门店维度汇总：成本-风险关联
    const costRisk = await query(`
      SELECT
        r.store_code, r.store_name, r.risk_level,
        r.received, r.avg_daily_received,
        COALESCE(r.theoretical_margin_pct, 0) AS avg_margin,
        COALESCE(c.avg_cost_variance_pct, 20) AS avg_cost_variance_pct,
        CASE
          WHEN r.risk_level = '红色' AND COALESCE(c.avg_cost_variance_pct, 20) > 30 THEN '成本失控+高风险'
          WHEN r.risk_level = '红色' THEN '高风险'
          WHEN r.risk_level = '黄色' AND COALESCE(c.avg_cost_variance_pct, 20) > 25 THEN '成本偏高+中风险'
          WHEN COALESCE(c.avg_cost_variance_pct, 20) > 30 THEN '成本失控'
          ELSE '正常'
        END AS correlation_status
      FROM analytics.mv_store_risk_rating_monthly r
      LEFT JOIN (
        SELECT store_code,
          round(avg(LEAST(variance_to_theoretical_pct, 50))::numeric, 1) AS avg_cost_variance_pct
        FROM analytics.mv_store_theoretical_actual_cost_monthly
        WHERE month_start = $1 AND variance_to_theoretical_pct IS NOT NULL
        GROUP BY store_code
      ) c ON r.store_code = c.store_code
      WHERE r.received IS NOT NULL
      ORDER BY
        CASE WHEN r.risk_level = '红色' AND COALESCE(c.avg_cost_variance_pct, 20) > 30 THEN 0
             WHEN r.risk_level = '红色' THEN 1
             WHEN r.risk_level = '黄色' AND COALESCE(c.avg_cost_variance_pct, 20) > 25 THEN 2
             ELSE 3 END,
        r.received DESC NULLS LAST
    `, [month])

    // 会员-平台-营收三角
    const channelRisk = await query(`
      SELECT
        r.store_code, r.store_name, r.received,
        COALESCE(p.platform_share, 0) AS platform_share,
        COALESCE(r.member_bill_share_pct, 0) AS member_share_pct,
        COALESCE(m.repeat_rate_pct, 0) AS repeat_rate_pct,
        CASE
          WHEN COALESCE(p.platform_share, 0) > 40 AND COALESCE(r.member_bill_share_pct, 0) < 20 THEN '渠道依赖预警'
          WHEN COALESCE(p.platform_share, 0) > 30 AND COALESCE(r.member_bill_share_pct, 0) < 30 THEN '渠道风险'
          WHEN COALESCE(r.member_bill_share_pct, 0) > 50 THEN '会员驱动型'
          ELSE '均衡型'
        END AS channel_status
      FROM analytics.mv_store_risk_rating_monthly r
      LEFT JOIN (
        SELECT pe.store_code,
          round((COALESCE(pe.meituan_received, 0) + COALESCE(pe.taobao_received, 0) + COALESCE(pe.jd_received, 0)) / nullif(r2.received, 0) * 100, 1) AS platform_share
        FROM analytics.mv_store_platform_economics_monthly pe
        JOIN analytics.mv_store_risk_rating_monthly r2 ON pe.store_code = r2.store_code AND r2.month_start = pe.month_start
        WHERE pe.month_start = $1
      ) p ON r.store_code = p.store_code
      LEFT JOIN analytics.mv_store_repeat_summary_monthly m ON r.store_code = m.store_code AND m.month_start = $1::date
      WHERE r.received IS NOT NULL
      ORDER BY
        CASE WHEN COALESCE(p.platform_share, 0) > 40 AND COALESCE(r.member_bill_share_pct, 0) < 20 THEN 0 ELSE 1 END,
        r.received DESC
    `, [month])

    // 考勤-营收关联
    const hrRevenue = await query(`
      WITH hr AS (
        SELECT s.org_level5 AS store_name,
          count(*) AS emp_count,
          round(avg(s.actual_attend)::numeric, 1) AS avg_attend,
          round(sum(s.absent_days)::numeric, 0) AS total_absent,
          round(count(*) FILTER (WHERE s.actual_attend / nullif(s.expected_attend, 0) < 0.8)::numeric / nullif(count(*), 0) * 100, 1) AS low_attend_rate
        FROM salary_detail_records s
        WHERE s.org_level2 = '西部马华品牌门店' AND s.org_level5 IS NOT NULL AND s.org_level5 != ''
        GROUP BY s.org_level5
      ),
      rev AS (
        SELECT store_name, received, bill_count, avg_bill_value
        FROM analytics.v_store_scorecard
        WHERE received IS NOT NULL
      ),
      mapping AS (
        SELECT salary_name, bill_name FROM public.store_name_mapping
      )
      SELECT
        COALESCE(r.store_name, h.store_name) AS store_name,
        COALESCE(r.received, 0) AS received,
        COALESCE(r.bill_count, 0) AS bill_count,
        COALESCE(h.emp_count, 0) AS emp_count,
        COALESCE(h.avg_attend, 0) AS avg_attend,
        COALESCE(h.total_absent, 0) AS total_absent,
        COALESCE(h.low_attend_rate, 0) AS low_attend_rate,
        round(COALESCE(r.received, 0) / nullif(COALESCE(h.emp_count, 0), 0), 0) AS revenue_per_emp,
        CASE
          WHEN COALESCE(h.low_attend_rate, 0) > 30 AND COALESCE(r.received, 0) > 0 THEN '出勤低+有营收'
          WHEN COALESCE(h.low_attend_rate, 0) > 30 THEN '出勤低+营收低'
          WHEN COALESCE(h.total_absent, 0) > 10 THEN '旷工严重'
          ELSE '正常'
        END AS hr_status
      FROM hr h
      LEFT JOIN mapping mp ON mp.salary_name = h.store_name
      LEFT JOIN rev r ON r.store_name = mp.bill_name
      ORDER BY
        CASE WHEN COALESCE(h.low_attend_rate, 0) > 30 THEN 0 ELSE 1 END,
        COALESCE(h.total_absent, 0) DESC
    `)

    sendSuccess(res, {
      staffing_efficiency: staffingRows,
      cost_risk: costRisk.rows,
      channel_risk: channelRisk.rows,
      hr_revenue: hrRevenue.rows,
    })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

// ============ P2: 趋势预测 ============

router.get('/forecast', async (req: AuthRequest, res) => {
  try {
    const month = parseMonth(req)
    // 客流预测：基于历史4周小时数据，按工作日/周末+小时维度计算P85
    const trafficForecast = await query(`
      WITH daily_hourly AS (
        SELECT extract(hour FROM c175::timestamp)::int AS hour,
          CASE WHEN extract(dow FROM c175::timestamp)::int IN (0, 6) THEN '周末' ELSE '工作日' END AS day_type,
          DATE(c175::timestamp) AS bill_date,
          count(*) AS bills
        FROM bill_records
        WHERE c175 IS NOT NULL AND c175 != ''
          AND c175::timestamp >= $1::date AND c175::timestamp < ($1::date + interval '1 month')
        GROUP BY hour, day_type, bill_date
      ),
      hourly_stats AS (
        SELECT hour, day_type,
          round(avg(bills)::numeric, 0)::int AS avg_bills,
          round(percentile_cont(0.85) WITHIN GROUP (ORDER BY bills)::numeric, 0)::int AS p85_bills,
          round(percentile_cont(0.5) WITHIN GROUP (ORDER BY bills)::numeric, 0)::int AS p50_bills,
          round((max(bills) - min(bills))::numeric / nullif(avg(bills), 0), 2)::float AS volatility
        FROM daily_hourly
        GROUP BY hour, day_type
      )
      SELECT hour, day_type, avg_bills, p50_bills, p85_bills, volatility,
        CASE
          WHEN volatility > 1.5 THEN '波动大'
          WHEN volatility > 0.8 THEN '中等波动'
          ELSE '稳定'
        END AS stability
      FROM hourly_stats
      ORDER BY day_type, hour
    `, [month])

    // 成本趋势：菜品成本差异恶化TOP
    const costTrend = await query(`
      SELECT dish_name, dish_code, category_level1,
        round(sales_amount::numeric, 2) AS sales_amount,
        round(theoretical_margin_rate_pct::numeric, 2) AS theo_margin,
        round(actual_margin_rate_pct::numeric, 2) AS actual_margin,
        round(cost_variance_amount::numeric, 2) AS variance,
        CASE
          WHEN actual_margin_rate_pct < 0 THEN '数据异常'
          WHEN cost_variance_amount > 0 AND theoretical_cost > 0 AND (cost_variance_amount / theoretical_cost) > 0.3 THEN '恶化'
          WHEN cost_variance_amount > 0 AND theoretical_cost > 0 AND (cost_variance_amount / theoretical_cost) > 0.1 THEN '关注'
          ELSE '正常'
        END AS trend_status
      FROM public.dish_cost_analysis_summary
      WHERE actual_margin_rate_pct IS NOT NULL
      ORDER BY variance DESC
      LIMIT 20
    `)

    // 人员流失预警
    const turnoverAlert = await query(`
      SELECT org_level5 AS store_name,
        count(*) AS total_emp,
        count(*) FILTER (WHERE leave_date IS NOT NULL AND leave_date != '' AND leave_date >= $1) AS left_count,
        count(*) FILTER (WHERE hire_date IS NOT NULL AND hire_date >= $1) AS new_count,
        round(count(*) FILTER (WHERE leave_date IS NOT NULL AND leave_date != '' AND leave_date >= $1)::numeric / nullif(count(*), 0) * 100, 1) AS turnover_rate
      FROM salary_detail_records
      WHERE org_level2 = '西部马华品牌门店' AND org_level5 IS NOT NULL AND org_level5 != ''
      GROUP BY org_level5
      HAVING count(*) FILTER (WHERE leave_date IS NOT NULL AND leave_date != '' AND leave_date >= $1) > 0
      ORDER BY turnover_rate DESC
    `, [month])

    sendSuccess(res, {
      traffic_forecast: trafficForecast.rows,
      cost_trend: costTrend.rows,
      turnover_alert: turnoverAlert.rows,
    })
  } catch (err: any) {
    sendError(res, err.message)
  }
})

export default router
