'use client'

import { useEffect, useState, useCallback, useRef } from 'react'
import { Spinner } from '@phosphor-icons/react'
import type { BrainfishCollection, BrainfishRESTRequest, BrainfishDocGroup } from '@/lib/api-docs/types'
import { DocsSidebar } from './sidebar'
import { NotFoundPage } from './content/not-found-page'
import { ApiPlayground } from './playground'
import type { DebugContext } from './playground/response-viewer'
import { RightSidebar } from './sidebar/right-sidebar'
import { RequestDetails } from './content/request-details'
import { DocPage } from './content/doc-page'
import { ChangelogPage } from './content/changelog-page'
import { GraphQLPlayground, type GraphQLOperationItem } from './playground/graphql-playground'
import { makeBrainfishCollection } from '@/lib/api-docs/factories'
import { parse, Kind, type DocumentNode, type FieldDefinitionNode, type InputValueDefinitionNode, type TypeNode } from 'graphql'
import { GlobalAuthModal } from './global-auth-modal'
import { AuthProvider } from '@/lib/api-docs/auth'
import { PlaygroundProvider, usePlaygroundPrefill } from '@/lib/api-docs/playground/context'
import { PlaygroundNavigationProvider, usePlaygroundNavigation, type PlaygroundTab, type HighlightField } from '@/lib/api-docs/playground/navigation-context'
import { NavigationProvider } from '@/lib/api-docs/navigation-context'
import type { PrefillData } from '@/lib/api-docs/agent/types'
import { ModeProvider, useModeContext } from '@/lib/api-docs/code-editor'
import { NotesMode } from './code-editor'
import { DocsHeader } from '@/components/docs-header'
import { Notice } from '../docs/notice'
import { DocsNavigationProvider } from '@/lib/docs-navigation-context'
import { Button } from '@/components/ui/button'
import { Code, TestTube, Book } from '@phosphor-icons/react'
import { cn } from '@/lib/utils'
import { SearchDialog, useSearch } from './search'
import { useTheme } from 'next-themes'

// Helper to convert GraphQL TypeNode to string
function typeNodeToString(typeNode: TypeNode): string {
  switch (typeNode.kind) {
    case Kind.NAMED_TYPE:
      return typeNode.name.value
    case Kind.NON_NULL_TYPE:
      return `${typeNodeToString(typeNode.type)}!`
    case Kind.LIST_TYPE:
      return `[${typeNodeToString(typeNode.type)}]`
    default:
      return 'Unknown'
  }
}

// Parse GraphQL schema using the graphql library
function parseGraphQLSchema(schemaSDL: string): GraphQLOperationItem[] {
  const operations: GraphQLOperationItem[] = []
  
  try {
    const ast: DocumentNode = parse(schemaSDL)
    
    // Find Query, Mutation, Subscription type definitions
    for (const def of ast.definitions) {
      if (def.kind === Kind.OBJECT_TYPE_DEFINITION) {
        const typeName = def.name.value
        
        // Only process root operation types
        if (!['Query', 'Mutation', 'Subscription'].includes(typeName)) continue
        
        const operationType = typeName.toLowerCase() as 'query' | 'mutation' | 'subscription'
        
        // Process each field
        for (const field of def.fields || []) {
          const name = field.name.value
          
          // Skip internal fields
          if (name.startsWith('_')) continue
          
          // Get description
          const description = field.description?.value || null
          
          // Get return type
          const returnType = typeNodeToString(field.type)
          
          // Build args string for query generation
          const args = (field.arguments || [])
            .map((arg: InputValueDefinitionNode) => `${arg.name.value}: ${typeNodeToString(arg.type)}`)
            .join(', ')
          
          const query = generateGraphQLQuery(operationType, name, field.arguments || [], returnType)
          const exampleVariables = generateGraphQLVariables(field.arguments || [])
          
          operations.push({
            id: `${operationType}-${name}`,
            name,
            description,
            operationType,
            query,
            exampleVariables,
          })
        }
      }
    }
    
  } catch (err) {
    console.error('[GraphQL Parser] Failed to parse schema:', err)
  }
  
  return operations
}

// Generate example GraphQL query from AST
function generateGraphQLQuery(
  operationType: string,
  name: string,
  args: readonly InputValueDefinitionNode[],
  returnType: string
): string {
  let query = `${operationType} ${name.charAt(0).toUpperCase() + name.slice(1)}`
  
  if (args.length > 0) {
    const varDefs = args.map(arg => `$${arg.name.value}: ${typeNodeToString(arg.type)}`).join(', ')
    query += `(${varDefs})`
  }
  
  query += ` {\n  ${name}`
  
  if (args.length > 0) {
    const argPairs = args.map(arg => `${arg.name.value}: $${arg.name.value}`).join(', ')
    query += `(${argPairs})`
  }
  
  const baseType = returnType.replace(/[\[\]!]/g, '').trim()
  if (['String', 'Int', 'Float', 'Boolean', 'ID'].includes(baseType)) {
    query += '\n}'
  } else {
    query += ` {\n    id\n    __typename\n  }\n}`
  }
  
  return query
}

// Generate example variables from AST args
function generateGraphQLVariables(args: readonly InputValueDefinitionNode[]): Record<string, unknown> {
  const variables: Record<string, unknown> = {}
  
  for (const arg of args) {
    const name = arg.name.value
    const type = typeNodeToString(arg.type).replace(/[\[\]!]/g, '').trim()
    
    switch (type) {
      case 'String': variables[name] = 'example'; break
      case 'Int': variables[name] = 1; break
      case 'Float': variables[name] = 1.0; break
      case 'Boolean': variables[name] = true; break
      case 'ID': variables[name] = '1'; break
      default: variables[name] = {}
    }
  }
  
  return variables
}

// Convert GraphQL operations to BrainfishCollection for sidebar
function convertGraphQLToCollection(
  operations: GraphQLOperationItem[],
  endpoint: string
): BrainfishCollection {
  const queries = operations.filter(op => op.operationType === 'query')
  const mutations = operations.filter(op => op.operationType === 'mutation')
  const subscriptions = operations.filter(op => op.operationType === 'subscription')
  
  const toRequest = (op: GraphQLOperationItem): BrainfishRESTRequest => ({
    id: op.id,
    name: op.name,
    description: op.description || '',
    method: 'POST',
    endpoint,
    params: [],
    headers: [],
    auth: { authType: 'none', authActive: false },
    body: { contentType: 'application/json', body: JSON.stringify({ query: op.query, variables: op.exampleVariables }, null, 2) },
    requestVariables: [],
    responses: {},
    tags: [op.operationType],
  })
  
  const folders: BrainfishCollection[] = []
  
  if (queries.length > 0) {
    folders.push(makeBrainfishCollection({
      name: 'Queries',
      description: 'GraphQL Query operations',
      requests: queries.map(toRequest),
      folders: [],
      variables: [],
      auth: { authType: 'none', authActive: false },
      headers: [],
    }))
  }
  
  if (mutations.length > 0) {
    folders.push(makeBrainfishCollection({
      name: 'Mutations',
      description: 'GraphQL Mutation operations',
      requests: mutations.map(toRequest),
      folders: [],
      variables: [],
      auth: { authType: 'none', authActive: false },
      headers: [],
    }))
  }
  
  if (subscriptions.length > 0) {
    folders.push(makeBrainfishCollection({
      name: 'Subscriptions',
      description: 'GraphQL Subscription operations',
      requests: subscriptions.map(toRequest),
      folders: [],
      variables: [],
      auth: { authType: 'none', authActive: false },
      headers: [],
    }))
  }
  
  return makeBrainfishCollection({
    name: 'GraphQL API',
    description: 'GraphQL operations',
    folders,
    requests: [],
    variables: [],
    auth: { authType: 'none', authActive: false },
    headers: [],
  })
}

