const Database = require('better-sqlite3');
const path = require('path');
const fs = require('fs');
const bcrypt = require('bcryptjs');
const DB_PATH = path.join(__dirname, '..', 'data', 'litemall.db');
    // NOTE: initDatabase 仅启动时执行一次，拆分收益极低；保持单函数确保建表顺序正确
function initDatabase() {
  const dir = path.dirname(DB_PATH);
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
  const db = new Database(DB_PATH);
  db.pragma('journal_mode = WAL');
  db.pragma('foreign_keys = ON');
  // ========== 用户体系 ==========
  db.exec(`
    CREATE TABLE IF NOT EXISTS users (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      nickname TEXT DEFAULT '',
      avatar TEXT DEFAULT '',
      phone TEXT UNIQUE,
      password TEXT,
      openid TEXT,
      unionid TEXT,
      level_id INTEGER DEFAULT 1,
      experience INTEGER DEFAULT 0,
      balance DECIMAL(10,2) DEFAULT 0.00,
      freeze_balance DECIMAL(10,2) DEFAULT 0.00,
      total_consumed DECIMAL(12,2) DEFAULT 0.00,
      order_count INTEGER DEFAULT 0,
      points INTEGER DEFAULT 0,
      parent_id INTEGER,
      parent_ids TEXT DEFAULT '',
      team_count INTEGER DEFAULT 0,
      status INTEGER DEFAULT 1,
      is_admin INTEGER DEFAULT 0,
      is_demo INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS user_levels (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      level TINYINT UNIQUE NOT NULL,
      min_experience INTEGER DEFAULT 0,
      discount DECIMAL(3,2) DEFAULT 1.00,
      icon TEXT DEFAULT '',
      description TEXT DEFAULT '',
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS user_addresses (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL REFERENCES users(id),
      name TEXT NOT NULL,
      phone TEXT NOT NULL,
      province TEXT,
      city TEXT,
      district TEXT,
      detail TEXT,
      zip_code TEXT,
      is_default INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 会员体系 ==========
    CREATE TABLE IF NOT EXISTS membership_plans (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      type TEXT CHECK(type IN ('monthly','quarterly','yearly','permanent')),
      price DECIMAL(10,2) NOT NULL,
      original_price DECIMAL(10,2) DEFAULT 0,
      level_id INTEGER REFERENCES user_levels(id),
      give_experience INTEGER DEFAULT 0,
      give_coupon_ids TEXT DEFAULT '',
      description TEXT DEFAULT '',
      status INTEGER DEFAULT 1,
      sort INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS user_memberships (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL REFERENCES users(id),
      plan_id INTEGER REFERENCES membership_plans(id),
      start_time DATETIME,
      end_time DATETIME,
      status TEXT CHECK(status IN ('active','expired','cancelled')) DEFAULT 'active',
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 商品体系 ==========
    CREATE TABLE IF NOT EXISTS categories (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      pid INTEGER DEFAULT 0,
      icon TEXT DEFAULT '',
      image TEXT DEFAULT '',
      sort INTEGER DEFAULT 0,
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS products (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      subtitle TEXT DEFAULT '',
      category_id INTEGER REFERENCES categories(id),
      brand TEXT DEFAULT '',
      unit TEXT DEFAULT '件',
      image TEXT DEFAULT '',
      images TEXT DEFAULT '[]',
      video TEXT DEFAULT '',
      description TEXT DEFAULT '',
      spec_type INTEGER DEFAULT 0,
      price DECIMAL(10,2) DEFAULT 0.00,
      original_price DECIMAL(10,2) DEFAULT 0.00,
      cost_price DECIMAL(10,2) DEFAULT 0.00,
      stock INTEGER DEFAULT 0,
      sales INTEGER DEFAULT 0,
      min_qty INTEGER DEFAULT 1,
      max_qty INTEGER DEFAULT 999,
      weight DECIMAL(10,2) DEFAULT 0,
      shipping_template_id INTEGER,
      status INTEGER DEFAULT 1,
      is_new INTEGER DEFAULT 0,
      is_hot INTEGER DEFAULT 0,
      is_recommend INTEGER DEFAULT 0,
      sort INTEGER DEFAULT 0,
      seo_keywords TEXT DEFAULT '',
      seo_description TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS product_skus (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      product_id INTEGER NOT NULL REFERENCES products(id),
      sku_code TEXT DEFAULT '',
      image TEXT DEFAULT '',
      specs TEXT DEFAULT '[]',
      price DECIMAL(10,2) NOT NULL,
      original_price DECIMAL(10,2) DEFAULT 0.00,
      cost_price DECIMAL(10,2) DEFAULT 0.00,
      stock INTEGER DEFAULT 0,
      sales INTEGER DEFAULT 0,
      weight DECIMAL(10,2) DEFAULT 0,
      bar_code TEXT DEFAULT '',
      status INTEGER DEFAULT 1,
      sort INTEGER DEFAULT 0
    );
    CREATE TABLE IF NOT EXISTS product_images (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      product_id INTEGER NOT NULL REFERENCES products(id),
      url TEXT NOT NULL,
      type INTEGER DEFAULT 0,
      sort INTEGER DEFAULT 0
    );
    CREATE TABLE IF NOT EXISTS product_specs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      product_id INTEGER NOT NULL REFERENCES products(id),
      name TEXT NOT NULL,
      spec_values TEXT NOT NULL DEFAULT '[]',
      sort INTEGER DEFAULT 0
    );
    -- ========== 购物车与订单 ==========
    CREATE TABLE IF NOT EXISTS carts (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL REFERENCES users(id),
      product_id INTEGER NOT NULL REFERENCES products(id),
      sku_id INTEGER REFERENCES product_skus(id),
      quantity INTEGER DEFAULT 1,
      selected INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS orders (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      order_no TEXT UNIQUE NOT NULL,
      user_id INTEGER NOT NULL REFERENCES users(id),
      total_amount DECIMAL(12,2) NOT NULL,
      discount_amount DECIMAL(12,2) DEFAULT 0.00,
      shipping_fee DECIMAL(10,2) DEFAULT 0.00,
      pay_amount DECIMAL(12,2) NOT NULL,
      paid_amount DECIMAL(12,2) DEFAULT 0.00,
      payment_method TEXT CHECK(payment_method IN ('wechat','alipay','balance','none')) DEFAULT 'none',
      status TEXT CHECK(status IN ('pending_pay','pending_ship','shipped','received','completed','closed','refunding','refunded')) DEFAULT 'pending_pay',
      refund_status TEXT DEFAULT '',
      consignee TEXT DEFAULT '',
      phone TEXT DEFAULT '',
      province TEXT DEFAULT '',
      city TEXT DEFAULT '',
      district TEXT DEFAULT '',
      address TEXT DEFAULT '',
      zip_code TEXT DEFAULT '',
      shipping_company TEXT DEFAULT '',
      shipping_no TEXT DEFAULT '',
      shipping_time DATETIME,
      confirm_time DATETIME,
      close_time DATETIME,
      remark TEXT DEFAULT '',
      close_reason TEXT DEFAULT '',
      use_coupon_ids TEXT DEFAULT '',
      is_distributed INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS order_items (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      order_id INTEGER NOT NULL REFERENCES orders(id),
      product_id INTEGER NOT NULL,
      sku_id INTEGER,
      product_name TEXT NOT NULL,
      sku_info TEXT DEFAULT '',
      image TEXT DEFAULT '',
      price DECIMAL(10,2) NOT NULL,
      quantity INTEGER NOT NULL,
      subtotal DECIMAL(12,2) NOT NULL,
      after_sale_status INTEGER DEFAULT 0
    );
    CREATE TABLE IF NOT EXISTS order_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      order_id INTEGER NOT NULL REFERENCES orders(id),
      action TEXT NOT NULL,
      operator TEXT DEFAULT 'system',
      content TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS payment_records (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      trade_no TEXT UNIQUE NOT NULL,
      order_id INTEGER REFERENCES orders(id),
      user_id INTEGER NOT NULL,
      amount DECIMAL(12,2) NOT NULL,
      method TEXT CHECK(method IN ('wechat','alipay','balance')),
      status TEXT CHECK(status IN ('pending','success','failed','refunded')) DEFAULT 'pending',
      transaction_id TEXT DEFAULT '',
      pay_time DATETIME,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS refunds (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      refund_no TEXT UNIQUE NOT NULL,
      order_id INTEGER NOT NULL REFERENCES orders(id),
      order_item_id INTEGER,
      user_id INTEGER NOT NULL REFERENCES users(id),
      type TEXT CHECK(type IN ('only_refund','refund_and_return','exchange')),
      reason TEXT NOT NULL,
      explain_text TEXT DEFAULT '',
      images TEXT DEFAULT '[]',
      amount DECIMAL(12,2) NOT NULL,
      status TEXT CHECK(status IN ('pending','approved','rejected','shipped_back','received','completed','cancelled')) DEFAULT 'pending',
      reject_reason TEXT DEFAULT '',
      shipping_company TEXT DEFAULT '',
      shipping_no TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 支付对账日志 ==========
    CREATE TABLE IF NOT EXISTS payment_reconciliations (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      order_id INTEGER REFERENCES orders(id),
      trade_no TEXT DEFAULT '',
      action TEXT CHECK(action IN ('auto_poll','manual_retry','daily_reconcile','auto_fix')) NOT NULL,
      before_status TEXT DEFAULT '',
      after_status TEXT DEFAULT '',
      result TEXT CHECK(result IN ('fixed','no_change','error','warning')) DEFAULT 'no_change',
      message TEXT DEFAULT '',
      operator TEXT DEFAULT 'system',
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 分销体系 ==========
    CREATE TABLE IF NOT EXISTS distribution_config (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      key TEXT UNIQUE NOT NULL,
      value TEXT DEFAULT '',
      description TEXT DEFAULT ''
    );
    CREATE TABLE IF NOT EXISTS distribution_levels (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      level INTEGER UNIQUE NOT NULL,
      min_team_count INTEGER DEFAULT 0,
      min_team_sales DECIMAL(12,2) DEFAULT 0.00,
      commission_rate DECIMAL(5,4) DEFAULT 0.0000,
      commission_rate2 DECIMAL(5,4) DEFAULT 0.0000,
      commission_rate3 DECIMAL(5,4) DEFAULT 0.0000,
      upgrade_type TEXT DEFAULT 'auto',
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS distribution_records (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      order_id INTEGER NOT NULL,
      order_item_id INTEGER,
      buyer_id INTEGER NOT NULL,
      user_id INTEGER NOT NULL,
      level INTEGER NOT NULL,
      product_amount DECIMAL(12,2) NOT NULL,
      rate DECIMAL(5,4) NOT NULL,
      commission DECIMAL(12,2) NOT NULL,
      status TEXT CHECK(status IN ('pending','settled','cancelled')) DEFAULT 'pending',
      settled_at DATETIME,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 佣金变更审计日志 ==========
    CREATE TABLE IF NOT EXISTS commission_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL REFERENCES users(id),
      amount DECIMAL(12,2) NOT NULL,
      type TEXT CHECK(type IN ('earn','settle','adjust','withdraw','reversal')) NOT NULL DEFAULT 'earn',
      source TEXT CHECK(source IN ('order','auto','manual','withdraw','admin')) DEFAULT 'order',
      source_id INTEGER DEFAULT 0,
      note TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS withdraw_requests (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL REFERENCES users(id),
      amount DECIMAL(12,2) NOT NULL,
      fee DECIMAL(10,2) DEFAULT 0.00,
      real_amount DECIMAL(12,2) NOT NULL,
      account_type TEXT CHECK(account_type IN ('wechat','alipay','bank')) NOT NULL,
      account_info TEXT DEFAULT '',
      status TEXT CHECK(status IN ('pending','approved','rejected','completed')) DEFAULT 'pending',
      reject_reason TEXT DEFAULT '',
      completed_at DATETIME,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 营销体系 ==========
    CREATE TABLE IF NOT EXISTS coupons (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      type TEXT CHECK(type IN ('full_reduce','discount','cash')) NOT NULL,
      value DECIMAL(10,2) NOT NULL,
      min_amount DECIMAL(10,2) DEFAULT 0.00,
      max_amount DECIMAL(10,2) DEFAULT 0.00,
      total_count INTEGER DEFAULT 0,
      used_count INTEGER DEFAULT 0,
      per_limit INTEGER DEFAULT 1,
      valid_days INTEGER DEFAULT 30,
      start_time DATETIME,
      end_time DATETIME,
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS user_coupons (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL REFERENCES users(id),
      coupon_id INTEGER NOT NULL REFERENCES coupons(id),
      status TEXT CHECK(status IN ('unused','used','expired')) DEFAULT 'unused',
      used_time DATETIME,
      expired_time DATETIME,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS seckill_products (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      product_id INTEGER NOT NULL REFERENCES products(id),
      seckill_price DECIMAL(10,2) NOT NULL,
      stock INTEGER DEFAULT 0,
      sales INTEGER DEFAULT 0,
      per_limit INTEGER DEFAULT 1,
      start_time DATETIME NOT NULL,
      end_time DATETIME NOT NULL,
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS group_buy_products (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      product_id INTEGER NOT NULL REFERENCES products(id),
      group_price DECIMAL(10,2) NOT NULL,
      min_people INTEGER DEFAULT 2,
      stock INTEGER DEFAULT 0,
      sales INTEGER DEFAULT 0,
      start_time DATETIME NOT NULL,
      end_time DATETIME NOT NULL,
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS group_buy_orders (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      group_id TEXT NOT NULL,
      order_id INTEGER NOT NULL REFERENCES orders(id),
      user_id INTEGER NOT NULL,
      status TEXT CHECK(status IN ('pending','success','failed')) DEFAULT 'pending',
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 每日签到 ==========
    CREATE TABLE IF NOT EXISTS user_checkins (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL REFERENCES users(id),
      points INTEGER DEFAULT 5,
      streak INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE INDEX IF NOT EXISTS idx_checkins_user_date ON user_checkins(user_id, date(created_at));
    -- ========== AI客服知识库 ==========
    CREATE TABLE IF NOT EXISTS ai_knowledge_base (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      category TEXT DEFAULT '',
      question TEXT NOT NULL,
      answer TEXT NOT NULL,
      keywords TEXT DEFAULT '',
      weight INTEGER DEFAULT 0,
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS chat_conversations (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER REFERENCES users(id),
      title TEXT DEFAULT '',
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS chat_messages (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      conversation_id INTEGER NOT NULL REFERENCES chat_conversations(id),
      role TEXT CHECK(role IN ('user','assistant','system')) NOT NULL,
      content TEXT NOT NULL,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 系统配置 ==========
    CREATE TABLE IF NOT EXISTS system_config (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      group_name TEXT DEFAULT 'base',
      key TEXT UNIQUE NOT NULL,
      value TEXT DEFAULT '',
      type TEXT DEFAULT 'text',
      description TEXT DEFAULT '',
      sort INTEGER DEFAULT 0
    );
    CREATE TABLE IF NOT EXISTS banners (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      title TEXT DEFAULT '',
      image TEXT NOT NULL,
      url TEXT DEFAULT '',
      sort INTEGER DEFAULT 0,
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS pages (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      title TEXT NOT NULL,
      type TEXT CHECK(type IN ('about','policy','service','custom')) DEFAULT 'custom',
      content TEXT DEFAULT '',
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS download_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      pkg_name TEXT NOT NULL,
      ip TEXT DEFAULT '',
      user_agent TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS login_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER,
      phone TEXT,
      ip TEXT DEFAULT '',
      user_agent TEXT DEFAULT '',
      result TEXT CHECK(result IN ('success','fail')),
      reason TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS shipping_templates (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      type TEXT CHECK(type IN ('weight','piece','free')) DEFAULT 'piece',
      free_shipping_amount DECIMAL(10,2) DEFAULT 0.00,
      first_piece INTEGER DEFAULT 1,
      first_fee DECIMAL(10,2) DEFAULT 0.00,
      extra_piece INTEGER DEFAULT 1,
      extra_fee DECIMAL(10,2) DEFAULT 0.00,
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 操作日志 ==========
    CREATE TABLE IF NOT EXISTS operation_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      admin_id INTEGER DEFAULT 0,
      action TEXT NOT NULL,
      module TEXT DEFAULT '',
      target_id INTEGER,
      detail TEXT DEFAULT '',
      ip TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 通知消息 ==========
    CREATE TABLE IF NOT EXISTS notifications (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER DEFAULT 0,
      type TEXT DEFAULT 'system',
      title TEXT NOT NULL,
      content TEXT DEFAULT '',
      is_read INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 会员储值充值 ==========
    CREATE TABLE IF NOT EXISTS recharge_plans (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      amount REAL NOT NULL,
      give_amount REAL DEFAULT 0,
      give_points INTEGER DEFAULT 0,
      sort INTEGER DEFAULT 0,
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS recharge_orders (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      order_no TEXT UNIQUE NOT NULL,
      user_id INTEGER NOT NULL,
      plan_id INTEGER,
      amount REAL NOT NULL,
      give_amount REAL DEFAULT 0,
      give_points INTEGER DEFAULT 0,
      status TEXT DEFAULT 'pending',
      payment_method TEXT DEFAULT '',
      paid_at DATETIME,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 积分商城 ==========
    CREATE TABLE IF NOT EXISTS exchange_products (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      image TEXT DEFAULT '',
      points INTEGER NOT NULL DEFAULT 0,
      price REAL DEFAULT 0,
      stock INTEGER DEFAULT 0,
      limit_count INTEGER DEFAULT 0,
      description TEXT DEFAULT '',
      status INTEGER DEFAULT 1,
      sort INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS exchange_orders (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      order_no TEXT UNIQUE NOT NULL,
      user_id INTEGER NOT NULL,
      product_id INTEGER NOT NULL REFERENCES exchange_products(id),
      product_name TEXT NOT NULL,
      product_image TEXT DEFAULT '',
      points INTEGER NOT NULL,
      price REAL DEFAULT 0,
      quantity INTEGER DEFAULT 1,
      recipient_name TEXT DEFAULT '',
      recipient_phone TEXT DEFAULT '',
      recipient_address TEXT DEFAULT '',
      status TEXT DEFAULT 'pending',
      remark TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      shipped_at DATETIME,
      received_at DATETIME
    );
    -- ========== 通知服务 ==========
    CREATE TABLE IF NOT EXISTS notification_templates (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      code TEXT UNIQUE NOT NULL,
      type TEXT CHECK(type IN ('sms','email','subscribe')) NOT NULL,
      title TEXT NOT NULL,
      content TEXT NOT NULL,
      variables TEXT DEFAULT '[]',
      channels TEXT DEFAULT '[]',
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS notification_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL,
      template_code TEXT NOT NULL,
      channel TEXT CHECK(channel IN ('sms','email','wechat')) NOT NULL,
      receiver TEXT DEFAULT '',
      params TEXT DEFAULT '{}',
      content TEXT DEFAULT '',
      status TEXT CHECK(status IN ('pending','sent','failed')) DEFAULT 'pending',
      error_msg TEXT DEFAULT '',
      sent_at DATETIME,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS user_notification_prefs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL,
      template_code TEXT NOT NULL,
      channels TEXT DEFAULT '[]',
      enabled INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      UNIQUE(user_id, template_code)
    );
    -- ========== 商品评价 ==========
    CREATE TABLE IF NOT EXISTS product_reviews (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      product_id INTEGER NOT NULL REFERENCES products(id),
      order_id INTEGER NOT NULL REFERENCES orders(id),
      user_id INTEGER NOT NULL REFERENCES users(id),
      sku_info TEXT DEFAULT '',
      rating INTEGER CHECK(rating BETWEEN 1 AND 5) DEFAULT 5,
      content TEXT DEFAULT '',
      images TEXT DEFAULT '[]',
      reply TEXT DEFAULT '',
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 收藏 ==========
    CREATE TABLE IF NOT EXISTS user_favorites (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL REFERENCES users(id),
      product_id INTEGER NOT NULL REFERENCES products(id),
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      UNIQUE(user_id, product_id)
    );
    -- ========== 搜索历史 ==========
    CREATE TABLE IF NOT EXISTS search_history (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL REFERENCES users(id),
      keyword TEXT NOT NULL,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS browse_history (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER NOT NULL REFERENCES users(id),
      product_id INTEGER NOT NULL,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE INDEX IF NOT EXISTS idx_browse_history_user ON browse_history(user_id);
    -- ========== AI 运营助手调用日志 ==========
    CREATE TABLE IF NOT EXISTS ai_assistant_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      admin_id INTEGER NOT NULL,
      type TEXT NOT NULL,
      input TEXT DEFAULT '',
      output TEXT DEFAULT '',
      tokens INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== AI 内容审核表（人工审核链路） ==========
    -- 设计依据：软著审查要求AI生成内容必须有人工干预节点
    -- 2026-06-21 新增：所有AI运营助手生成的内容先进入待审池
    -- 运营人员确认后（审核通过/驳回带理由）才允许发布
    -- 审核操作日志用于软著材料中的"人工创新"举证
    CREATE TABLE IF NOT EXISTS ai_content_reviews (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      source_type TEXT NOT NULL,  -- 'description','xiaohongshu','moments','seo','review'
      source_id INTEGER DEFAULT 0,
      source_name TEXT DEFAULT '',
      content TEXT NOT NULL,
      status TEXT CHECK(status IN ('pending_review','approved','rejected')) DEFAULT 'pending_review',
      review_comment TEXT DEFAULT '',
      reviewed_by INTEGER DEFAULT 0,
      reviewed_at DATETIME,
      request_input TEXT DEFAULT '',
      admin_id INTEGER NOT NULL,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== AI 分析结果记录 ==========
    CREATE TABLE IF NOT EXISTS ai_analysis_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      type TEXT NOT NULL,
      days INTEGER DEFAULT 7,
      raw_data TEXT DEFAULT '',
      analysis TEXT DEFAULT '',
      admin_id INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 商品SEO建议 ==========
    CREATE TABLE IF NOT EXISTS product_seo_suggestions (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      product_id INTEGER NOT NULL,
      field TEXT NOT NULL,
      original TEXT DEFAULT '',
      suggestion TEXT DEFAULT '',
      applied INTEGER DEFAULT 0,
      ai_generated INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    -- ========== 商家自定义提示词 ==========
    CREATE TABLE IF NOT EXISTS ai_prompts (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      merchant_id INTEGER DEFAULT 0,
      skill TEXT NOT NULL,
      custom_prompt TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
  `);
  // ========== 团购/预售模块 E3 ==========
  db.exec(`
    CREATE TABLE IF NOT EXISTS presale_products (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      product_id INTEGER NOT NULL,
      name TEXT NOT NULL,
      deposit REAL DEFAULT 0,
      deposit_expand REAL DEFAULT 0,
      final_start_time DATETIME,
      final_end_time DATETIME,
      delivery_time TEXT DEFAULT '',
      total_stock INTEGER DEFAULT 0,
      limit_count INTEGER DEFAULT 0,
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS bulk_group_products (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      product_id INTEGER NOT NULL,
      name TEXT NOT NULL,
      tiers TEXT NOT NULL DEFAULT '[]',
      total_stock INTEGER DEFAULT 0,
      min_people INTEGER DEFAULT 1,
      limit_count INTEGER DEFAULT 0,
      start_time DATETIME,
      end_time DATETIME,
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS presale_orders (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      order_no TEXT UNIQUE NOT NULL,
      user_id INTEGER NOT NULL,
      presale_id INTEGER NOT NULL,
      product_id INTEGER NOT NULL,
      product_name TEXT NOT NULL,
      product_image TEXT DEFAULT '',
      quantity INTEGER DEFAULT 1,
      deposit REAL DEFAULT 0,
      deposit_expand REAL DEFAULT 0,
      final_amount REAL DEFAULT 0,
      total_amount REAL DEFAULT 0,
      status TEXT DEFAULT 'deposit_pending',
      payment_method TEXT DEFAULT 'wechat',
      trade_no TEXT DEFAULT '',
      deposit_paid_at DATETIME,
      final_paid_at DATETIME,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS bulk_group_orders (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      order_no TEXT UNIQUE NOT NULL,
      user_id INTEGER NOT NULL,
      bulk_id INTEGER NOT NULL,
      product_id INTEGER NOT NULL,
      product_name TEXT NOT NULL,
      quantity INTEGER DEFAULT 1,
      unit_price REAL DEFAULT 0,
      total_amount REAL DEFAULT 0,
      status TEXT DEFAULT 'pending',
      paid_at DATETIME,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS bargain_activities (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      product_id INTEGER NOT NULL,
      name TEXT NOT NULL,
      image TEXT DEFAULT '',
      original_price REAL DEFAULT 0,
      floor_price REAL DEFAULT 0,
      stock INTEGER DEFAULT 0,
      limit_count INTEGER DEFAULT 0,
      help_limit INTEGER DEFAULT 0,
      expire_hours INTEGER DEFAULT 24,
      start_time DATETIME,
      end_time DATETIME,
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS bargain_sessions (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      session_no TEXT UNIQUE NOT NULL,
      activity_id INTEGER NOT NULL,
      user_id INTEGER NOT NULL,
      original_price REAL DEFAULT 0,
      current_price REAL DEFAULT 0,
      floor_price REAL DEFAULT 0,
      quantity INTEGER DEFAULT 1,
      helped_count INTEGER DEFAULT 0,
      status TEXT DEFAULT 'bargaining',
      expire_at DATETIME,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS bargain_helps (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      session_id INTEGER NOT NULL,
      activity_id INTEGER NOT NULL,
      user_id INTEGER NOT NULL,
      amount REAL DEFAULT 0,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE INDEX IF NOT EXISTS idx_bargain_helps_session ON bargain_helps(session_id, user_id);
    -- P2 转化漏斗：用户行为埋点
    CREATE TABLE IF NOT EXISTS user_events (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      user_id INTEGER DEFAULT 0,
      source TEXT DEFAULT 'h5',
      action TEXT NOT NULL,
      page TEXT DEFAULT '',
      product_id INTEGER DEFAULT 0,
      ip TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE INDEX IF NOT EXISTS idx_user_events_created ON user_events(created_at);
    CREATE INDEX IF NOT EXISTS idx_user_events_action ON user_events(action);
    -- 营销自动化
    CREATE TABLE IF NOT EXISTS marketing_automations (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      trigger_type TEXT NOT NULL,
      name TEXT NOT NULL,
      coupon_id INTEGER DEFAULT 0,
      threshold_hours INTEGER DEFAULT 3,
      repurchase_days INTEGER DEFAULT 15,
      notify_template TEXT DEFAULT '',
      title TEXT DEFAULT '',
      valid_days INTEGER DEFAULT 30,
      enabled INTEGER DEFAULT 1,
      last_run_at DATETIME,
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS automation_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      trigger_type TEXT NOT NULL,
      user_id INTEGER,
      coupon_id INTEGER,
      status TEXT DEFAULT 'success',
      reason TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE INDEX IF NOT EXISTS idx_automation_logs_user ON automation_logs(user_id, trigger_type);
  `);
  // 兼容旧数据库：逐列检查添加（每列独立 try，避免某列已存在导致后续迁移全部跳过）
  try { db.exec('ALTER TABLE users ADD COLUMN is_admin INTEGER DEFAULT 0'); } catch {}
  try { db.exec('ALTER TABLE users ADD COLUMN birthday TEXT DEFAULT \"\"'); } catch {}
    try { db.exec('ALTER TABLE users ADD COLUMN is_demo INTEGER DEFAULT 0'); } catch {}
    // 2026-06-15: 商品扩展字段
    try { db.exec('ALTER TABLE products ADD COLUMN member_rates TEXT DEFAULT \'[]\''); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN commission_rate DECIMAL(5,2) DEFAULT 0.00'); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN is_flash_sale INTEGER DEFAULT 0'); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN flash_sale_config TEXT DEFAULT \'\''); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN is_group_buy INTEGER DEFAULT 0'); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN group_buy_config TEXT DEFAULT \'\''); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN publish_time TEXT DEFAULT \'\''); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN stock_warning INTEGER DEFAULT 0'); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN is_hidden INTEGER DEFAULT 0'); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN bar_code TEXT DEFAULT \'\''); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN brief TEXT DEFAULT \'\''); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN command_code TEXT DEFAULT \'\''); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN service_guarantees TEXT DEFAULT \'[]\''); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN product_params TEXT DEFAULT \'[]\''); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN recommend_image TEXT DEFAULT \'\''); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN give_points INTEGER DEFAULT 0'); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN give_coupon_id INTEGER DEFAULT 0'); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN is_limited INTEGER DEFAULT 0'); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN is_pre_sale INTEGER DEFAULT 0'); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN pre_sale_time TEXT DEFAULT \'\''); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN is_premium INTEGER DEFAULT 0'); } catch {}
    try { db.exec('ALTER TABLE products ADD COLUMN fake_sales INTEGER DEFAULT 0'); } catch {}
  // ========== 种子数据 ==========
  // 默认用户等级
  const levelCount = db.prepare('SELECT COUNT(*) as c FROM user_levels').get();
  if (levelCount.c === 0) {
    db.prepare('INSERT INTO user_levels (name, level, min_experience, discount, description) VALUES (?,?,?,?,?)').run('普通用户', 1, 0, 1.00, '注册即享');
    db.prepare('INSERT INTO user_levels (name, level, min_experience, discount, description) VALUES (?,?,?,?,?)').run('白银会员', 2, 500, 0.90, '购物享9折');
    db.prepare('INSERT INTO user_levels (name, level, min_experience, discount, description) VALUES (?,?,?,?,?)').run('黄金会员', 3, 2000, 0.85, '购物享85折');
    db.prepare('INSERT INTO user_levels (name, level, min_experience, discount, description) VALUES (?,?,?,?,?)').run('钻石会员', 4, 8000, 0.80, '购物享8折');
  }
  // 默认管理员账号
  const adminCount = db.prepare("SELECT COUNT(*) as c FROM users WHERE phone='admin'").get();
  if (adminCount.c === 0) {
    const hash = bcrypt.hashSync('admin888', 10);
    db.prepare('INSERT INTO users (nickname, phone, password, level_id, is_admin) VALUES (?,?,?,?,?)').run('管理员', 'admin', hash, 4, 1);
  } else {
    // 确保已有管理员标记
    db.prepare("UPDATE users SET is_admin=1 WHERE phone='admin' AND is_admin=0").run();
  }
  // 演示账号
  const demoCount = db.prepare("SELECT COUNT(*) as c FROM users WHERE phone='demo'").get();
  if (demoCount.c === 0) {
    const demoHash = bcrypt.hashSync('demo123456', 10);
    db.prepare('INSERT INTO users (nickname, phone, password, level_id, is_admin, is_demo) VALUES (?,?,?,?,?,?)').run('体验账号', 'demo', demoHash, 4, 1, 1);
  } else {
    db.prepare("UPDATE users SET is_demo=1, is_admin=1 WHERE phone='demo'").run();
  }
  // 默认分销等级
  const distLevelCount = db.prepare('SELECT COUNT(*) as c FROM distribution_levels').get();
  if (distLevelCount.c === 0) {
    db.prepare('INSERT INTO distribution_levels (name, level, min_team_count, commission_rate, commission_rate2, commission_rate3) VALUES (?,?,?,?,?,?)').run('普通分销商', 1, 0, 0.0500, 0.0200, 0.0100);
    db.prepare('INSERT INTO distribution_levels (name, level, min_team_count, min_team_sales, commission_rate, commission_rate2, commission_rate3) VALUES (?,?,?,?,?,?,?)').run('高级分销商', 2, 10, 5000.00, 0.0800, 0.0300, 0.0150);
    db.prepare('INSERT INTO distribution_levels (name, level, min_team_count, min_team_sales, commission_rate, commission_rate2, commission_rate3) VALUES (?,?,?,?,?,?,?)').run('金牌分销商', 3, 50, 50000.00, 0.1200, 0.0500, 0.0200);
  }
  // 默认系统配置
  const configCount = db.prepare('SELECT COUNT(*) as c FROM system_config').get();
  if (configCount.c === 0) {
    const configs = [
      ['base', 'site_name', '省胜优铺轻商城', 'text', '站点名称'],
      ['base', 'site_logo', '', 'image', '站点Logo'],
      ['base', 'site_description', '轻量级电商系统', 'text', '站点描述'],
      ['base', 'icp_beian', '', 'text', 'ICP备案号'],
      ['base', 'contact_phone', '', 'text', '客服电话'],
      ['base', 'contact_email', '', 'text', '客服邮箱'],
      ['payment', 'wechat_appid', '', 'text', '微信AppId'],
      ['payment', 'wechat_mchid', '', 'text', '微信商户号'],
      ['payment', 'wechat_key', '', 'password', '微信API密钥'],
      ['payment', 'alipay_appid', '', 'text', '支付宝AppId'],
      ['payment', 'alipay_private_key', '', 'password', '支付宝私钥'],
      ['payment', 'alipay_public_key', '', 'text', '支付宝公钥'],
      ['distribution', 'is_open', '1', 'switch', '是否开启分销'],
      ['distribution', 'auto_settle_days', '7', 'number', '佣金自动结算天数'],
      ['distribution', 'min_withdraw', '10', 'number', '最低提现金额'],
      ['distribution', 'withdraw_fee_rate', '0', 'number', '提现手续费率%'],
      ['share', 'share_title', '快来这个好商城逛逛', 'text', '分享标题'],
      ['share', 'share_desc', '品质好物，一站购齐', 'text', '分享描述'],
      ['share', 'share_image', '', 'image', '分享图片'],
      ['ai', 'ai_enabled', '0', 'switch', '开启AI客服'],
      ['ai', 'ai_welcome', '您好，我是AI客服，有什么可以帮您的吗？', 'text', 'AI欢迎语'],
      ['ai', 'ai_auto_reply', '0', 'switch', '未匹配知识库时自动回复'],
      ['ai', 'ai_fallback', '您好，这个问题我需要转接人工客服，请稍等。', 'text', 'AI兜底回复'],
    ];
    const stmt = db.prepare('INSERT INTO system_config (group_name, key, value, type, description) VALUES (?,?,?,?,?)');
    for (const c of configs) stmt.run(...c);
  }
  // 默认会员套餐
  const planCount = db.prepare('SELECT COUNT(*) as c FROM membership_plans').get();
  if (planCount.c === 0) {
    db.prepare('INSERT INTO membership_plans (name, type, price, original_price, level_id, give_experience, description) VALUES (?,?,?,?,?,?,?)').run('白银月卡', 'monthly', 39.00, 59.00, 2, 500, '开通即升白银会员，享全场9折');
    db.prepare('INSERT INTO membership_plans (name, type, price, original_price, level_id, give_experience, description) VALUES (?,?,?,?,?,?,?)').run('黄金月卡', 'monthly', 69.00, 99.00, 3, 2000, '开通即升黄金会员，享全场85折');
    db.prepare('INSERT INTO membership_plans (name, type, price, original_price, level_id, give_experience, description) VALUES (?,?,?,?,?,?,?)').run('钻石月卡', 'monthly', 119.00, 169.00, 4, 8000, '开通即升钻石会员，享全场8折');
  }
  // 默认分销配置
  const distConfigCount = db.prepare('SELECT COUNT(*) as c FROM distribution_config').get();
  if (distConfigCount.c === 0) {
    const distConfigs = [
      ['is_open', '1', '是否开启分销'],
      ['auto_settle_days', '7', '佣金自动结算天数'],
      ['min_withdraw', '10', '最低提现金额'],
      ['withdraw_fee_rate', '0', '提现手续费率%'],
      ['register_earn_self', '1', '自购返佣'],
    ];
    const stmt = db.prepare('INSERT INTO distribution_config (key, value, description) VALUES (?,?,?)');
    for (const c of distConfigs) stmt.run(...c);
  }
  // 默认订单配置（2026-06-15 新增）
  const orderConfigs = {
    free_shipping: { val: '1', desc: '全场包邮（满0元包邮）' },
    invoice_enabled: { val: '1', desc: '发票功能开启' },
    refund_days: { val: '7', desc: '售后退款期限(天)' },
    cancel_minutes: { val: '30', desc: '下单后X分钟内可取消' },
    auto_receive_days: { val: '15', desc: '发货后自动确认收货(天)' },
    auto_review_days: { val: '30', desc: '收货后自动好评(天)' },
    self_pickup_enabled: { val: '0', desc: '开启到店自提' },
    stock_warning: { val: '10', desc: '警戒库存阈值' },
  };
  const upsertConfig = db.prepare('INSERT OR REPLACE INTO system_config (key, group_name, value, type, description) VALUES (?,?,?,?,?)');
  for (const [key, cfg] of Object.entries(orderConfigs)) {
    const exist = db.prepare('SELECT id FROM system_config WHERE key=?').get(key);
    if (!exist) upsertConfig.run(key, 'order', cfg.val, 'text', cfg.desc);
  }
  // 补充分销配置 (2026-06-15)
  const extraDistConfigs = {
    dist_mode: 'everyone',
    bind_mode: 'auto',
    bind_valid_days: '365',
    commission_levels: '3',
    division_enabled: '0',
    agent_apply_enabled: '1',
    commission_float_enabled: '0',
    poster_image: '',
  };
  const upsertDistCfg = db.prepare('INSERT OR IGNORE INTO distribution_config(key,value,description) VALUES(?,?,?)');
  for (const [key, val] of Object.entries(extraDistConfigs)) {
    const descMap = {
      dist_mode: '分销模式: designated=指定分销/everyone=人人分销/threshold=满额分销',
      bind_mode: '绑定模式: auto=自动绑定/manual=手动绑定/qrcode=扫码绑定',
      bind_valid_days: '绑定有效期(天)',
      commission_levels: '分销层级(1-3)',
      division_enabled: '事业部开关',
      agent_apply_enabled: '代理商申请开关',
      commission_float_enabled: '佣金悬浮窗开关',
      poster_image: '分销海报图',
    };
    upsertDistCfg.run(key, val, descMap[key] || '');
  }
  // 新分销相关表 (2026-06-15)
  db.exec(`CREATE TABLE IF NOT EXISTS distributor_applies (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL REFERENCES users(id),
    real_name TEXT DEFAULT '',
    phone TEXT DEFAULT '',
    wechat TEXT DEFAULT '',
    reason TEXT DEFAULT '',
    status TEXT CHECK(status IN ('pending','approved','rejected')) DEFAULT 'pending',
    reject_reason TEXT DEFAULT '',
    created_at DATETIME DEFAULT (datetime('now','localtime')),
    handled_at DATETIME
  )`);
  db.exec(`CREATE TABLE IF NOT EXISTS business_divisions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    manager_id INTEGER REFERENCES users(id),
    description TEXT DEFAULT '',
    commission_rate DECIMAL(5,2) DEFAULT 0.00,
    member_count INTEGER DEFAULT 0,
    total_sales DECIMAL(12,2) DEFAULT 0.00,
    status INTEGER DEFAULT 1,
    created_at DATETIME DEFAULT (datetime('now','localtime'))
  )`);
  // 用户分销扩展字段
  try { db.exec('ALTER TABLE users ADD COLUMN distributor_status TEXT DEFAULT \'none\''); } catch {}
  try { db.exec('ALTER TABLE users ADD COLUMN distributor_level INTEGER DEFAULT 0'); } catch {}
  try { db.exec('ALTER TABLE users ADD COLUMN distributor_real_name TEXT DEFAULT \'\''); } catch {}
  try { db.exec('ALTER TABLE users ADD COLUMN distributor_phone TEXT DEFAULT \'\''); } catch {}
  try { db.exec('ALTER TABLE users ADD COLUMN distributor_wechat TEXT DEFAULT \'\''); } catch {}
  try { db.exec('ALTER TABLE users ADD COLUMN freeze_balance DECIMAL(12,2) DEFAULT 0.00'); } catch {}
  try { db.exec('ALTER TABLE users ADD COLUMN parent_id INTEGER DEFAULT NULL'); } catch {}
  try { db.exec('ALTER TABLE users ADD COLUMN team_count INTEGER DEFAULT 0'); } catch {}
  try { db.exec('ALTER TABLE users ADD COLUMN total_commission DECIMAL(12,2) DEFAULT 0.00'); } catch {}
  // 品牌表
  db.exec(`CREATE TABLE IF NOT EXISTS brands (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    logo TEXT DEFAULT '',
    sort INTEGER DEFAULT 0,
    status INTEGER DEFAULT 1,
    created_at DATETIME DEFAULT (datetime('now','localtime'))
  )`);
    db.exec(`CREATE TABLE IF NOT EXISTS design_templates (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,terminal TEXT DEFAULT \"h5\",page TEXT DEFAULT \"home\",thumbnail TEXT DEFAULT \"\",is_default INTEGER DEFAULT 0,status INTEGER DEFAULT 1,content TEXT DEFAULT '{"components":[]}',created_at TEXT,updated_at TEXT)`);
  db.exec(`CREATE TABLE IF NOT EXISTS design_components (id INTEGER PRIMARY KEY AUTOINCREMENT,template_id INTEGER,comp_type TEXT NOT NULL,sort INTEGER DEFAULT 0,config TEXT DEFAULT \"{}\",created_at TEXT)`);
  // 文章+分类+帮助表
  db.exec(`CREATE TABLE IF NOT EXISTS theme_customs (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT NOT NULL,colors TEXT DEFAULT '{}',is_active INTEGER DEFAULT 0,created_at DATETIME DEFAULT (datetime('now','localtime')))`);
  db.exec(`CREATE TABLE IF NOT EXISTS article_categories (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    sort INTEGER DEFAULT 0,
    created_at DATETIME DEFAULT (datetime('now','localtime'))
  )`);
  db.exec(`CREATE TABLE IF NOT EXISTS articles (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    category_id INTEGER REFERENCES article_categories(id),
    author TEXT DEFAULT 'admin',
    cover TEXT DEFAULT '',
    summary TEXT DEFAULT '',
    content TEXT DEFAULT '',
    views INTEGER DEFAULT 0,
    sort INTEGER DEFAULT 0,
    status INTEGER DEFAULT 1,
    created_at DATETIME DEFAULT (datetime('now','localtime')),
    updated_at DATETIME DEFAULT (datetime('now','localtime'))
  )`);
  db.exec(`CREATE TABLE IF NOT EXISTS helps (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    category TEXT DEFAULT '',
    content TEXT DEFAULT '',
    sort INTEGER DEFAULT 0,
    status INTEGER DEFAULT 1,
    created_at DATETIME DEFAULT (datetime('now','localtime'))
  )`);
  // 默认帮助数据
  const helpCount = db.prepare('SELECT COUNT(*) as c FROM helps').get();
  if (helpCount.c === 0) {
    db.prepare('INSERT INTO helps(title,category,content,sort) VALUES(?,?,?,?)').run('如何下单购买？', '购物指南', '1. 浏览商品加入购物车\n2. 确认订单信息\n3. 选择支付方式完成支付\n4. 等待发货收货', 1);
    db.prepare('INSERT INTO helps(title,category,content,sort) VALUES(?,?,?,?)').run('支持哪些支付方式？', '支付问题', '支持微信支付和支付宝两种支付方式。', 2);
    db.prepare('INSERT INTO helps(title,category,content,sort) VALUES(?,?,?,?)').run('如何申请退款？', '售后政策', '在订单详情页点击"申请退款"按钮，填写原因提交即可。管理员审核后将会退款到您的账户。', 3);
  }
  const notifCount = db.prepare('SELECT COUNT(*) as c FROM notifications').get();
  if (notifCount.c === 0) {
    db.prepare('INSERT INTO notifications(user_id,type,title,content) VALUES(?,?,?,?)').run(0, 'system', '欢迎使用省胜优铺轻商城', '感谢您的注册！在这里您可以浏览商品、下单购买、享受会员折扣和其他优惠。');
  }
  // 默认通知模板
  const tmplCount = db.prepare('SELECT COUNT(*) as c FROM notification_templates').get();
  if (tmplCount.c === 0) {
    const tmplStmt = db.prepare('INSERT INTO notification_templates(code,type,title,content,variables,channels) VALUES(?,?,?,?,?,?)');
    const templates = [
      ['order_created', 'sms', '下单成功通知', '您好，您的订单{order_no}已创建成功，金额¥{amount}，请及时支付。', '["order_no","amount"]', '["sms","email","wechat"]'],
      ['payment_success', 'sms', '支付成功通知', '您好，您的订单{order_no}已支付成功（¥{amount}），我们将尽快为您发货。', '["order_no","amount"]', '["sms","email","wechat"]'],
      ['order_shipped', 'sms', '发货通知', '您好，您的订单{order_no}已通过{shipping_company}发出，快递单号{shipping_no}，请留意查收。', '["order_no","shipping_company","shipping_no"]', '["sms","email","wechat"]'],
      ['refund_processed', 'sms', '退款处理通知', '您好，您的退款申请(原订单:{order_no})已{result}，退款金额¥{amount}，预计1-7个工作日到账。', '["order_no","result","amount"]', '["sms","email","wechat"]'],
      ['commission_received', 'sms', '佣金到账通知', '您好，您的佣金¥{amount}已到账（来自订单{order_no}），当前可提现余额¥{balance}。', '["amount","order_no","balance"]', '["sms","email","wechat"]'],
      ['withdraw_result', 'sms', '提现结果通知', '您好，您申请的提现¥{amount}已{result}。{reason}', '["amount","result","reason"]', '["sms","email"]'],
      ['membership_expiry', 'sms', '会员到期提醒', '您好，您的会员将于{expire_date}到期，到期后将恢复普通用户折扣，点击续费享优惠。', '["expire_date"]', '["sms","email"]'],
      ['password_reset', 'sms', '密码重置验证码', '您的验证码是{code}，用于重置密码，{expire_minutes}分钟内有效，请勿泄露。', '["code","expire_minutes"]', '["sms"]'],
    ];
    for (const t of templates) tmplStmt.run(...t);
  }
  // 默认页面
  const pageCount = db.prepare('SELECT COUNT(*) as c FROM pages').get();
  if (pageCount.c === 0) {
    db.prepare('INSERT INTO pages (title, type, content) VALUES (?,?,?)').run('关于我们', 'about', '<p>省胜优铺轻商城 - 轻量级电商解决方案</p>');
    db.prepare('INSERT INTO pages (title, type, content) VALUES (?,?,?)').run('隐私政策', 'policy', '<p>我们重视您的隐私...</p>');
    db.prepare('INSERT INTO pages (title, type, content) VALUES (?,?,?)').run('服务条款', 'service', '<p>使用本商城即表示同意以下条款...</p>');
  }
  // ========== APP配置 & 版本管理 ==========
  db.exec(`
    CREATE TABLE IF NOT EXISTS app_config (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      splash_image TEXT DEFAULT '',
      splash_link TEXT DEFAULT '',
      ad_image TEXT DEFAULT '',
      ad_link TEXT DEFAULT '',
      ad_duration INTEGER DEFAULT 3,
      bottom_nav TEXT DEFAULT '[]',
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
    CREATE TABLE IF NOT EXISTS app_versions (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      version_name TEXT NOT NULL,
      version_code INTEGER NOT NULL,
      update_log TEXT DEFAULT '',
      download_url TEXT DEFAULT '',
      force_update INTEGER DEFAULT 0,
      platform TEXT CHECK(platform IN ('android','ios','all')) DEFAULT 'all',
      status INTEGER DEFAULT 1,
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
  `);
  // 补齐现有 theme_page_map（theme.js 引用了但未建表，潜在bug）
  db.exec(`
    CREATE TABLE IF NOT EXISTS theme_page_map (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      page_key TEXT UNIQUE NOT NULL,
      theme_id TEXT NOT NULL DEFAULT 'global',
      created_at DATETIME DEFAULT (datetime('now','localtime')),
      updated_at DATETIME DEFAULT (datetime('now','localtime'))
    );
  `);
  // ========== 一键搬家 - 迁移日志 ==========
  db.exec(`
    CREATE TABLE IF NOT EXISTS migration_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      type TEXT CHECK(type IN ('import','export')) NOT NULL,
      status TEXT CHECK(status IN ('success','failed','pending')) DEFAULT 'pending',
      source_platform TEXT DEFAULT '',
      stats TEXT DEFAULT '{}',
      options TEXT DEFAULT '{}',
      error TEXT DEFAULT '',
      file_path TEXT DEFAULT '',
      created_at DATETIME DEFAULT (datetime('now','localtime'))
    );
  `);
  // ========== 自动SEO文章生成器 ==========
  db.exec(`
    CREATE TABLE IF NOT EXISTS search_keywords (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      keyword TEXT NOT NULL,
      count INTEGER DEFAULT 1,
      last_seen TEXT,
      created_at TEXT DEFAULT (datetime('now','localtime')),
      UNIQUE(keyword)
    );
    CREATE INDEX IF NOT EXISTS idx_search_keywords_count ON search_keywords(count DESC);
    CREATE TABLE IF NOT EXISTS seo_article_tasks (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      enabled INTEGER DEFAULT 1,
      generate_time TEXT DEFAULT '06:30',
      daily_count INTEGER DEFAULT 1,
      mode TEXT DEFAULT 'random',
      category_id INTEGER DEFAULT 0,
      max_price REAL DEFAULT 0,
      keyword_source TEXT DEFAULT 'combo',
      article_status INTEGER DEFAULT 0,
      last_run_date TEXT,
      created_at TEXT DEFAULT (datetime('now','localtime')),
      updated_at TEXT
    );
    CREATE TABLE IF NOT EXISTS seo_generate_logs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      task_id INTEGER,
      product_id INTEGER,
      article_id INTEGER,
      mode TEXT,
      gen_date TEXT,
      title TEXT,
      status TEXT DEFAULT 'success',
      message TEXT,
      created_at TEXT DEFAULT (datetime('now','localtime'))
    );
    CREATE INDEX IF NOT EXISTS idx_seo_logs_product_date ON seo_generate_logs(product_id, gen_date);
  `);
  // articles 扩展 SEO 字段（幂等）
  const _addArtCol = (col, def) => {
    const c = db.prepare("SELECT COUNT(*) c FROM pragma_table_info('articles') WHERE name=?").get(col);
    if (!c.c) db.exec('ALTER TABLE articles ADD COLUMN ' + col + ' ' + def);
  };
  _addArtCol('seo_keywords', "TEXT DEFAULT ''");
  _addArtCol('source_product_id', 'INTEGER');
  _addArtCol('is_ai_generated', 'INTEGER DEFAULT 0');
  _addArtCol('ai_mode', 'TEXT');
  _addArtCol('publish_time', 'TEXT');
  // ========== 索引 ==========
  db.exec(`
    CREATE INDEX IF NOT EXISTS idx_orders_user_id ON orders(user_id);
    CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status);
    CREATE INDEX IF NOT EXISTS idx_orders_created_at ON orders(created_at);
    CREATE INDEX IF NOT EXISTS idx_order_items_order_id ON order_items(order_id);
    CREATE INDEX IF NOT EXISTS idx_carts_user_id ON carts(user_id);
    CREATE INDEX IF NOT EXISTS idx_products_category_id ON products(category_id);
    CREATE INDEX IF NOT EXISTS idx_products_status ON products(status);
    CREATE INDEX IF NOT EXISTS idx_user_addresses_user_id ON user_addresses(user_id);
    CREATE INDEX IF NOT EXISTS idx_distribution_records_user_id ON distribution_records(user_id);
    CREATE INDEX IF NOT EXISTS idx_distribution_records_order_id ON distribution_records(order_id);
    CREATE INDEX IF NOT EXISTS idx_operation_logs_admin_id ON operation_logs(admin_id);
    CREATE INDEX IF NOT EXISTS idx_product_skus_product_id ON product_skus(product_id);
    CREATE INDEX IF NOT EXISTS idx_product_specs_product_id ON product_specs(product_id);
    CREATE INDEX IF NOT EXISTS idx_product_reviews_product_id ON product_reviews(product_id);
    CREATE INDEX IF NOT EXISTS idx_user_favorites_user_id ON user_favorites(user_id);
    CREATE INDEX IF NOT EXISTS idx_login_logs_user_id ON login_logs(user_id);
    CREATE INDEX IF NOT EXISTS idx_chat_messages_conversation_id ON chat_messages(conversation_id);
    CREATE INDEX IF NOT EXISTS idx_user_coupons_user_id ON user_coupons(user_id);
  `);
  console.log('✅ 数据库初始化完成');
  db.close();
}
if (require.main === module) {
  initDatabase();
}
module.exports = { initDatabase, DB_PATH };
