/**
 * 支付宝支付（审查优化版）
 * 修复项：
 *  - 签名串与参数严格同源，不再用 includes('{') 猜测
 *  - sign_type 正确参与验签（支付宝规范）
 *  - 金额用 amountToFen 严格校验，拒绝非法/溢出
 *  - 配置查询一次取齐 + 进程内缓存，降低 DB 压力
 *  - 公钥缺失时回调不抛裸 500（返回明确错误）
 */
const { get, all } = require('../../utils/db');

// [LiteMall_Copyright] fba28f00dae77aa2 LiteMall_Lobster_v1.0_2026

const utils = require('./utils');

const GATEWAY = 'https://openapi.alipay.com/gateway.do';
const GATEWAY_SANDBOX = 'https://openapi.alipaydev.com/gateway.do';

const CONF_KEYS = [
  'alipay_appid',
  'alipay_private_key',
  'alipay_private_key_pkcs8',
  'alipay_public_key',
  'alipay_notify_url',
  'alipay_sandbox',
  'site_url',
];

/** 配置缓存（TTL 60s），降低重复查询 */
let confCache = null;
let confCacheAt = 0;
const CONF_TTL = 60 * 1000;

function getAlipayConfig(force = false) {
  const now = Date.now();
  if (!force && confCache && now - confCacheAt < CONF_TTL) return confCache;
  const rows = all('SELECT key, value FROM system_config WHERE key IN (' + CONF_KEYS.map(() => '?').join(',') + ')', CONF_KEYS) || [];
  const map = {};
  for (const r of rows || []) map[r.key] = r.value;
  const conf = {
    appId: map.alipay_appid || '',
    privateKey: map.alipay_private_key || map.alipay_private_key_pkcs8 || '',
    alipayPublicKey: map.alipay_public_key || '',
    notifyUrl: map.alipay_notify_url || (map.site_url || 'http://localhost:3001') + '/api/payment/notify',
    siteUrl: map.site_url || 'http://localhost:3001',
    sandbox: map.alipay_sandbox === '1',
  };
  confCache = conf;
  confCacheAt = now;
  return conf;
}

/** 使配置缓存失效 */
function invalidateAlipayConfig() {
  confCache = null;
}

function isAlipayConfigured() {
  const c = getAlipayConfig();
  return !!(c.appId && c.privateKey);
}

/**
 * 支付宝统一请求：构造参数 + 签名（RSA2）
 * 要点：签名串用同一份 params，逐值原样拼接，biz_content 用 JSON.stringify 原始字符串
 */
function buildSignedParams(conf, method, bizContent, opts = {}) {
  const bizStr = JSON.stringify(bizContent);
  const params = {
    app_id: conf.appId,
    method,
    format: 'JSON',
    charset: 'utf-8',
    sign_type: 'RSA2',
    timestamp: new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''),
    version: '1.0',
    notify_url: opts.notifyUrl || conf.notifyUrl,
    return_url: opts.returnUrl || conf.siteUrl + '/pay/result',
    biz_content: bizStr,
  };
  // 支付宝签名串：所有非空字段（含sign_type）按字母序，k=v
  const signStr = Object.keys(params)
    .filter(k => params[k] !== '' && params[k] !== null && params[k] !== undefined)
    .sort()
    .map(k => `${k}=${params[k]}`)
    .join('&');
  params.sign = utils.alipaySign(params, conf.privateKey); // 内部会用相同规则拼
  // 返回原始串用于调试/日志（可选）
  params._signSource = signStr;
  return params;
}

/** PC 页面支付：返回自动提交表单 HTML */
function createPagePay({ tradeNo, amount, subject, returnUrl }) {
  const fen = utils.amountToFen(amount);
  if (Number.isNaN(fen) || fen <= 0) throw new Error('非法金额');
  const conf = getAlipayConfig();
  const params = buildSignedParams(conf, 'alipay.trade.page.pay', {
    out_trade_no: tradeNo,
    total_amount: fenToYuanStr(fen),
    subject: subject || '商城订单',
    product_code: 'FAST_INSTANT_TRADE_PAY',
  }, { returnUrl });
  const formFields = Object.keys(params)
    .filter(k => !k.startsWith('_'))
    .map(k => `<input name="${k}" value="${escapeHtml(params[k])}">`)
    .join('');
  const gateway = (conf.sandbox ? GATEWAY_SANDBOX : GATEWAY) + '?_input_charset=utf-8';
  return `<form id="alipay_submit" name="alipaysubmit" action="${gateway}" method="post">${formFields}<input type="submit" value="立即支付" style="display:none"></form><script>document.forms['alipaysubmit'].submit();</script>`;
}