// Helper to find request by ID in collection
function findRequestById(collection: BrainfishCollection, id: string): BrainfishRESTRequest | null {
  // Check direct requests
  const found = collection.requests.find(r => r.id === id)
  if (found) return found
  
  // Check folders recursively
  for (const folder of collection.folders) {
    const request = findRequestById(folder, id)
    if (request) return request
  }
  return null
}

// Helper to get the first endpoint from collection
function getFirstEndpoint(collection: BrainfishCollection): BrainfishRESTRequest | null {
  // Check direct requests first
  if (collection.requests.length > 0) {
    return collection.requests[0]
  }
  
  // Check folders recursively
  for (const folder of collection.folders) {
    const firstInFolder = getFirstEndpoint(folder)
    if (firstInFolder) return firstInFolder
  }
  return null
}

// Helper to check if a doc group belongs to a specific tab
// Group IDs are formatted as: group-{tab-id}-{group-name}
function isGroupForTab(groupId: string, tabId: string): boolean {
  // Check if the group ID starts with "group-{tabId}-"
  const prefix = `group-${tabId}-`
  return groupId.startsWith(prefix)
}

// Helper to check if a tab has doc groups (MDX pages)
function hasDocGroupsForTab(
  docGroups: BrainfishDocGroup[] | undefined, 
  tabId: string
): boolean {
  if (!docGroups || docGroups.length === 0) return false
  
  // Check if any doc group belongs to this tab and has pages
  return docGroups.some(g => isGroupForTab(g.id, tabId) && g.pages.length > 0)
}

// Helper to get the first page from doc groups for a tab
function getFirstDocPageForTab(
  docGroups: BrainfishDocGroup[] | undefined,
  tabId: string
): string | null {
  if (!docGroups || docGroups.length === 0) return null
  
  const tabDocGroup = docGroups.find(g => isGroupForTab(g.id, tabId) && g.pages.length > 0)
  
  return tabDocGroup?.pages[0]?.slug || null
}


// API version
interface ApiVersion {
  version: string
  spec: string
  default: boolean
}

// GraphQL schema info for graphql tabs
interface GraphQLSchemaInfo {
  name: string
  schema: string
  endpoint: string
  default: boolean
}

// Navigation tab from config
interface NavigationTab {
  id: string
  tab: string  // Tab name (used for both navigation and page header)
  type: 'docs' | 'openapi' | 'changelog' | 'graphql'
  path?: string
  order: number
  versions?: ApiVersion[]  // Available API versions (for openapi type)
  graphqlSchemas?: GraphQLSchemaInfo[]  // GraphQL schemas (for graphql type)
}

interface ChangelogRelease {
  version: string
  date: string
  title: string
  slug: string
}

// Extended collection type with apiSummary from server
interface DocsLogo {
  url?: string
  alt?: string
  width?: number
  height?: number
  light?: string
  dark?: string
}

interface DocsHeaderConfig {
  showSearch?: boolean
  showThemeToggle?: boolean
}

interface DocsNavbarLink {
  label: string
  href: string
  external?: boolean
}

interface DocsNavbarPrimary {
  label: string
  href: string
}

interface DocsNavbar {
  links?: DocsNavbarLink[]
  primary?: DocsNavbarPrimary
}

interface DocsColors {
  primary?: string
  primaryLight?: string
  primaryDark?: string
}

interface NoticeConfig {
  content: string
  dismissible?: boolean
}

interface CollectionWithSummary extends BrainfishCollection {
  apiSummary?: string | null
  specVersion?: string
  docsName?: string | null
  docsFavicon?: string | null
  docsLogo?: DocsLogo | null
  docsHeader?: DocsHeaderConfig | null
  docsNavbar?: DocsNavbar | null
  docsColors?: DocsColors | null
  defaultTheme?: 'light' | 'dark' | 'system' | null
  customCss?: string | null
  navigationTabs?: NavigationTab[]
  changelogReleases?: ChangelogRelease[]
  apiVersions?: ApiVersion[]
  selectedApiVersion?: string
  notice?: NoticeConfig | null
}

