/**
 * SVS MSP Calculator — Quote Engine Tests
 *
 * Run:   node svsmspcalc/tests/test-quote-engine.js
 *
 * Zero dependencies. Uses a minimal test harness built-in.
 * Tests the pure calculateQuote(state, pricing) function against
 * known-good expected values using default pricing.
 */

// ── Minimal test harness ───────────────────────────────────────
let _passed = 0;
let _failed = 0;
let _group = '';

function describe(name, fn) {
  _group = name;
  console.log(`\n  ${name}`);
  fn();
}

function it(name, fn) {
  try {
    fn();
    _passed++;
    console.log(`    \x1b[32m✓\x1b[0m ${name}`);
  } catch (e) {
    _failed++;
    console.log(`    \x1b[31m✗\x1b[0m ${name}`);
    console.log(`      \x1b[31m${e.message}\x1b[0m`);
  }
}

function assert(condition, msg) {
  if (!condition) throw new Error(msg || 'Assertion failed');
}

function eq(actual, expected, label) {
  if (actual !== expected) {
    throw new Error(`${label || 'Value'}: expected ${expected}, got ${actual}`);
  }
}

function near(actual, expected, tolerance, label) {
  if (Math.abs(actual - expected) > tolerance) {
    throw new Error(`${label || 'Value'}: expected ~${expected} (±${tolerance}), got ${actual}`);
  }
}

// ── Load engine (mock window as global) ────────────────────────
const _global = {};
(function loadModules() {
  const fs = require('fs');
  const path = require('path');
  const dir = path.resolve(__dirname, '..');

  // Load quote-pricing.js — sets DEFAULTS on _global
  const pricingSrc = fs.readFileSync(path.join(dir, 'quote-pricing.js'), 'utf8')
    .replace(/\(window\)\s*;?\s*$/, '(_global);');
  new Function('_global', pricingSrc)(_global);

  // Load quote-engine.js — sets calculateQuote on _global
  const engineSrc = fs.readFileSync(path.join(dir, 'quote-engine.js'), 'utf8')
    .replace(/\(window\)\s*;?\s*$/, '(_global);');
  new Function('_global', engineSrc)(_global);
})();

const calculateQuote = _global.calculateQuote;
const DEFAULTS = _global.SVSQuotePricing.DEFAULTS;

// Helper: build a state object with sensible defaults
function makeState(overrides) {
  return Object.assign({
    byol: false,
    users: 0,
    endpoints: 0,
    servers: 0,
    addExtHours: false,
    addPWM: false,
    addINKY: false,
    addZT: false,
    addUSB: false,
    addBMB: false,
    ztSeats: 0,
    ztRouters: 0,
    voipTier: 'basic',
    voipSeats: 0,
    addVoipPhone: false,
    addVoipFax: false,
    clientName: '',
    contractTerm: 'm2m',
    hstEnabled: false,
    oneTimeFee: 0,
    adminWaived: false
  }, overrides);
}

// ── Tests ──────────────────────────────────────────────────────
console.log('\n\x1b[1mSVS Quote Engine — Test Suite\x1b[0m');

// ── 1. Basic pricing ──────────────────────────────────────────
describe('Basic M365 quote (1 user, 1 endpoint, m2m)', () => {
  const q = calculateQuote(makeState({ users: 1, endpoints: 1 }), DEFAULTS);

  it('userBase = 140 (m2m rate)', () => eq(q.userBase, 140, 'userBase'));
  it('userTotal = 140', () => eq(q.userTotal, 140, 'userTotal'));
  it('endpointBase = 35', () => eq(q.endpointBase, 35, 'endpointBase'));
  it('endpointTotal = 35', () => eq(q.endpointTotal, 35, 'endpointTotal'));
  it('baseSubtotal = 175', () => eq(q.baseSubtotal, 175, 'baseSubtotal'));
  it('admin fee scales: max(150, 650-175) = 475', () => eq(q.siteAdminBase, 475, 'siteAdminBase'));
  it('adminFeeNet = 475', () => eq(q.adminFeeNet, 475, 'adminFeeNet'));
  it('MRR = 650', () => eq(q.MRR, 650, 'MRR'));
  it('annual = 7800', () => eq(q.annual, 7800, 'annual'));
  it('no discount at m2m', () => eq(q.discountAmt, 0, 'discountAmt'));
  it('effectiveMrr = MRR', () => eq(q.effectiveMrr, 650, 'effectiveMrr'));
});

// ── 2. BYOL rate ──────────────────────────────────────────────
describe('BYOL rate (1 user, 1 endpoint)', () => {
  const q = calculateQuote(makeState({ users: 1, endpoints: 1, byol: true }), DEFAULTS);

  it('baseUserRate = 110 (BYOL)', () => eq(q.baseUserRate, 110, 'baseUserRate'));
  it('userBase = 110', () => eq(q.userBase, 110, 'userBase'));
  it('baseSubtotal = 145', () => eq(q.baseSubtotal, 145, 'baseSubtotal'));
  it('admin fee scales: max(150, 650-145) = 505', () => eq(q.siteAdminBase, 505, 'siteAdminBase'));
  it('MRR still = 650 (admin absorbs difference)', () => eq(q.MRR, 650, 'MRR'));
});

// ── 3. Admin fee floor ────────────────────────────────────────
describe('Admin fee floor (high service volume)', () => {
  // 5 users + 1 endpoint: baseSubtotal = 675+35 = 710 > 650
  const q = calculateQuote(makeState({ users: 5, endpoints: 1 }), DEFAULTS);

  it('baseSubtotal = 735', () => eq(q.baseSubtotal, 735, 'baseSubtotal'));
  it('admin hits floor: max(150, 650-710) = 150', () => eq(q.siteAdminBase, 150, 'siteAdminBase'));
  it('adminFeeNet = 150', () => eq(q.adminFeeNet, 150, 'adminFeeNet'));
});

// ── 4. Admin fee ZT premium ───────────────────────────────────
describe('Admin fee with Zero Trust premium', () => {
  const q = calculateQuote(makeState({ users: 5, endpoints: 1, addZT: true }), DEFAULTS);

  it('ztActive = true', () => assert(q.ztActive, 'ztActive'));
  it('admin includes ZT premium: 150 + 250 = 400', () => eq(q.adminFeeNet, 400, 'adminFeeNet'));
});

describe('Admin fee ZT premium via ztSeats (no addZT checkbox)', () => {
  const q = calculateQuote(makeState({ users: 5, endpoints: 1, ztSeats: 2 }), DEFAULTS);

  it('ztActive = true (from ztSeats > 0)', () => assert(q.ztActive, 'ztActive'));
  it('admin includes ZT premium', () => eq(q.adminFeeNet, 400, 'adminFeeNet'));
});

