/**
 * 支付模块 - 路由层
 * ============================================
 * 统一管理支付创建、回调、查询、退款的全流程。
 *
 * 架构分层:
 *   routes/payment.js  →  路由控制层（参数校验、响应格式化）
 *   lib/payment/index.js  →  业务逻辑层（策略选择、错误降级）
 *   lib/payment/wechat.js  →  微信支付 SDK
 *   lib/payment/alipay.js  →  支付宝 SDK
 *   lib/payment/utils.js  →  通用工具（签名、HTTP、XML）
 *   lib/payment/logger.js  →  支付日志
 *
 * 支付模式:
 *   模拟模式(simulate)：系统默认，点击确认即完成支付，无需真实商户号
 *   生产模式(production)：对接微信/支付宝官方API，真实扣款
 *   切换条件: 后台 系统设置>支付配置 > 填写商户号/密钥，关闭"测试模式"
 *
 * 支付流程:
 *   用户提交订单 -> POST /api/payment/create (生成支付单)
 *   -> 返回支付参数给调起支付 -> 用户完成支付
 *   -> 微信/支付宝异步通知 -> 订单状态自动变更
 *   -> 前端轮询 GET /api/payment/status/:orderNo
 *
 * 退款流程:
 *   用户申请 -> POST /api/payment/refund/create -> 管理员审核
 *   -> POST /api/payment/refund/process -> 调渠道退款
 */
const express = require('express');

// [LiteMall_Copyright] fba28f00dae77aa2 LiteMall_Lobster_v1.0_2026


const router = express.Router();
const { get, run, all, transaction } = require('../utils/db');
const { success, fail, page } = require('../utils/response');
const { authUser, authAdmin } = require('../middleware/auth');
const paymentSdk = require('../lib/payment');
const wechatSdk = require('../lib/payment/wechat');
const alipaySdk = require('../lib/payment/alipay');
const logger = require('../lib/payment/logger');
const notification = require('../lib/notification');
const reconciliation = require('../lib/payment/reconciliation');
const commission = require('../lib/commission');
// ===================================================================
// 工具函数
// ===================================================================
    // NOTE: genTradeNo 前缀+日期+时间+随机数，唯一性足够；边界：Math.random 非加密安全
