---
import VerticalSideBarLayout from '@layouts/VerticalSideBarLayout.astro';
import { render } from 'astro:content';
import config from '@config';
import { AlignLeftIcon, UserIcon, UsersIcon } from 'lucide-react';

import mdxComponents from '@components/MDX/components';

import { getOwner } from '@utils/collections/owners';
import { buildUrl, buildEditUrlForResource } from '@utils/url-builder';
import { resourceToCollectionMap } from '@utils/collections/util';
import { getMDXComponentsByName, parseMdxBooleanProp } from '@utils/markdown';
import { getAdjacentPages, getNavigationItems } from '@enterprise/custom-documentation/utils/custom-docs';
import CustomDocsNav from '@enterprise/custom-documentation/components/CustomDocsNav/CustomDocsNav.astro';
import NodeGraph from '@components/MDX/NodeGraph/NodeGraph.astro';
import CopyAsMarkdown from '@components/CopyAsMarkdown';

import { isVisualiserEnabled, isMarkdownDownloadEnabled, isRSSEnabled, isEventCatalogChatEnabled } from '@utils/feature';

const props = Astro.props;
const doc = props.data;
const { Content, headings } = await render(props as any);
const currentSlug = props.id;

const nodeGraphs =
  getMDXComponentsByName(props.body, 'NodeGraph')?.filter((nodeGraph: any) => {
    return nodeGraph.id && nodeGraph.version && nodeGraph.type;
  }) || [];

const { prev, next } = await getAdjacentPages(currentSlug);

const ownersRaw = doc?.owners || [];
const owners = await Promise.all<ReturnType<typeof getOwner>>(ownersRaw.map(getOwner));
const filteredOwners = owners.filter((o) => o !== undefined);

const ownersList = filteredOwners.map((o) => ({
  label: o.data.name,
  type: o.collection,
  badge: o.collection === 'users' ? o.data.role : 'Team',
  avatarUrl: o.collection === 'users' ? o.data.avatarUrl : '',
  href: buildUrl(`/docs/${o.collection}/${o.data.id}`),
}));

const badges = doc?.badges || [];