// ── 5. Admin fee 1Password markup ─────────────────────────────
describe('Admin fee with 1Password markup', () => {
  // 5 users, 1 endpoint, addPWM
  // userPWM = 5 * 9 = 45, admin1PWM = round(45 * 0.10) = 5
  const q = calculateQuote(makeState({ users: 5, endpoints: 1, addPWM: true }), DEFAULTS);

  it('userPWM = 45', () => eq(q.userPWM, 45, 'userPWM'));
  it('admin1PWM = 5 (10% of 45, rounded)', () => eq(q.admin1PWM, 5, 'admin1PWM'));
  it('adminFeeNet = 150 + 5 = 155', () => eq(q.adminFeeNet, 155, 'adminFeeNet'));
});

// ── 6. Admin waived ───────────────────────────────────────────
describe('Admin fee waived', () => {
  const q = calculateQuote(makeState({ users: 1, endpoints: 1, adminWaived: true }), DEFAULTS);

  it('adminFeeNet still calculated = 475', () => eq(q.adminFeeNet, 475, 'adminFeeNet'));
  it('admin does not contribute to MRR', () => {
    eq(q.MRR, 140 + 35, 'MRR without admin'); // 175
  });
});

// ── 7. User add-ons ──────────────────────────────────────────
describe('All user add-ons (10 users)', () => {
  const q = calculateQuote(makeState({
    users: 10, endpoints: 1,
    addExtHours: true, addPWM: true, addINKY: true, addZT: true
  }), DEFAULTS);

  it('userExt = 250', () => eq(q.userExt, 250, 'userExt'));
  it('userPWM = 90', () => eq(q.userPWM, 90, 'userPWM'));
  it('userINKY = 80', () => eq(q.userINKY, 80, 'userINKY'));
  it('userZT = 550', () => eq(q.userZT, 550, 'userZT'));
  it('addonRate = 25+9+8+55 = 97', () => {
    eq(q.totalUserRate - q.baseUserRate, 97, 'addonRate');
  });
  it('userTotal = 10 * (140+97) = 2370', () => eq(q.userTotal, 2370, 'userTotal'));
});

// ── 8. Endpoint add-ons ──────────────────────────────────────
describe('Endpoint add-ons (10 endpoints)', () => {
  const q = calculateQuote(makeState({
    users: 1, endpoints: 10, addUSB: true, addBMB: true
  }), DEFAULTS);

  it('endpointBase = 350', () => eq(q.endpointBase, 350, 'endpointBase'));
  it('endpointUSB = 40', () => eq(q.endpointUSB, 40, 'endpointUSB'));
  it('endpointBMB = 250', () => eq(q.endpointBMB, 250, 'endpointBMB'));
  it('endpointTotal = 640 (includes no servers)', () => eq(q.endpointTotal, 640, 'endpointTotal'));
});

// ── 9. Server pricing ────────────────────────────────────────
describe('Server pricing', () => {
  const q = calculateQuote(makeState({ users: 1, endpoints: 1, servers: 3 }), DEFAULTS);

  it('serverBase = 360', () => eq(q.serverBase, 360, 'serverBase'));
  it('servers included in endpointTotal', () => eq(q.endpointTotal, 35 + 360, 'endpointTotal'));
  it('servers in baseSubtotal', () => eq(q.baseSubtotal, 140 + 35 + 360, 'baseSubtotal'));
});

// ── 10. Contract discounts ───────────────────────────────────
describe('Contract term discounts', () => {
  const base = { users: 10, endpoints: 10 };

  it('m2m = 0% discount', () => {
    const q = calculateQuote(makeState({ ...base, contractTerm: 'm2m' }), DEFAULTS);
    eq(q.discountPct, 0, 'discountPct');
    eq(q.discountAmt, 0, 'discountAmt');
  });

  it('12mo = 3% discount', () => {
    const q = calculateQuote(makeState({ ...base, contractTerm: '12mo' }), DEFAULTS);
    eq(q.discountPct, 0.03, 'discountPct');
    eq(q.discountAmt, Math.round(q.MRR * 0.03), 'discountAmt');
    eq(q.effectiveMrr, q.MRR - q.discountAmt, 'effectiveMrr');
  });

  it('24mo = 5% discount', () => {
    const q = calculateQuote(makeState({ ...base, contractTerm: '24mo' }), DEFAULTS);
    eq(q.discountPct, 0.05, 'discountPct');
    eq(q.discountAmt, Math.round(q.MRR * 0.05), 'discountAmt');
  });
});

// ── 10b. M365 term-aware rate ────────────────────────────────
describe('M365 rate varies by contract term', () => {
  it('m2m uses RATE_M365_M2M ($140)', () => {
    const q = calculateQuote(makeState({ users: 1, endpoints: 1, contractTerm: 'm2m' }), DEFAULTS);
    eq(q.m365Rate, 140, 'm365Rate');
    eq(q.baseUserRate, 140, 'baseUserRate');
  });
  it('12mo uses RATE_M365 ($130)', () => {
    const q = calculateQuote(makeState({ users: 1, endpoints: 1, contractTerm: '12mo' }), DEFAULTS);
    eq(q.m365Rate, 130, 'm365Rate');
    eq(q.baseUserRate, 130, 'baseUserRate');
  });
  it('24mo uses RATE_M365 ($130)', () => {
    const q = calculateQuote(makeState({ users: 1, endpoints: 1, contractTerm: '24mo' }), DEFAULTS);
    eq(q.m365Rate, 130, 'm365Rate');
    eq(q.baseUserRate, 130, 'baseUserRate');
  });
  it('BYOL rate unaffected by term', () => {
    const q = calculateQuote(makeState({ users: 1, endpoints: 1, byol: true, contractTerm: '12mo' }), DEFAULTS);
    eq(q.baseUserRate, 110, 'baseUserRate');
  });
});

// ── 11. HST calculation ──────────────────────────────────────
describe('HST calculation', () => {
  const q = calculateQuote(makeState({
    users: 1, endpoints: 1, hstEnabled: true
  }), DEFAULTS);

  it('hstAmt = round(650 * 0.13) = 85', () => eq(q.hstAmt, 85, 'hstAmt'));
  it('mrrWithHst = 650 + 85 = 735', () => eq(q.mrrWithHst, 735, 'mrrWithHst'));
});

describe('HST disabled = 0', () => {
  const q = calculateQuote(makeState({
    users: 1, endpoints: 1, hstEnabled: false
  }), DEFAULTS);

  it('hstAmt = 0', () => eq(q.hstAmt, 0, 'hstAmt'));
  it('mrrWithHst = effectiveMrr', () => eq(q.mrrWithHst, q.effectiveMrr, 'mrrWithHst'));
});

// ── 12. VoIP tiers ───────────────────────────────────────────
describe('VoIP tiers', () => {
  it('basic = $28/seat', () => {
    const q = calculateQuote(makeState({ voipSeats: 5, voipTier: 'basic' }), DEFAULTS);
    eq(q.voipSeatRate, 28, 'voipSeatRate');
    eq(q.voipSeatsAmt, 140, 'voipSeatsAmt');
  });

  it('standard = $35/seat', () => {
    const q = calculateQuote(makeState({ voipSeats: 5, voipTier: 'standard' }), DEFAULTS);
    eq(q.voipSeatRate, 35, 'voipSeatRate');
    eq(q.voipSeatsAmt, 175, 'voipSeatsAmt');
  });

  it('premium = $45/seat', () => {
    const q = calculateQuote(makeState({ voipSeats: 5, voipTier: 'premium' }), DEFAULTS);
    eq(q.voipSeatRate, 45, 'voipSeatRate');
    eq(q.voipSeatsAmt, 225, 'voipSeatsAmt');
  });
});

