/* ============================================================
   Partner ref capture (A1 Session 3).

   A partner shares vyndr.app/?ref=CODE. On first visit we set a
   FIRST-PARTY cookie `vyndr_ref` (90 days). Signup forwards the code
   into Supabase user metadata as `partner_ref`, which is what the
   internal /api/partners/report/:code attribution reads.

   Attribution model = FIRST TOUCH: an existing vyndr_ref cookie is
   never overwritten by a later ?ref= visit. Codes are sanitized
   (A-Z 0-9 - _, max 32) and stored UPPERCASE — the same convention
   as Stripe promo codes (see docs/PARTNERS.md).

   CommonJS so the plain-JS Jest suite exercises it directly.
   ============================================================ */

const REF_COOKIE = 'vyndr_ref';
const REF_TTL_DAYS = 90;

/** Sanitize a raw code → canonical UPPERCASE code, or null. */
function sanitizeRefCode(raw) {
  const s = String(raw == null ? '' : raw).trim().toUpperCase();
  if (!s || s.length > 32) return null;
  return /^[A-Z0-9_-]+$/.test(s) ? s : null;
}

/** Pull a sanitized ?ref= code out of a location.search string. */
function parseRefFromSearch(search) {
  try {
    const params = new URLSearchParams(search || '');
    return sanitizeRefCode(params.get('ref'));
  } catch {
    return null;
  }
}

/** Read the vyndr_ref value out of a document.cookie string. */
function readRefCookie(cookieStr) {
  const parts = String(cookieStr == null ? '' : cookieStr).split(';');
  for (const part of parts) {
    const [name, ...rest] = part.split('=');
    if (name && name.trim() === REF_COOKIE) {
      return sanitizeRefCode(decodeURIComponent(rest.join('=').trim()));
    }
  }
  return null;
}

/** Build the Set-Cookie string for a code (first-party, 90d, lax). */
function buildRefCookie(code, { days = REF_TTL_DAYS, secure = false } = {}) {
  const clean = sanitizeRefCode(code);
  if (!clean) return null;
  const maxAge = Math.round(days * 24 * 60 * 60);
  return `${REF_COOKIE}=${encodeURIComponent(clean)}; Max-Age=${maxAge}; Path=/; SameSite=Lax${secure ? '; Secure' : ''}`;
}

/**
 * Capture ?ref=CODE from the current visit into the cookie.
 * First-touch: no-op when the cookie already exists. `win` is
 * injectable for tests (defaults to the browser window).
 * Returns the code that was captured, or null.
 */
function captureRef(win) {
  const w = win || (typeof window !== 'undefined' ? window : null);
  if (!w || !w.document || !w.location) return null;
  const code = parseRefFromSearch(w.location.search);
  if (!code) return null;
  if (readRefCookie(w.document.cookie)) return null; // first touch wins
  const cookie = buildRefCookie(code, { secure: w.location.protocol === 'https:' });
  if (!cookie) return null;
  w.document.cookie = cookie;
  return code;
}

module.exports = {
  REF_COOKIE,
  REF_TTL_DAYS,
  sanitizeRefCode,
  parseRefFromSearch,
  readRefCookie,
  buildRefCookie,
  captureRef,
};
