/**
 * 营销自动化引擎
 * ===============
 * 对标 CRMEB「营销自动化」：在正确时机给正确用户发对的券 + 站内通知。
 * 四类触发：
 *   cart_remind   购物车召回（有车未下单超阈值）
 *   birthday_gift 生日礼（生日当天）
 *   first_order   首单礼（支付首单后）
 *   repurchase    复购券（距上次下单超 N 天）
 *
 * 铁律遵守：
 *   - 发券/通知在事务内执行（transaction + CAS 防超发）
 *   - 幂等去重：同一 user+trigger_type+窗口只发一次（automation_logs 判定 + NOT EXISTS）
 *   - 金额沿用 coupons 表 DECIMAL 字段，无浮点运算
 */
const { get, all, run, transaction } = require('../utils/db');

// 阈值默认值
const DEFAULTS = {
  cart_remind_hours: 3,
  repurchase_days: 15,
  coupon_valid_days: 30
};

/**
 * 写站内通知
 */
function notifyUser(userId, title, content, type = 'marketing_auto') {
  run('INSERT INTO notifications(user_id,type,title,content) VALUES(?,?,?,?)',
    [userId, type, title, content]);
}

/**
 * 幂等检查：同 user + trigger_type 在窗口内(默认30天)是否已触发
 */
function alreadyTriggered(userId, triggerType, windowDays = 30) {
  const row = get(
    "SELECT id FROM automation_logs WHERE user_id=? AND trigger_type=? AND status IN ('success','skipped') AND created_at>=datetime('now','localtime',?) LIMIT 1",
    [userId, triggerType, `-${windowDays} days`]
  );
  return !!row;
}

/**
 * 发券（事务内 CAS 防超发 + 幂等）。
 * @returns {{ok:boolean, reason?:string, couponId?:number}}
 */
function issueCoupon(userId, couponId, validDays) {
  if (!couponId) return { ok: true, reason: 'no_coupon' };
  const coupon = get('SELECT * FROM coupons WHERE id=? AND status=1', [couponId]);
  if (!coupon) return { ok: false, reason: 'coupon_not_found' };

  try {
    // CAS 原子领取总量控制：used_count < total_count 才累加
    const upd = run('UPDATE coupons SET used_count=used_count+1 WHERE id=? AND used_count<?', [couponId, coupon.total_count]);
    if (!upd.changes || upd.changes === 0) return { ok: false, reason: 'coupon_sold_out' };

    const expired = new Date();
    const days = validDays || coupon.valid_days || DEFAULTS.coupon_valid_days;
    if (days) expired.setDate(expired.getDate() + days);
    else if (coupon.end_time) expired.setTime(new Date(coupon.end_time).getTime());
    else expired.setDate(expired.getDate() + 30);

    run('INSERT INTO user_coupons(user_id,coupon_id,expired_time) VALUES(?,?,?)',
      [userId, couponId, expired.toISOString()]);
    return { ok: true, reason: 'issued', couponId };
  } catch (e) {
    return { ok: false, reason: 'db_error:' + e.message };
  }
}

/**
 * 执行单条规则的单个用户命中。
 * @param {object} rule - marketing_automations 记录
 * @param {number} userId
 */
function applyAction(rule, userId) {
  // 幂等去重
  if (alreadyTriggered(userId, rule.trigger_type)) {
    run("INSERT INTO automation_logs(trigger_type,user_id,coupon_id,status,reason) VALUES(?,?,?,?,?)",
      [rule.trigger_type, userId, rule.coupon_id, 'skipped', 'duplicate_window']);
    return { status: 'skipped', reason: 'duplicate' };
  }

  let status = 'success';
  let reason = '';
  try {
    transaction(() => {
      // 1. 发券（CAS 防超发）
      const res = issueCoupon(userId, rule.coupon_id, rule.valid_days);
      if (!res.ok && res.reason !== 'no_coupon') {
        throw new Error(res.reason);
      }
      // 2. 站内通知
      const title = (rule.title || '{nickname}，有一张专属福利待领取').replace(/\{nickname\}/g, getNickname(userId));
      const content = buildNotifyContent(rule, userId, res);
      notifyUser(userId, title, content);
      // 3. 写日志
      run("INSERT INTO automation_logs(trigger_type,user_id,coupon_id,status,reason) VALUES(?,?,?,?,?)",
        [rule.trigger_type, userId, rule.coupon_id, status, reason]);
    });
    return { status: 'success' };
  } catch (e) {
    status = 'error';
    reason = e.message;
    try {
      run("INSERT INTO automation_logs(trigger_type,user_id,coupon_id,status,reason) VALUES(?,?,?,?,?)",
        [rule.trigger_type, userId, rule.coupon_id, 'error', String(reason).slice(0, 200)]);
    } catch (_) { /* ignore */ }
    return { status: 'error', reason: String(reason) };
  }
}

function getNickname(userId) {
  const u = get('SELECT nickname FROM users WHERE id=?', [userId]);
  return (u && u.nickname) || '亲';
}

/**
 * 拼装通知内容
 */
function buildNotifyContent(rule, userId, issueResult) {
  const nickname = getNickname(userId);
  const couponName = rule.coupon_id ? (() => { const c = get('SELECT name FROM coupons WHERE id=?', [rule.coupon_id]); return c ? c.name : ''; })() : '';
  if (rule.trigger_type === 'cart_remind') {
    return `${nickname}，你购物车里的宝贝还在等你哦～${couponName ? '送你『' + couponName + '』' : '快去下单'}吧，别让心仪好货溜走！`;
  }
  if (rule.trigger_type === 'birthday_gift') {
    return `${nickname}，生日快乐！🎂${couponName ? '专为你准备了『' + couponName + '』' : '送上生日祝福'}，犒劳一下自己吧。`;
  }
  if (rule.trigger_type === 'first_order') {
    return `${nickname}，感谢首单支持！${couponName ? '送你『' + couponName + '』' : '专属礼遇'}，下次购物更划算～`;
  }
  if (rule.trigger_type === 'repurchase') {
    return `${nickname}，好久不见～${couponName ? '为你准备了『' + couponName + '』' : '老友福利'}，快回来看看吧！`;
  }
  return `${nickname}，${couponName ? '送你『' + couponName + '』' : '专属福利'}，快来领取！`;
}