// ── 13. VoIP add-ons ─────────────────────────────────────────
describe('VoIP phone + fax add-ons', () => {
  const q = calculateQuote(makeState({
    voipSeats: 10, voipTier: 'standard',
    addVoipPhone: true, addVoipFax: true
  }), DEFAULTS);

  it('voipPhoneAmt = 150', () => eq(q.voipPhoneAmt, 150, 'voipPhoneAmt'));
  it('voipFaxAmt = 100', () => eq(q.voipFaxAmt, 100, 'voipFaxAmt'));
  it('voipTotal = 350+150+100 = 600', () => eq(q.voipTotal, 600, 'voipTotal'));
});

// ── 14. Zero Trust networking ────────────────────────────────
describe('Zero Trust networking', () => {
  const q = calculateQuote(makeState({ ztSeats: 10, ztRouters: 2 }), DEFAULTS);

  it('ztNetSeats = 250', () => eq(q.ztNetSeats, 250, 'ztNetSeats'));
  it('ztNetRouters = 200', () => eq(q.ztNetRouters, 200, 'ztNetRouters'));
  it('ztNetTotal = 450', () => eq(q.ztNetTotal, 450, 'ztNetTotal'));
  it('ztActive = true', () => assert(q.ztActive, 'ztActive'));
});

// ── 15. Zero users edge case ─────────────────────────────────
describe('Zero users edge case', () => {
  const q = calculateQuote(makeState({ users: 0, endpoints: 0 }), DEFAULTS);

  it('perUserAllin = 0', () => eq(q.perUserAllin, 0, 'perUserAllin'));
  it('perUserServices = 0', () => eq(q.perUserServices, 0, 'perUserServices'));
  it('userTotal = 0', () => eq(q.userTotal, 0, 'userTotal'));
  it('admin still applies (floor)', () => {
    // baseSubtotal = 0, max(150, 650-0) = 650
    eq(q.siteAdminBase, 650, 'siteAdminBase');
  });
});

// ── 16. Per-user breakdown ───────────────────────────────────
describe('Per-user cost breakdown', () => {
  const q = calculateQuote(makeState({ users: 10, endpoints: 10 }), DEFAULTS);

  it('perUserServices = round(userTotal / users)', () => {
    eq(q.perUserServices, Math.round(q.userTotal / 10), 'perUserServices');
  });
  it('perUserSiteOvhd = round((effectiveMrr - userTotal) / users)', () => {
    eq(q.perUserSiteOvhd, Math.round((q.effectiveMrr - q.userTotal) / 10), 'perUserSiteOvhd');
  });
  it('perUserAllin = MRR / users', () => {
    eq(q.perUserAllin, q.MRR / 10, 'perUserAllin');
  });
});

// ── 17. HST + discount combo ─────────────────────────────────
describe('HST applied AFTER contract discount', () => {
  const q = calculateQuote(makeState({
    users: 10, endpoints: 10,
    contractTerm: '12mo', hstEnabled: true
  }), DEFAULTS);

  it('discount applied first', () => {
    eq(q.effectiveMrr, q.MRR - q.discountAmt, 'effectiveMrr');
  });
  it('HST on discounted amount', () => {
    eq(q.hstAmt, Math.round(q.effectiveMrr * 0.13), 'hstAmt');
  });
  it('mrrWithHst = effectiveMrr + hstAmt', () => {
    eq(q.mrrWithHst, q.effectiveMrr + q.hstAmt, 'mrrWithHst');
  });
});

// ── 18. Realistic full quote ─────────────────────────────────
describe('Realistic 22-user full quote', () => {
  const q = calculateQuote(makeState({
    users: 22, endpoints: 22, servers: 2,
    addPWM: true, addINKY: true,
    ztSeats: 5, ztRouters: 1,
    voipSeats: 15, voipTier: 'standard', addVoipPhone: true,
    contractTerm: '12mo', hstEnabled: true
  }), DEFAULTS);

  it('userTotal = 22 * (130+9+8) = 3234', () => eq(q.userTotal, 3234, 'userTotal'));
  it('endpointBase = 770', () => eq(q.endpointBase, 770, 'endpointBase'));
  it('serverBase = 240', () => eq(q.serverBase, 240, 'serverBase'));
  it('ztNetTotal = 5*25 + 1*100 = 225', () => eq(q.ztNetTotal, 225, 'ztNetTotal'));
  it('voipTotal = 15*35 + 15*15 = 750', () => eq(q.voipTotal, 750, 'voipTotal'));

  it('admin: baseSubtotal = 2860+770+240 = 3870, floor applies', () => {
    // baseSubtotal = 22*130 + 22*35 + 2*120 = 2860+770+240 = 3870
    // Wait: baseSubtotal = userBase + endpointBase + serverBase
    // userBase = 22*130 = 2860, endpointBase = 770, serverBase = 240
    eq(q.baseSubtotal, 3870, 'baseSubtotal');
    eq(q.siteAdminBase, 150, 'siteAdminBase (floor)');
  });

  it('admin includes ZT premium + 1PWM', () => {
    // ztActive because ztSeats > 0
    // admin1PWM = round(22*9 * 0.10) = round(19.8) = 20
    eq(q.admin1PWM, 20, 'admin1PWM');
    eq(q.adminFeeNet, 150 + 250 + 20, 'adminFeeNet'); // 420
  });

  it('MRR components sum correctly', () => {
    const expected = q.userTotal + q.endpointTotal + q.adminFeeNet + q.ztNetTotal + q.voipTotal;
    eq(q.MRR, expected, 'MRR');
  });

  it('12mo discount = 3%', () => {
    eq(q.discountAmt, Math.round(q.MRR * 0.03), 'discountAmt');
  });

  it('HST on discounted total', () => {
    eq(q.hstAmt, Math.round(q.effectiveMrr * 0.13), 'hstAmt');
  });

  it('effectiveAnnual = effectiveMrr * 12', () => {
    eq(q.effectiveAnnual, q.effectiveMrr * 12, 'effectiveAnnual');
  });
});

