/* ============================================================
   BOOK IT deep-link builder (A1 Session 3).

   Builds a per-book player-prop hand-off URL:
     buildBookLink({ book, player, sport, state? }) → { url, tracking } | null

   - Base hosts mirror the scan page's legacy SPORTSBOOKS list; the
     organic URL shape (`/?search=<player>`) is the shape the product
     has always shipped.
   - The affiliate layer reads web/src/lib/affiliateConfig.js. Every
     book is `enabled: false` today (no program approved), so links are
     clean + organic. Flipping a book's config produces a tracked URL —
     no component changes needed.
   - Every rendered book anchor must carry BOOK_LINK_REL
     ("sponsored noopener noreferrer") — sponsored is required for
     affiliate compliance and harmless on organic links.
   - Unknown book → null. Absent beats wrong.

   CommonJS so the plain-JS Jest suite requires it AND .tsx imports it
   (allowJs) — same pattern as slateAdapter/books/playerName.
   ============================================================ */

const { bookKey } = require('./books');
const { AFFILIATE_CONFIG } = require('./affiliateConfig');

/** rel attribute every sportsbook anchor must render. */
const BOOK_LINK_REL = 'sponsored noopener noreferrer';

/** The books we build deep links for (order = display order). */
const SUPPORTED_BOOKS = [
  { id: 'draftkings', label: 'DraftKings', host: 'sportsbook.draftkings.com' },
  { id: 'fanduel', label: 'FanDuel', host: 'sportsbook.fanduel.com' },
  { id: 'betmgm', label: 'BetMGM', host: 'sports.betmgm.com' },
  { id: 'caesars', label: 'Caesars', host: 'sportsbook.caesars.com' },
  // BetRivers routes by state subdomain (mi.betrivers.com); www works
  // as the state-agnostic landing.
  { id: 'betrivers', label: 'BetRivers', host: 'www.betrivers.com' },
];

const HOSTS = SUPPORTED_BOOKS.reduce((m, b) => {
  m[b.id] = b.host;
  return m;
}, {});

/** Canonicalize any book spelling ("DK", "DraftKings", "draftkings") →
 *  a SUPPORTED_BOOKS id, or null when it isn't a book we link to. */
function resolveBookId(book) {
  const k = bookKey(book);
  return HOSTS[k] ? k : null;
}

/** Two-letter US state code or null — anything else is dropped, never guessed. */
function cleanState(state) {
  const s = String(state == null ? '' : state).trim().toLowerCase();
  return /^[a-z]{2}$/.test(s) ? s : null;
}

/**
 * Build the deep link for one book + player.
 *
 * @param {{ book: string, player: string, sport?: string, state?: string }} input
 * @param {object} [config] — injectable for tests; defaults to AFFILIATE_CONFIG.
 * @returns {{ url: string, tracking: boolean } | null}
 */
function buildBookLink(input, config = AFFILIATE_CONFIG) {
  const { book, player, state } = input || {};
  const id = resolveBookId(book);
  if (!id || !player) return null;

  let host = HOSTS[id];
  if (id === 'betrivers') {
    const st = cleanState(state);
    if (st) host = `${st}.betrivers.com`;
  }

  const url = new URL(`https://${host}/`);
  url.searchParams.set('search', String(player));

  // Affiliate layer — only when the operator flipped this book on AND
  // real (non-empty) params exist. Otherwise the link stays organic.
  let tracking = false;
  const cfg = config && config[id];
  if (cfg && cfg.enabled === true && cfg.params && typeof cfg.params === 'object') {
    for (const [key, value] of Object.entries(cfg.params)) {
      const v = String(value == null ? '' : value).trim();
      if (!key || !v) continue; // never emit an empty/fabricated id
      url.searchParams.set(key, v);
      tracking = true;
    }
  }

  return { url: url.toString(), tracking };
}

module.exports = { buildBookLink, resolveBookId, SUPPORTED_BOOKS, BOOK_LINK_REL };
