---
export interface Props {
  title?: string;
  toggleLabel?: string;
  targetSelector?: string;
  headingSelector?: string;
  minLevel?: number;
  maxLevel?: number;
  defaultOpenBreakpoint?: string;
}

const {
  title = '页面导航',
  toggleLabel = '导航',
  targetSelector = '[data-report-content]',
  headingSelector,
  minLevel = 2,
  maxLevel = 3,
  defaultOpenBreakpoint = '(min-width: 1280px)'
} = Astro.props;

const sidebarId = `report-sidebar-${Math.random().toString(36).slice(2, 10)}`;
const navListId = `${sidebarId}-list`;
const config = {
  sidebarId,
  navListId,
  title,
  toggleLabel,
  targetSelector,
  headingSelector: headingSelector ?? '',
  minLevel,
  maxLevel,
  breakpoint: defaultOpenBreakpoint
};
---

<aside
  id={sidebarId}
  class="report-sidebar collapsed"
  data-report-sidebar
  data-breakpoint={defaultOpenBreakpoint}
>
  <button
    class="report-sidebar__toggle"
    type="button"
    aria-expanded="false"
    aria-controls={navListId}
  >
    <span class="report-sidebar__toggle-icon" aria-hidden="true">☰</span>
    <span class="report-sidebar__toggle-label">{toggleLabel}</span>
  </button>

  <div class="report-sidebar__panel" role="dialog" aria-modal="false">
    <div class="report-sidebar__header">
      <h2 class="report-sidebar__title">{title}</h2>
      <button class="report-sidebar__close" type="button" aria-label="收起导航">
        ×
      </button>
    </div>
    <nav class="report-sidebar__nav" aria-label={title}>
      <ul id={navListId} class="report-sidebar__list"></ul>
    </nav>
  </div>
</aside>

