/**
 * 积分服务（会员积分闭环）
 * ============================================
 * 职责（与经验值 experience 完全解耦）：
 *   1. 积分变动统一入口（加/减），原子化 + 防并发
 *   2. 每次变动记录 points_logs 流水（可审计）
 *   3. 提供积分余额查询 / 流水查询
 *   4. 签到奖励、消费送积分、积分抵现 数值配置读取
 *
 * ⚠️ 铁律：
 *   - 所有扣减必须用 条件更新 WHERE points>=?  防止扣成负数
 *   - 所有变动写 points_logs 流水
 *   - points 与 experience（会员等级依据）互不干扰
 */
const { get, run, all, transaction } = require('../utils/db');

// ============ 配置读取 ============
function cfgVal(key, def) {
  const r = get('SELECT value FROM system_config WHERE key=?', [key]);
  return r ? (r.value === '' ? def : r.value) : def;
}

// 积分抵现开关
function pointsDeductEnabled() { return cfgVal('points_deduct_enabled', '1') === '1'; }
// 积分抵现比例: 多少积分抵1元
function pointsDeductRatio() { return Math.max(1, parseInt(cfgVal('points_deduct_ratio', '100')) || 100); }
// 每单抵现积分上限
function pointsDeductLimit() { return Math.max(0, parseInt(cfgVal('points_deduct_limit', '500')) || 0); }
// 消费送积分: 每消费1元送N积分
function orderRewardRatio() { return Math.max(0, parseInt(cfgVal('order_reward_ratio', '1')) || 0); }

// ============ 核心: 变动积分 ============
/**
 * 增加用户积分（正数）
 * @param {number} userId
 * @param {number} amount  正积分
 * @param {string} type    sign|order_reward|recharge|admin|refund_refund
 * @param {string} refNo   关联单号
 * @param {string} remark
 */
function addPoints(userId, amount, type, refNo, remark) {
  if (!userId || !amount || amount <= 0) return { ok: false, reason: '参数无效' };
  return transaction(() => {
    // 原子加积分 + 累计
    run('UPDATE users SET points=COALESCE(points,0)+?, total_points=COALESCE(total_points,0)+? WHERE id=?',
      [amount, amount, userId]);
    const u = get('SELECT points FROM users WHERE id=?', [userId]);
    const balance = u ? u.points : 0;
    run(`INSERT INTO points_logs(user_id,change_type,change_amount,balance_after,ref_no,remark)
        VALUES(?,?,?,?,?,?)`, [userId, type, amount, balance, refNo || '', remark || '']);
    return { ok: true, balance, change: amount };
  });
}

/**
 * 扣减积分（负数），条件更新防超扣
 * @returns {object} {ok, balance?, reason?}
 */
function deductPoints(userId, amount, type, refNo, remark) {
  if (!userId || !amount || amount <= 0) return { ok: false, reason: '参数无效' };
  return transaction(() => {
    const upd = run('UPDATE users SET points=points-? WHERE id=? AND points>=?', [amount, userId, amount]);
    if (upd.changes === 0) {
      const u = get('SELECT points FROM users WHERE id=?', [userId]);
      return { ok: false, reason: '积分不足，当前积分: ' + ((u && u.points) || 0) };
    }
    const u = get('SELECT points FROM users WHERE id=?', [userId]);
    const balance = u ? u.points : 0;
    run(`INSERT INTO points_logs(user_id,change_type,change_amount,balance_after,ref_no,remark)
        VALUES(?,?,?,?,?,?)`, [userId, type, -amount, balance, refNo || '', remark || '']);
    return { ok: true, balance, change: -amount };
  });
}

// ============ 查询 ============
function getBalance(userId) {
  const u = get('SELECT points, total_points FROM users WHERE id=?', [userId]);
  return u ? { points: u.points || 0, total_points: u.total_points || 0 } : { points: 0, total_points: 0 };
}

function getLogs(userId, page = 1, pageSize = 20) {
  const offset = Math.max(0, (page - 1) * pageSize);
  const list = all('SELECT * FROM points_logs WHERE user_id=? ORDER BY id DESC LIMIT ? OFFSET ?',
    [userId, pageSize, offset]);
  const total = get('SELECT COUNT(*) c FROM points_logs WHERE user_id=?', [userId]).c;
  return { list, total, page, pageSize };
}

// ============ 消费送积分（订单支付成功回调）============
/**
 * @param {number} userId
 * @param {number} payAmount  实付金额(元)
 * @param {string} orderNo
 */
function rewardOrderPoints(userId, payAmount, orderNo) {
  const ratio = orderRewardRatio();
  if (ratio <= 0 || !payAmount) return { ok: false, reason: '未开启消费送积分' };
  const points = Math.floor(payAmount * ratio);
  if (points <= 0) return { ok: false, reason: '积分不足1' };
  return addPoints(userId, points, 'order_reward', orderNo, '消费送积分');
}

module.exports = {
  cfgVal,
  pointsDeductEnabled,
  pointsDeductRatio,
  pointsDeductLimit,
  orderRewardRatio,
  addPoints,
  deductPoints,
  getBalance,
  getLogs,
  rewardOrderPoints,
};