/** WAP 手机网页支付 */
function createWapPay({ tradeNo, amount, subject, returnUrl }) {
  const fen = utils.amountToFen(amount);
  if (Number.isNaN(fen) || fen <= 0) throw new Error('非法金额');
  const conf = getAlipayConfig();
  return buildSignedParams(conf, 'alipay.trade.wap.pay', {
    out_trade_no: tradeNo,
    total_amount: fenToYuanStr(fen),
    subject: subject || '商城订单',
    product_code: 'QUICK_WAP_WAY',
  }, { returnUrl });
}

/** 统一收单交易创建 */
function createTrade({ tradeNo, amount, subject }) {
  const fen = utils.amountToFen(amount);
  if (Number.isNaN(fen) || fen <= 0) throw new Error('非法金额');
  const conf = getAlipayConfig();
  return buildSignedParams(conf, 'alipay.trade.create', {
    out_trade_no: tradeNo,
    total_amount: fenToYuanStr(fen),
    subject: subject || '商城订单',
  });
}

/** 分 → 元字符串（2位小数） */
function fenToYuanStr(fen) {
  return (fen / 100).toFixed(2);
}

function escapeHtml(s) {
  return String(s).replace(/&/g, '&amp;').replace(/"/g, '&quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
}

/** 支付宝回调验签 + 解析（兼容旧结构）
 *  返回 {success:boolean, tradeNo, tradeStatus, alipayTradeNo, payTime, totalAmount}
 *  验签失败或未配置公钥时 success=false
 */
function verifyNotify(data) {
  const conf = getAlipayConfig();
  if (!conf.alipayPublicKey) {
    return { success: false, tradeNo: data.out_trade_no || '', tradeStatus: data.trade_status || '', errorMsg: '未配置支付宝公钥' };
  }
  if (!utils.verifyAlipaySign(data, conf.alipayPublicKey)) {
    return { success: false, tradeNo: data.out_trade_no || '', tradeStatus: data.trade_status || '', errorMsg: '签名验证失败' };
  }
  const parsed = parseNotify(data);
  return { success: true, tradeNo: parsed.tradeNo, tradeStatus: parsed.tradeStatus, alipayTradeNo: parsed.transactionId, payTime: parsed.payTime, totalAmount: parsed.totalAmount };
}

/** 异步通知结果解析 */
function parseNotify(data) {
  const fen = utils.amountToFen(data.total_amount || data.receipt_amount || 0);
  return {
    tradeNo: data.out_trade_no,
    tradeStatus: data.trade_status,
    transactionId: data.trade_no,
    totalAmount: Number.isNaN(fen) ? 0 : fen / 100,
    payerId: data.buyer_id || '',
    payTime: data.gmt_payment || '',
    raw: data,
  };
}

/** 查询交易（支付宝收到 GET/POST 表单，返回 JSON） */
async function queryTrade(tradeNo) {
  const conf = getAlipayConfig();
  const params = buildSignedParams(conf, 'alipay.trade.query', { out_trade_no: tradeNo });
  delete params._signSource;
  const resp = await utils.httpsPost(conf.sandbox ? GATEWAY_SANDBOX : GATEWAY, params, 'application/x-www-form-urlencoded');
  const body = typeof resp.data === 'string' ? resp.data : JSON.stringify(resp.data);
  return JSON.parse(body);
}

/** 退款 */
async function refund({ tradeNo, refundNo, refundAmount, reason }) {
  const fen = utils.amountToFen(refundAmount);
  if (Number.isNaN(fen) || fen <= 0) throw new Error('非法退款金额');
  const conf = getAlipayConfig();
  const params = buildSignedParams(conf, 'alipay.trade.refund', {
    out_trade_no: tradeNo,
    out_request_no: refundNo,
    refund_amount: fenToYuanStr(fen),
    refund_reason: reason || '用户申请退款',
  });
  delete params._signSource;
  const resp = await utils.httpsPost(conf.sandbox ? GATEWAY_SANDBOX : GATEWAY, params, 'application/x-www-form-urlencoded');
  return JSON.parse(resp.data);
}

/** 查询退款 */
async function queryRefund(tradeNo, refundNo) {
  const conf = getAlipayConfig();
  const params = buildSignedParams(conf, 'alipay.trade.fastpay.refund.query', { out_trade_no: tradeNo, out_request_no: refundNo });
  delete params._signSource;
  const resp = await utils.httpsPost(conf.sandbox ? GATEWAY_SANDBOX : GATEWAY, params, 'application/x-www-form-urlencoded');
  const body = typeof resp.data === 'string' ? resp.data : JSON.stringify(resp.data);
  return JSON.parse(body);
}

module.exports = {
  isAlipayConfigured,
  getAlipayConfig,
  invalidateAlipayConfig,
  createPagePay,
  createWapPay,
  createTrade,
  verifyNotify,
  parseNotify,
  queryTrade,
  refund,
  queryRefund,
};