<script is:inline define:vars={{ CONFIG: config }}>
const script = document.currentScript;
(function () {
  if (!script) return;
  const sidebar = document.getElementById(CONFIG.sidebarId);
  if (!sidebar || sidebar.dataset.initialized === 'true') return;
  sidebar.dataset.initialized = 'true';

  const navList = sidebar.querySelector('.report-sidebar__list');
  const toggleBtn = sidebar.querySelector('.report-sidebar__toggle');
  const closeBtn = sidebar.querySelector('.report-sidebar__close');
  if (!navList || !toggleBtn || !closeBtn) return;

  const matchBreakpoint = window.matchMedia(CONFIG.breakpoint);
  const headingLevels = Array.from({ length: CONFIG.maxLevel - CONFIG.minLevel + 1 }, (_, idx) => `h${CONFIG.minLevel + idx}`);
  const selector = CONFIG.headingSelector && CONFIG.headingSelector.trim().length > 0
    ? CONFIG.headingSelector
    : headingLevels.join(',');

  const slugify = (text) => {
    if (!text) return 'section';
    return text
      .toLowerCase()
      .replace(/[\p{Extended_Pictographic}\p{Emoji_Presentation}\p{Emoji_Component}\p{Emoji}\p{Symbol}\p{Open_Punctuation}\p{Close_Punctuation}]/gu, '')
      .replace(/[^a-z0-9\u4e00-\u9fa5\-\s]/g, '')
      .replace(/\s+/g, '-')
      .replace(/-+/g, '-')
      .replace(/^-|-$/g, '') || 'section';
  };

  const buildNavigation = () => {
    const targetRoot = document.querySelector(CONFIG.targetSelector) ?? document.body;
    const headings = Array.from(targetRoot.querySelectorAll(selector))
      .filter((heading) => heading instanceof HTMLElement);

    if (!headings.length) {
      sidebar.classList.add('report-sidebar--empty');
      return;
    }

    sidebar.classList.remove('report-sidebar--empty');

    const existingIds = new Set(headings.filter((h) => h.id).map((h) => h.id));

    headings.forEach((heading) => {
      if (!heading.id) {
        const base = slugify(heading.textContent ?? 'section');
        let candidate = base;
        let counter = 1;
        while (existingIds.has(candidate) || document.getElementById(candidate)) {
          candidate = `${base}-${counter++}`;
        }
        heading.id = candidate;
        existingIds.add(candidate);
      }
    });

    // 清空并重建导航
    navList.innerHTML = '';

    headings.forEach((heading) => {
      const level = parseInt(heading.tagName.replace('H', ''), 10) || CONFIG.minLevel;
      const text = heading.textContent?.trim() ?? '';
      if (!text) return;

      // 计算缩进层级（相对于最小层级）
      const depth = Math.max(0, level - CONFIG.minLevel);

      const listItem = document.createElement('li');
      listItem.className = `nav-item nav-item--level-${level} nav-item--depth-${depth}`;
      
      const link = document.createElement('a');
      link.className = `nav-link nav-link--level-${level}`;
      link.href = `#${heading.id}`;
      link.textContent = text;
      link.dataset.targetId = heading.id;
      link.dataset.level = String(level);
      link.dataset.depth = String(depth);
      
      // 设置内联样式
      const indentPx = depth * 20; // 每层20px缩进
      let fontSize, fontWeight, color;
      
      switch(level) {
        case 2:
          fontSize = '18px';
          fontWeight = '700';
          color = '#0f172a';
          break;
        case 3:
          fontSize = '16px';
          fontWeight = '600';
          color = '#1e293b';
          break;
        default:
          fontSize = '13px';
          fontWeight = '400';
          color = '#475569';
      }
      
      link.style.cssText = `
        margin-left: ${indentPx}px;
        font-size: ${fontSize};
        font-weight: ${fontWeight};
        color: ${color};
        padding: ${level === 2 ? '12px 16px' : level === 3 ? '10px 14px' : '8px 12px'};
        display: block;
        text-decoration: none;
        border-radius: 8px;
        transition: all 0.2s ease;
      `;
      
      listItem.appendChild(link);
      navList.appendChild(listItem);
    });

    setupScrollSpy(headings);
  };

  const setCollapsed = (collapsed) => {
    sidebar.classList.toggle('collapsed', collapsed);
    toggleBtn.setAttribute('aria-expanded', String(!collapsed));
  };

  const handleToggle = () => {
    setCollapsed(!sidebar.classList.contains('collapsed'));
  };

  toggleBtn.addEventListener('click', handleToggle);
  closeBtn.addEventListener('click', () => setCollapsed(true));

  const handleLinkClick = (event) => {
    const link = event.target.closest('.nav-link');
    if (!link) return;
    event.preventDefault();
    const targetId = link.dataset.targetId;
    const target = targetId ? document.getElementById(targetId) : null;
    if (target) {
      target.scrollIntoView({ behavior: 'smooth', block: 'start' });
      history.replaceState(null, '', `#${targetId}`);
    }
    if (!matchBreakpoint.matches) {
      setCollapsed(true);
    }
  };

  navList.addEventListener('click', handleLinkClick);

  const applyBreakpointState = () => {
    setCollapsed(!matchBreakpoint.matches);
  };

  matchBreakpoint.addEventListener('change', applyBreakpointState);

  let activeLink = null;
  let observer = null;

  const setActiveLink = (id) => {
    if (activeLink) {
      activeLink.classList.remove('nav-link--active');
    }
    const next = navList.querySelector(`.nav-link[data-target-id="${id}"]`);
    if (next) {
      next.classList.add('nav-link--active');
      activeLink = next;
    } else {
      activeLink = null;
    }
  };

  const setupScrollSpy = (headings) => {
    if (observer) {
      observer.disconnect();
    }

    observer = new IntersectionObserver((entries) => {
      const visible = entries
        .filter((entry) => entry.isIntersecting)
        .sort((a, b) => b.intersectionRatio - a.intersectionRatio);
      if (visible.length > 0) {
        setActiveLink(visible[0].target.id);
        return;
      }
      const sorted = entries
        .slice()
        .sort((a, b) => a.target.offsetTop - b.target.offsetTop);
      const current = sorted.find((entry) => window.scrollY + 120 <= entry.target.offsetTop + entry.target.offsetHeight);
      if (current) {
        setActiveLink(current.target.id);
      }
    }, {
      rootMargin: '-35% 0px -55% 0px',
      threshold: [0, 0.25, 0.5, 0.75, 1]
    });

    headings.forEach((heading) => observer.observe(heading));
  };

  const initialize = () => {
    buildNavigation();
    applyBreakpointState();
  };

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initialize, { once: true });
  } else {
    initialize();
  }

  document.addEventListener('astro:after-swap', () => {
    buildNavigation();
    applyBreakpointState();
  });
})();
</script>

