/**
 * 支付门面（审查优化版）
 * 修复项：
 *  - 支付模式用常量，去掉 magic number
 *  - getPayMode 加进程内缓存 + 失效接口
 *  - 生产模式严禁任何模拟回退（资金安全）
 *  - 日志对敏感参数脱敏
 *  - 回调入口提示幂等（需路由层配合）
 */
const { get, run } = require('../../utils/db');

// [LiteMall_Copyright] fba28f00dae77aa2 LiteMall_Lobster_v1.0_2026

const wechatPay = require('./wechat');
const alipayPay = require('./alipay');
const logger = require('./logger');

const PAY_MODE = {
  TEST: '1',      // 测试/模拟
  PROD: '0',      // 生产
};

/** 支付模式缓存（TTL 30s） */
let modeCache = PAY_MODE.TEST;
let modeCacheAt = 0;
const MODE_TTL = 30 * 1000;

/** 支付模式：'1'=simulate(测试)  其它=production */
function getPayMode() {
  const now = Date.now();
  if (now - modeCacheAt >= MODE_TTL) {
    modeCacheAt = now;
    modeCache = get("SELECT value FROM system_config WHERE key='payment_test_mode'")?.value || '1';
  }
  return modeCache;
}

function isSimulateMode() {
  return getPayMode() === PAY_MODE.TEST;
}

/** 支付模式变更时调用，使缓存失效 */
function invalidatePayMode() {
  modeCacheAt = 0;
}

/** 金额校验包装：非法金额直接抛错 */
function assertAmount(amount) {
  const fen = Math.round((Number(amount) || 0) * 100);
  if (!Number.isFinite(fen) || fen <= 0) throw new Error('非法金额');
  return fen;
}

/** 脱敏：日志中隐藏预支付/交易敏感串 */
function safeString(v) {
  if (v == null) return '';
  const s = String(v);
  return s.length > 16 ? s.slice(0, 8) + '…' : s;
}

/**
 * 创建支付
 * @param {string} tradeNo  业务订单号
 * @param {number|string} amount 金额(元)
 * @param {string} subject   商品描述
 * @param {string} channel   wechat | alipay
 * @param {object} opts      {openid, clientIp, returnUrl}
 */
async function createPayment(tradeNo, amount, subject, channel, opts = {}) {
  assertAmount(amount);
  const mode = getPayMode();
  logger.log(tradeNo, 'create_payment', `创建支付: ${channel}, 金额: ¥${amount}, 模式: ${mode === PAY_MODE.TEST ? '测试' : '生产'}`, { channel, level: 'info' });

  // 测试模式：返回模拟支付
  if (mode === PAY_MODE.TEST) {
    return { mode: 'simulate', payUrl: `/api/payment/mock-pay?trade_no=${tradeNo}`, isMock: true };
  }

  // ===== 生产模式：任何异常都抛错，绝不回退模拟支付 =====
  if (channel === 'wechat') {
    if (!wechatPay.isWechatConfigured()) {
      logger.log(tradeNo, 'create_payment', '微信支付未配置完整', { channel, level: 'warn' });
      throw new Error('微信支付未配置，请联系管理员');
    }
    try {
      const clientIp = opts.clientIp || '127.0.0.1';
      const openid = opts.openid || '';
      if (openid) {
        const r = await wechatPay.createJsapiPay(tradeNo, amount, subject, clientIp, openid);
        logger.log(tradeNo, 'create_payment', 'JSAPI支付创建成功', { channel });
        return { mode: 'production', method: channel, payType: 'jsapi', isMock: false, jsParams: r.jsParams, prepayId: safeString(r.prepayId) };
      }
      const r = await wechatPay.createNativePay(tradeNo, amount, subject);
      logger.log(tradeNo, 'create_payment', 'Native支付创建成功', { channel });
      return { mode: 'production', method: channel, payType: 'native', isMock: false, codeUrl: r.codeUrl, h5Url: `/api/payment/h5-pay?trade_no=${tradeNo}` };
    } catch (e) {
      logger.log(tradeNo, 'create_payment', `微信支付异常: ${e.message}`, { channel, level: 'error' });
      throw new Error('微信支付创建失败: ' + e.message);
    }
  }

  if (channel === 'alipay') {
    if (!alipayPay.isAlipayConfigured()) {
      logger.log(tradeNo, 'create_payment', '支付宝支付未配置完整', { channel, level: 'warn' });
      throw new Error('支付宝支付未配置，请联系管理员');
    }
    try {
      if (opts.returnUrl) {
        const r = alipayPay.createWapPay({ tradeNo, amount, subject, returnUrl: opts.returnUrl });
        return { mode: 'production', method: channel, payType: 'wap', isMock: false, payParams: r };
      }
      const html = alipayPay.createPagePay({ tradeNo, amount, subject, returnUrl: opts.returnUrl });
      return { mode: 'production', method: channel, payType: 'page', isMock: false, html };
    } catch (e) {
      logger.log(tradeNo, 'create_payment', `支付宝支付异常: ${e.message}`, { channel, level: 'error' });
      throw new Error('支付宝支付创建失败: ' + e.message);
    }
  }

  throw new Error(`不支持的支付渠道: ${channel}`);
}

