(() => {
  const architectureHotspots = [
    { id: 'workflow', label: 'Workflow layer details', top: 9.9, left: 1.6, width: 93.4, height: 11 },
    { id: 'apps', label: 'Applications layer details', top: 22.9, left: 1.6, width: 93.4, height: 11 },
    { id: 'agents', label: 'Banking agents layer details', top: 35.8, left: 1.6, width: 93.4, height: 21.1 },
    { id: 'core', label: 'Core services layer details', top: 58.7, left: 1.6, width: 93.4, height: 19 },
    { id: 'gateways', label: 'Integration services layer details', top: 79.8, left: 1.6, width: 93.4, height: 10.9 },
  ];

  const embedded = document.getElementById('sections-data');
  const data = JSON.parse(embedded.textContent);
  const byId = new Map(data.sections.map((section) => [section.id, section]));
  const currentSectionId = document.body.dataset.sectionId || 'overview';
  const currentSection = byId.get(currentSectionId) || data.sections[0];
  const state = { query: '' };
  const nav = document.getElementById('sidebar-nav');
  const root = document.getElementById('sections-root');
  const search = document.getElementById('site-search');
  const modal = document.getElementById('callout-modal');
  const modalPanel = modal.querySelector('.modal');
  const modalContent = document.getElementById('modal-content');
  const closeModalButton = modal.querySelector('[data-close-modal]');
  const moduleNamePattern = /(?:`|\*\*)?((?:HB_(?:AccountServices|Backoffice|BankGateway|CommonServices|CommunicationAgent|CreditGateway|DataSync|DocumentIntelligenceAgent|KYCServices|LoanOriginationAgent|LoanOriginationWorkflow|LoanServices|Mobile|PolicyAndSupportAgent|RegulatoryGateway|RiskFraudAssessmentAgent|SampleData|Web)|S(?:ol|OL)_CommonServices))(?:`|\*\*)?/g;
  const markdownStrongPattern = /\*\*([^*]+)\*\*/g;

  render();

  function pageHref(sectionOrId) {
    const id = typeof sectionOrId === 'string' ? sectionOrId : sectionOrId.id;
    return id === 'overview' ? 'index.html' : `${id}.html`;
  }

  function normalize(value) {
    return String(value || '').toLowerCase();
  }

  function sectionText(section) {
    return normalize([
      section.title,
      section.group,
      section.summary,
      section.summaryHtml || '',
      ...(section.keyPoints || []),
      ...(section.orderedItems || []),
      section.bodyText || '',
      section.htmlContent || '',
    ].join(' '));
  }

  function filteredSections() {
    const query = normalize(state.query).trim();
    if (!query) return data.sections;
    return data.sections.filter((section) => sectionText(section).includes(query));
  }

  function render() {
    renderNav(filteredSections());
    renderSection(currentSection);
  }

  function renderNav(sections) {
    nav.textContent = '';
    if (!sections.length) {
      const empty = document.createElement('p');
      empty.className = 'nav-empty';
      empty.textContent = 'No sections match your search.';
      nav.appendChild(empty);
      return;
    }

    const groups = groupBy(sections, 'group');
    Object.entries(groups).forEach(([group, items]) => {
      const heading = document.createElement('div');
      heading.className = 'nav-group-title';
      heading.textContent = group;
      nav.appendChild(heading);
      items.forEach((section) => {
        const link = document.createElement('a');
        link.href = pageHref(section);
        link.textContent = section.title;
        link.dataset.sectionId = section.id;
        if (section.id === currentSection.id) {
          link.classList.add('active');
          link.setAttribute('aria-current', 'page');
        }
        nav.appendChild(link);
      });
    });
  }

  function renderSection(section) {
    root.textContent = '';
    const article = document.createElement('article');
    article.className = 'doc-section';
    article.id = section.id;
    article.tabIndex = -1;

    article.appendChild(renderSectionHeader(section));
    const summary = document.createElement('p');
    summary.className = 'summary';
    if (section.summaryHtml) {
      summary.innerHTML = section.summaryHtml;
      formatModuleNames(summary);
    } else {
      appendFormattedText(summary, section.summary);
    }
    article.appendChild(summary);

    if (section.placeholder) {
      const placeholder = document.createElement('p');
      placeholder.className = 'badge placeholder';
      placeholder.textContent = 'More detail to be added';
      article.appendChild(placeholder);
    }

    const imageWithOrderedItems = section.image && section.imageLayout === 'ordered-side-by-side';

    if (section.architecture) {
      article.appendChild(renderArchitecture(section));
    } else if (section.image && section.imageLayout === 'side-by-side') {
      article.appendChild(renderImageAndPoints(section));
    } else if (section.image && !imageWithOrderedItems) {
      article.appendChild(renderImage(section.image, `${section.title} slide`));
    }

    if (section.bodyText) {
      article.appendChild(renderBodyText(section.bodyText));
    }

    if (imageWithOrderedItems && section.orderedItems && section.orderedItems.length) {
      article.appendChild(renderImageAndOrderedItems(section));
    } else if (section.orderedItems && section.orderedItems.length) {
      const orderedList = document.createElement('ol');
      orderedList.className = 'ordered-points';
      section.orderedItems.forEach((point) => {
        const li = document.createElement('li');
        appendFormattedText(li, point);
        orderedList.appendChild(li);
      });
      article.appendChild(orderedList);
    }

    if (section.architecture && section.keyPoints && section.keyPoints.length) {
      article.appendChild(renderKeyPoints(section.keyPoints));
    }

    if (section.htmlContent) {
      const customContent = document.createElement('div');
      customContent.className = 'section-html-content';
      customContent.innerHTML = section.htmlContent;
      formatModuleNames(customContent);
      article.appendChild(customContent);
    }

    if (!section.architecture && section.imageLayout !== 'side-by-side' && section.keyPoints && section.keyPoints.length) {
      if (section.keyPointsTitle) {
        article.appendChild(renderSubTitle(section.keyPointsTitle));
      }
      article.appendChild(renderKeyPoints(section.keyPoints));
    }

    if (section.integrationPattern) {
      article.appendChild(renderIntegrationPattern(section.integrationPattern));
    }

    article.appendChild(renderRelated(section));
    article.appendChild(renderPrevNext(section));
    root.appendChild(article);
  }

  function renderSectionHeader(section) {
    const header = document.createElement('div');
    header.className = 'section-header';
    const titleWrap = document.createElement('div');
    titleWrap.className = 'section-title-row';
    const number = document.createElement('span');
    number.className = 'section-number';
    number.textContent = String(data.sections.findIndex((item) => item.id === section.id) + 1);
    const title = document.createElement('h2');
    title.textContent = section.title;
    titleWrap.append(number, title);
    const anchor = document.createElement('a');
    anchor.href = pageHref(section);
    anchor.textContent = '#';
    anchor.setAttribute('aria-label', `Deep link to ${section.title}`);
    header.append(titleWrap, anchor);
    return header;
  }

  function renderBodyText(text) {
    const wrap = document.createElement('div');
    wrap.className = 'body-text';
    text
      .split(/\n\s*\n/)
      .map((paragraph) => paragraph.trim())
      .filter(Boolean)
      .forEach((paragraph) => {
        const bulletLines = paragraph
          .split('\n')
          .map((line) => line.trim())
          .filter(Boolean);
        if (bulletLines.length && bulletLines.every((line) => line.startsWith('- '))) {
          const list = document.createElement('ul');
          list.className = 'key-points';
          bulletLines.forEach((line) => {
            const item = document.createElement('li');
            appendFormattedText(item, line.replace(/^-\s+/, ''));
            list.appendChild(item);
          });
          wrap.appendChild(list);
          return;
        }

        const bodyText = document.createElement('p');
        appendFormattedText(bodyText, paragraph);
        wrap.appendChild(bodyText);
      });
    return wrap;
  }

  function appendFormattedText(element, text) {
    const value = String(text || '');
    let cursor = 0;
    markdownStrongPattern.lastIndex = 0;
    let match = markdownStrongPattern.exec(value);

    while (match) {
      if (match.index > cursor) {
        appendModuleFormattedText(element, value.slice(cursor, match.index));
      }
      const strong = document.createElement('strong');
      strong.textContent = match[1];
      element.appendChild(strong);
      cursor = match.index + match[0].length;
      match = markdownStrongPattern.exec(value);
    }

    if (cursor < value.length) {
      appendModuleFormattedText(element, value.slice(cursor));
    }
  }

  function appendModuleFormattedText(element, text) {
    const value = String(text || '');
    let cursor = 0;
    moduleNamePattern.lastIndex = 0;
    value.replace(moduleNamePattern, (match, moduleName, offset) => {
      if (offset > cursor) {
        element.appendChild(document.createTextNode(value.slice(cursor, offset)));
      }
      const strong = document.createElement('strong');
      strong.textContent = moduleName;
      element.appendChild(strong);
      cursor = offset + match.length;
      return match;
    });
    if (cursor < value.length) {
      element.appendChild(document.createTextNode(value.slice(cursor)));
    }
  }

  function formatModuleNames(rootElement) {
    const walker = document.createTreeWalker(rootElement, NodeFilter.SHOW_TEXT, {
      acceptNode(node) {
        const parent = node.parentElement;
        if (!parent || parent.closest('code, pre, script, style, strong')) {
          return NodeFilter.FILTER_REJECT;
        }
        moduleNamePattern.lastIndex = 0;
        markdownStrongPattern.lastIndex = 0;
        return moduleNamePattern.test(node.nodeValue) || markdownStrongPattern.test(node.nodeValue)
          ? NodeFilter.FILTER_ACCEPT
          : NodeFilter.FILTER_REJECT;
      },
    });
    const nodes = [];
    while (walker.nextNode()) nodes.push(walker.currentNode);
    nodes.forEach((node) => {
      const fragment = document.createDocumentFragment();
      appendFormattedText(fragment, node.nodeValue);
      node.replaceWith(fragment);
    });
  }

  function renderSubTitle(text) {
    const title = document.createElement('h3');
    title.className = 'section-subtitle';
    title.textContent = text;
    return title;
  }

  function renderImage(src, alt) {
    const wrap = document.createElement('figure');
    wrap.className = 'slide-image-wrap';
    const img = document.createElement('img');
    img.className = 'slide-image';
    img.src = src;
    img.alt = alt;
    wrap.appendChild(img);
    return wrap;
  }

  function renderKeyPoints(points) {
    const list = document.createElement('ul');
    list.className = 'key-points';
    points.forEach((point) => {
      const li = document.createElement('li');
      appendFormattedText(li, point);
      list.appendChild(li);
    });
    return list;
  }

  function renderImageAndPoints(section) {
    const wrap = document.createElement('div');
    wrap.className = 'image-points-layout';
    const sideCount = Number.isInteger(section.sidePointCount) ? section.sidePointCount : 4;
    const sidePoints = section.keyPoints.slice(0, sideCount);
    const remainingPoints = section.keyPoints.slice(sideCount);
    wrap.appendChild(renderImage(section.image, `${section.title} slide`));
    const side = document.createElement('div');
    side.className = 'image-points-side';
    side.appendChild(renderKeyPoints(sidePoints));
    wrap.appendChild(side);

    if (remainingPoints.length) {
      if (section.sideRemainderTitle) {
        const secondary = document.createElement('div');
        secondary.className = 'image-points-secondary';
        secondary.appendChild(renderSubTitle(section.sideRemainderTitle));
        secondary.appendChild(renderKeyPoints(remainingPoints));
        side.appendChild(secondary);
      } else {
        const below = document.createElement('div');
        below.className = 'image-points-below';
        below.appendChild(renderKeyPoints(remainingPoints));
        wrap.appendChild(below);
      }
    }

    return wrap;
  }

  function renderImageAndOrderedItems(section) {
    const wrap = document.createElement('div');
    wrap.className = 'image-ordered-layout';
    const sideCount = Number.isInteger(section.orderedSideCount)
      ? section.orderedSideCount
      : section.orderedItems.length;
    if (sideCount <= 0) {
      wrap.classList.add('image-first-full');
      wrap.appendChild(renderImage(section.image, `${section.title} workflow`));
      const below = document.createElement('div');
      below.className = 'image-points-below';
      below.appendChild(renderOrderedList(section.orderedItems));
      wrap.appendChild(below);
      return wrap;
    }
    const sideItems = section.orderedItems.slice(0, sideCount);
    const remainingItems = section.orderedItems.slice(sideCount);
    wrap.appendChild(renderImage(section.image, `${section.title} workflow`));
    wrap.appendChild(renderOrderedList(sideItems));

    if (remainingItems.length) {
      const below = document.createElement('div');
      below.className = 'image-points-below';
      below.appendChild(renderOrderedList(remainingItems, sideCount + 1));
      wrap.appendChild(below);
    }

    return wrap;
  }

  function renderOrderedList(items, start = 1) {
    const orderedList = document.createElement('ol');
    orderedList.className = 'ordered-points';
    if (start > 1) {
      orderedList.start = start;
    }
    items.forEach((point) => {
      const li = document.createElement('li');
      appendFormattedText(li, point);
      orderedList.appendChild(li);
    });
    return orderedList;
  }

  function renderIntegrationPattern(pattern) {
    const wrap = document.createElement('div');
    wrap.className = 'integration-pattern-layout';
    wrap.appendChild(renderImage(pattern.image, pattern.title));

    const copy = document.createElement('div');
    copy.className = 'integration-pattern-copy';
    const title = document.createElement('h3');
    title.textContent = pattern.title;
    const description = document.createElement('p');
    appendFormattedText(description, pattern.description);
    copy.append(title, description, renderKeyPoints(pattern.points || []));
    wrap.appendChild(copy);

    return wrap;
  }

  function renderArchitecture(section) {
    const grid = document.createElement('div');
    grid.className = 'architecture-grid';
    const figure = document.createElement('figure');
    figure.className = 'architecture-image-wrap architecture-image-layout';
    const stage = document.createElement('div');
    stage.className = 'architecture-image-stage';
    const img = document.createElement('img');
    img.className = 'slide-image architecture-image';
    img.src = section.image;
    img.alt = 'Global Agentic Loan Applications architecture diagram with clickable layers';
    stage.appendChild(img);

    architectureHotspots.forEach((hotspot) => {
      const callout = data.architectureCallouts.find((item) => item.id === hotspot.id);
      if (!callout) return;
      const button = document.createElement('button');
      button.className = 'architecture-hotspot';
      button.type = 'button';
      button.setAttribute('aria-label', `Open ${hotspot.label}`);
      button.title = `Open ${callout.title}`;
      button.style.setProperty('--hotspot-top', `${hotspot.top}%`);
      button.style.setProperty('--hotspot-left', `${hotspot.left}%`);
      button.style.setProperty('--hotspot-width', `${hotspot.width}%`);
      button.style.setProperty('--hotspot-height', `${hotspot.height}%`);
      button.addEventListener('click', () => openCallout(hotspot.id));
      stage.appendChild(button);
    });

    figure.append(stage, renderArchitectureInstruction());
    grid.appendChild(figure);
    return grid;
  }

  function renderArchitectureInstruction() {
    const caption = document.createElement('figcaption');
    caption.className = 'architecture-instruction';
    caption.textContent = 'Click a layer in the diagram to open its details.';
    return caption;
  }

  function renderRelated(section) {
    const wrap = document.createElement('div');
    wrap.className = 'related';
    const title = document.createElement('strong');
    title.textContent = 'Related sections';
    const links = document.createElement('div');
    links.className = 'related-links';
    (section.related || []).forEach((id) => {
      const target = byId.get(id) || data.sections.find((item) => item.id === id);
      if (!target) return;
      const link = document.createElement('a');
      link.href = pageHref(target);
      link.textContent = target.title;
      links.appendChild(link);
    });
    wrap.append(title, links);
    return wrap;
  }

  function renderPrevNext(section) {
    const index = data.sections.findIndex((item) => item.id === section.id);
    const wrap = document.createElement('div');
    wrap.className = 'prev-next';
    const previous = data.sections[index - 1];
    const next = data.sections[index + 1];
    const prevLink = document.createElement(previous ? 'a' : 'span');
    prevLink.textContent = previous ? `Previous: ${previous.title}` : '';
    if (previous) prevLink.href = pageHref(previous);
    const nextLink = document.createElement(next ? 'a' : 'span');
    nextLink.textContent = next ? `Next: ${next.title}` : '';
    if (next) nextLink.href = pageHref(next);
    wrap.append(prevLink, nextLink);
    return wrap;
  }

  function openCallout(id) {
    const callout = data.architectureCallouts.find((item) => item.id === id);
    if (!callout) return;
    const target = data.sections.find((section) => section.id === callout.sectionId);
    modalContent.textContent = '';
    const title = document.createElement('h2');
    title.id = 'modal-title';
    title.textContent = callout.title;
    const summary = document.createElement('p');
    summary.className = 'summary';
    appendFormattedText(summary, callout.summary);
    const img = document.createElement('img');
    img.src = callout.slide;
    img.alt = `${callout.title} callout slide`;
    const list = document.createElement('ul');
    list.className = 'key-points';
    callout.points.forEach((point) => {
      const li = document.createElement('li');
      appendFormattedText(li, point);
      list.appendChild(li);
    });
    const link = document.createElement('a');
    link.className = 'button button-light';
    link.href = pageHref(target);
    link.textContent = `Open ${target.title}`;
    link.addEventListener('click', closeModal);
    modalContent.append(title, summary, img, list, link);
    modal.hidden = false;
    modalPanel.focus();
  }

  function closeModal() {
    modal.hidden = true;
    modalContent.textContent = '';
  }

  function groupBy(items, key) {
    return items.reduce((groups, item) => {
      const group = item[key] || 'Other';
      groups[group] = groups[group] || [];
      groups[group].push(item);
      return groups;
    }, {});
  }

  function escapeHtml(value) {
    return String(value).replace(/[&<>"]/g, (char) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[char]));
  }

  search.addEventListener('input', (event) => {
    state.query = event.target.value;
    renderNav(filteredSections());
  });
  closeModalButton.addEventListener('click', closeModal);
  modal.addEventListener('click', (event) => {
    if (event.target === modal) closeModal();
  });
  document.addEventListener('keydown', (event) => {
    if (event.key === 'Escape' && !modal.hidden) closeModal();
  });
})();