// ── 19. MRR components always sum ────────────────────────────
describe('MRR = sum of all components (various configs)', () => {
  const configs = [
    { users: 1, endpoints: 1 },
    { users: 50, endpoints: 50, servers: 5, addPWM: true, addZT: true },
    { users: 0, endpoints: 0, voipSeats: 20, voipTier: 'premium' },
    { users: 10, endpoints: 10, adminWaived: true },
    { users: 3, endpoints: 3, ztSeats: 10, ztRouters: 3 }
  ];

  configs.forEach((cfg, i) => {
    it(`config #${i + 1}: MRR = user + endpoint + admin + zt + voip`, () => {
      const q = calculateQuote(makeState(cfg), DEFAULTS);
      const adminEff = q.adminWaived ? 0 : q.adminFeeNet;
      const expected = q.userTotal + q.endpointTotal + adminEff + q.ztNetTotal + q.voipTotal;
      eq(q.MRR, expected, 'MRR sum');
    });
  });
});

// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Pricing Defaults Integrity ────────────────────
// ══════════════════════════════════════════════════════════════

describe('Pricing DEFAULTS integrity', () => {
  const requiredKeys = [
    'RATE_M365', 'RATE_M365_M2M', 'RATE_BYOL',
    'ADDON_EXT_HOURS', 'ADDON_1PASSWORD', 'ADDON_INKY', 'ADDON_ZERO_TRUST_USER',
    'RATE_ENDPOINT', 'RATE_SERVER',
    'ADDON_USB_BLOCKING', 'ADDON_BARE_METAL_BACKUP',
    'ZT_SEAT_RATE', 'ZT_ROUTER_RATE',
    'ADMIN_FEE_FLOOR', 'ADMIN_FEE_MINIMUM', 'ADMIN_FEE_ZT', 'ADMIN_1PWM_PCT',
    'VOIP_RATE_BASIC', 'VOIP_RATE_STANDARD', 'VOIP_RATE_PREMIUM',
    'VOIP_PHONE_RATE', 'VOIP_FAX_RATE',
    'DISCOUNT_M2M', 'DISCOUNT_12MO', 'DISCOUNT_24MO',
    'HST_RATE'
  ];

  requiredKeys.forEach(key => {
    it(`DEFAULTS.${key} exists and is a number`, () => {
      assert(key in DEFAULTS, `${key} missing from DEFAULTS`);
      assert(typeof DEFAULTS[key] === 'number', `${key} is not a number`);
    });
  });

  it('DEFAULTS is frozen (immutable)', () => {
    assert(Object.isFrozen(DEFAULTS), 'DEFAULTS should be frozen');
  });

  it('M365 m2m rate > annual rate', () => {
    assert(DEFAULTS.RATE_M365_M2M > DEFAULTS.RATE_M365, 'm2m should exceed annual');
  });

  it('BYOL rate < M365 annual rate', () => {
    assert(DEFAULTS.RATE_BYOL < DEFAULTS.RATE_M365, 'BYOL should be less than M365');
  });

  it('VoIP tiers in ascending order', () => {
    assert(DEFAULTS.VOIP_RATE_BASIC < DEFAULTS.VOIP_RATE_STANDARD, 'basic < standard');
    assert(DEFAULTS.VOIP_RATE_STANDARD < DEFAULTS.VOIP_RATE_PREMIUM, 'standard < premium');
  });

  it('Discount rates in ascending order (m2m < 12mo < 24mo)', () => {
    assert(DEFAULTS.DISCOUNT_M2M < DEFAULTS.DISCOUNT_12MO, 'm2m < 12mo');
    assert(DEFAULTS.DISCOUNT_12MO < DEFAULTS.DISCOUNT_24MO, '12mo < 24mo');
  });

  it('HST_RATE is 13%', () => {
    eq(DEFAULTS.HST_RATE, 0.13, 'HST_RATE');
  });

  it('ADMIN_FEE_FLOOR < ADMIN_FEE_MINIMUM', () => {
    assert(DEFAULTS.ADMIN_FEE_FLOOR < DEFAULTS.ADMIN_FEE_MINIMUM, 'floor < minimum');
  });

  it('Known pricing values match spec', () => {
    eq(DEFAULTS.RATE_M365, 130, 'M365 annual');
    eq(DEFAULTS.RATE_M365_M2M, 140, 'M365 m2m');
    eq(DEFAULTS.RATE_BYOL, 110, 'BYOL');
    eq(DEFAULTS.ADDON_EXT_HOURS, 25, 'ExtHours');
    eq(DEFAULTS.ADDON_1PASSWORD, 9, '1PWM');
    eq(DEFAULTS.ADDON_INKY, 8, 'INKY');
    eq(DEFAULTS.ADDON_ZERO_TRUST_USER, 55, 'ZT user');
    eq(DEFAULTS.RATE_ENDPOINT, 35, 'endpoint');
    eq(DEFAULTS.RATE_SERVER, 120, 'server');
    eq(DEFAULTS.ADMIN_FEE_FLOOR, 150, 'admin floor');
    eq(DEFAULTS.ADMIN_FEE_MINIMUM, 650, 'admin minimum');
    eq(DEFAULTS.ADMIN_FEE_ZT, 250, 'admin ZT');
  });
});

// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Engine Edge Cases & Boundaries ────────────────
// ══════════════════════════════════════════════════════════════

describe('Admin fee exact threshold (baseSubtotal = 500)', () => {
  // baseSubtotal = 500 → max(150, 650-500) = max(150, 150) = 150
  const q = calculateQuote(makeState({ users: 3, endpoints: 1, byol: true }), DEFAULTS);
  // 3 * 110 = 330 + 35 = 365 … not 500. Let me use custom pricing.

  it('at threshold: admin = max(floor, minimum - subtotal)', () => {
    // 3 users BYOL + 1 endpoint: 330 + 35 = 365
    eq(q.baseSubtotal, 365, 'baseSubtotal');
    eq(q.siteAdminBase, Math.max(150, 650 - 365), 'siteAdminBase');
  });
});

describe('Admin fee exactly at minimum (baseSubtotal = 650)', () => {
  // Need baseSubtotal = 650. 4 users M365 m2m = 560, + ~3 endpoints = 105 → 665 too much
  // 4 users m2m = 560 + 2 endpoints = 70 → 630; + 0 servers → 630
  // Use: 4 users BYOL = 440 + 6 endpoints = 210 → 650
  const q = calculateQuote(makeState({ users: 4, endpoints: 6, byol: true }), DEFAULTS);

  it('baseSubtotal = 650 exactly', () => eq(q.baseSubtotal, 650, 'baseSubtotal'));
  it('admin = floor (650-650=0, floor wins)', () => eq(q.siteAdminBase, 150, 'siteAdminBase'));
});

describe('Admin fee when baseSubtotal just under minimum', () => {
  // 4 users BYOL = 440, 5 endpoints = 175 → 615
  const q = calculateQuote(makeState({ users: 4, endpoints: 5, byol: true }), DEFAULTS);

  it('baseSubtotal = 615', () => eq(q.baseSubtotal, 615, 'baseSubtotal'));
  it('admin = max(150, 650-615) = max(150, 35) = 150', () => eq(q.siteAdminBase, 150, 'siteAdminBase'));
});

