import type { CollectionEntry } from "astro:content";
import type { SidebarItem } from "node_modules/@astrojs/starlight/schemas/sidebar";
import fs from 'node:fs';
import path from 'node:path';
import matter from 'gray-matter';
import { sidebar as sidebarTemplate } from '../../../../astro.config.mjs';

function createCommandSidebarItem(command: CollectionEntry<'commands'>): SidebarItem & { originalPath: string } {
  const data = command.data;
  const sidebarItem = {
    label: data.name,
    slug: `reference/cli/commands/${data.path}`,
    originalPath: data.path,
  } as SidebarItem & { originalPath: string };

  if (data.experiment) {
    sidebarItem.badge = {
      variant: 'tip',
      text: 'exp',
    };
  }

  return sidebarItem;
}

function organizeCommandsIntoGroups(flatCommandItems: (SidebarItem & { originalPath: string })[]): SidebarItem[] {
  const commandItems: SidebarItem[] = [];
  const groupedCommands: Record<string, SidebarItem[]> = {};

  flatCommandItems.forEach((item) => {
    const parts = item.originalPath.split('/');

    if (parts.length === 1) {
      // Root-level command
      const { originalPath, ...cleanItem } = item;
      commandItems.push(cleanItem);
    } else {
      // Nested command
      const groupName = parts[0];
      if (!groupedCommands[groupName]) {
        groupedCommands[groupName] = [];
        commandItems.push({
          label: groupName,
          collapsed: true,
          translations: {},
          items: groupedCommands[groupName]
        });
      }
      const { originalPath, ...cleanItem } = item;
      groupedCommands[groupName].push(cleanItem);
    }
  });

  return commandItems;
}

function insertCommandsIntoSidebar(
  sidebar: SidebarItem[],
  commandItems: SidebarItem[]
): void {
  const referenceSection = sidebar.find(item =>
    typeof item === 'object' && 'label' in item && item.label === 'Reference'
  ) as { items: SidebarItem[] };

  if (!referenceSection?.items) return;

  const cliSection = referenceSection.items.find(item =>
    typeof item === 'object' && 'label' in item && item.label === 'CLI'
  ) as { items: SidebarItem[] };

  if (!cliSection?.items) return;

  // Remove existing Commands section
  cliSection.items = cliSection.items.filter(item =>
    !(typeof item === 'object' && 'label' in item && item.label === 'Commands')
  );

  // Insert new Commands section after Overview
  const overviewIndex = cliSection.items.findIndex(item =>
    typeof item === 'object' && 'label' in item && item.label === 'Overview'
  );

  if (overviewIndex !== -1) {
    cliSection.items.splice(overviewIndex + 1, 0, {
      label: 'Commands',
      collapsed: true,
      translations: {},
      items: commandItems
    });
  }
}

function populateAutogeneratedSections(items: SidebarItem[]) {
  for (const item of items) {
    if (typeof item === 'object' && 'autogenerate' in item) {
      const dirPath = path.join(process.cwd(), 'src/content/docs', item.autogenerate.directory);
      if (fs.existsSync(dirPath)) {
        const files = fs.readdirSync(dirPath)
          .filter(file => file.endsWith('.mdx') || file.endsWith('.md'));

        (item as SidebarItem & { items: SidebarItem[] }).items = files.map(file => {
          const content = fs.readFileSync(path.join(dirPath, file), 'utf-8');
          const { data } = matter(content);
          return {
            label: data.title as string,
            translations: {},
            slug: data.slug as string,
            attrs: {}
          };
        });
        delete (item as any).autogenerate;
      }
    }

    if (typeof item === 'object' && 'items' in item) {
      populateAutogeneratedSections(item.items);
    }
  }
}

export async function getSidebar(commands: CollectionEntry<'commands'>[]): Promise<SidebarItem[]> {
  // Deep clone the sidebar template to avoid mutations
  const sidebar = JSON.parse(JSON.stringify(sidebarTemplate));

  // Create flat list of command items
  const flatCommandItems = commands
    .sort((a, b) => a.data.sidebar.order - b.data.sidebar.order)
    .map(createCommandSidebarItem);

  // Organize commands into nested groups
  const commandItems = organizeCommandsIntoGroups(flatCommandItems);

  // Insert commands into the sidebar
  insertCommandsIntoSidebar(sidebar, commandItems);

  // Handle autogenerated sections
  populateAutogeneratedSections(sidebar);

  return sidebar;
}