// Find the immediate parent group label, for the accent header label above the title.
// Walks the processed navigation tree (which expands `autogenerated` directories into nested groups)
// so that nested groups like "Creating new microservices" are surfaced rather than only the top-level section.
const normalizeSlug = (s: string | undefined) => (s || '').replace(/^\//, '').replace(/^docs\//, '');
const currentSlugNorm = normalizeSlug(currentSlug);
const navigationItems = await getNavigationItems();

type NavItem = { label: string; slug?: string; items?: NavItem[] };

const findParentLabel = (items: NavItem[], parentLabel: string): string | null => {
  for (const item of items) {
    if (item.slug && normalizeSlug(item.slug) === currentSlugNorm) {
      return parentLabel;
    }
    if (item.items?.length) {
      const found = findParentLabel(item.items, item.label);
      if (found !== null) return found;
    }
  }
  return null;
};

const sectionLabel = findParentLabel(navigationItems as NavItem[], '') || '';

const editUrl =
  (doc as any)?.editUrl ||
  (config.editUrl && (props as any)?.filePath ? buildEditUrlForResource(config.editUrl, (props as any).filePath) : '');
---

<VerticalSideBarLayout title={doc.title || 'Documentation'} showNestedSideBar={false}>
  <div class="custom-docs-shell flex w-full" data-pagefind-body data-pagefind-meta={`title:${doc.title}`}>
    <!-- Left Sidebar Navigation -->
    <aside
      class="sidebar-transition fixed top-0 bottom-0 left-[var(--ec-vertical-nav-width,14rem)] z-10 w-[var(--ec-custom-docs-sidebar-width,20rem)] overflow-hidden border-r border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-rail-bg))]"
    >
      <div class="h-full">
        <CustomDocsNav />
      </div>
    </aside>

    <div class="sidebar-transition flex w-full min-w-0" style="margin-left: var(--ec-custom-docs-sidebar-width, 20rem);">
      <main class="min-w-0 flex-1">
        <div
          class="w-full lg:mr-2 pr-10 py-10 bg-[rgb(var(--ec-page-bg))]"
          style="padding-left: var(--ec-app-content-padding-left, 5rem);"
        >
          <div class="border-b border-[rgb(var(--ec-page-border))] md:pb-4">
            <div class="flex flex-col gap-4">
              {
                sectionLabel && (
                  <span class="text-xs md:text-sm font-semibold text-[rgb(var(--ec-accent))] capitalize">{sectionLabel}</span>
                )
              }
              <div class="flex justify-between items-center gap-4">
                <h2 id="doc-page-header" class="text-2xl md:text-4xl font-bold text-[rgb(var(--ec-page-text))]">
                  {doc.title}
                </h2>
                <div class="hidden lg:block shrink-0">
                  <CopyAsMarkdown
                    client:only="react"
                    schemas={[]}
                    chatEnabled={isEventCatalogChatEnabled()}
                    markdownDownloadEnabled={isMarkdownDownloadEnabled()}
                    rssFeedEnabled={isRSSEnabled()}
                    editUrl={editUrl}
                    preferChatAsDefault={isEventCatalogChatEnabled()}
                  />
                </div>
              </div>
              <p class="text-base text-[rgb(var(--ec-page-text-muted))] font-light">{doc.summary}</p>
              {
                badges && badges.length > 0 && (
                  <div class="flex flex-wrap gap-3 py-2">
                    {badges.map((badge: any) => {
                      return (
                        <a href={badge.url || '#'}>
                          <span
                            id={badge.id || ''}
                            class={`
                              inline-flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm font-medium
                              bg-[rgb(var(--ec-content-hover))] border border-[rgb(var(--ec-page-border))]
                              text-[rgb(var(--ec-page-text))]
                              shadow-xs
                              ${badge.class ? badge.class : ''}
                            `}
                          >
                            {badge.icon && <badge.icon className="w-4 h-4 flex-shrink-0 text-[rgb(var(--ec-icon-color))]" />}
                            {badge.iconURL && <img src={badge.iconURL} class="w-4 h-4 flex-shrink-0 opacity-80" alt="" />}
                            <span>{badge.content}</span>
                          </span>
                        </a>
                      );
                    })}
                  </div>
                )
              }
            </div>
          </div>
          <div class="prose prose-md max-w-none py-4 w-full text-[15px]">
            <Content components={{ ...mdxComponents(props) }} />
          </div>

          {
            nodeGraphs.length > 0 &&
              nodeGraphs.map((nodeGraph: any) => {
                const collection = resourceToCollectionMap[nodeGraph.type as keyof typeof resourceToCollectionMap];
                return (
                  <NodeGraph
                    id={nodeGraph.id}
                    version={nodeGraph.version}
                    collection={collection}
                    title={nodeGraph.title}
                    mode={nodeGraph.mode || 'simple'}
                    linksToVisualiser={true}
                    showSearch={parseMdxBooleanProp(nodeGraph.search, true)}
                    showLegend={parseMdxBooleanProp(nodeGraph.legend, true)}
                    href={
                      isVisualiserEnabled()
                        ? {
                            label: 'Open in Visualiser',
                            url: buildUrl(`/visualiser/${collection}/${nodeGraph.id}/${nodeGraph.version}`),
                          }
                        : undefined
                    }
                  />
                );
              })
          }

          <!-- Previous / Next Navigation -->
          <div class="py-8 border-t border-[rgb(var(--ec-page-border))] mt-8">
            <div class="flex flex-col sm:flex-row justify-between w-full gap-4">
              {
                prev && (
                  <a
                    href={buildUrl(`/docs/custom/${prev.slug}`)}
                    class="group flex flex-col border border-[rgb(var(--ec-page-border))] rounded-lg p-4 hover:border-[rgb(var(--ec-content-text-muted))] hover:bg-[rgb(var(--ec-content-hover))] transition-colors w-full sm:w-1/2"
                  >
                    <span class="text-sm text-[rgb(var(--ec-page-text-muted))] mb-1">Previous</span>
                    <span class="font-medium text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-accent))] transition-colors">
                      {prev.label}
                    </span>
                  </a>
                )
              }

              {!prev && <div class="w-full sm:w-1/2" />}

              {
                next && (
                  <a
                    href={buildUrl(`/docs/custom/${next.slug}`)}
                    class="group flex flex-col items-end text-right border border-[rgb(var(--ec-page-border))] rounded-lg p-4 hover:border-[rgb(var(--ec-content-text-muted))] hover:bg-[rgb(var(--ec-content-hover))] transition-colors w-full sm:w-1/2"
                  >
                    <span class="text-sm text-[rgb(var(--ec-page-text-muted))] mb-1">Next</span>
                    <span class="font-medium text-[rgb(var(--ec-page-text))] group-hover:text-[rgb(var(--ec-accent))] transition-colors">
                      {next.label}
                    </span>
                  </a>
                )
              }
            </div>
          </div>
        </div>
      </main>

      <!-- Right Sidebar TOC -->
      <aside
        id="eventcatalog-docs-sidebar"
        class="hidden xl:block sticky top-[4rem] self-start w-[200px] max-h-[calc(100vh-4rem)] overflow-y-auto py-2 flex-shrink-0 bg-[rgb(var(--ec-page-bg))]"
      >
        <div class="mt-8 space-y-8">
          {
            headings.length > 0 && (
              <div>
                <h3 class="text-xs text-[rgb(var(--ec-page-text))] font-semibold capitalize flex items-center gap-2 mb-4">
                  <AlignLeftIcon className="w-4 h-4" />
                  On this page
                </h3>
                <nav class="text-xs border-l border-[rgb(var(--ec-page-border))]">
                  {headings.map((heading) => {
                    const level = heading.depth > 2 ? heading.depth : 1;
                    if (heading.depth > 3) {
                      return null;
                    }
                    return (
                      <a
                        href={`#${heading.slug}`}
                        class="block py-1.5 pr-2.5 leading-5 text-[rgb(var(--ec-page-text-muted))] hover:border-[rgb(var(--ec-page-border))] hover:text-[rgb(var(--ec-page-text))] border-l-2 border-transparent -ml-px transition-all duration-200"
                        style={`padding-left: ${level * 0.75}rem`}
                      >
                        {heading.text}
                      </a>
                    );
                  })}
                </nav>
              </div>
            )
          }
          {
            ownersList.length > 0 && (
              <div>
                <h3 class="text-xs text-[rgb(var(--ec-page-text))] font-semibold capitalize mb-4">
                  {`Document Owners (${ownersList.length})`}
                </h3>
                <div class="space-y-2">
                  {ownersList.map((owner) => (
                    <a
                      href={owner.href}
                      class="flex items-center gap-2 text-xs text-[rgb(var(--ec-page-text-muted))] hover:text-[rgb(var(--ec-page-text))] transition-colors"
                    >
                      {owner.type === 'users' ? (
                        <UserIcon className="h-4 w-4 flex-shrink-0 text-[rgb(var(--ec-page-text-muted))]" />
                      ) : (
                        <UsersIcon className="h-4 w-4 flex-shrink-0 text-[rgb(var(--ec-page-text-muted))]" />
                      )}
                      <span class="truncate">{owner.label}</span>
                    </a>
                  ))}
                </div>
              </div>
            )
          }
        </div>
      </aside>
    </div>
  </div>
</VerticalSideBarLayout>

<style is:global>
  :root {
    --ec-custom-docs-sidebar-width: 20rem;
  }

  #eventcatalog-header {
    left: calc(var(--ec-vertical-nav-width, 14rem) + var(--ec-custom-docs-sidebar-width, 20rem)) !important;
  }

  .custom-docs-shell {
    margin-left: calc(var(--ec-app-content-padding-left, 5rem) * -1);
    margin-right: calc(var(--ec-app-content-padding-right, 5rem) * -1);
  }

  .mermaid svg {
    margin: 1em auto 2em;
  }

  /* Fix for architecture diagrams */
  .mermaid[data-content*='architecture'] svg {
    max-width: 350px !important;
    margin: 0;
    /* width: 100px !important; */
  }

  /* TOC active state - uses accent CSS variable */
  .toc-active-text {
    color: rgb(var(--ec-accent));
  }

  .toc-active-border {
    border-color: rgb(var(--ec-accent));
  }