describe('Large user count (100 users, 100 endpoints)', () => {
  const q = calculateQuote(makeState({
    users: 100, endpoints: 100, servers: 10,
    addExtHours: true, addPWM: true, addINKY: true, addZT: true,
    addUSB: true, addBMB: true,
    contractTerm: '24mo', hstEnabled: true
  }), DEFAULTS);

  it('userTotal = 100 * (130+25+9+8+55) = 22700', () => eq(q.userTotal, 22700, 'userTotal'));
  it('endpointBase = 3500', () => eq(q.endpointBase, 3500, 'endpointBase'));
  it('endpointUSB = 400', () => eq(q.endpointUSB, 400, 'endpointUSB'));
  it('endpointBMB = 2500', () => eq(q.endpointBMB, 2500, 'endpointBMB'));
  it('serverBase = 1200', () => eq(q.serverBase, 1200, 'serverBase'));
  it('admin hits floor', () => eq(q.siteAdminBase, 150, 'siteAdminBase'));
  it('MRR is positive integer', () => assert(q.MRR > 0 && Number.isInteger(q.MRR), 'MRR'));
  it('24mo discount = 5%', () => eq(q.discountPct, 0.05, 'discountPct'));
  it('HST calculated on discounted MRR', () => {
    eq(q.hstAmt, Math.round(q.effectiveMrr * 0.13), 'hstAmt');
  });
  it('annual = effectiveMrr * 12', () => eq(q.effectiveAnnual, q.effectiveMrr * 12, 'effectiveAnnual'));
});

describe('String coercion for numeric inputs', () => {
  const q = calculateQuote(makeState({ users: '5', endpoints: '3', servers: '2' }), DEFAULTS);

  it('users parsed from string', () => eq(q.users, 5, 'users'));
  it('endpoints parsed from string', () => eq(q.endpoints, 3, 'endpoints'));
  it('servers parsed from string', () => eq(q.servers, 2, 'servers'));
  it('calculations correct with string inputs', () => {
    eq(q.userBase, 5 * 140, 'userBase');
    eq(q.endpointBase, 3 * 35, 'endpointBase');
    eq(q.serverBase, 2 * 120, 'serverBase');
  });
});

describe('Invalid inputs handled gracefully', () => {
  it('NaN endpoints → 0', () => {
    const q = calculateQuote(makeState({ users: 1, endpoints: NaN }), DEFAULTS);
    eq(q.endpoints, 0, 'endpoints');
  });
  it('undefined servers → 0', () => {
    const q = calculateQuote(makeState({ users: 1, servers: undefined }), DEFAULTS);
    eq(q.servers, 0, 'servers');
  });
  it('null users → 0', () => {
    const q = calculateQuote(makeState({ users: null, endpoints: 1 }), DEFAULTS);
    eq(q.users, 0, 'users');
  });
  it('empty string users → 0', () => {
    const q = calculateQuote(makeState({ users: '', endpoints: 1 }), DEFAULTS);
    eq(q.users, 0, 'users');
  });
});

describe('Single endpoint, no users', () => {
  const q = calculateQuote(makeState({ users: 0, endpoints: 1 }), DEFAULTS);

  it('endpointBase = 35', () => eq(q.endpointBase, 35, 'endpointBase'));
  it('userTotal = 0', () => eq(q.userTotal, 0, 'userTotal'));
  it('admin still scales', () => {
    // baseSubtotal = 0 + 35 + 0 = 35, max(150, 650-35) = 615
    eq(q.siteAdminBase, 615, 'siteAdminBase');
  });
});

describe('Only servers, no users or endpoints', () => {
  const q = calculateQuote(makeState({ users: 0, endpoints: 0, servers: 5 }), DEFAULTS);

  it('serverBase = 600', () => eq(q.serverBase, 600, 'serverBase'));
  it('endpointTotal includes servers', () => eq(q.endpointTotal, 600, 'endpointTotal'));
  it('baseSubtotal = 600', () => eq(q.baseSubtotal, 600, 'baseSubtotal'));
  it('admin = max(150, 650-600) = 150', () => eq(q.siteAdminBase, 150, 'siteAdminBase'));
});

describe('VoIP only quote (no users, no endpoints)', () => {
  const q = calculateQuote(makeState({
    users: 0, endpoints: 0,
    voipSeats: 20, voipTier: 'premium', addVoipPhone: true, addVoipFax: true
  }), DEFAULTS);

  it('voipSeatsAmt = 900', () => eq(q.voipSeatsAmt, 900, 'voipSeatsAmt'));
  it('voipPhoneAmt = 300', () => eq(q.voipPhoneAmt, 300, 'voipPhoneAmt'));
  it('voipFaxAmt = 200', () => eq(q.voipFaxAmt, 200, 'voipFaxAmt'));
  it('voipTotal = 1400', () => eq(q.voipTotal, 1400, 'voipTotal'));
  it('admin is full (no user/endpoint base)', () => eq(q.siteAdminBase, 650, 'siteAdminBase'));
});

describe('VoIP fax without phone', () => {
  const q = calculateQuote(makeState({
    voipSeats: 5, voipTier: 'basic', addVoipFax: true, addVoipPhone: false
  }), DEFAULTS);

  it('voipFaxAmt = 50', () => eq(q.voipFaxAmt, 50, 'voipFaxAmt'));
  it('voipPhoneAmt = 0', () => eq(q.voipPhoneAmt, 0, 'voipPhoneAmt'));
  it('voipTotal = 140 + 50 = 190', () => eq(q.voipTotal, 190, 'voipTotal'));
});

describe('VoIP addons with zero seats', () => {
  const q = calculateQuote(makeState({
    voipSeats: 0, voipTier: 'standard', addVoipPhone: true, addVoipFax: true
  }), DEFAULTS);

  it('voipPhoneAmt = 0 (no seats)', () => eq(q.voipPhoneAmt, 0, 'voipPhoneAmt'));
  it('voipFaxAmt = 0 (no seats)', () => eq(q.voipFaxAmt, 0, 'voipFaxAmt'));
  it('voipTotal = 0', () => eq(q.voipTotal, 0, 'voipTotal'));
});

describe('ZT networking without ZT user addon', () => {
  const q = calculateQuote(makeState({
    users: 5, endpoints: 5, addZT: false, ztSeats: 10, ztRouters: 1
  }), DEFAULTS);

  it('ztActive = true (from ztSeats)', () => assert(q.ztActive, 'ztActive'));
  it('userZT = 0 (addZT is false)', () => eq(q.userZT, 0, 'userZT'));
  it('ztNetTotal = 250 + 100 = 350', () => eq(q.ztNetTotal, 350, 'ztNetTotal'));
  it('admin includes ZT supplement', () => {
    assert(q.adminFeeNet >= q.siteAdminBase + 250, 'admin includes ZT');
  });
});

describe('Admin waived still calculates adminFeeNet', () => {
  const q = calculateQuote(makeState({
    users: 10, endpoints: 10, addPWM: true, addZT: true, adminWaived: true
  }), DEFAULTS);

  it('adminWaived flag is true', () => assert(q.adminWaived, 'adminWaived'));
  it('adminFeeNet is still calculated (non-zero)', () => assert(q.adminFeeNet > 0, 'adminFeeNet > 0'));
  it('MRR excludes admin', () => {
    const expected = q.userTotal + q.endpointTotal + q.ztNetTotal + q.voipTotal;
    eq(q.MRR, expected, 'MRR without admin');
  });
});