/**
 * 处理支付回调 / 退款回调
 * 注意：调用方必须在同一次事务内做「验签 + 幂等检查(trade_no去重) + 状态更新」
 */
async function processNotify(channel, data) {
  if (channel === 'wechat') {
    return wechatPay.verifyNotify(data); // 失败抛错
  }
  if (channel === 'alipay') {
    const result = alipayPay.verifyNotify(data);
    if (!result.success) throw new Error(result.errorMsg || '支付宝回调验签失败');
    return result;
  }
  throw new Error(`不支持的支付渠道: ${channel}`);
}

/** 查询交易 */
async function queryTrade(channel, tradeNo) {
  if (channel === 'wechat') return wechatPay.queryOrder(tradeNo);
  if (channel === 'alipay') return alipayPay.queryTrade(tradeNo);
  throw new Error(`不支持的支付渠道: ${channel}`);
}

/** 支付能力检测：返回各渠道是否已配置完整 */
function getPaymentCapabilities() {
  return { wechat: wechatPay.isWechatConfigured(), alipay: alipayPay.isAlipayConfigured() };
}

/** 退款（金额已由各渠道校验） */
async function refund(channel, params) {
  if (channel === 'wechat') {
    return wechatPay.refund(params.tradeNo, params.refundNo, params.totalAmount, params.refundAmount, params.reason);
  }
  if (channel === 'alipay') return alipayPay.refund(params);
  throw new Error(`不支持的支付渠道: ${channel}`);
}

/**
 * 退款适配层（兼容旧版路由调用签名）
 * @param {string} tradeNo      商户订单号
 * @param {string} refundNo     退款单号
 * @param {number} totalAmount  订单总金额（元）
 * @param {number} refundAmount 退款金额（元）
 * @param {string} reason       退款原因
 * @param {string} channel      wechat | alipay
 */
async function processRefund(tradeNo, refundNo, totalAmount, refundAmount, reason, channel) {
  const ch = channel || (refundNo && getPayMode ? 'wechat' : 'wechat');
  if (ch === 'wechat') {
    return wechatPay.refund(tradeNo, refundNo, totalAmount, refundAmount, reason || '');
  }
  if (ch === 'alipay') {
    return alipayPay.refund({ tradeNo, refundNo, refundAmount, reason: reason || '' });
  }
  throw new Error(`不支持的支付渠道: ${ch}`);
}

module.exports = {
  PAY_MODE,
  getPayMode,
  isSimulateMode,
  invalidatePayMode,
  createPayment,
  processNotify,
  queryTrade,
  refund,
  processRefund,
  getPaymentCapabilities,
};