</style>

<script define:vars={{ props, config }}>
  // Fix to pass information to componets that are client side only
  // and require catalog information
  window.eventcatalog = {};
  // @ts-ignore

  window.eventcatalog.mermaid = config.mermaid;
</script>

<script>
  // @ts-nocheck
  function setupObserver() {
    try {
      const observerOptions = {
        rootMargin: '0px 0px -40% 0px',
        threshold: 0.1,
      };

      // Flag to temporarily disable observer after click
      let observerPaused = false;

      // Function to highlight a TOC item
      function highlightTocItem(id: string) {
        // Remove active class from all links
        document.querySelectorAll('#eventcatalog-docs-sidebar .active-toc-item').forEach((link) => {
          link.classList.remove('active-toc-item', 'toc-active-text', 'font-medium', 'toc-active-border');
          link.classList.add('border-transparent');
        });

        // Add active class to current link
        const tocLink = document.querySelector(`#eventcatalog-docs-sidebar nav a[href="#${id}"]`);
        if (tocLink) {
          tocLink.classList.add('active-toc-item', 'toc-active-text', 'font-medium', 'toc-active-border');
          tocLink.classList.remove('border-transparent');

          // Scroll the highlighted item into view with a small delay to ensure DOM updates first
          setTimeout(() => {
            tocLink.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' });
          }, 10);
        }
      }

      // Set up the intersection observer for scrolling
      const observer = new IntersectionObserver((entries) => {
        // If observer is paused, don't process entries
        if (observerPaused) return;

        entries.forEach((entry) => {
          try {
            const id = entry.target.getAttribute('id');
            if (entry.isIntersecting && id) {
              highlightTocItem(id);
            }
          } catch (entryError) {
            console.error('Error processing intersection entry:', entryError);
          }
        });
      }, observerOptions);

      // Find all headings in the content area within the .prose container to observe
      const prose = document.querySelector('.prose');
      if (!prose) {
        console.warn('No .prose container found for TOC highlighting');
        return;
      }

      // First try to find headings with IDs
      const headings = prose.querySelectorAll('h1[id], h2[id], h3[id]');

      if (headings.length > 0) {
        headings.forEach((heading) => {
          observer.observe(heading);
        });
      } else {
        // Fallback: If no headings with IDs found, attach IDs to them
        const allHeadings = prose.querySelectorAll('h1, h2, h3');

        allHeadings.forEach((heading) => {
          // Only add ID if it doesn't exist
          if (!heading.id) {
            const text = heading.textContent || '';
            const slug = text
              .toLowerCase()
              .replace(/[^\w\s-]/g, '')
              .replace(/\s+/g, '-');
            heading.id = slug;
          }
          observer.observe(heading);
        });
      }

      // Add click event listeners to all TOC links
      const tocLinks = document.querySelectorAll('#eventcatalog-docs-sidebar nav a[href^="#"]');
      tocLinks.forEach((link) => {
        link.addEventListener('click', (e) => {
          // Get the ID from the href attribute
          const hrefAttr = link.getAttribute('href');
          if (!hrefAttr) return;

          const id = hrefAttr.substring(1);

          // Highlight the clicked item
          highlightTocItem(id);

          // Temporarily pause the observer to prevent immediate highlighting changes
          observerPaused = true;

          // Resume the observer after a delay (1.5 seconds)
          setTimeout(() => {
            observerPaused = false;
          }, 500);
        });
      });
    } catch (error) {
      console.error('Error setting up TOC highlighting:', error);
    }
  }

  setupObserver();

  document.addEventListener('astro:page-load', setupObserver);
</script>

<script>
  import { destroyZoomInstances, renderMermaidWithZoom, renderPlantUMLWithZoom } from '@utils/mermaid-zoom';

  function initDiagrams() {
    destroyZoomInstances();

    const mermaidGraphs = document.getElementsByClassName('mermaid');
    if (mermaidGraphs.length > 0) {
      renderMermaidWithZoom(mermaidGraphs, window.eventcatalog?.mermaid);
    }

    const plantumlBlocks = document.getElementsByClassName('plantuml');
    if (plantumlBlocks.length > 0) {
      renderPlantUMLWithZoom(plantumlBlocks);
    }
  }

  // Run on initial load and page transitions
  initDiagrams();
  document.addEventListener('astro:page-load', initDiagrams);

  // Make available globally for accordion component
  window.renderDiagrams = (graphs: HTMLCollectionOf<Element>) => {
    renderMermaidWithZoom(graphs, window.eventcatalog?.mermaid);
  };
  window.renderPlantUML = (blocks: HTMLCollectionOf<Element>) => {
    renderPlantUMLWithZoom(blocks);
  };
</script>