describe('All addons combined with 12mo discount', () => {
  const q = calculateQuote(makeState({
    users: 15, endpoints: 15, servers: 3,
    addExtHours: true, addPWM: true, addINKY: true, addZT: true,
    addUSB: true, addBMB: true,
    ztSeats: 8, ztRouters: 2,
    voipSeats: 10, voipTier: 'standard', addVoipPhone: true, addVoipFax: true,
    contractTerm: '12mo', hstEnabled: true
  }), DEFAULTS);

  it('all user addons active', () => {
    assert(q.userExt > 0, 'userExt');
    assert(q.userPWM > 0, 'userPWM');
    assert(q.userINKY > 0, 'userINKY');
    assert(q.userZT > 0, 'userZT');
  });

  it('all endpoint addons active', () => {
    assert(q.endpointUSB > 0, 'endpointUSB');
    assert(q.endpointBMB > 0, 'endpointBMB');
  });

  it('ztNetTotal > 0', () => assert(q.ztNetTotal > 0, 'ztNetTotal'));
  it('voipTotal > 0', () => assert(q.voipTotal > 0, 'voipTotal'));
  it('12mo discount applied', () => eq(q.discountPct, 0.03, 'discountPct'));
  it('HST on discounted total', () => {
    eq(q.hstAmt, Math.round(q.effectiveMrr * 0.13), 'hstAmt');
  });
  it('MRR components sum', () => {
    const expected = q.userTotal + q.endpointTotal + q.adminFeeNet + q.ztNetTotal + q.voipTotal;
    eq(q.MRR, expected, 'MRR sum');
  });
});

describe('Per-user breakdown with admin waived', () => {
  const q = calculateQuote(makeState({
    users: 10, endpoints: 10, adminWaived: true
  }), DEFAULTS);

  it('perUserAllin = MRR / users', () => {
    eq(q.perUserAllin, q.MRR / 10, 'perUserAllin');
  });
  it('perUserSiteOvhd reflects waived admin', () => {
    eq(q.perUserSiteOvhd, Math.round((q.effectiveMrr - q.userTotal) / 10), 'perUserSiteOvhd');
  });
});

describe('1Password admin markup scales with users', () => {
  it('1 user: admin1PWM = round(9 * 0.10) = 1', () => {
    const q = calculateQuote(makeState({ users: 1, endpoints: 1, addPWM: true }), DEFAULTS);
    eq(q.admin1PWM, 1, 'admin1PWM');
  });

  it('50 users: admin1PWM = round(450 * 0.10) = 45', () => {
    const q = calculateQuote(makeState({ users: 50, endpoints: 1, addPWM: true }), DEFAULTS);
    eq(q.admin1PWM, 45, 'admin1PWM');
  });

  it('no 1PWM addon: admin1PWM = 0', () => {
    const q = calculateQuote(makeState({ users: 50, endpoints: 1, addPWM: false }), DEFAULTS);
    eq(q.admin1PWM, 0, 'admin1PWM');
  });
});

describe('HST with admin waived', () => {
  const q = calculateQuote(makeState({
    users: 10, endpoints: 10, hstEnabled: true, adminWaived: true
  }), DEFAULTS);

  it('HST computed on MRR without admin', () => {
    eq(q.hstAmt, Math.round(q.effectiveMrr * 0.13), 'hstAmt');
  });
  it('mrrWithHst = effectiveMrr + hstAmt', () => {
    eq(q.mrrWithHst, q.effectiveMrr + q.hstAmt, 'mrrWithHst');
  });
});

describe('Contract term does not affect BYOL rate', () => {
  ['m2m', '12mo', '24mo'].forEach(term => {
    it(`${term}: BYOL rate = 110`, () => {
      const q = calculateQuote(makeState({ users: 1, endpoints: 1, byol: true, contractTerm: term }), DEFAULTS);
      eq(q.baseUserRate, 110, 'baseUserRate');
    });
  });
});

describe('Discount amounts are rounded integers', () => {
  ['12mo', '24mo'].forEach(term => {
    it(`${term} discount is integer`, () => {
      const q = calculateQuote(makeState({ users: 7, endpoints: 7, contractTerm: term }), DEFAULTS);
      assert(Number.isInteger(q.discountAmt), `discountAmt should be integer, got ${q.discountAmt}`);
    });
  });
});

// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Export JSON Schema Validation ─────────────────
// ══════════════════════════════════════════════════════════════