<style>
  .report-sidebar {
    --sidebar-width: var(--report-sidebar-width, clamp(260px, 24vw, 320px));
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    width: var(--sidebar-width);
    z-index: 40;
  }

  .report-sidebar__toggle {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.65rem 1rem;
    border-radius: 999px;
    border: 1px solid rgba(91, 119, 142, 0.35);
    background: rgba(255, 255, 255, 0.18);
    color: #0f172a;
    font-weight: 600;
    cursor: pointer;
    box-shadow: 0 8px 24px rgba(15, 23, 42, 0.1);
    transition: transform 0.25s ease, box-shadow 0.25s ease, background 0.25s ease;
    backdrop-filter: blur(12px);
  }

  .report-sidebar__toggle:hover {
    transform: translateY(-1px);
    box-shadow: 0 12px 30px rgba(15, 23, 42, 0.16);
    background: rgba(255, 255, 255, 0.28);
  }

  .report-sidebar__toggle-icon {
    font-size: 1.1rem;
  }

  .report-sidebar__panel {
    width: var(--sidebar-width);
    background: rgba(255, 255, 255, 0.3);
    border: 1px solid rgba(91, 119, 142, 0.25);
    border-radius: 1.25rem;
    padding: 1.25rem;
    box-shadow: 0 18px 40px rgba(15, 23, 42, 0.15);
    backdrop-filter: blur(18px);
    transition: transform 0.35s ease, opacity 0.35s ease, visibility 0.35s ease;
    position: sticky;
    top: 6.5rem;
    max-height: calc(100vh - 7.5rem);
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }

  .collapsed .report-sidebar__panel {
    opacity: 0;
    visibility: hidden;
    transform: translateX(-12px);
    pointer-events: none;
  }

  .report-sidebar__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 1rem;
  }

  .report-sidebar__title {
    font-size: 1.125rem;
    font-weight: 700;
    margin: 0;
    color: #0f172a;
  }

  .report-sidebar__close {
    border: none;
    background: rgba(15, 23, 42, 0.06);
    color: #0f172a;
    width: 2rem;
    height: 2rem;
    border-radius: 999px;
    cursor: pointer;
    font-size: 1.25rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 0.2s ease, transform 0.2s ease;
  }

  .report-sidebar__close:hover {
    background: rgba(15, 23, 42, 0.12);
    transform: scale(1.05);
  }

  .report-sidebar__nav {
    flex: 1;
    overflow-y: auto;
    overflow-x: hidden;
    padding-right: 8px;
    margin-right: -8px;
  }

  /* 自定义滚动条样式 */
  .report-sidebar__nav::-webkit-scrollbar {
    width: 6px;
  }

  .report-sidebar__nav::-webkit-scrollbar-track {
    background: rgba(148, 163, 184, 0.1);
    border-radius: 3px;
  }

  .report-sidebar__nav::-webkit-scrollbar-thumb {
    background: rgba(148, 163, 184, 0.4);
    border-radius: 3px;
  }

  .report-sidebar__nav::-webkit-scrollbar-thumb:hover {
    background: rgba(148, 163, 184, 0.6);
  }

  .report-sidebar__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
  }

  /* 导航项基础样式 */
  .nav-item {
    position: relative;
    margin: 2px 0;
  }

  .nav-link:hover {
    background: rgba(59, 130, 246, 0.1) !important;
    transform: translateX(4px);
  }

  /* 激活状态 */
  .nav-link--active {
    background: linear-gradient(135deg, rgba(59, 130, 246, 0.2), rgba(29, 78, 216, 0.15)) !important;
    color: #1d4ed8 !important;
    font-weight: 700 !important;
    border-left: 4px solid #3b82f6;
    box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3);
  }

  @media (min-width: 1280px) {
    .report-sidebar {
      --sidebar-width: var(--report-sidebar-width, clamp(260px, 22vw, 320px));
      --sidebar-inline-offset: clamp(1rem, 2.5vw, 3rem);
      position: fixed;
      top: 6rem;
      left: calc(env(safe-area-inset-left) + var(--sidebar-inline-offset));
      height: calc(100vh - 7rem);
      align-items: stretch;
      gap: 1rem;
    }

    .report-sidebar__toggle {
      justify-content: center;
      width: 100%;
    }

    .report-sidebar__panel {
      position: relative;
      top: auto;
      width: var(--sidebar-width);
      max-height: 100%;
      height: 100%;
      overflow: hidden;
      display: flex;
      flex-direction: column;
    }

    .report-sidebar__nav {
      flex: 1;
      overflow-y: auto;
      overflow-x: hidden;
    }

    .collapsed .report-sidebar__panel {
      transform: translateX(-16px);
    }
  }

  @media (max-width: 1279px) {
    .report-sidebar {
      position: fixed;
      bottom: 1.5rem;
      right: 1.5rem;
      width: auto;
      gap: 0.5rem;
      align-items: flex-end;
      z-index: 55;
    }

    .report-sidebar__toggle {
      background: rgba(15, 23, 42, 0.8);
      color: #f8fafc;
      box-shadow: 0 15px 30px rgba(15, 23, 42, 0.35);
    }

    .report-sidebar__panel {
      position: fixed;
      bottom: 0;
      right: 0;
      top: auto;
      left: 0;
      width: 100%;
      max-height: min(520px, 85vh);
      border-radius: 1.5rem 1.5rem 0 0;
      padding: 1.5rem;
      transform: translateY(100%);
    }

    .collapsed .report-sidebar__panel {
      transform: translateY(110%);
    }

    .report-sidebar__panel,
    .collapsed .report-sidebar__panel {
      opacity: 1;
      visibility: visible;
      pointer-events: auto;
    }
  }

  @media (prefers-reduced-motion: reduce) {
    .report-sidebar__panel,
    .report-sidebar__toggle,
    .nav-link {
      transition: none;
    }
  }
</style>
