/* Shared search vocabulary: scopes, typeahead index, placeholders, URL helpers. Castle Connolly IA (v2). */
(function () {
  const SCOPES = [
    { id: 'ask', label: 'Ask', icon: 'Sparkle', placeholder: 'Ask anything, or find a Top Doctor, dentist or hospital', tag: 'Ask' },
    { id: 'doctors', label: 'Doctors', icon: 'Stethoscope', placeholder: 'Search by specialty, name, condition or treatment', tag: 'Doctor' },
    { id: 'dentists', label: 'Dentists', icon: 'Tooth', placeholder: 'Search by dental specialty, name, condition or treatment', tag: 'Dentist' },
    { id: 'hospitals', label: 'Hospitals', icon: 'MapPin', placeholder: 'Procedure, hospital name, or location', tag: 'Hospital' },
    { id: 'topics', label: 'Topics', icon: 'Book', placeholder: 'Condition, procedure, specialty, or appointment guide', tag: 'Topic' },
  ];
  const HERO_SCOPES = SCOPES.filter((s) => s.id !== 'ask');

  const PLACEHOLDERS = [
    'Best pediatrician within 10 miles of me who takes Blue Cross and sees new patients',
    'Top Doctor cardiologists in Boston, MA who take Aetna',
    'Which Boston hospitals are Castle Connolly Top Hospitals for heart care?',
    'Top dentist for my 7-year-old who takes Delta Dental',
    'Should I see the top-rated cardiologist at a community hospital or one at Mass General?',
  ];

  /* Landing suggestions: four signed out, four signed in. `short` keeps each on one line; `text` is the query asked. */
  const RECOMMENDED_ROWS = [
    { text: 'Top Doctor cardiologists in Boston, MA who take Aetna', short: 'Top Doctor cardiologists in Boston who take Aetna', to: 'CARDIO_AETNA', signedOut: true, signedIn: true },
    { text: 'Best pediatrician within 10 miles of me who takes Blue Cross and sees new patients', short: 'Best pediatrician within 10 miles who takes Blue Cross and sees new patients', to: 'PEDIATRICIAN_BCBS', signedOut: true },
    { text: 'Which Boston hospitals are Castle Connolly Top Hospitals for heart care?', short: 'Which Boston hospitals are Top Hospitals for heart care?', to: 'HOSPITALS_CARDIAC', signedOut: true },
    { text: 'Top dentist for my 7-year-old who takes Delta Dental', short: 'Top dentist for my 7-year-old who takes Delta Dental', to: 'DENTIST_MAYA', signedOut: true, signedIn: true },
    { text: 'Which Top Doctor cardiologists near me take my plan and can see me this month?', short: 'Which Top Doctor cardiologists near me take my plan this month?', to: 'CARDIO_MY_PLAN', user: true, signedIn: true },
    { text: 'Should I see the top-rated cardiologist at a community hospital or one at Mass General?', short: 'Top cardiologist at a community hospital, or one at Mass General?', to: 'COMPARE_HOSPITAL', user: true, signedIn: true },
  ];
  const RECOMMENDED = RECOMMENDED_ROWS.map((r) => r.text);

  /* Typeahead and prompts are generated from the flows and their aliases, so every suggestion lands on an answer. */
  const FLOWS = {
    CARDIO_AETNA: { scope: 'doctors', aliases: ['Top Doctor cardiologists in Boston, MA who take Aetna', 'Top Doctor cardiologists in Boston who take Aetna', 'Top Doctors in cardiology near me', 'Cardiologist who takes Aetna in Boston', 'Heart doctor near Boston'] },
    PEDIATRICIAN_BCBS: { scope: 'doctors', aliases: ['Best pediatrician within 10 miles of me who takes Blue Cross and sees new patients', 'Pediatrician near me accepting new patients', 'Pediatrician who takes Blue Cross Blue Shield'] },
    CARDIO_MY_PLAN: { scope: 'doctors', user: true, aliases: ['Which Top Doctor cardiologists near me take my plan and can see me this month?', 'Which Top Doctor cardiologists near me take my plan this month?', 'Cardiologists on my plan with appointments this month'] },
    COMPARE_HOSPITAL: { scope: 'ask', user: true, aliases: ['Should I see the top-rated cardiologist at a community hospital or one at Mass General?', 'Compare a community hospital cardiologist with one at Mass General'] },
    DENTIST_MAYA: { scope: 'dentists', aliases: ['Top dentist for my 7-year-old who takes Delta Dental', 'Pediatric dentist near me who takes Delta Dental', 'Top Dentists in Boston for kids'] },
    HOSPITALS_CARDIAC: { scope: 'hospitals', aliases: ['Which Boston hospitals are Castle Connolly Top Hospitals for heart care?', 'Which Boston hospitals are Top Hospitals for heart care?', 'Top Hospitals near Boston', 'Which hospitals have the most Top Doctors?', 'Hospitals ranked for cardiac care'] },
    CARDIO_TELEHEALTH: { scope: 'doctors', aliases: ['Which of these cardiologists offer telehealth?', 'Cardiologists near me who offer telehealth'] },
    CARDIO_EVENING: { scope: 'doctors', aliases: ['Which have evening appointments?', 'Cardiologists with evening appointments near me'] },
    PEDIATRICIAN_FIRST_VISIT: { scope: 'topics', aliases: ['What should I bring to a first pediatrician visit?'] },
    DENTIST_FIRST_VISIT: { scope: 'topics', aliases: ['What happens at a child\u2019s first dental visit?'] },
    WHAT_IS_TOP_DOCTOR: { scope: 'topics', aliases: ['How are Castle Connolly Top Doctors selected?', 'What does Top Doctor mean?'] },
    BOOK_ONLINE: { scope: 'topics', aliases: ['How does booking online work?', 'Can I book an appointment online?'] },
  };
  const SEARCH_INDEX = Object.entries(FLOWS).flatMap(([to, f]) => f.aliases.map((text) => ({ text, scope: f.scope, to })));

  /* Try asking, per scope pill. Personal rows appear only under Answer and Doctors when signed in. */
  const SCOPE_PROMPTS = {
    ask: { out: ['CARDIO_AETNA', 'PEDIATRICIAN_BCBS', 'HOSPITALS_CARDIAC', 'DENTIST_MAYA'], in: ['CARDIO_AETNA', 'DENTIST_MAYA', 'CARDIO_MY_PLAN', 'COMPARE_HOSPITAL'] },
    doctors: { out: ['CARDIO_AETNA', 'PEDIATRICIAN_BCBS', 'CARDIO_TELEHEALTH', 'CARDIO_EVENING'], in: ['CARDIO_AETNA', 'PEDIATRICIAN_BCBS', 'CARDIO_MY_PLAN', 'COMPARE_HOSPITAL'] },
    dentists: { out: ['DENTIST_MAYA', 'DENTIST_MAYA:1', 'DENTIST_MAYA:2', 'DENTIST_FIRST_VISIT'], in: ['DENTIST_MAYA', 'DENTIST_MAYA:1', 'DENTIST_MAYA:2', 'DENTIST_FIRST_VISIT'] },
    hospitals: { out: ['HOSPITALS_CARDIAC:1', 'HOSPITALS_CARDIAC:2', 'HOSPITALS_CARDIAC:3'], in: ['HOSPITALS_CARDIAC:1', 'HOSPITALS_CARDIAC:2', 'HOSPITALS_CARDIAC:3'] },
    topics: { out: ['WHAT_IS_TOP_DOCTOR', 'PEDIATRICIAN_FIRST_VISIT', 'DENTIST_FIRST_VISIT', 'BOOK_ONLINE'], in: ['WHAT_IS_TOP_DOCTOR', 'PEDIATRICIAN_FIRST_VISIT', 'DENTIST_FIRST_VISIT', 'BOOK_ONLINE'] },
  };
  /* 'KEY' uses the flow's canonical query; 'KEY:n' uses alias n. Returns { text, short, to, scope }. */
  function promptsFor(scopeId, user) {
    const list = (SCOPE_PROMPTS[scopeId] || SCOPE_PROMPTS.ask)[user ? 'in' : 'out'];
    return list.map((id) => {
      const [key, n] = id.split(':'); const f = FLOWS[key]; const text = f.aliases[Number(n || 0)];
      const rec = RECOMMENDED_ROWS.find((r) => r.to === key && r.text === text);
      return { text, short: rec ? rec.short : text, to: key, scope: f.scope, user: !!f.user };
    });
  }

  const DEMO_QUERIES = new Map(SEARCH_INDEX.map((r) => [r.text.toLowerCase(), r.to]));

  function getSuggestions(text, scopeId, limit) {
    const q = (text || '').trim().toLowerCase();
    if (!q) return [];
    const words = q.split(/\s+/).filter(Boolean);
    const ranked = SEARCH_INDEX.map((r) => {
      const lo = r.text.toLowerCase();
      let score = 0;
      if (lo.startsWith(q)) score = 100;
      else if (lo.includes(q)) score = 60;
      else {
        const hits = words.filter((w) => lo.includes(w)).length;
        if (hits === words.length) score = 40 + hits;
        else if (hits > 0 && hits >= Math.ceil(words.length / 2)) score = 10 + hits;
      }
      if (score && scopeId && scopeId !== 'ask' && r.scope === scopeId) score += 25;
      return { ...r, score };
    }).filter((r) => r.score > 0);
    ranked.sort((a, b) => b.score - a.score || a.text.length - b.text.length);
    const seen = new Set();
    return ranked.filter((r) => (seen.has(r.text) ? false : seen.add(r.text))).slice(0, limit || 6);
  }

  /* Resolve free text to a template key. Ordered most specific → generic. Returns null for anything off script. */
  function resolveKey(q) {
    const ql = (q || '').toLowerCase();
    const exact = DEMO_QUERIES.get(ql.trim());
    if (exact) return exact;
    const has = (...kw) => kw.some((k) => ql.includes(k));
    if (has('community hospital', 'mass general', 'or one at', 'compare')) return 'COMPARE_HOSPITAL';
    if (has('book online', 'booking', 'zocdoc')) return 'BOOK_ONLINE';
    if (has('what does top doctor', 'top doctor mean', 'how are', 'selected', 'methodology')) return 'WHAT_IS_TOP_DOCTOR';
    if (has('telehealth', 'video visit', 'virtual')) return 'CARDIO_TELEHEALTH';
    if (has('evening', 'after work', 'after 5')) return 'CARDIO_EVENING';
    if (has('first dental', 'first visit') && has('dent', 'tooth', 'teeth')) return 'DENTIST_FIRST_VISIT';
    if (has('first visit', 'first appointment', 'what to bring') && has('pediatric', 'child', 'kid')) return 'PEDIATRICIAN_FIRST_VISIT';
    if (has('dentist', 'dental', 'teeth', 'tooth', 'orthodont')) return 'DENTIST_MAYA';
    if (has('pediatric', 'kids doctor', 'child doctor', 'children', 'my child', 'my son', 'my daughter')) return 'PEDIATRICIAN_BCBS';
    if (has('hospital') && has('heart', 'cardiac', 'top hospital', 'best hospital', 'ranked')) return 'HOSPITALS_CARDIAC';
    if (has('my plan', 'this month', 'take my', 'my insurance')) return 'CARDIO_MY_PLAN';
    if (has('cardiolog', 'heart', 'aetna')) return 'CARDIO_AETNA';
    return null;
  }

  /* Structured form → template. Specialty must match; insurance and everything else become filters. */
  function resolveStructured(form) {
    const D = window.EHData || {};
    const spec = (form.specialty || '').toLowerCase();
    if (!spec) return null;
    const rows = Object.values(D).filter((t) => t && t.structured && t.key);
    const bySpec = rows.filter((t) => (t.structured.specialty || '').toLowerCase() === spec);
    if (!bySpec.length) return null;
    const exact = bySpec.find((t) => (t.structured.insurance || '') === (form.insurance || ''));
    return (exact || bySpec[0]).key;
  }

  const scale = { physicians: '1.3M+', dentists: '250K+', hospitals: '6K+' };

  /* Nav variant lives in the path on Vercel (/top, /top/search via rewrites) and in ?nav=top locally. */
  const cleanUrls = !/^(localhost|127\.0\.0\.1)$/.test(location.hostname);
  const navOf = () => (new URLSearchParams(location.search).get('nav') === 'top' || /^\/top(\/|$)/.test(location.pathname)) ? 'top' : 'rail';
  const homeUrl = (nav) => cleanUrls ? (nav === 'top' ? '/top' : '/') : ('/' + (nav === 'top' ? '?nav=top' : ''));
  const searchUrl = (nav, params) => {
    const p = new URLSearchParams(params || {});
    if (!cleanUrls && nav === 'top') p.set('nav', 'top');
    const qs = p.toString();
    return (cleanUrls ? (nav === 'top' ? '/top/search' : '/search') : '/search/') + (qs ? '?' + qs : '');
  };

  window.EHSearch = { SCOPES, HERO_SCOPES, PLACEHOLDERS, RECOMMENDED, RECOMMENDED_ROWS, FLOWS, SEARCH_INDEX, SCOPE_PROMPTS, promptsFor, DEMO_QUERIES, getSuggestions, resolveKey, resolveStructured, scale, cleanUrls, navOf, homeUrl, searchUrl };
})();