function DocsContent() {
  const [collection, setCollection] = useState<CollectionWithSummary | null>(null)
  const [selectedRequest, setSelectedRequest] = useState<BrainfishRESTRequest | null>(null)
  const [selectedDocSection, setSelectedDocSection] = useState<string | null>(null)
  const [selectedDocPage, setSelectedDocPage] = useState<string | null>(null)
  const [activeTab, setActiveTab] = useState<string>('api-reference')
  const [selectedApiVersion, setSelectedApiVersion] = useState<string | null>(null)
  const [loading, setLoading] = useState(true)
  const [isVersionLoading, setIsVersionLoading] = useState(false) // For version switch only
  const [error, setError] = useState<string | null>(null)
  const [showAuthModal, setShowAuthModal] = useState(false)
  const [notFoundSlug, setNotFoundSlug] = useState<string | null>(null) // Track 404 for invalid URLs
  
  // Prefill context for agent
  const { setPrefill } = usePlaygroundPrefill()
  
  // Playground navigation context for tab navigation
  const { navigateAndHighlight, resetNavigation } = usePlaygroundNavigation()
  
  // Mode context for switching modes
  const { switchToDocs } = useModeContext()
  
  // Ref for the scrollable content area
  const contentRef = useRef<HTMLDivElement>(null)
  
  // Update URL hash without triggering navigation
  // Format: #tab or #tab/type/id (e.g., #api-reference, #api-reference/endpoint/123, #guides/page/quickstart)
  const updateUrlHash = useCallback((hash: string, tab?: string) => {
    const currentTab = tab || activeTab
    let newUrl: string
    
    if (!hash) {
      // Just the tab
      newUrl = `#${currentTab}`
    } else {
      // Tab + path
      newUrl = `#${currentTab}/${hash}`
    }
    
    window.history.pushState(null, '', newUrl)
  }, [activeTab])
  
  // Navigate to hash - used for initial load and popstate
  // Parse hash format: #tab or #tab/type/id
  const parseHash = useCallback((hash: string) => {
    if (!hash) return { tab: null, type: null, id: null }
    
    const parts = hash.split('/')
    const tab = parts[0] || null
    const type = parts[1] || null
    const id = parts.slice(2).join('/') || null // Rejoin in case id has slashes
    
    return { tab, type, id }
  }, [])

  const navigateToHash = useCallback((collectionData: BrainfishCollection) => {
    const hash = window.location.hash.slice(1) // Remove #

    if (!hash) {
      // No hash - auto-select first endpoint
      setSelectedDocSection(null)
      setSelectedDocPage(null)
      const firstEndpoint = getFirstEndpoint(collectionData)
      if (firstEndpoint) {
        setSelectedRequest(firstEndpoint)
      } else {
        setSelectedRequest(null)
      }
      return
    }

    // Notes mode is handled by ModeContext, just clear API selection
    if (hash === 'notes' || hash.startsWith('notes/')) {
      setSelectedRequest(null)
      setSelectedDocSection(null)
      setSelectedDocPage(null)
      return
    }

    // Parse new format: #tab/type/id
    const { tab, type, id } = parseHash(hash)
    
    // Set the active tab if specified
    if (tab) {
      setActiveTab(tab)
    }

    // Handle legacy format (endpoint/xxx, page/xxx, doc/xxx without tab prefix)
    const legacyType = hash.startsWith('endpoint/') ? 'endpoint' 
      : hash.startsWith('page/') ? 'page'
      : hash.startsWith('doc/') ? 'doc'
      : null
    
    const actualType = type || legacyType
    const actualId = id || (legacyType ? hash.replace(`${legacyType}/`, '') : null)

    if (actualType === 'endpoint' && actualId) {
      const request = findRequestById(collectionData, actualId)
      if (request) {
        setSelectedRequest(request)
        setSelectedDocSection(null)
        setSelectedDocPage(null)
        setNotFoundSlug(null)
      } else {
        // Endpoint not found - show 404 page
        setSelectedRequest(null)
        setSelectedDocSection(null)
        setSelectedDocPage(null)
        setNotFoundSlug(`endpoint/${actualId}`)
      }
    } else if (actualType === 'page' && actualId) {
      setNotFoundSlug(null) // Clear not found state - DocPage handles its own 404
      setSelectedDocPage(actualId)
      setSelectedRequest(null)
      setSelectedDocSection(null)
    } else if (actualType === 'doc' && actualId) {
      setSelectedDocSection(actualId)
      setSelectedRequest(null)
      setSelectedDocPage(null)

      // Scroll to section after DOM update
      setTimeout(() => {
        const element = document.getElementById(actualId)
        if (element) {
          element.scrollIntoView({ behavior: 'smooth', block: 'start' })
        }
      }, 100)
    } else if (tab && !type) {
      // Just a tab, no specific content - show default for that tab
      setSelectedRequest(null)
      setSelectedDocSection(null)
      setSelectedDocPage(null)
    }
  }, [parseHash])
  
  const handleSelectRequest = useCallback((request: BrainfishRESTRequest) => {
    setSelectedRequest(request)
    setSelectedDocSection(null)
    setSelectedDocPage(null)
    setNotFoundSlug(null) // Clear 404 state when selecting an endpoint
    updateUrlHash(`endpoint/${request.id}`)
    // Reset tab navigation so the new endpoint can determine its default tab
    resetNavigation()
    // Switch to Docs mode to show endpoint documentation first
    switchToDocs()
  }, [updateUrlHash, resetNavigation, switchToDocs])
  
  const handleSelectDocumentation = useCallback((headingId: string) => {
    const isIntro = headingId === 'introduction'
    setSelectedDocSection(isIntro ? null : headingId)
    setSelectedRequest(null)
    setSelectedDocPage(null)
    setNotFoundSlug(null) // Clear 404 state
    
    updateUrlHash(isIntro ? '' : `doc/${headingId}`)
    
    // Switch to Docs mode when selecting documentation
    switchToDocs()
    
    setTimeout(() => {
      if (isIntro) {
        contentRef.current?.scrollTo({ top: 0, behavior: 'smooth' })
      } else {
        const element = document.getElementById(headingId)
        if (element) {
          element.scrollIntoView({ behavior: 'smooth', block: 'start' })
        }
      }
    }, 50)
  }, [updateUrlHash, switchToDocs])
  
  const handleSelectDocPage = useCallback((slug: string) => {
    // Find which tab this doc page belongs to
    let targetTab = activeTab
    let releaseSlug: string | null = null
    let sectionId: string | null = null
    
    // Parse section from slug (e.g., "essentials/markdown#headings" -> slug: "essentials/markdown", section: "headings")
    let pageSlug = slug
    if (slug.includes('#')) {
      const [pagePart, sectionPart] = slug.split('#')
      pageSlug = pagePart
      sectionId = sectionPart
    }
    
    // Special handling for changelog pages
    if (pageSlug.startsWith('changelog/') || pageSlug === 'changelog') {
      // Find the changelog tab
      const changelogTab = collection?.navigationTabs?.find(t => t.type === 'changelog')
      if (changelogTab) {
        targetTab = changelogTab.id
      }
      // Extract the release slug for scrolling (e.g., "changelog/v1.2.0" -> "v1.2.0")
      if (pageSlug.startsWith('changelog/')) {
        releaseSlug = pageSlug.replace('changelog/', '')
      }
    } else if (collection?.docGroups) {
      for (const group of collection.docGroups) {
        const hasPage = (pages: typeof group.pages): boolean => {
          for (const page of pages) {
            if (page.slug === pageSlug) return true
            if (page.children && hasPage(page.children)) return true
          }
          return false
        }
        if (hasPage(group.pages)) {
          // Extract tab from group ID (e.g., "group-guides-getting-started" -> "guides")
          const tabPart = group.id.replace('group-', '').split('-')[0]
          // Find the actual tab ID that matches
          const matchingTab = collection.navigationTabs?.find(t => 
            t.id === tabPart || t.id.startsWith(tabPart)
          )
          if (matchingTab) {
            targetTab = matchingTab.id
          }
          break
        }
      }
    }
    
    // Switch to the correct tab
    setActiveTab(targetTab)
    setSelectedDocPage(pageSlug)
    setSelectedRequest(null)
    setSelectedDocSection(null)
    setNotFoundSlug(null) // Clear 404 state
    updateUrlHash(`page/${pageSlug}`, targetTab)
    switchToDocs()
    
    // Scroll to specific release if navigating to a changelog entry
    if (releaseSlug) {
      // Wait for the changelog page to render, then scroll to the release
      setTimeout(() => {
        const releaseElement = document.getElementById(`release-${releaseSlug}`)
        if (releaseElement) {
          releaseElement.scrollIntoView({ behavior: 'smooth', block: 'start' })
        }
      }, 600)
    } else if (sectionId) {
      // Scroll to section within the page after it renders
      setTimeout(() => {
        const sectionElement = document.getElementById(sectionId)
        if (sectionElement) {
          sectionElement.scrollIntoView({ behavior: 'smooth', block: 'start' })
        }
      }, 300)
    } else {
      // Scroll to top of content when navigating to a new page
      setTimeout(() => {
        contentRef.current?.scrollTo({ top: 0, behavior: 'smooth' })
      }, 50)
    }
  }, [updateUrlHash, switchToDocs, collection, activeTab])

  // Handle API version change
  const handleApiVersionChange = useCallback((version: string) => {
    if (version !== selectedApiVersion) {
      setSelectedApiVersion(version)
      // Clear selected request when switching versions as endpoints may differ
      setSelectedRequest(null)
      setSelectedDocSection(null)
    }
  }, [selectedApiVersion])

  // Handle tab change from header
  const handleTabChange = useCallback((tabId: string) => {
    setActiveTab(tabId)
    
    // Reset mode to docs when switching tabs (exit sandbox/api-client mode)
    switchToDocs()

    // Find the tab config to check its type
    const tabConfig = collection?.navigationTabs?.find(t => t.id === tabId)
    const isApiTab = tabConfig?.type === 'openapi' || tabConfig?.type === 'graphql' || tabId === 'api-reference'

    if (tabId === 'changelog') {
      // Switch to Changelog tab
      setSelectedDocPage(null)
      setSelectedRequest(null)
      setSelectedDocSection(null)
      updateUrlHash('', tabId)
    } else if (isApiTab) {
      // API Reference or GraphQL tab
      setSelectedDocSection(null)
      
      // Check if there are doc groups for this tab (MDX pages)
      const hasGroups = hasDocGroupsForTab(collection?.docGroups, tabId)
      
      if (hasGroups) {
        // Has doc groups - select the first page from groups
        const firstPage = getFirstDocPageForTab(collection?.docGroups, tabId)
        if (firstPage) {
          setSelectedDocPage(firstPage)
          setSelectedRequest(null)
          updateUrlHash(`page/${firstPage}`, tabId)
          switchToDocs()
        } else {
          // No pages in groups - auto-select first endpoint
          setSelectedDocPage(null)
          const firstEndpoint = collection ? getFirstEndpoint(collection) : null
          if (firstEndpoint) {
            setSelectedRequest(firstEndpoint)
            updateUrlHash(`endpoint/${firstEndpoint.id}`, tabId)
          } else {
            setSelectedRequest(null)
            updateUrlHash('', tabId)
          }
        }
      } else {
        // No doc groups - auto-select first endpoint
        setSelectedDocPage(null)
        const firstEndpoint = collection ? getFirstEndpoint(collection) : null
        if (firstEndpoint) {
          setSelectedRequest(firstEndpoint)
          updateUrlHash(`endpoint/${firstEndpoint.id}`, tabId)
        } else {
          setSelectedRequest(null)
          updateUrlHash('', tabId)
        }
      }
    } else {
      // Switch to a doc group tab - find and select the first page in that tab
      setSelectedRequest(null)
      setSelectedDocSection(null)

      // Find the first doc group for this tab and select its first page
      if (collection?.docGroups) {
        const tabDocGroup = collection.docGroups.find(g => isGroupForTab(g.id, tabId))

        if (tabDocGroup && tabDocGroup.pages.length > 0) {
          const firstPage = tabDocGroup.pages[0]
          setSelectedDocPage(firstPage.slug)
          updateUrlHash(`page/${firstPage.slug}`, tabId)
          switchToDocs()
        } else {
          setSelectedDocPage(null)
          updateUrlHash('', tabId)
        }
      }
    }
  }, [collection, updateUrlHash, switchToDocs])
  
  // Handler for agent navigation
  const handleAgentNavigate = useCallback((endpointId: string) => {
    if (!collection) return
    const request = findRequestById(collection, endpointId)
    if (request) {
      // Set the tab to API Reference first
      setActiveTab('api-reference')
      // Then set the selected request
      setSelectedRequest(request)
      setSelectedDocSection(null)
      setSelectedDocPage(null)
      updateUrlHash(`endpoint/${endpointId}`, 'api-reference')
      // Reset tab navigation so the new endpoint can determine its default tab
      resetNavigation()
    }
  }, [collection, updateUrlHash, resetNavigation])
  
  // Handler for agent prefilling parameters
  const handleAgentPrefill = useCallback((data: PrefillData) => {
    console.log('[Agent] Prefill requested:', data)
    setPrefill(data)
  }, [setPrefill])
  
  // State for debug context - used to trigger agent debugging
  const [debugContext, setDebugContext] = useState<DebugContext | null>(null)
  
  // Handler for debug requests from playground
  const handleDebugRequest = useCallback((context: DebugContext) => {
    setDebugContext(context)
  }, [])
  
  // Clear debug context after it's been used
  const clearDebugContext = useCallback(() => {
    setDebugContext(null)
  }, [])
  
  // State for explain context - used to trigger agent explanation
  const [explainContext, setExplainContext] = useState<DebugContext | null>(null)
  
  // Handler for explain requests from playground
  const handleExplainRequest = useCallback((context: DebugContext) => {
    setExplainContext(context)
  }, [])
  
  // Clear explain context after it's been used
  const clearExplainContext = useCallback(() => {
    setExplainContext(null)
  }, [])

  // Handle browser back/forward
  useEffect(() => {
    if (!collection) return
    
    const handlePopState = () => {
      navigateToHash(collection)
    }
    
    window.addEventListener('popstate', handlePopState)
    return () => window.removeEventListener('popstate', handlePopState)
  }, [collection, navigateToHash])

  // Dynamically set favicon from docs.json config
  useEffect(() => {
    if (!collection?.docsFavicon) return
    
    const faviconPath = collection.docsFavicon
    
    // Update or create link elements for favicon
    const updateFaviconLink = (rel: string, href: string) => {
      let link = document.querySelector(`link[rel="${rel}"]`) as HTMLLinkElement
      if (!link) {
        link = document.createElement('link')
        link.rel = rel
        document.head.appendChild(link)
      }
      link.href = href
    }
    
    // Determine the type based on file extension
    const ext = faviconPath.split('.').pop()?.toLowerCase()
    const type = ext === 'svg' ? 'image/svg+xml' 
      : ext === 'png' ? 'image/png'
      : ext === 'ico' ? 'image/x-icon'
      : 'image/png'
    
    // Update the favicon link with type
    let iconLink = document.querySelector('link[rel="icon"]') as HTMLLinkElement
    if (!iconLink) {
      iconLink = document.createElement('link')
      iconLink.rel = 'icon'
      document.head.appendChild(iconLink)
    }
    iconLink.type = type
    iconLink.href = faviconPath
    
    // Also update shortcut icon and apple-touch-icon
    updateFaviconLink('shortcut icon', faviconPath)
    updateFaviconLink('apple-touch-icon', faviconPath)
  }, [collection?.docsFavicon])

  useEffect(() => {
    async function fetchCollection() {
      try {
        // Only show full loading on initial load
        const isInitialLoad = !collection
        if (isInitialLoad) {
          setLoading(true)
        } else {
          setIsVersionLoading(true)
        }
        setError(null)
        
        // Build URL with version param if selected
        const url = selectedApiVersion 
          ? `/api/collections?version=${encodeURIComponent(selectedApiVersion)}`
          : '/api/collections'
        
        const response = await fetch(url)
        
        if (!response.ok) {
          throw new Error(`Failed to fetch collection: ${response.status}`)
        }

        const data = await response.json()
        setCollection(data)
        
        // Set initial API version if not already set
        if (!selectedApiVersion && data?.selectedApiVersion) {
          setSelectedApiVersion(data.selectedApiVersion)
        }
        
        // Only run initial navigation logic on first load, not on version changes
        if (isInitialLoad) {
          // Set initial active tab from config (first tab) and select first item
          let initialTabId = 'api-reference'
          if (data?.navigationTabs && data.navigationTabs.length > 0) {
            const sortedTabs = [...data.navigationTabs].sort((a, b) => a.order - b.order)
            initialTabId = sortedTabs[0].id
            setActiveTab(initialTabId)
          }
          
          // Handle initial hash navigation after collection loads
          if (data) {
            // Use setTimeout to ensure state is set before navigation
            setTimeout(() => {
              const hash = window.location.hash.slice(1)

              if (!hash) {
                // No hash - set URL to initial tab
                setSelectedDocSection(null)

                // Find the tab config to check its type
                const tabConfig = data.navigationTabs?.find((t: NavigationTab) => t.id === initialTabId)
                const isApiTab = tabConfig?.type === 'openapi' || tabConfig?.type === 'graphql' || initialTabId === 'api-reference'

                if (isApiTab) {
                  // API Reference or GraphQL tab
                  setSelectedDocSection(null)
                  
                  // Check if there are doc groups for this tab (MDX pages)
                  const hasGroups = hasDocGroupsForTab(data.docGroups, initialTabId)
                  
                  if (hasGroups) {
                    // Has doc groups - select the first page from groups
                    const firstPage = getFirstDocPageForTab(data.docGroups, initialTabId)
                    if (firstPage) {
                      setSelectedDocPage(firstPage)
                      setSelectedRequest(null)
                      updateUrlHash(`page/${firstPage}`, initialTabId)
                    } else {
                      // No pages in groups - auto-select first endpoint
                      setSelectedDocPage(null)
                      const firstEndpoint = getFirstEndpoint(data)
                      if (firstEndpoint) {
                        setSelectedRequest(firstEndpoint)
                        updateUrlHash(`endpoint/${firstEndpoint.id}`, initialTabId)
                      } else {
                        setSelectedRequest(null)
                        updateUrlHash('', initialTabId)
                      }
                    }
                  } else {
                    // No doc groups - auto-select first endpoint
                    setSelectedDocPage(null)
                    const firstEndpoint = getFirstEndpoint(data)
                    if (firstEndpoint) {
                      setSelectedRequest(firstEndpoint)
                      updateUrlHash(`endpoint/${firstEndpoint.id}`, initialTabId)
                    } else {
                      setSelectedRequest(null)
                      updateUrlHash('', initialTabId)
                    }
                  }
                  switchToDocs()
                } else {
                  // Doc group tab - select first page
                  setSelectedRequest(null)
                  const tabDocGroup = data.docGroups?.find((g: BrainfishDocGroup) => 
                    isGroupForTab(g.id, initialTabId)
                  )

                  if (tabDocGroup && tabDocGroup.pages.length > 0) {
                    const firstPage = tabDocGroup.pages[0]
                    setSelectedDocPage(firstPage.slug)
                    updateUrlHash(`page/${firstPage.slug}`, initialTabId)
                    switchToDocs()
                  } else {
                    setSelectedDocPage(null)
                    updateUrlHash('', initialTabId)
                    switchToDocs()
                  }
                }
              } else if (hash === 'notes' || hash.startsWith('notes/')) {
                // Notes mode - handled by ModeContext, just clear API selection
                setSelectedRequest(null)
                setSelectedDocSection(null)
              } else {
                // Parse the hash to get tab and content info
                // Format: #tab or #tab/type/id (e.g., #api-reference/endpoint/123)
                const parts = hash.split('/')
                const hashTab = parts[0]
                const hashType = parts[1]
                const hashId = parts.slice(2).join('/')
                
                // Set the tab from the hash
                if (hashTab && data.navigationTabs?.some((t: NavigationTab) => t.id === hashTab)) {
                  setActiveTab(hashTab)
                }
                
                // Handle legacy format (endpoint/xxx without tab prefix)
                const isLegacyFormat = hash.startsWith('endpoint/') || hash.startsWith('page/') || hash.startsWith('doc/')
                const actualType = isLegacyFormat ? parts[0] : hashType
                const actualId = isLegacyFormat ? parts.slice(1).join('/') : hashId
                
                if (actualType === 'endpoint' && actualId) {
                  const request = findRequestById(data, actualId)
                  if (request) {
                    setSelectedRequest(request)
                    setSelectedDocSection(null)
                    setSelectedDocPage(null)
                    switchToDocs()
                    return
                  } else {
                    setSelectedRequest(null)
                    setSelectedDocSection(null)
                    setSelectedDocPage(null)
                    switchToDocs()
                  }
                } else if (actualType === 'page' && actualId) {
                  setSelectedDocPage(actualId)
                  setSelectedRequest(null)
                  setSelectedDocSection(null)
                  switchToDocs()
                } else if (actualType === 'doc' && actualId) {
                  setSelectedDocSection(actualId)
                  setSelectedRequest(null)
                  setSelectedDocPage(null)
                  switchToDocs()
                  setTimeout(() => {
                    const element = document.getElementById(actualId)
                    if (element) {
                      element.scrollIntoView({ behavior: 'smooth', block: 'start' })
                    }
                  }, 100)
                } else if (hashTab && !hashType) {
                  // Just a tab, show its default content
                  setSelectedDocSection(null)
                  
                  // Check if this is an API tab
                  const tabConfig = data.navigationTabs?.find((t: NavigationTab) => t.id === hashTab)
                  const isApiTab = tabConfig?.type === 'openapi' || tabConfig?.type === 'graphql' || hashTab === 'api-reference'
                  
                  if (isApiTab) {
                    // Check if there are doc groups for this tab (MDX pages)
                    const hasGroups = hasDocGroupsForTab(data.docGroups, hashTab)
                    
                    if (hasGroups) {
                      // Has doc groups - select the first page from groups
                      const firstPage = getFirstDocPageForTab(data.docGroups, hashTab)
                      if (firstPage) {
                        setSelectedDocPage(firstPage)
                        setSelectedRequest(null)
                        updateUrlHash(`page/${firstPage}`, hashTab)
                      } else {
                        // No pages in groups - auto-select first endpoint
                        setSelectedDocPage(null)
                        const firstEndpoint = getFirstEndpoint(data)
                        if (firstEndpoint) {
                          setSelectedRequest(firstEndpoint)
                          updateUrlHash(`endpoint/${firstEndpoint.id}`, hashTab)
                        } else {
                          setSelectedRequest(null)
                        }
                      }
                    } else {
                      // No doc groups - auto-select first endpoint
                      setSelectedDocPage(null)
                      const firstEndpoint = getFirstEndpoint(data)
                      if (firstEndpoint) {
                        setSelectedRequest(firstEndpoint)
                        updateUrlHash(`endpoint/${firstEndpoint.id}`, hashTab)
                      } else {
                        setSelectedRequest(null)
                      }
                    }
                  } else {
                    setSelectedDocPage(null)
                    setSelectedRequest(null)
                  }
                  switchToDocs()
                }
              }
            }, 0)
          }
        } else {
          // Version change - clear selected endpoint as it may not exist in the new version
          setSelectedRequest(null)
          setSelectedDocSection(null)
        }
      } catch (err) {
        console.error('Error fetching collection:', err)
        setError(err instanceof Error ? err.message : 'Failed to load API documentation')
      } finally {
        setLoading(false)
        setIsVersionLoading(false)
      }
    }

    fetchCollection()
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [switchToDocs, selectedApiVersion])

  // Only show full-page loading on initial load
  if (loading && !collection) {
    return (
      <div className="flex items-center justify-center h-screen">
        <div className="text-center">
          <Spinner size={32} className="text-muted-foreground animate-spin mx-auto mb-3" />
          <p className="text-sm text-muted-foreground">Loading API documentation...</p>
        </div>
      </div>
    )
  }

  if (error) {
    return (
      <div className="flex items-center justify-center h-screen">
        <div className="text-center">
          <p className="text-destructive text-lg mb-2">Error loading documentation</p>
          <p className="text-muted-foreground">{error}</p>
        </div>
      </div>
    )
  }

  if (!collection) {
    return (
      <div className="flex items-center justify-center h-screen">
        <div className="text-center max-w-md">
          <p className="text-muted-foreground mb-2">No API documentation available</p>
          <p className="text-sm text-muted-foreground">
            Please configure your Brainfish API credentials in your environment variables.
          </p>
        </div>
      </div>
    )
  }

  // Only show "configure credentials" if there are no endpoints AND no doc groups
  // Multi-tenant docs may have only doc groups without API endpoints
  const hasDocGroups = collection.docGroups && collection.docGroups.length > 0
  const hasEndpoints = collection.requests.length > 0 || collection.folders.length > 0
  
  if (!hasEndpoints && !hasDocGroups) {
    return (
      <div className="flex items-center justify-center h-screen">
        <div className="text-center max-w-lg p-8">
          <h2 className="text-2xl font-semibold mb-2">{collection.name || 'Documentation'}</h2>
          <p className="text-muted-foreground mb-6">
            {collection.description || 'No documentation content available yet.'}
          </p>
          <div className="bg-muted/50 rounded-lg p-5 text-left text-sm space-y-4">
            <p className="font-medium">Get started with DevDoc:</p>
            <div className="space-y-3">
              <div>
                <p className="text-muted-foreground text-xs mb-1">Create a new project</p>
                <code className="block bg-background px-3 py-2 rounded-md font-mono text-xs">
                  npx create-devdoc-doc my-docs
                </code>
              </div>
              <div>
                <p className="text-muted-foreground text-xs mb-1">Start local development</p>
                <code className="block bg-background px-3 py-2 rounded-md font-mono text-xs">
                  npx devdoc dev
                </code>
              </div>
              <div>
                <p className="text-muted-foreground text-xs mb-1">Deploy to production</p>
                <code className="block bg-background px-3 py-2 rounded-md font-mono text-xs">
                  npx devdoc deploy
                </code>
              </div>
            </div>
            <a 
              href="https://devdoc.sh" 
              target="_blank" 
              rel="noopener noreferrer"
              className="inline-flex items-center gap-1.5 text-primary hover:underline text-sm font-medium"
            >
              Learn more at devdoc.sh
              <svg className="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}>
                <path strokeLinecap="round" strokeLinejoin="round" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
              </svg>
            </a>
          </div>
        </div>
      </div>
    )
  }

  return (
    <NavigationProvider collection={collection} onSelectRequest={handleSelectRequest}>
      <DocsWithMode
        collection={collection}
        selectedRequest={selectedRequest}
        selectedDocSection={selectedDocSection}
        selectedDocPage={selectedDocPage}
        activeTab={activeTab}
        onTabChange={handleTabChange}
        contentRef={contentRef}
        showAuthModal={showAuthModal}
        setShowAuthModal={setShowAuthModal}
        handleSelectRequest={handleSelectRequest}
        handleSelectDocumentation={handleSelectDocumentation}
        handleSelectDocPage={handleSelectDocPage}
        handleDebugRequest={handleDebugRequest}
        handleExplainRequest={handleExplainRequest}
        handleAgentNavigate={handleAgentNavigate}
        handleAgentPrefill={handleAgentPrefill}
        debugContext={debugContext}
        clearDebugContext={clearDebugContext}
        explainContext={explainContext}
        clearExplainContext={clearExplainContext}
        navigateAndHighlight={navigateAndHighlight}
        selectedApiVersion={selectedApiVersion}
        handleApiVersionChange={handleApiVersionChange}
        isVersionLoading={isVersionLoading}
        notFoundSlug={notFoundSlug}
      />
    </NavigationProvider>
  )
}

// Mode-aware rendering component
interface DocsWithModeProps {
  collection: CollectionWithSummary
  selectedRequest: BrainfishRESTRequest | null
  selectedDocSection: string | null
  selectedDocPage: string | null
  activeTab: string
  onTabChange: (tabId: string) => void
  contentRef: React.RefObject<HTMLDivElement | null>
  showAuthModal: boolean
  setShowAuthModal: (show: boolean) => void
  handleSelectRequest: (request: BrainfishRESTRequest) => void
  handleSelectDocumentation: (headingId: string) => void
  handleSelectDocPage: (slug: string) => void
  handleDebugRequest: (context: DebugContext) => void
  handleExplainRequest: (context: DebugContext) => void
  handleAgentNavigate: (endpointId: string) => void
  handleAgentPrefill: (data: PrefillData) => void
  debugContext: DebugContext | null
  clearDebugContext: () => void
  explainContext: DebugContext | null
  clearExplainContext: () => void
  navigateAndHighlight: (tab: PlaygroundTab, field?: HighlightField, showError?: boolean) => void
  selectedApiVersion: string | null
  handleApiVersionChange: (version: string) => void
  isVersionLoading: boolean
  notFoundSlug: string | null
}

// Mode toggle tabs - switches between Docs, API Client, and Notes
function ModeToggleTabs({ hasEndpoint }: { hasEndpoint: boolean }) {
  const { mode, switchToDocs, switchToApiClient, switchToNotes } = useModeContext()
  
  return (
    <div className="flex items-center gap-1 p-1 rounded-lg bg-muted/50 shrink-0">
      <Button
        variant={mode === 'docs' ? 'secondary' : 'ghost'}
        size="sm"
        onClick={() => switchToDocs()}
        className={cn(
          "text-xs h-7 px-2 sm:px-3 gap-1.5",
          mode === 'docs' ? 'bg-background shadow-sm' : 'text-muted-foreground hover:text-foreground'
        )}
      >
        <Book className="h-3.5 w-3.5" weight="bold" />
        <span className="hidden xs:inline">Docs</span>
      </Button>
      {hasEndpoint && (
        <Button
          variant={mode === 'api_client' ? 'secondary' : 'ghost'}
          size="sm"
          onClick={() => switchToApiClient()}
          className={cn(
            "text-xs h-7 px-2 sm:px-3 gap-1.5",
            mode === 'api_client' ? 'bg-background shadow-sm' : 'text-muted-foreground hover:text-foreground'
          )}
        >
          <TestTube className="h-3.5 w-3.5" weight="bold" />
          <span className="hidden xs:inline">API Client</span>
        </Button>
      )}
      <Button
        variant={mode === 'notes' ? 'secondary' : 'ghost'}
        size="sm"
        onClick={() => switchToNotes()}
        className={cn(
          "text-xs h-7 px-2 sm:px-3 gap-1.5",
          mode === 'notes' ? 'bg-background shadow-sm' : 'text-muted-foreground hover:text-foreground'
        )}
      >
        <Code className="h-3.5 w-3.5" weight="bold" />
        <span className="hidden xs:inline">Sandbox</span>
      </Button>
    </div>
  )
}

function DocsWithMode({
  collection,
  selectedRequest,
  selectedDocSection,
  selectedDocPage,
  activeTab,
  onTabChange,
  contentRef,
  showAuthModal,
  setShowAuthModal,
  handleSelectRequest,
  handleSelectDocumentation,
  handleSelectDocPage,
  handleDebugRequest,
  handleExplainRequest,
  handleAgentNavigate,
  handleAgentPrefill,
  debugContext,
  clearDebugContext,
  explainContext,
  clearExplainContext,
  navigateAndHighlight,
  selectedApiVersion,
  handleApiVersionChange,
  isVersionLoading,
  notFoundSlug,
}: DocsWithModeProps) {
  const { mode, switchToDocs } = useModeContext()
  const { setTheme } = useTheme()
  
  // GraphQL state
  const [graphqlOperations, setGraphqlOperations] = useState<GraphQLOperationItem[]>([])
  const [graphqlCollection, setGraphqlCollection] = useState<BrainfishCollection | null>(null)
  const [selectedGraphQLOperation, setSelectedGraphQLOperation] = useState<GraphQLOperationItem | null>(null)
  
  // Get API spec URL from environment or collection
  const apiSpecUrl = process.env.NEXT_PUBLIC_OPENAPI_URL || collection.name || 'default'
  
  // Check if there are endpoints
  const hasEndpoints = collection.folders.length > 0 || collection.requests.length > 0
  
  // Search functionality
  const { isOpen: searchOpen, setIsOpen: setSearchOpen, openSearch, searchItems } = useSearch({
    requests: collection.requests,
    folders: collection.folders,
    docGroups: collection.docGroups,
  })
  
  // Handle search item selection - use URL hash navigation
  const handleSearchSelect = useCallback((item: { id: string; type: string; href: string }) => {
    if (item.type === 'endpoint') {
      // Navigate to endpoint via hash - format: #api-reference/endpoint/{id}
      window.location.hash = `api-reference/endpoint/${item.id}`
    } else if (item.type === 'doc') {
      // Navigate to doc page via hash - the href already has the correct format
      // Extract tab and path from href (e.g., #guides/page/quickstart)
      const hashPath = item.href.replace('#', '')
      window.location.hash = hashPath
    }
  }, [])
  
  // Wrap agent navigate to switch to Docs mode and navigate to endpoint
  const handleAgentNavigateWithModeSwitch = useCallback((endpointId: string) => {
    // Just navigate - handleAgentNavigate already sets the tab via setActiveTab
    handleAgentNavigate(endpointId)
  }, [handleAgentNavigate])
  
  // Get the current content title for header
  // Find the active tab's config
  const activeTabConfig = collection.navigationTabs?.find(t => t.id === activeTab)
  const activeTabType = activeTabConfig?.type || 'docs'

  
  // Filter doc groups for sidebar based on active tab
  // Group IDs are like "group-guides-getting-started", tab IDs are like "guides"
  // Filter doc groups for sidebar based on active tab
  // Group IDs are formatted as: group-{tab-id}-{group-name}
  const filteredDocGroups = collection.docGroups?.filter(g => isGroupForTab(g.id, activeTab)) || []
  
  // Show endpoints in sidebar only when OpenAPI tab is active
  const showEndpoints = activeTabType === 'openapi'
  
  // Show changelog when changelog tab is active
  const showChangelog = activeTabType === 'changelog'
  
  // Show GraphQL playground when graphql tab is active
  const showGraphQL = activeTabType === 'graphql'
  const activeGraphQLSchemas = activeTabConfig?.graphqlSchemas || []
  
  // Get the first schema path for stable dependency
  const schemaPath = activeGraphQLSchemas[0]?.schema
  const schemaEndpoint = activeGraphQLSchemas[0]?.endpoint
  
  // Load GraphQL operations when graphql tab is active
  useEffect(() => {
    if (!showGraphQL || !schemaPath) {
      setGraphqlOperations([])
      setGraphqlCollection(null)
      setSelectedGraphQLOperation(null) // Clear selection when leaving GraphQL tab
      return
    }
    
    // Load and parse GraphQL schema
    const loadGraphQLSchema = async () => {
      try {
        const response = await fetch(`/api/schema?path=${encodeURIComponent(schemaPath)}`)
        if (!response.ok) return
        
        const schemaContent = await response.text()
        const operations = parseGraphQLSchema(schemaContent)
        setGraphqlOperations(operations)
        
        // Convert to BrainfishCollection for sidebar
        const gqlCollection = convertGraphQLToCollection(operations, schemaEndpoint || '')
        setGraphqlCollection(gqlCollection)
      } catch (err) {
        console.error('Failed to load GraphQL schema:', err)
      }
    }
    
    loadGraphQLSchema()
  }, [showGraphQL, schemaPath, schemaEndpoint])
  
  // Auto-select GraphQL operation from URL hash or default to first operation
  useEffect(() => {
    if (!showGraphQL || graphqlOperations.length === 0) {
      return
    }
    
    // Check if there's a selection in the URL hash first
    const hash = window.location.hash.slice(1) // Remove #
    if (hash) {
      const parts = hash.split('/')
      const hashType = parts[1]
      const hashId = parts.slice(2).join('/')
      
      if (hashType === 'endpoint' && hashId) {
        // Try to find and select the operation from the URL hash
        const operation = graphqlOperations.find(op => op.id === hashId)
        if (operation) {
          setSelectedGraphQLOperation(operation)
          return
        }
      }
    }
    
    // If already have a selection, don't override it
    if (selectedGraphQLOperation) {
      return
    }
    
    // Check if there are doc groups for this tab first
    const hasGroups = hasDocGroupsForTab(collection?.docGroups, activeTab)
    if (!hasGroups) {
      // No doc groups - auto-select first GraphQL operation
      const firstOperation = graphqlOperations[0]
      setSelectedGraphQLOperation(firstOperation)
      window.history.pushState(null, '', `#${activeTab}/endpoint/${firstOperation.id}`)
    }
  }, [showGraphQL, graphqlOperations, selectedGraphQLOperation, activeTab, collection?.docGroups])
  
  // Handle GraphQL operation selection from sidebar
  const handleSelectGraphQLOperation = useCallback((request: BrainfishRESTRequest) => {
    // Find the matching GraphQL operation
    const operation = graphqlOperations.find(op => op.id === request.id)
    if (operation) {
      setSelectedGraphQLOperation(operation)
      // Update URL hash
      window.history.pushState(null, '', `#${activeTab}/endpoint/${request.id}`)
      switchToDocs()
    }
  }, [graphqlOperations, activeTab, switchToDocs])
  
  // Inject custom CSS and color variables
  useEffect(() => {
    // Create or update style element for custom CSS
    let styleEl = document.getElementById('docs-custom-css') as HTMLStyleElement | null
    if (!styleEl) {
      styleEl = document.createElement('style')
      styleEl.id = 'docs-custom-css'
      document.head.appendChild(styleEl)
    }
    
    // Build CSS with color variables
    let cssContent = ''
    
    // Add color variables if provided
    if (collection.docsColors) {
      const colors = collection.docsColors
      cssContent += `:root {\n`
      if (colors.primary) cssContent += `  --docs-primary: ${colors.primary};\n`
      if (colors.primaryLight) cssContent += `  --docs-primary-light: ${colors.primaryLight};\n`
      if (colors.primaryDark) cssContent += `  --docs-primary-dark: ${colors.primaryDark};\n`
      cssContent += `}\n\n`
    }
    
    // Add custom CSS if provided
    if (collection.customCss) {
      cssContent += collection.customCss
    }
    
    styleEl.textContent = cssContent
    
    return () => {
      // Cleanup on unmount
      const el = document.getElementById('docs-custom-css')
      if (el) el.remove()
    }
  }, [collection.customCss, collection.docsColors])
  
  // Apply default theme from theme.json on initial load
  // Use a ref to track if we've already applied the default theme
  const hasAppliedDefaultTheme = useRef(false)
  useEffect(() => {
    if (collection?.defaultTheme && !hasAppliedDefaultTheme.current) {
      setTheme(collection.defaultTheme)
      hasAppliedDefaultTheme.current = true
    }
  }, [collection?.defaultTheme, setTheme])
  
  return (
    <div className="docs-viewer-root flex flex-col h-screen overflow-hidden">
      {/* Notice */}
      {collection.notice && (
        <Notice config={collection.notice} storageKey="docs-notice" />
      )}
      
      {/* Search Dialog */}
      <SearchDialog
        open={searchOpen}
        onOpenChange={setSearchOpen}
        items={searchItems}
        onSelect={handleSearchSelect}
      />
      
      {/* Header with tabs */}
      <DocsHeader
        docGroups={collection.docGroups}
        navigationTabs={collection.navigationTabs}
        activeTab={activeTab}
        onTabChange={onTabChange}
        hasEndpoints={hasEndpoints}
        docsName={collection.docsName}
        docsLogo={collection.docsLogo}
        onSearchClick={openSearch}
        docsHeader={collection.docsHeader}
        docsNavbar={collection.docsNavbar}
      />
      
      <div className="docs-layout flex flex-1 overflow-hidden relative z-0 min-h-0">
        {/* Left Sidebar - Hidden for changelog */}
        {!showChangelog && (
          <DocsSidebar
            collection={{
              ...collection,
              // Show GraphQL operations when GraphQL tab is active, else show REST endpoints
              folders: showGraphQL && graphqlCollection 
                ? graphqlCollection.folders 
                : (showEndpoints ? collection.folders : []),
              requests: showGraphQL && graphqlCollection
                ? graphqlCollection.requests
                : (showEndpoints ? collection.requests : []),
              // Only show filtered doc groups
              docGroups: filteredDocGroups,
            }}
            selectedRequest={showGraphQL ? (selectedGraphQLOperation ? { id: selectedGraphQLOperation.id } as BrainfishRESTRequest : null) : selectedRequest}
            selectedDocSection={selectedDocSection}
            selectedDocPage={selectedDocPage}
            activeTab={activeTab}
            onSelectRequest={showGraphQL ? handleSelectGraphQLOperation : handleSelectRequest}
            onSelectDocumentation={handleSelectDocumentation}
            onSelectDocPage={handleSelectDocPage}
            apiVersions={collection.apiVersions}
            selectedApiVersion={selectedApiVersion}
            onApiVersionChange={handleApiVersionChange}
            isVersionLoading={isVersionLoading}
          />
        )}
        
        {/* Center - Toggles between API Client/Playground and Notes */}
        <div className="docs-main flex-1 flex flex-col overflow-hidden" style={{ minWidth: 0, flexBasis: 0, flexGrow: 1 }}>
          {/* Mode Toggle Header */}
          <div className="docs-main-header flex items-center justify-end px-3 sm:px-4 h-[41px] border-b border-border bg-muted/30 flex-shrink-0">
            <ModeToggleTabs hasEndpoint={!!selectedRequest} />
          </div>
          
          {/* Content Area */}
          {mode === 'docs' ? (
            <DocsNavigationProvider
              onNavigateToPage={handleSelectDocPage}
              onSwitchTab={onTabChange}
              activeTab={activeTab}
            >
              <div 
                ref={contentRef}
                className={cn(
                  "docs-content-area flex-1 bg-background min-w-0",
                  (showChangelog || (showGraphQL && selectedGraphQLOperation)) ? "overflow-hidden flex flex-col" : "overflow-y-auto scroll-smooth"
                )}
              >
                {showGraphQL && selectedGraphQLOperation ? (
                  <div className="flex-1 flex flex-col h-full">
                    <GraphQLPlayground
                      endpoint={activeGraphQLSchemas[0]?.endpoint || ''}
                      defaultQuery={selectedGraphQLOperation?.query}
                      operations={graphqlOperations}
                      selectedOperationId={selectedGraphQLOperation?.id}
                      hideExplorer={true}
                      headers={{}}
                      theme="dark"
                    />
                  </div>
                ) : showChangelog ? (
                  <ChangelogPage
                    releases={collection.changelogReleases || []}
                    tabName={activeTabConfig?.tab}
                  />
                ) : selectedRequest ? (
                  <RequestDetails request={selectedRequest} />
                ) : selectedDocPage ? (
                  <DocPage slug={selectedDocPage} onSearch={openSearch} />
                ) : notFoundSlug ? (
                  <NotFoundPage slug={notFoundSlug} onSearch={openSearch} />
                ) : (
                  <div className="flex-1 flex items-center justify-center bg-background">
                    <div className="text-center text-muted-foreground">
                      <Book className="h-12 w-12 mx-auto mb-3 opacity-40" />
                      <p className="text-sm">Select an endpoint from the sidebar</p>
                    </div>
                  </div>
                )}
              </div>
            </DocsNavigationProvider>
          ) : mode === 'notes' ? (
            <div className="flex-1 flex flex-col min-h-0 overflow-hidden">
              <NotesMode apiSpecUrl={apiSpecUrl} apiName={collection.name} />
            </div>
          ) : selectedRequest ? (
            <div className="flex-1 flex flex-col min-h-0 overflow-hidden">
              <ApiPlayground 
                request={selectedRequest} 
                onDebugRequest={handleDebugRequest}
                onExplainRequest={handleExplainRequest}
              />
            </div>
          ) : (
            <div className="flex-1 flex items-center justify-center bg-background">
              <div className="text-center text-muted-foreground">
                <TestTube className="h-12 w-12 mx-auto mb-3 opacity-40" />
                <p className="text-sm">Select an endpoint from the sidebar to test</p>
              </div>
            </div>
          )}
        </div>

        {/* Right Sidebar - Agent Panel (drawer on mobile, always visible on desktop) */}
        <RightSidebar
          request={selectedRequest}
          collection={collection}
          apiSummary={collection.apiSummary}
          onNavigateToEndpoint={handleAgentNavigateWithModeSwitch}
          onPrefillParameters={handleAgentPrefill}
          debugContext={debugContext}
          onClearDebugContext={clearDebugContext}
          explainContext={explainContext}
          onClearExplainContext={clearExplainContext}
          onOpenGlobalAuth={() => setShowAuthModal(true)}
          onNavigateToAuthTab={() => {
            navigateAndHighlight('auth', { type: 'auth' }, true)
          }}
          onNavigateToParamsTab={() => {
            navigateAndHighlight('params', { type: 'param' }, true)
          }}
          onNavigateToBodyTab={() => {
            navigateAndHighlight('body', { type: 'body' }, true)
          }}
          onNavigateToHeadersTab={() => {
            navigateAndHighlight('headers', { type: 'header' }, true)
          }}
          onNavigateToDocSection={handleSelectDocumentation}
          onNavigateToDocPage={handleSelectDocPage}
        />
      </div>

      {/* Global Auth Modal */}
      <GlobalAuthModal 
        open={showAuthModal} 
        onClose={() => setShowAuthModal(false)} 
      />
    </div>
  )
}

// Wrapper component with providers
export function Docs() {
  return (
    <AuthProvider>
      <ModeProvider>
        <PlaygroundProvider>
          <PlaygroundNavigationProvider>
            <DocsContent />
          </PlaygroundNavigationProvider>
        </PlaygroundProvider>
      </ModeProvider>
    </AuthProvider>
  )
}