describe('Export JSON payload schema (simulated)', () => {
  // Simulate the payload that exportQuoteJSON() builds from a quote result
  function buildExportPayload(q, overrides) {
    const o = overrides || {};
    const termMap = { m2m: 'Month-to-Month', '12mo': '12-Month', '24mo': '24-Month' };
    return {
      version: '1.1',
      quoteRef: o.quoteRef || 'SVS-20260315-1234',
      quoteDate: o.quoteDate || '2026-03-15',
      clientName: q.clientName || '',
      repName: o.repName || '',
      quoteNotes: o.quoteNotes || '',
      contractTerm: termMap[q.contractTerm] || 'Month-to-Month',
      licensing: q.byol ? 'BYOL' : 'M365-Included',
      users: q.users,
      endpoints: q.endpoints,
      servers: q.servers,
      addons: {
        extendedHours: q.addExtHours,
        passwordManager: q.addPWM,
        inkyPro: q.addINKY,
        zeroTrustUsers: q.addZT,
        baremetalBackup: q.addBMB,
        usbBlocking: q.addUSB
      },
      zeroTrustNetwork: {
        seats: q.ztSeats,
        routers: q.ztRouters
      },
      voip: {
        tier: q.voipSeats > 0 ? q.voipTier : null,
        seats: q.voipSeats,
        phoneHardware: q.addVoipPhone,
        faxLine: q.addVoipFax,
        currentPhoneBill: 0
      },
      adminWaived: q.adminWaived || false,
      onboardingWaived: false,
      onboardingManual: false,
      pricing: {
        baseMrr: q.MRR,
        discountPct: Math.round(q.discountPct * 100),
        discountAmt: q.discountAmt,
        effectiveMrr: q.effectiveMrr,
        annual: q.effectiveAnnual,
        oneTimeFee: q.oneTimeFee,
        hstIncluded: q.hstEnabled,
        hstAmt: q.hstAmt,
        mrrWithHst: q.mrrWithHst
      }
    };
  }

  const q = calculateQuote(makeState({
    users: 10, endpoints: 10, servers: 1,
    addPWM: true, addINKY: true, addZT: true,
    ztSeats: 5, ztRouters: 1,
    voipSeats: 8, voipTier: 'standard', addVoipPhone: true,
    contractTerm: '12mo', hstEnabled: true,
    clientName: 'Acme Corp'
  }), DEFAULTS);

  const payload = buildExportPayload(q);

  it('has version field = "1.1"', () => eq(payload.version, '1.1', 'version'));
  it('has quoteRef string', () => assert(typeof payload.quoteRef === 'string' && payload.quoteRef.length > 0, 'quoteRef'));
  it('has quoteDate string', () => assert(typeof payload.quoteDate === 'string', 'quoteDate'));
  it('clientName matches', () => eq(payload.clientName, 'Acme Corp', 'clientName'));
  it('contractTerm is display label', () => eq(payload.contractTerm, '12-Month', 'contractTerm'));
  it('licensing is M365-Included', () => eq(payload.licensing, 'M365-Included', 'licensing'));

  it('users/endpoints/servers are numbers', () => {
    assert(typeof payload.users === 'number', 'users');
    assert(typeof payload.endpoints === 'number', 'endpoints');
    assert(typeof payload.servers === 'number', 'servers');
  });

  it('addons object has all 6 boolean keys', () => {
    const keys = ['extendedHours', 'passwordManager', 'inkyPro', 'zeroTrustUsers', 'baremetalBackup', 'usbBlocking'];
    keys.forEach(k => {
      assert(typeof payload.addons[k] === 'boolean', `addons.${k} should be boolean`);
    });
  });

  it('zeroTrustNetwork has seats and routers', () => {
    assert(typeof payload.zeroTrustNetwork.seats === 'number', 'zt seats');
    assert(typeof payload.zeroTrustNetwork.routers === 'number', 'zt routers');
  });

  it('voip object has required fields', () => {
    assert(typeof payload.voip.seats === 'number', 'voip seats');
    assert(typeof payload.voip.phoneHardware === 'boolean', 'voip phone');
    assert(typeof payload.voip.faxLine === 'boolean', 'voip fax');
    assert(payload.voip.tier === 'standard', 'voip tier');
  });

  it('voip tier is null when no seats', () => {
    const q2 = calculateQuote(makeState({ users: 1, endpoints: 1, voipSeats: 0 }), DEFAULTS);
    const p2 = buildExportPayload(q2);
    eq(p2.voip.tier, null, 'voip tier null');
  });

  it('pricing object has all required fields', () => {
    const pricingKeys = ['baseMrr', 'discountPct', 'discountAmt', 'effectiveMrr', 'annual', 'oneTimeFee', 'hstIncluded', 'hstAmt', 'mrrWithHst'];
    pricingKeys.forEach(k => {
      assert(k in payload.pricing, `pricing.${k} missing`);
    });
  });

  it('pricing.discountPct is integer percentage', () => {
    eq(payload.pricing.discountPct, 3, 'discountPct as integer %');
  });

  it('pricing.baseMrr matches engine MRR', () => {
    eq(payload.pricing.baseMrr, q.MRR, 'baseMrr');
  });

  it('pricing.effectiveMrr matches engine', () => {
    eq(payload.pricing.effectiveMrr, q.effectiveMrr, 'effectiveMrr');
  });

  it('pricing.mrrWithHst matches engine', () => {
    eq(payload.pricing.mrrWithHst, q.mrrWithHst, 'mrrWithHst');
  });

  it('BYOL licensing label', () => {
    const q2 = calculateQuote(makeState({ users: 1, endpoints: 1, byol: true }), DEFAULTS);
    const p2 = buildExportPayload(q2);
    eq(p2.licensing, 'BYOL', 'licensing');
  });

  it('m2m contractTerm label', () => {
    const q2 = calculateQuote(makeState({ users: 1, endpoints: 1, contractTerm: 'm2m' }), DEFAULTS);
    const p2 = buildExportPayload(q2);
    eq(p2.contractTerm, 'Month-to-Month', 'contractTerm');
  });

  it('24mo contractTerm label', () => {
    const q2 = calculateQuote(makeState({ users: 1, endpoints: 1, contractTerm: '24mo' }), DEFAULTS);
    const p2 = buildExportPayload(q2);
    eq(p2.contractTerm, '24-Month', 'contractTerm');
  });

  it('repName is string', () => {
    assert(typeof payload.repName === 'string', 'repName should be string');
  });

  it('quoteNotes is string', () => {
    assert(typeof payload.quoteNotes === 'string', 'quoteNotes should be string');
  });

  it('repName populates from override', () => {
    const p2 = buildExportPayload(q, { repName: 'Jane Doe' });
    eq(p2.repName, 'Jane Doe', 'repName');
  });

  it('quoteNotes populates from override', () => {
    const p2 = buildExportPayload(q, { quoteNotes: 'Special pricing approved.' });
    eq(p2.quoteNotes, 'Special pricing approved.', 'quoteNotes');
  });
});

// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Persistence State Shape ───────────────────────
// ══════════════════════════════════════════════════════════════

describe('Persistence state shape (save round-trip)', () => {
  // Simulate the state shape that saveState() produces
  function buildPersistenceState(overrides) {
    return Object.assign({
      clientName: '',
      users: 0,
      endpoints: 0,
      servers: 0,
      byol: false,
      addExtHours: false,
      addPWM: false,
      addINKY: false,
      addZT: false,
      addUSB: false,
      addBMB: false,
      ztSeats: 0,
      ztRouters: 0,
      voipTier: 'basic',
      voipSeats: 0,
      addVoipPhone: false,
      addVoipFax: false,
      phoneBill: 0,
      contractTerm: 'm2m',
      hstEnabled: false,
      oneTimeFee: 0,
      adminWaived: false,
      onboardingWaived: false,
      onboardingManual: false,
      repName: '',
      quoteNotes: ''
    }, overrides);
  }

  const fullState = buildPersistenceState({
    clientName: 'Test Client',
    users: 15, endpoints: 12, servers: 2,
    byol: true, addExtHours: true, addPWM: true, addINKY: true,
    addZT: true, addUSB: true, addBMB: true,
    ztSeats: 5, ztRouters: 1,
    voipTier: 'premium', voipSeats: 10,
    addVoipPhone: true, addVoipFax: true, phoneBill: 250,
    contractTerm: '24mo', hstEnabled: true,
    oneTimeFee: 500, adminWaived: true,
    onboardingWaived: true, onboardingManual: false
  });

  it('serializes to valid JSON', () => {
    const json = JSON.stringify(fullState);
    const parsed = JSON.parse(json);
    assert(typeof parsed === 'object', 'valid JSON object');
  });

  it('round-trip preserves all string fields', () => {
    const parsed = JSON.parse(JSON.stringify(fullState));
    eq(parsed.clientName, 'Test Client', 'clientName');
    eq(parsed.voipTier, 'premium', 'voipTier');
    eq(parsed.contractTerm, '24mo', 'contractTerm');
  });

  it('round-trip preserves all numeric fields', () => {
    const parsed = JSON.parse(JSON.stringify(fullState));
    eq(parsed.users, 15, 'users');
    eq(parsed.endpoints, 12, 'endpoints');
    eq(parsed.servers, 2, 'servers');
    eq(parsed.ztSeats, 5, 'ztSeats');
    eq(parsed.ztRouters, 1, 'ztRouters');
    eq(parsed.voipSeats, 10, 'voipSeats');
    eq(parsed.phoneBill, 250, 'phoneBill');
    eq(parsed.oneTimeFee, 500, 'oneTimeFee');
  });

  it('round-trip preserves all boolean fields', () => {
    const parsed = JSON.parse(JSON.stringify(fullState));
    const boolKeys = ['byol', 'addExtHours', 'addPWM', 'addINKY', 'addZT',
      'addUSB', 'addBMB', 'addVoipPhone', 'addVoipFax',
      'hstEnabled', 'adminWaived', 'onboardingWaived', 'onboardingManual'];
    boolKeys.forEach(k => {
      assert(typeof parsed[k] === 'boolean', `${k} should be boolean after round-trip`);
    });
  });

  it('persistence state feeds engine correctly', () => {
    const q = calculateQuote(fullState, DEFAULTS);
    eq(q.users, 15, 'users');
    eq(q.byol, true, 'byol');
    eq(q.contractTerm, '24mo', 'contractTerm');
    assert(q.MRR > 0, 'MRR > 0');
  });

  it('default state produces valid zero quote', () => {
    const q = calculateQuote(buildPersistenceState(), DEFAULTS);
    eq(q.users, 0, 'users');
    eq(q.userTotal, 0, 'userTotal');
    eq(q.endpointTotal, 0, 'endpointTotal');
    eq(q.voipTotal, 0, 'voipTotal');
  });
});

// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Import Payload Mapping ────────────────────────
// ══════════════════════════════════════════════════════════════

describe('Import payload reverse-maps contract term correctly', () => {
  const termReverseMap = {
    'Month-to-Month': 'm2m',
    '12-Month': '12mo',
    '24-Month': '24mo'
  };

  it('Month-to-Month → m2m', () => eq(termReverseMap['Month-to-Month'], 'm2m', 'term'));
  it('12-Month → 12mo', () => eq(termReverseMap['12-Month'], '12mo', 'term'));
  it('24-Month → 24mo', () => eq(termReverseMap['24-Month'], '24mo', 'term'));
  it('unknown defaults to m2m', () => eq(termReverseMap['bogus'] || 'm2m', 'm2m', 'fallback'));
});

describe('Import → engine round-trip (full payload)', () => {
  // Build an export payload, then feed it back through the engine
  const original = calculateQuote(makeState({
    users: 20, endpoints: 18, servers: 2,
    byol: true, addPWM: true, addINKY: true,
    ztSeats: 3, ztRouters: 1,
    voipSeats: 12, voipTier: 'premium', addVoipPhone: true,
    contractTerm: '12mo', hstEnabled: true,
    clientName: 'Round Trip Inc'
  }), DEFAULTS);

  // Simulate import: map export payload fields back to engine state
  const imported = makeState({
    users: original.users,
    endpoints: original.endpoints,
    servers: original.servers,
    byol: original.byol,
    addPWM: original.addPWM,
    addINKY: original.addINKY,
    addExtHours: original.addExtHours,
    addZT: original.addZT,
    addUSB: original.addUSB,
    addBMB: original.addBMB,
    ztSeats: original.ztSeats,
    ztRouters: original.ztRouters,
    voipTier: original.voipTier,
    voipSeats: original.voipSeats,
    addVoipPhone: original.addVoipPhone,
    addVoipFax: original.addVoipFax,
    contractTerm: original.contractTerm,
    hstEnabled: original.hstEnabled,
    clientName: original.clientName,
    adminWaived: original.adminWaived
  });

  const reimported = calculateQuote(imported, DEFAULTS);

  it('MRR matches after round-trip', () => eq(reimported.MRR, original.MRR, 'MRR'));
  it('effectiveMrr matches', () => eq(reimported.effectiveMrr, original.effectiveMrr, 'effectiveMrr'));
  it('mrrWithHst matches', () => eq(reimported.mrrWithHst, original.mrrWithHst, 'mrrWithHst'));
  it('userTotal matches', () => eq(reimported.userTotal, original.userTotal, 'userTotal'));
  it('endpointTotal matches', () => eq(reimported.endpointTotal, original.endpointTotal, 'endpointTotal'));
  it('voipTotal matches', () => eq(reimported.voipTotal, original.voipTotal, 'voipTotal'));
  it('adminFeeNet matches', () => eq(reimported.adminFeeNet, original.adminFeeNet, 'adminFeeNet'));
  it('effectiveAnnual matches', () => eq(reimported.effectiveAnnual, original.effectiveAnnual, 'effectiveAnnual'));
});

// ══════════════════════════════════════════════════════════════
// ── EXPANSION: Quote Output Invariants ───────────────────────
// ══════════════════════════════════════════════════════════════

describe('Quote output invariants across random configs', () => {
  const configs = [
    { users: 1, endpoints: 1 },
    { users: 25, endpoints: 25, servers: 5, addPWM: true },
    { users: 0, endpoints: 0, voipSeats: 30, voipTier: 'premium' },
    { users: 50, endpoints: 50, addZT: true, ztSeats: 20, ztRouters: 5, contractTerm: '24mo', hstEnabled: true },
    { users: 10, endpoints: 10, adminWaived: true, contractTerm: '12mo' },
    { users: 3, endpoints: 3, byol: true, addExtHours: true, addINKY: true }
  ];

  configs.forEach((cfg, i) => {
    const q = calculateQuote(makeState(cfg), DEFAULTS);

    it(`config #${i + 1}: effectiveMrr = MRR - discountAmt`, () => {
      eq(q.effectiveMrr, q.MRR - q.discountAmt, 'effectiveMrr');
    });

    it(`config #${i + 1}: effectiveAnnual = effectiveMrr * 12`, () => {
      eq(q.effectiveAnnual, q.effectiveMrr * 12, 'effectiveAnnual');
    });

    it(`config #${i + 1}: mrrWithHst = effectiveMrr + hstAmt`, () => {
      eq(q.mrrWithHst, q.effectiveMrr + q.hstAmt, 'mrrWithHst');
    });

    it(`config #${i + 1}: all monetary values ≥ 0`, () => {
      assert(q.MRR >= 0, 'MRR >= 0');
      assert(q.effectiveMrr >= 0, 'effectiveMrr >= 0');
      assert(q.hstAmt >= 0, 'hstAmt >= 0');
      assert(q.mrrWithHst >= 0, 'mrrWithHst >= 0');
    });
  });
});

// ── Results ──────────────────────────────────────────────────
console.log(`\n${'─'.repeat(50)}`);
if (_failed === 0) {
  console.log(`\x1b[32m  All ${_passed} tests passed.\x1b[0m\n`);
  process.exit(0);
} else {
  console.log(`\x1b[31m  ${_failed} of ${_passed + _failed} tests failed.\x1b[0m\n`);
  process.exit(1);
}