/* ==================== 各类目标查找 ==================== */

/**
 * 购物车召回：carts 有货 && 最近加购时间距 now >= 阈值 && 阈值期间未下单
 */
function findCartRemindTargets(rule) {
  const hours = rule.threshold_hours || DEFAULTS.cart_remind_hours;
  // 最近一次加购 >= hours 小时前
  const rows = all(
    `SELECT c.user_id, MAX(c.created_at) AS last_cart
     FROM carts c
     JOIN products p ON c.product_id = p.id
     WHERE c.user_id IS NOT NULL
     GROUP BY c.user_id
     HAVING last_cart <= datetime('now','localtime','-${hours} hours')
        AND last_cart >= datetime('now','localtime','-${hours * 24} hours')`
  );
  const targets = [];
  for (const r of rows) {
    // 阈值期间是否已下单
    const order = get(
      `SELECT id FROM orders WHERE user_id=? AND created_at >= datetime('now','localtime','-${hours} hours') AND status NOT IN ('cancelled','closed') LIMIT 1`,
      [r.user_id]
    );
    if (!order) targets.push(r.user_id);
  }
  return targets;
}

/**
 * 生日礼：birthday 的 MM-DD == 今天 && 一年内未发过
 */
function findBirthdayTargets(rule) {
  const rows = all(
    `SELECT id AS user_id FROM users
     WHERE birthday IS NOT NULL AND birthday <> ''
       AND substr(birthday, -5) = strftime('%m-%d','now','localtime')
       AND status = 1`
  );
  const targets = [];
  for (const r of rows) {
    if (!alreadyTriggered(r.user_id, 'birthday_gift', 365)) targets.push(r.user_id);
  }
  return targets;
}

/**
 * 复购：最近下单距今 >= N 天 && 上次发券距今 >= N 天
 */
function findRepurchaseTargets(rule) {
  const days = rule.repurchase_days || DEFAULTS.repurchase_days;
  const rows = all(
    `SELECT user_id, MAX(created_at) AS last_order FROM orders
     WHERE status NOT IN ('cancelled','closed')
     GROUP BY user_id
     HAVING last_order <= datetime('now','localtime','-${days} days')
        AND last_order >= datetime('now','localtime','-${days * 3} days')`
  );
  return rows.map(r => r.user_id);
}

/**
 * 首单礼：事件触发（支付成功后调），判断是否首单
 */
function findFirstOrderTargets(userId) {
  if (!userId) return [];
  const paid = get("SELECT COUNT(*) c FROM orders WHERE user_id=? AND status='pending_ship'", [userId]);
  // 首单：恰好支付了第一单（支付记录数==1 可判定）
  const payCount = get('SELECT COUNT(*) c FROM payment_records WHERE user_id=? AND status=?', [userId, 'success']);
  return (payCount && payCount.c === 1) ? [userId] : [];
}

/**
 * 按类型执行一条规则（对所有命中用户）
 */
function runRule(rule) {
  if (!rule || !rule.enabled) return { type: rule && rule.trigger_type, processed: 0 };
  let targets = [];
  if (rule.trigger_type === 'cart_remind') targets = findCartRemindTargets(rule);
  else if (rule.trigger_type === 'birthday_gift') targets = findBirthdayTargets(rule);
  else if (rule.trigger_type === 'repurchase') targets = findRepurchaseTargets(rule);
  else if (rule.trigger_type === 'first_order') targets = findFirstOrderTargets(rule.user_id);
  let ok = 0, skip = 0, err = 0;
  for (const uid of targets) {
    const res = applyAction(rule, uid);
    if (res.status === 'success') ok++;
    else if (res.status === 'skipped') skip++;
    else err++;
  }
  run("UPDATE marketing_automations SET last_run_at=datetime('now','localtime') WHERE id=?", [rule.id]);
  return { type: rule.trigger_type, processed: targets.length, ok, skip, err };
}

/**
 * 扫描所有启用的自动化规则（定时器调用）
 */
function scanAll() {
  const rules = all("SELECT * FROM marketing_automations WHERE enabled=1 ORDER BY id");
  const results = [];
  for (const rule of rules) results.push(runRule(rule));
  return results;
}

/**
 * 首单礼事件触发入口（order.js 支付成功后调用）
 */
function onOrderPaid(userId) {
  try {
    const rule = get("SELECT * FROM marketing_automations WHERE trigger_type='first_order' AND enabled=1 LIMIT 1");
    if (!rule) return;
    const paid = get("SELECT COUNT(*) c FROM orders WHERE user_id=? AND status='pending_ship'", [userId]);
    const payCount = get('SELECT COUNT(*) c FROM payment_records WHERE user_id=? AND status=?', [userId, 'success']);
    if (payCount && payCount.c === 1) {
      applyAction(rule, userId);
    }
  } catch (e) { /* 首单礼失败不影响主流程 */ console.error('[营销自动化-首单]', e.message); }
}

module.exports = {
  DEFAULTS,
  runRule,
  scanAll,
  onOrderPaid,
  applyAction,
  findCartRemindTargets,
  findBirthdayTargets,
  findRepurchaseTargets,
  findFirstOrderTargets,
  alreadyTriggered
};