function genTradeNo() {
  const now = new Date();
  const date = `${now.getFullYear()}${String(now.getMonth() + 1).padStart(2, '0')}${String(now.getDate()).padStart(2, '0')}`;
  const time = String(now.getHours()).padStart(2, '0') + String(now.getMinutes()).padStart(2, '0') + String(now.getSeconds()).padStart(2, '0');
  const rand = String(Math.floor(Math.random() * 100000)).padStart(5, '0');
  return `TN${date}${time}${rand}`;
}
function genRefundNo() {
  return `TK${Date.now()}${Math.floor(Math.random() * 10000)}`;
}
// ===================================================================
// 1. 创建支付 - POST /api/payment/create
// 生产模式：调用微信/支付宝生成正式支付参数
// 模拟模式：返回模拟支付页面链接（保留原有能力）
// ===================================================================
router.post('/create', authUser, async (req, res) => {
  try {
    const { order_no, method } = req.body;
    if (!order_no) return res.json(fail('订单号不能为空'));
    if (!method || !['wechat', 'alipay'].includes(method)) {
      return res.json(fail('请选择支付方式（wechat/alipay）'));
    }
    // 查询订单并验证归属
    const order = get('SELECT * FROM orders WHERE order_no=? AND user_id=?', [order_no, req.userId]);
    if (!order) return res.json(fail('订单不存在'));
    if (order.status !== 'pending_pay') {
      return res.json(fail('订单状态异常，无法支付（当前状态: ' + order.status + '）'));
    }
    // 检查是否已有支付记录
    const existing = get('SELECT * FROM payment_records WHERE order_id=? AND status=?', [order.id, 'pending']);
    if (existing) {
      logger.log(existing.trade_no, 'payment_retry', `重复创建支付，订单: ${order_no}`, { channel: method, level: 'warn' });
      return res.json(success({
        trade_no: existing.trade_no,
        amount: order.pay_amount,
        method: existing.method,
        is_mock: paymentSdk.isSimulateMode()
      }, '已有待支付记录'));
    }
    // 生成支付单号并插入记录
    const tradeNo = genTradeNo();
    run("INSERT INTO payment_records(trade_no, order_id, user_id, amount, method, status, created_at) VALUES(?,?,?,?,?,?, datetime('now','localtime'))",
      [tradeNo, order.id, req.userId, order.pay_amount, method, 'pending']);
    // 获取商品信息作为支付描述
    const orderItem = get('SELECT * FROM order_items WHERE order_id=? LIMIT 1', [order.id]);
    const subject = orderItem ? orderItem.product_name : '商城订单-' + order_no;
    // ===== 调用统一支付入口 =====
    const payResult = await paymentSdk.createPayment(tradeNo, order.pay_amount, subject, method, {
      clientIp: req.ip || req.headers['x-forwarded-for'] || '127.0.0.1',
      isMobile: !!(req.headers['user-agent']?.toLowerCase().includes('mobile') || req.query.mobile === '1')
    });
    // 写入订单日志
    run('INSERT INTO order_logs(order_id, action, content, operator) VALUES(?,?,?,?)',
      [order.id, 'payment_create', '创建支付单: ' + tradeNo + ', 方式: ' + method + ', 金额: ¥' + order.pay_amount + ', 模式: ' + payResult.mode, 'system']);
    // 启动支付状态轮询（补单防护）
    reconciliation.startPolling(order_no, tradeNo);
    const responseData = {
      trade_no: tradeNo,
      order_no: order_no,
      amount: order.pay_amount,
      method: method,
      mode: payResult.mode,
      is_mock: payResult.isMock !== false,
      pay_url: payResult.payUrl || '',
      message: payResult.warn || '支付创建成功'
    };
    // 不同支付类型返回不同参数
    if (payResult.payType === 'jsapi') {
      responseData.js_params = payResult.jsParams;
    }
    if (payResult.codeUrl) {
      responseData.code_url = payResult.codeUrl;
    }
    if (payResult.payForm) {
      responseData.pay_form = payResult.payForm;
    }
    if (payResult.h5Url) {
      responseData.h5_url = payResult.h5Url;
    }
    return res.json(success(responseData, payResult.warn || '支付创建成功'));
  } catch (e) {
    console.error('[支付] 创建支付失败:', e);
    return res.json(fail('创建支付失败: ' + e.message));
  }
});
// ===================================================================
// 2. 微信支付回调通知 - POST /api/payment/notify
// 微信以 XML 格式 POST 到此接口
// ===================================================================
router.post('/notify', async (req, res) => {
  try {
    // 微信回调以 XML 格式发送，需要原始 body
    const rawBody = req.rawBody || (typeof req.body === 'object' ? JSON.stringify(req.body) : req.body) || '';
    // 尝试解析 XML，如果失败则可能是 JSON（支付宝或其他）
    let notifyResult;
    let channel = 'wechat';
    // 检查请求头 Content-Type 判断来源
    const contentType = req.headers['content-type'] || '';
    if (contentType.includes('xml') || rawBody.includes('<xml>')) {
      // 微信支付回调 (XML)
      notifyResult = wechatSdk.verifyNotify(rawBody);
    } else if (req.body?.sign && req.body?.app_id) {
      // 支付宝异步通知 (form-data)
      channel = 'alipay';
      notifyResult = alipaySdk.verifyNotify(req.body);
    } else {
      // 未知格式 - 尝试兼容处理
      return res.type('text/plain').send('fail');
    }
    if (!notifyResult.success) {
      logger.log(notifyResult.tradeNo, 'notify_failed', `${channel}支付失败回调: ${notifyResult.errorMsg}`,
        { channel, level: 'warn', responseData: rawBody.slice(0, 500) });
      return res.type('text/plain').send('success'); // 仍返回 success 避免重复通知
    }
    // 查询支付记录
    const record = get('SELECT * FROM payment_records WHERE trade_no=?', [notifyResult.tradeNo]);
    if (!record) {
      logger.log(notifyResult.tradeNo, 'notify_no_record', `${channel}回调: 支付记录不存在`,
        { channel, level: 'error' });
      return res.type('text/plain').send('fail');
    }
    // 🔒 资金安全：校验回调金额与支付记录应付金额一致（元），防止金额被篡改/异常回调改单
    const notifyAmount = Number(notifyResult.totalFee);
    const expectedAmount = Number(record.amount);
    if (!Number.isFinite(notifyAmount) || !Number.isFinite(expectedAmount) || notifyAmount < expectedAmount) {
      logger.log(notifyResult.tradeNo, 'notify_amount_mismatch', `微信回调金额不一致: 回调¥${notifyAmount}, 应付¥${expectedAmount}`,
        { channel, level: 'error' });
      return res.type('text/plain').send('fail');
    }
    // 防止重复回调
    if (record.status === 'success') {
      return res.type('text/plain').send('success');
    }
    // 更新支付记录和订单状态
    transaction(() => {
      run("UPDATE payment_records SET status='success', transaction_id=?, pay_time=COALESCE(?, datetime('now','localtime')) WHERE trade_no=?",
        [notifyResult.transactionId || '', notifyResult.payTime || '', notifyResult.tradeNo]);
      const orderId = record.order_id;
      const order = get('SELECT * FROM orders WHERE id=?', [orderId]);
      if (order && order.status === 'pending_pay') {
        // 🔒 会员订单支付成功 -> 发放会员权益（幂等，仅待支付订单）
        //    注意：必须在状态流转前调用（激活逻辑依赖 status='pending_pay'）
        const { activateMembership } = require('../lib/membership-activate');
        activateMembership(orderId);
        run("UPDATE orders SET status='pending_ship', payment_method=?, paid_amount=?, updated_at=datetime('now','localtime') WHERE id=?",
          [record.method, record.amount, orderId]);
        run('INSERT INTO order_logs(order_id, action, content, operator) VALUES(?,?,?,?)',
          [orderId, 'pay', `支付成功, 金额: ¥${record.amount}, 方式: ${record.method}, 交易号: ${notifyResult.transactionId || ''}`, 'system']);
      }
    });
    logger.log(notifyResult.tradeNo, 'notify_success', `${channel}回调处理成功, 金额: ¥${record.amount}`,
      { channel, responseData: JSON.stringify(notifyResult).slice(0, 500) });
    // 异步通知 - 支付成功
    const orderForNotif = get('SELECT * FROM orders WHERE id=?', [record.order_id]);
    if (orderForNotif) {
      notification.send('payment_success', orderForNotif.user_id, {
        order_no: orderForNotif.order_no,
        amount: record.amount.toFixed(2)
      }).catch(err => console.error('[通知] 支付回调通知失败:', err.message));
    }
    // 微信/支付宝要求返回 success
    return res.type('text/plain').send('success');
  } catch (e) {
    console.error('[支付回调] 处理异常:', e);
    logger.log('', 'notify_error', `回调处理异常: ${e.message}`,
      { level: 'error' });
    return res.type('text/plain').send('fail');
  }
});
// ===================================================================
// 3. 支付宝异步通知 - POST /api/payment/alipay-notify
// 支付宝单独的通知入口(可选，也可以统一走 /notify)
// ===================================================================
router.post('/alipay-notify', (req, res) => {
  try {
    const params = req.body || {};
    const result = alipaySdk.verifyNotify(params);
    if (!result.success) {
      logger.log(result.tradeNo, 'alipay_notify_failed', `支付宝回调: 支付未成功(${result.tradeStatus})`,
        { channel: 'alipay', level: 'warn' });
      return res.send('success');
    }
    // 查询并更新支付记录
    const record = get('SELECT * FROM payment_records WHERE trade_no=?', [result.tradeNo]);
    if (!record) {
      logger.log(result.tradeNo, 'alipay_notify_no_record', `支付宝回调: 记录不存在`,
        { channel: 'alipay', level: 'error' });
      return res.send('fail');
    }
    // 🔒 资金安全：校验回调金额与应付金额一致
    const notifyAmount = Number(result.totalAmount || result.total_amount || 0);
    const expectedAmount = Number(record.amount);
    if (!Number.isFinite(notifyAmount) || !Number.isFinite(expectedAmount) || notifyAmount < expectedAmount) {
      logger.log(result.tradeNo, 'alipay_notify_amount_mismatch', `支付宝回调金额不一致: 回调¥${notifyAmount}, 应付¥${expectedAmount}`,
        { channel: 'alipay', level: 'error' });
      return res.send('fail');
    }
    if (record.status === 'success') return res.send('success');
    transaction(() => {
      run("UPDATE payment_records SET status='success', transaction_id=?, pay_time=? WHERE trade_no=?",
        [result.alipayTradeNo || '', result.payTime || '', result.tradeNo]);
      const orderId = record.order_id;
      const order = get('SELECT * FROM orders WHERE id=?', [orderId]);
      if (order && order.status === 'pending_pay') {
        // 🔒 会员订单支付成功 -> 发放会员权益（幂等，状态流转前调用）
        const { activateMembership } = require('../lib/membership-activate');
        activateMembership(orderId);
        run("UPDATE orders SET status='pending_ship', payment_method=?, paid_amount=?, updated_at=datetime('now','localtime') WHERE id=?",
          [record.method, record.amount, orderId]);
        run('INSERT INTO order_logs(order_id, action, content, operator) VALUES(?,?,?,?)',
          [orderId, 'pay', `支付宝支付成功, 金额: ¥${record.amount}, 交易号: ${result.alipayTradeNo}`, 'system']);
      }
    });
    logger.log(result.tradeNo, 'alipay_notify_success', `支付宝回调处理成功`,
      { channel: 'alipay' });
    // 异步通知 - 支付成功
    const orderForNotif = get('SELECT * FROM orders WHERE id=?', [record.order_id]);
    if (orderForNotif) {
      notification.send('payment_success', orderForNotif.user_id, {
        order_no: orderForNotif.order_no,
        amount: record.amount.toFixed(2)
      }).catch(err => console.error('[通知] 支付宝回调通知失败:', err.message));
    }
    return res.send('success');
  } catch (e) {
    console.error('[支付宝回调] 异常:', e);
    return res.send('fail');
  }
});
// ===================================================================
// 4. 查询支付状态 - GET /api/payment/status/:orderNo
// ===================================================================
router.get('/status/:orderNo', authUser, (req, res) => {
  try {
    const { orderNo } = req.params;
    const order = get('SELECT * FROM orders WHERE order_no=? AND user_id=?', [orderNo, req.userId]);
    if (!order) return res.json(fail('订单不存在'));
    const record = get('SELECT * FROM payment_records WHERE order_id=? ORDER BY id DESC LIMIT 1', [order.id]);
    const isPaid = order.status !== 'pending_pay' && (order.paid_amount > 0 || record?.status === 'success');
    return res.json(success({
      paid: isPaid,
      order_no: orderNo,
      order_status: order.status,
      trade_no: record?.trade_no || '',
      pay_time: record?.pay_time || null,
      amount: record?.amount || order.pay_amount,
      method: record?.method || order.payment_method || '',
      status: record?.status || (isPaid ? 'success' : 'pending'),
      transaction_id: record?.transaction_id || ''
    }, '查询成功'));
  } catch (e) {
    console.error('[支付] 查询状态失败:', e);
    return res.json(fail('查询失败'));
  }
});
// ===================================================================
// 5. 模拟支付页面 - GET /api/payment/mock-pay（保留完整功能）
// ===================================================================
router.get('/mock-pay', (req, res) => {
  // [安全] 生产模式禁止模拟支付（防止伪造支付成功）
  if (paymentSdk.getPayMode() !== 'simulate') return res.status(403).send('模拟支付已禁用');
  const { trade_no, order_no } = req.query;
  if (!trade_no) return res.status(400).send('参数错误');
  const record = get('SELECT * FROM payment_records WHERE trade_no=?', [trade_no]);
  if (!record) return res.status(404).send('支付记录不存在');
  const order = get('SELECT * FROM orders WHERE id=?', [record.order_id]);
  res.send(`<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><title>模拟支付</title><style>
    *{margin:0;padding:0;box-sizing:border-box}body{font-family:-apple-system,PingFang SC,sans-serif;background:#f5f6fa;display:flex;justify-content:center;align-items:center;min-height:100vh}
    .card{background:#fff;border-radius:16px;padding:40px 32px;width:360px;max-width:90%;text-align:center;box-shadow:0 4px 20px rgba(0,0,0,.08)}
    .amount{font-size:36px;font-weight:700;color:#F53F3F;margin:16px 0}
    .amount span{font-size:20px}
    .order-info{font-size:13px;color:#6B7280;margin:8px 0}
    .btn{margin-top:24px;width:100%;padding:14px;background:linear-gradient(135deg,#4A7CF7,#7C9FFF);color:#fff;border:none;border-radius:12px;font-size:16px;font-weight:600;cursor:pointer;transition:all .2s}
    .btn:active{transform:scale(.96);opacity:.85}
    .btn:hover{box-shadow:0 4px 12px rgba(74,124,247,.3)}
    .btn.disabled{background:#d1d5db;cursor:not-allowed}
    .hint{font-size:12px;color:#b0b7c3;margin-top:12px}
    .success-icon{display:none;font-size:64px;margin-bottom:12px}
  </style></head><body>
  <div class="card" id="app">
    <div id="loading" style="font-size:16px;color:#6B7280">⏳ 正在加载支付信息...</div>
    <div id="content" style="display:none">
      <div class="success-icon" id="successIcon">✅</div>
      <div style="font-size:18px;font-weight:600" id="title">订单支付</div>
      <div class="order-info">订单号: ${order_no || order?.order_no || ''}</div>
      <div class="amount"><span>¥</span>${record.amount.toFixed(2)}</div>
      <div class="order-info">支付方式: ${record.method === 'wechat' ? '微信支付' : '支付宝'}</div>
      <button class="btn" id="payBtn" onclick="payNow()">✅ 模拟支付成功</button>
      <div class="hint">⚠️ 模拟模式下点击即可完成支付</div>
    </div>
  </div>
  <script>
    document.getElementById('loading').style.display='none';
    document.getElementById('content').style.display='block';
    async function payNow() {
      const btn = document.getElementById('payBtn');
      btn.disabled = true; btn.className = 'btn disabled'; btn.textContent = '处理中...';
      try {
        const r = await fetch('/api/payment/mock-notify', {
          method: 'POST', headers: {'Content-Type': 'application/json'},
          body: JSON.stringify({order_no: '${order_no || order?.order_no || ''}', trade_no: '${trade_no}', payment_method: '${record.method}'})
        });
        const data = await r.json();
        if (data.code === 0) {
          document.getElementById('title').textContent = '🎉 支付成功';
          document.getElementById('successIcon').style.display = 'block';
          btn.textContent = '✅ 支付已完成'; btn.className = 'btn disabled';
          if (window.opener) window.opener.postMessage({type:'payment_success', order_no:'${order_no || order?.order_no || ''}'}, '*');
          setTimeout(() => window.close(), 2000);
        } else {
          alert('支付失败: ' + data.message);
          btn.disabled = false; btn.className = 'btn'; btn.textContent = '✅ 模拟支付成功';
        }
      } catch(e) {
        alert('网络错误: ' + e.message);
        btn.disabled = false; btn.className = 'btn'; btn.textContent = '✅ 模拟支付成功';
      }
    }
  </script>
  </body></html>`);
});
// ===================================================================
// 6. 模拟支付通知（测试模式）- POST /api/payment/mock-notify
// ===================================================================
router.post('/mock-notify', (req, res) => {
  const { order_no, trade_no, payment_method } = req.body;
  const finalTradeNo = trade_no || ('MOCK' + Date.now());
  // 检查是否为充值订单(RC开头)
  if (order_no && order_no.startsWith('RC')) {
    // 充值订单回调
    const rechargeOrder = get('SELECT * FROM recharge_orders WHERE order_no=?', [order_no]);
    if (!rechargeOrder) return res.json(fail('充值订单不存在'));
    if (rechargeOrder.status === 'success') return res.json(success(null, '已处理'));
    transaction(() => {
      run("UPDATE recharge_orders SET status='success', paid_at=datetime('now','localtime') WHERE order_no=?", [order_no]);
      const totalAmount = (rechargeOrder.amount || 0) + (rechargeOrder.give_amount || 0);
      run('UPDATE users SET balance=balance+?, experience=experience+? WHERE id=?',
        [totalAmount, rechargeOrder.give_points || 0, rechargeOrder.user_id]);
    });
    logger.log(finalTradeNo, 'mock_notify', '充值模拟支付成功: ' + order_no, { channel: 'mock' });
    return res.json({ code: 0, message: 'success' });
  }
  const order = get('SELECT * FROM orders WHERE order_no=?', [order_no]);
  if (!order) return res.json(fail('订单不存在'));
  if (order.status !== 'pending_pay') return res.json(fail('订单状态不正确'));
  transaction(() => {
    // 更新订单状态
    run("UPDATE orders SET status='pending_ship', payment_method=?, paid_amount=pay_amount, updated_at=datetime('now','localtime') WHERE id=?",
      [payment_method || 'wechat', order.id]);
    // 更新已有的支付记录为成功，而非重新插入
    const existingRecord = get('SELECT * FROM payment_records WHERE order_id=? AND status=?', [order.id, 'pending']);
    if (existingRecord) {
      run("UPDATE payment_records SET status='success', transaction_id=?, pay_time=datetime('now','localtime') WHERE id=?",
        [finalTradeNo, existingRecord.id]);
    } else {
      // 没有待支付记录时，插入新的支付成功记录
      run("INSERT INTO payment_records(trade_no,order_id,user_id,amount,method,status,pay_time) VALUES(?,?,?,?,?,?,datetime('now','localtime'))",
        [finalTradeNo, order.id, order.user_id, order.pay_amount, payment_method || 'wechat', 'success']);
    }
    run('INSERT INTO order_logs(order_id,action,content) VALUES(?,?,?)', [order.id, 'pay', '支付通知回调成功（模拟）']);
    // 支付成功 -> 创建分销佣金记录
    try { commission.createCommissionRecords(order.id); } catch(e) { console.error('[佣金] 创建佣金记录失败:', e.message); }
    // 支付成功 -> 消费送积分
    try {
      const pts = require('../lib/points');
      pts.rewardOrderPoints(order.user_id, order.pay_amount, order.order_no);
    } catch(e) { console.error('[积分] 消费送积分失败:', e.message); }
  });
  logger.log(finalTradeNo, 'mock_notify', '模拟支付成功: ' + order_no, { channel: 'mock' });
  // 异步通知 - 支付成功
  notification.send('payment_success', order.user_id, {
    order_no: order.order_no,
    amount: order.pay_amount.toFixed(2)
  }).catch(err => console.error('[通知] 支付通知失败:', err.message));
  return res.json({ code: 0, message: 'success' });
});
// ===================================================================
// 7. 微信H5支付跳转 - GET /api/payment/h5-pay
// ===================================================================
router.get('/h5-pay', async (req, res) => {
  try {
    const { trade_no } = req.query;
    if (!trade_no) return res.status(400).send('参数错误');
    const record = get('SELECT * FROM payment_records WHERE trade_no=?', [trade_no]);
    if (!record) return res.status(404).send('支付记录不存在');
    const clientIp = req.ip || req.headers['x-forwarded-for'] || '127.0.0.1';
    const mwebUrl = await wechatSdk.getH5PayUrl(trade_no, record.amount, '商城订单', clientIp);
    if (mwebUrl) {
      // 302跳转到微信支付中间页
      // 注意：微信MWEB需添加referer后缀
      const redirectUrl = mwebUrl + '&redirect_url=' + encodeURIComponent((req.headers.origin || 'http://localhost:3001') + '/mobile');
      return res.redirect(redirectUrl);
    }
    return res.status(500).send('获取H5支付链接失败');
  } catch (e) {
    console.error('[支付] H5支付失败:', e);
    return res.status(500).send('H5支付异常: ' + e.message);
  }
});
// ===================================================================
// 8. 查询微信/支付宝交易状态（管理端）- GET /api/payment/query/:tradeNo
// ===================================================================
router.get('/query/:tradeNo', authAdmin, async (req, res) => {
  try {
    const { tradeNo } = req.params;
    const record = get('SELECT * FROM payment_records WHERE trade_no=?', [tradeNo]);
    if (!record) return res.json(fail('支付记录不存在'));
    if (paymentSdk.isSimulateMode()) {
      return res.json(success({
        trade_no: tradeNo,
        status: record.status,
        local_check: '模拟模式，仅返回本地状态'
      }));
    }
    const channel = record.method;
    const result = await paymentSdk.queryTrade(tradeNo, channel);
    return res.json(success({
      trade_no: tradeNo,
      method: channel,
      ...result,
      local_status: record.status
    }));
  } catch (e) {
    return res.json(fail('查询失败: ' + e.message));
  }
});
// ===================================================================
// 9. 创建退款申请（用户端）- POST /api/payment/refund/create
// ===================================================================
router.post('/refund/create', authUser, (req, res) => {
  try {
    const { order_no, reason, amount } = req.body;
    if (!order_no) return res.json(fail('订单号不能为空'));
    const order = get('SELECT * FROM orders WHERE order_no=? AND user_id=?', [order_no, req.userId]);
    if (!order) return res.json(fail('订单不存在'));
    const refundableStatuses = ['pending_ship', 'shipped', 'received'];
    if (!refundableStatuses.includes(order.status)) {
      return res.json(fail('当前订单状态不可申请退款'));
    }
    const pendingRefund = get('SELECT * FROM refunds WHERE order_id=? AND status=?', [order.id, 'pending']);
    if (pendingRefund) return res.json(fail('已有退款申请正在处理中'));
    const refundAmount = Math.min(
      parseFloat(amount || order.paid_amount || order.pay_amount),
      parseFloat(order.paid_amount || order.pay_amount)
    );
    if (refundAmount <= 0) return res.json(fail('退款金额无效'));
    const refundNo = genRefundNo();
    const result = run(
      "INSERT INTO refunds(refund_no, order_id, order_item_id, user_id, type, reason, amount, status, created_at) VALUES(?,?,?,?,?,?,?,?, datetime('now','localtime'))",
      [refundNo, order.id, null, req.userId, 'only_refund', reason || '用户申请退款', refundAmount, 'pending']
    );
    run("UPDATE orders SET status='refunding', updated_at=datetime('now','localtime') WHERE id=?", [order.id]);
    run('INSERT INTO order_logs(order_id, action, content, operator) VALUES(?,?,?,?)',
      [order.id, 'refund_apply', `用户申请退款，金额: ¥${refundAmount}，原因: ${reason || '无'}`, 'user']);
    // 记录支付退款日志
    const paymentRecord = get('SELECT * FROM payment_records WHERE order_id=? AND status=? ORDER BY id DESC LIMIT 1', [order.id, 'success']);
    if (paymentRecord) {
      run("INSERT INTO payment_records(trade_no, order_id, user_id, amount, method, status, created_at) VALUES(?,?,?,?,?,?, datetime('now','localtime'))",
        [refundNo, order.id, req.userId, refundAmount, order.payment_method || 'wechat', 'refunded']);
    }
    logger.log(refundNo, 'refund_create', `用户发起退款: ¥${refundAmount}`, { channel: order.payment_method || '' });
    return res.json(success({
      refund_id: result.lastInsertRowid,
      refund_no: refundNo,
      amount: refundAmount
    }, '退款申请已提交'));
  } catch (e) {
    console.error('[支付] 创建退款申请失败:', e);
    return res.json(fail('创建退款申请失败: ' + e.message));
  }
});
// ===================================================================
// 10. 处理退款（管理员审核）- POST /api/payment/refund/process
// 生产模式：审核通过后会调用微信/支付宝退款API
// ===================================================================
router.post('/refund/process', authAdmin, async (req, res) => {
  try {
    const { refund_id, action, reject_reason } = req.body;
    if (!refund_id) return res.json(fail('退款ID不能为空'));
    if (!action || !['approve', 'reject'].includes(action)) {
      return res.json(fail('操作类型无效（approve/reject）'));
    }
    const refund = get('SELECT * FROM refunds WHERE id=?', [refund_id]);
    if (!refund) return res.json(fail('退款申请不存在'));
    if (refund.status !== 'pending') return res.json(fail('该申请已处理'));
    const order = get('SELECT * FROM orders WHERE id=?', [refund.order_id]);
    if (!order) return res.json(fail('订单不存在'));
    // 获取原始的支付记录（渠道信息）
    const paymentRecord = get("SELECT * FROM payment_records WHERE order_id=? AND status='success' ORDER BY id DESC LIMIT 1", [order.id]);
    transaction(() => {
      if (action === 'approve') {
        // 审核通过 - 更新退款单状态
        run("UPDATE refunds SET status='completed', updated_at=datetime('now','localtime') WHERE id=?", [refund_id]);
        // 更新订单为已退款
        run("UPDATE orders SET status='refunded', refund_status='completed', updated_at=datetime('now','localtime') WHERE id=?", [order.id]);
        // 更新支付记录的退款状态
        if (paymentRecord) {
          run("UPDATE payment_records SET status='refunded' WHERE id=?", [paymentRecord.id]);
        }
        // 归还库存
        const items = all('SELECT * FROM order_items WHERE order_id=?', [order.id]);
        for (const item of items) {
          if (item.sku_id) {
            run('UPDATE product_skus SET stock=stock+?, sales=sales-? WHERE id=?', [item.quantity, item.quantity, item.sku_id]);
          } else {
            run('UPDATE products SET stock=stock+?, sales=sales-? WHERE id=?', [item.quantity, item.quantity, item.product_id]);
          }
        }
        // 生产模式调用渠道退款API（异步，不阻塞审核流程）
        if (!paymentSdk.isSimulateMode() && paymentRecord && paymentRecord.transaction_id) {
          const channel = paymentRecord.method || 'wechat';
          logger.log(refund.refund_no, 'refund_process', `生产模式，将调起${channel}退款`,
            { channel, level: 'info' });
          // 异步退款调用，不阻塞响应
          paymentSdk.processRefund(
            paymentRecord.trade_no,
            refund.refund_no,
            order.pay_amount,
            refund.amount,
            refund.reason || '',
            channel
          ).then(r => {
            logger.log(refund.refund_no, 'refund_api_success', `渠道退款成功: ${JSON.stringify(r)}`,
              { channel, level: 'info' });
          }).catch(e => {
            logger.log(refund.refund_no, 'refund_api_failed', `渠道退款失败: ${e.message}`,
              { channel, level: 'error' });
          });
        }
        run('INSERT INTO order_logs(order_id, action, content, operator) VALUES(?,?,?,?)',
          [refund.order_id, 'refund_approve', `退款审核通过，金额: ¥${refund.amount}`, 'admin']);
        // 异步通知 - 退款成功
        notification.send('refund_processed', refund.user_id, {
          order_no: order.order_no,
          result: '通过',
          amount: refund.amount.toFixed(2)
        }).catch(err => console.error('[通知] 退款通知失败:', err.message));
      } else {
        // 审核驳回
        run("UPDATE refunds SET status='rejected', reject_reason=?, updated_at=datetime('now','localtime') WHERE id=?",
          [reject_reason || '', refund_id]);
        const prevStatus = order.status === 'refunding' ? 'received' : order.status;
        run("UPDATE orders SET status=?, updated_at=datetime('now','localtime') WHERE id=?", [prevStatus, order.id]);
        run('INSERT INTO order_logs(order_id, action, content, operator) VALUES(?,?,?,?)',
          [refund.order_id, 'refund_reject', `退款审核驳回: ${reject_reason || '无'}`, 'admin']);
        // 异步通知 - 退款驳回
        notification.send('refund_processed', refund.user_id, {
          order_no: order.order_no,
          result: '驳回',
          amount: refund.amount.toFixed(2)
        }).catch(err => console.error('[通知] 退款驳回通知失败:', err.message));
      }
    });
    return res.json(success(null, action === 'approve' ? '退款已通过' : '已驳回'));
  } catch (e) {
    console.error('[支付] 处理退款失败:', e);
    return res.json(fail('操作失败: ' + e.message));
  }
});
// ===================================================================
// 11. 退款列表（管理员端）- GET /api/payment/refunds
// ===================================================================
router.get('/refunds', authAdmin, (req, res) => {
  try {
    const { page: p = 1, pageSize = 20, status } = req.query;
    const pageNum = Math.max(1, +p);
    const size = Math.min(100, Math.max(1, +pageSize));
    let where = 'WHERE 1=1';
    const params = [];
    if (status) {
      where += ' AND r.status=?';
      params.push(status);
    }
    const total = get(`SELECT COUNT(*) as c FROM refunds r ${where}`, params).c;
    const list = all(`SELECT r.*, u.nickname, u.phone as user_phone, o.order_no 
      FROM refunds r 
      LEFT JOIN users u ON r.user_id=u.id 
      LEFT JOIN orders o ON r.order_id=o.id 
      ${where} 
      ORDER BY r.id DESC 
      LIMIT ? OFFSET ?`,
      [...params, size, (pageNum - 1) * size]);
    return res.json(page({ list, total, page: pageNum, pageSize: size, totalPages: Math.ceil(total / size) }));
  } catch (e) {
    return res.json(fail('查询失败'));
  }
});
// ===================================================================
// 12. 我的退款列表（用户端）- GET /api/payment/refund/my
// ===================================================================
router.get('/refund/my', authUser, (req, res) => {
  try {
    const { page: p = 1, pageSize = 10 } = req.query;
    const pageNum = Math.max(1, +p);
    const size = Math.min(50, Math.max(1, +pageSize));
    const total = get('SELECT COUNT(*) as c FROM refunds WHERE user_id=?', [req.userId]).c;
    const list = all(`SELECT r.*, o.order_no 
      FROM refunds r 
      LEFT JOIN orders o ON r.order_id=o.id 
      WHERE r.user_id=? 
      ORDER BY r.id DESC 
      LIMIT ? OFFSET ?`,
      [req.userId, size, (pageNum - 1) * size]);
    return res.json(page(list, total, pageNum, size));
  } catch (e) {
    return res.json(fail('查询失败'));
  }
});
// ===================================================================
// 13. 支付能力检测 - GET /api/payment/capabilities
// 前端用来判断显示哪些支付方式
// ===================================================================
router.get('/capabilities', (req, res) => {
  const caps = paymentSdk.getPaymentCapabilities();
  const mode = paymentSdk.getPayMode();
  return res.json(success({
    mode: mode,  // 'simulate' | 'production'
    is_simulate: mode === 'simulate',
    wechat_configured: caps.wechat,
    alipay_configured: caps.alipay,
    wechat_enabled: caps.wechat || mode === 'simulate',
    alipay_enabled: caps.alipay || mode === 'simulate'
  }));
});
// ===================================================================
// 14. 支付日志查询（管理端）- GET /api/payment/logs
// ===================================================================
router.get('/logs', authAdmin, (req, res) => {
  try {
    const { trade_no, limit = 50 } = req.query;
    const logs = logger.queryLogs(trade_no || '', parseInt(limit));
    return res.json(success(logs));
  } catch (e) {
    return res.json(fail('查询日志失败'));
  }
});
// ===================================================================
// 15. 每日对账 - POST /api/payment/reconcile/daily
// 管理端主动触发对账，比对支付记录与订单状态一致性
// 注意：特定路由（无参数）必须放在参数化路由之前
// ===================================================================
router.post('/reconcile/daily', authAdmin, (req, res) => {
  try {
    const result = reconciliation.dailyReconcile();
    return res.json(success(result, `对账完成: 检查${result.total_orders}条记录, 修复${result.fixes}条, 异常${result.errors}条`));
  } catch (e) {
    return res.json(fail('对账失败: ' + e.message));
  }
});
// ===================================================================
// 16. 对账日志查询 - GET /api/payment/reconcile/logs
// ===================================================================
router.get('/reconcile/logs', authAdmin, (req, res) => {
  try {
    const { page: p = 1, pageSize = 20, result, action } = req.query;
    const pageNum = Math.max(1, +p);
    const size = Math.min(100, Math.max(1, +pageSize));
    const data = reconciliation.getReconcileLogs(pageNum, size, { result, action });
    return res.json(page(data.list, data.total, pageNum, size));
  } catch (e) {
    return res.json(fail('查询失败: ' + e.message));
  }
});
// ===================================================================
// 17. 手动补单 - POST /api/payment/reconcile/:orderNo
// 管理端手动触发补单，重新检查订单支付状态并修复
// ===================================================================
router.post('/reconcile/:orderNo', authAdmin, async (req, res) => {
  try {
    const { orderNo } = req.params;
    const result = await reconciliation.manualRetry(orderNo, req.adminName || 'admin');
    reconciliation.addReconcileLog({
      orderNo, tradeNo: '', action: 'manual_retry',
      beforeStatus: get('SELECT status FROM orders WHERE order_no=?', [orderNo])?.status || '',
      afterStatus: result.success ? 'pending_ship' : (get('SELECT status FROM orders WHERE order_no=?', [orderNo])?.status || ''),
      result: result.success ? 'fixed' : 'no_change',
      message: result.message,
      operator: req.adminName || 'admin'
    });
    if (result.success) {
      return res.json(success(result, result.message));
    }
    return res.json(fail(result.message));
  } catch (e) {
    return res.json(fail('补单操作失败: ' + e.message));
  }
});
// ===================================================================
// 18. 超时订单自动关闭 - POST /api/payment/timeout-cancel
// ===================================================================
router.post('/timeout-cancel', (req, res) => {
  try {
    const timeoutMinutes = +(req.body.minutes || 30);
    const result = transaction(() => {
      const expired = all(`SELECT id, order_no FROM orders WHERE status='pending_pay' AND 
        datetime(created_at, '+' || ? || ' minutes') < datetime('now','localtime')`, [timeoutMinutes]);
      for (const order of expired) {
        run("UPDATE orders SET status='closed', close_reason='超时未支付', close_time=datetime('now','localtime') WHERE id=?", [order.id]);
        run('INSERT INTO order_logs(order_id,action,content) VALUES(?,?,?)', [order.id, 'auto_close', '系统自动关闭超时订单']);
        const items = all('SELECT * FROM order_items WHERE order_id=?', [order.id]);
        for (const item of items) {
          if (item.sku_id) {
            run('UPDATE product_skus SET stock=stock+? WHERE id=?', [item.quantity, item.sku_id]);
          } else {
            run('UPDATE products SET stock=stock+? WHERE id=?', [item.quantity, item.product_id]);
          }
        }
      }
      return expired.length;
    });
    return res.json(success({ cancelled: result }, '处理完成'));
  } catch (e) {
    return res.json(fail('处理失败'));
  }
});
module.exports = router;