'use client'

import React, { useState, Children, isValidElement, ReactNode } from 'react'
import { cn } from '@/lib/utils'
import { Copy, Check } from '@phosphor-icons/react'

/**
 * CodeGroup Component for MDX Documentation
 * 
 * Groups multiple code blocks with tabs for language/file selection.
 * Similar to Mintlify's CodeGroup component.
 * 
 * Usage:
 * <CodeGroup>
 *   ```js title="helloWorld.js"
 *   console.log("Hello World");
 *   ```
 *   
 *   ```python title="hello_world.py"
 *   print("Hello World")
 *   ```
 * </CodeGroup>
 */

interface CodeBlockInfo {
  title: string
  language: string
  content: string
  element: React.ReactNode
}

interface CodeGroupProps {
  children: React.ReactNode
  className?: string
  /** Display variant: 'default' (dark with underline), 'tabs' (light tab style), 'pills' (pill buttons) */
  variant?: 'default' | 'tabs' | 'pills'
}

// Extract text content from nested React elements
function extractTextContent(node: ReactNode): string {
  if (typeof node === 'string') return node
  if (typeof node === 'number') return String(node)
  if (Array.isArray(node)) return node.map(extractTextContent).join('')
  if (isValidElement(node)) {
    const props = node.props as { children?: ReactNode }
    if (props.children) {
      return extractTextContent(props.children)
    }
  }
  return ''
}

// Extract title from code comment on first line (e.g., "// npm" or "# yarn")
function extractTitleFromComment(code: string): string | null {
  const firstLine = code.trim().split('\n')[0]
  
  // Match various comment styles
  const patterns = [
    /^\/\/\s*(.+)$/,      // // comment
    /^#\s*(.+)$/,         // # comment
    /^\/\*\s*(.+?)\s*\*\/$/,  // /* comment */
    /^<!--\s*(.+?)\s*-->$/,   // <!-- comment -->
    /^--\s*(.+)$/,        // -- comment (SQL)
  ]
  
  for (const pattern of patterns) {
    const match = firstLine.match(pattern)
    if (match && match[1] && match[1].length < 30) {
      return match[1].trim()
    }
  }
  
  return null
}

// Check if element type matches a tag name (handles both string and component types)
function isElementType(element: React.ReactElement, tagName: string): boolean {
  const type = element.type
  if (typeof type === 'string') {
    return type === tagName
  }
  // Check displayName or name for components
  if (typeof type === 'function') {
    const funcType = type as { displayName?: string; name?: string }
    return funcType.displayName === tagName || funcType.name === tagName
  }
  return false
}

// Recursively find all pre elements
function findPreElements(children: ReactNode, results: CodeBlockInfo[] = []): CodeBlockInfo[] {
  Children.forEach(children, (child) => {
    if (!child) return
    
    if (isValidElement(child)) {
      const props = child.props as Record<string, unknown>
      
      // Check if it's a pre element (either native or component)
      if (isElementType(child, 'pre')) {
        const codeChild = props.children
        let language = 'text'
        let content = ''
        
        if (isValidElement(codeChild)) {
          const codeProps = codeChild.props as Record<string, unknown>
          const className = (codeProps.className as string) || ''
          const match = className.match(/language-(\w+)/)
          language = match ? match[1] : 'text'
          content = extractTextContent(codeProps.children as ReactNode)
        } else if (typeof codeChild === 'string') {
          content = codeChild
        } else {
          // Try to get content from nested structure
          content = extractTextContent(codeChild as ReactNode)
        }
        
        // Also check pre element's className for language
        const preClassName = (props.className as string) || ''
        const preMatch = preClassName.match(/language-(\w+)/)
        if (preMatch) {
          language = preMatch[1]
        }
        
        // Check data-language attribute
        if (props['data-language']) {
          language = props['data-language'] as string
        }
        
        // Extract title from various possible locations
        // Priority: data-title > title prop > comment in code > language name
        const commentTitle = extractTitleFromComment(content)
        const title = (props['data-title'] as string) || 
                     (props.title as string) ||
                     commentTitle ||
                     getDisplayName(language)
        
        results.push({ title, language, content, element: child })
      }
      // Check for figure elements (used by some syntax highlighters like rehype-pretty-code)
      else if (isElementType(child, 'figure') && props['data-rehype-pretty-code-figure'] !== undefined) {
        // Find pre inside figure
        findPreElements(props.children as ReactNode, results)
      }
      // Check if it has children and recurse
      else if (props.children) {
        findPreElements(props.children as ReactNode, results)
      }
    }
  })
  
  return results
}

