'use client'

import React, { createContext, useContext, useState, useCallback, useEffect, useRef, type ReactNode } from 'react'
import type { PlaygroundMode } from './types'

/**
 * Streaming content for real-time code display
 */
interface StreamingContent {
  path: string
  content: string
  isStreaming: boolean
}

/**
 * Simplified mode context - toggles between Docs, API Client, and Notes
 * Uses URL hash for persistence: #notes or #notes/path/to/file.py
 */
interface ModeContextValue {
  // Current mode
  mode: PlaygroundMode
  
  // Active file in notes mode (for navigation from agent)
  activeFilePath: string | null
  setActiveFilePath: (path: string | null) => void
  
  // Streaming content for real-time display
  streamingContent: StreamingContent | null
  setStreamingContent: (content: StreamingContent | null) => void
  appendStreamingContent: (delta: string) => void
  
  // Mode switching
  switchToDocs: () => void
  switchToNotes: (openFile?: string) => void
  switchToApiClient: () => void
  
  // Notes refresh trigger - increment to signal notes-mode to refresh
  notesRefreshTrigger: number
  triggerNotesRefresh: () => void
}

const ModeContext = createContext<ModeContextValue | null>(null)

interface ModeProviderProps {
  children: ReactNode
  defaultMode?: PlaygroundMode
}

// Helper to parse notes path from URL hash
function parseNotesHash(): { isNotes: boolean; filePath: string | null } {
  if (typeof window === 'undefined') return { isNotes: false, filePath: null }
  
  const hash = window.location.hash.slice(1) // Remove #
  if (hash === 'notes') {
    return { isNotes: true, filePath: null }
  }
  if (hash.startsWith('notes/')) {
    // Decode any encoded characters but path should mostly be plain text
    const filePath = decodeURIComponent(hash.slice(6)) // Remove 'notes/'
    return { isNotes: true, filePath: filePath || null }
  }
  return { isNotes: false, filePath: null }
}

// Helper to update URL hash for notes
// Only encode special chars that would break the URL, keep slashes readable
function updateNotesHash(filePath: string | null): void {
  if (typeof window === 'undefined') return
  
  const newHash = filePath 
    ? `#notes/${filePath.replace(/#/g, '%23').replace(/\?/g, '%3F')}`
    : '#notes'
  
  window.history.pushState(null, '', newHash)
}

export function ModeProvider({ children, defaultMode = 'docs' }: ModeProviderProps) {
  const [mode, setMode] = useState<PlaygroundMode>(defaultMode)
  const [activeFilePath, setActiveFilePathState] = useState<string | null>(null)
  const [streamingContent, setStreamingContent] = useState<StreamingContent | null>(null)
  const [notesRefreshTrigger, setNotesRefreshTrigger] = useState(0)
  
  // Use ref to track mode for callbacks (avoids stale closure issues)
  const modeRef = useRef<PlaygroundMode>(defaultMode)
  
  // Keep ref in sync with state
  useEffect(() => {
    modeRef.current = mode
  }, [mode])

  // Initialize from URL hash on mount
  useEffect(() => {
    const { isNotes, filePath } = parseNotesHash()
    
    if (isNotes) {
      setMode('notes')
      modeRef.current = 'notes'
      setActiveFilePathState(filePath)
    }
  }, [])

  // Handle browser back/forward navigation
  useEffect(() => {
    const handlePopState = () => {
      const { isNotes, filePath } = parseNotesHash()
      
      if (isNotes) {
        setMode('notes')
        modeRef.current = 'notes'
        setActiveFilePathState(filePath)
      } else {
        // Default to docs mode when no notes hash
        setMode('docs')
        modeRef.current = 'docs'
      }
    }
    
    window.addEventListener('popstate', handlePopState)
    return () => window.removeEventListener('popstate', handlePopState)
  }, [])

  // Wrapper for setActiveFilePath that also updates URL
  const setActiveFilePath = useCallback((path: string | null) => {
    // Handle the ?t= timestamp suffix for forcing reloads
    const cleanPath = path?.split('?')[0] || null
    setActiveFilePathState(cleanPath)
    
    // Update URL if we're in notes mode (use ref to avoid stale closure)
    if (modeRef.current === 'notes') {
      updateNotesHash(cleanPath)
    }
  }, []) // No dependencies - uses ref

  const switchToNotes = useCallback((openFile?: string) => {
    const filePath = openFile || null
    setActiveFilePathState(filePath)
    setMode('notes')
    modeRef.current = 'notes'
    updateNotesHash(filePath)
  }, [])

  const switchToApiClient = useCallback(() => {
    setMode('api_client')
    modeRef.current = 'api_client'
    // Don't update URL here - let the main API docs component handle it
  }, [])

  const switchToDocs = useCallback(() => {
    setMode('docs')
    modeRef.current = 'docs'
    // Only clear the hash if it's a notes hash, preserve doc/endpoint hashes
    if (typeof window !== 'undefined') {
      const hash = window.location.hash.slice(1)
      if (hash === 'notes' || hash.startsWith('notes/')) {
        window.history.pushState(null, '', window.location.pathname + window.location.search)
      }
    }
  }, [])

  const appendStreamingContent = useCallback((delta: string) => {
    setStreamingContent(prev => {
      if (!prev) return prev
      return {
        ...prev,
        content: prev.content + delta,
      }
    })
  }, [])

  const triggerNotesRefresh = useCallback(() => {
    setNotesRefreshTrigger(prev => prev + 1)
  }, [])

  const value: ModeContextValue = {
    mode,
    activeFilePath,
    setActiveFilePath,
    streamingContent,
    setStreamingContent,
    appendStreamingContent,
    switchToDocs,
    switchToNotes,
    switchToApiClient,
    notesRefreshTrigger,
    triggerNotesRefresh,
  }

  return (
    <ModeContext.Provider value={value}>
      {children}
    </ModeContext.Provider>
  )
}

export function useModeContext() {
  const context = useContext(ModeContext)
  if (!context) {
    throw new Error('useModeContext must be used within a ModeProvider')
  }
  return context
}

// Hook for checking if we're in notes mode
export function useIsNotesMode() {
  const { mode } = useModeContext()
  return mode === 'notes'
}