// Get display name for language
function getDisplayName(language: string): string {
  const displayNames: Record<string, string> = {
    javascript: 'JavaScript',
    typescript: 'TypeScript',
    python: 'Python',
    java: 'Java',
    go: 'Go',
    rust: 'Rust',
    ruby: 'Ruby',
    php: 'PHP',
    csharp: 'C#',
    cpp: 'C++',
    c: 'C',
    swift: 'Swift',
    kotlin: 'Kotlin',
    bash: 'Bash',
    shell: 'Shell',
    json: 'JSON',
    yaml: 'YAML',
    html: 'HTML',
    css: 'CSS',
    sql: 'SQL',
    markdown: 'Markdown',
    text: 'Text',
    plaintext: 'Text',
  }
  return displayNames[language.toLowerCase()] || language.charAt(0).toUpperCase() + language.slice(1)
}

export function CodeGroup({ children, className, variant = 'default' }: CodeGroupProps) {
  const blocks = findPreElements(children)
  const [activeIndex, setActiveIndex] = useState(0)
  const [copied, setCopied] = useState(false)
  
  // If no code blocks found, just render children as-is
  if (blocks.length === 0) {
    return <div className={className}>{children}</div>
  }
  
  const activeBlock = blocks[activeIndex]
  
  const handleCopy = async () => {
    if (activeBlock?.content) {
      try {
        await navigator.clipboard.writeText(activeBlock.content.trim())
        setCopied(true)
        setTimeout(() => setCopied(false), 2000)
      } catch (err) {
        console.error('Failed to copy:', err)
      }
    }
  }

  // Tabs variant - dark theme with border tabs
  if (variant === 'tabs') {
    return (
      <div className={cn(
        'docs-code-group docs-code-group-tabs my-4 rounded-xl border border-zinc-800 overflow-hidden bg-[#1a1a1a]',
        className
      )}>
        {/* Tab headers */}
        <div className="docs-code-group-header flex items-center justify-between border-b border-zinc-800 bg-[#262626]">
          <div className="flex overflow-x-auto">
            {blocks.map((block, index) => (
              <button
                key={index}
                type="button"
                onClick={() => setActiveIndex(index)}
                className={cn(
                  'docs-code-group-tab px-4 py-2.5 text-sm font-medium whitespace-nowrap transition-colors border-b-2 -mb-px',
                  'hover:text-white',
                  'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50',
                  activeIndex === index
                    ? 'text-white border-emerald-500'
                    : 'text-zinc-400 border-transparent hover:border-zinc-600'
                )}
              >
                {block.title}
              </button>
            ))}
          </div>
          
          {/* Copy button */}
          <button
            type="button"
            onClick={handleCopy}
            className={cn(
              'mr-3 p-1.5 rounded text-zinc-500 hover:text-zinc-300',
              'hover:bg-zinc-700/50 transition-colors',
              'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50'
            )}
            title="Copy code"
          >
            {copied ? (
              <Check className="h-4 w-4 text-emerald-500" weight="bold" />
            ) : (
              <Copy className="h-4 w-4" />
            )}
          </button>
        </div>
        
        {/* Code content */}
        <div className={cn(
          'docs-code-group-content',
          '[&>pre]:my-0 [&>pre]:rounded-none [&>pre]:border-0 [&>pre]:bg-[#1a1a1a]',
          '[&_pre]:my-0 [&_pre]:rounded-none [&_pre]:border-0 [&_pre]:bg-[#1a1a1a]',
          '[&_code]:bg-transparent [&_pre]:p-4',
          '[&_pre]:text-sm [&_code]:text-sm'
        )}>
          {activeBlock?.element}
        </div>
      </div>
    )
  }

  // Pills variant - pill-shaped buttons with dark theme
  if (variant === 'pills') {
    return (
      <div className={cn(
        'docs-code-group docs-code-group-pills my-4 rounded-xl border border-zinc-800 overflow-hidden bg-[#1a1a1a]',
        className
      )}>
        {/* Pill headers */}
        <div className="docs-code-group-header flex items-center justify-between p-2 bg-[#262626] border-b border-zinc-800">
          <div className="flex gap-1 overflow-x-auto">
            {blocks.map((block, index) => (
              <button
                key={index}
                type="button"
                onClick={() => setActiveIndex(index)}
                className={cn(
                  'docs-code-group-tab px-3 py-1.5 text-xs font-medium whitespace-nowrap rounded-full transition-colors',
                  'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50',
                  activeIndex === index
                    ? 'bg-emerald-500 text-white'
                    : 'text-zinc-400 hover:text-white hover:bg-zinc-700'
                )}
              >
                {block.title}
              </button>
            ))}
          </div>
          
          {/* Copy button */}
          <button
            type="button"
            onClick={handleCopy}
            className={cn(
              'p-1.5 rounded text-zinc-500 hover:text-zinc-300',
              'hover:bg-zinc-700/50 transition-colors',
              'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50'
            )}
            title="Copy code"
          >
            {copied ? (
              <Check className="h-4 w-4 text-emerald-500" weight="bold" />
            ) : (
              <Copy className="h-4 w-4" />
            )}
          </button>
        </div>
        
        {/* Code content */}
        <div className={cn(
          'docs-code-group-content',
          '[&>pre]:my-0 [&>pre]:rounded-none [&>pre]:border-0 [&>pre]:bg-[#1a1a1a]',
          '[&_pre]:my-0 [&_pre]:rounded-none [&_pre]:border-0 [&_pre]:bg-[#1a1a1a]',
          '[&_code]:bg-transparent [&_pre]:p-4',
          '[&_pre]:text-sm [&_code]:text-sm'
        )}>
          {activeBlock?.element}
        </div>
      </div>
    )
  }

  // Default variant - dark theme with underline indicator
  return (
    <div className={cn(
      'docs-code-group docs-code-group-default my-4 rounded-xl border border-zinc-800 overflow-hidden bg-[#1a1a1a]',
      className
    )}>
      {/* Tab headers */}
      <div className="docs-code-group-header flex items-center justify-between bg-[#262626] px-2">
        <div className="flex overflow-x-auto">
          {blocks.map((block, index) => (
            <button
              key={index}
              type="button"
              onClick={() => setActiveIndex(index)}
              className={cn(
                'docs-code-group-tab px-4 py-2.5 text-sm font-medium whitespace-nowrap transition-colors relative',
                'hover:text-white',
                'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50',
                activeIndex === index
                  ? 'text-white'
                  : 'text-zinc-400'
              )}
            >
              {block.title}
              {/* Active indicator line */}
              {activeIndex === index && (
                <span className="absolute bottom-0 left-0 right-0 h-0.5 bg-emerald-500 rounded-full" />
              )}
            </button>
          ))}
        </div>
        
        {/* Copy button */}
        <div className="docs-code-group-actions flex items-center gap-1 pr-2">
          <button
            type="button"
            onClick={handleCopy}
            className={cn(
              'p-1.5 rounded text-zinc-500 hover:text-zinc-300',
              'hover:bg-zinc-700/50 transition-colors',
              'focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/50'
            )}
            title="Copy code"
          >
            {copied ? (
              <Check className="h-4 w-4 text-emerald-500" weight="bold" />
            ) : (
              <Copy className="h-4 w-4" />
            )}
          </button>
        </div>
      </div>
      
      {/* Code content */}
      <div className={cn(
        'docs-code-group-content',
        '[&>pre]:my-0 [&>pre]:rounded-none [&>pre]:border-0 [&>pre]:bg-[#1a1a1a]',
        '[&_pre]:my-0 [&_pre]:rounded-none [&_pre]:border-0 [&_pre]:bg-[#1a1a1a]',
        '[&_code]:bg-transparent [&_pre]:p-4',
        '[&_pre]:text-sm [&_code]:text-sm'
      )}>
        {activeBlock?.element}
      </div>
    </div>
  )
}

/**
 * CodeBlock component for individual code blocks within CodeGroup
 * or standalone use with filename headers
 */
interface CodeBlockProps {
  children: React.ReactNode
  title?: string
  language?: string
  className?: string
}

export function CodeBlockItem({ children, title, language, className }: CodeBlockProps) {
  return (
    <pre 
      className={cn('p-4 overflow-x-auto', className)} 
      data-title={title}
      data-language={language}
    >
      <code className={language ? `language-${language}` : ''}>
        {children}
      </code>
    </pre>
  )
}
