'use client'

import { useRef, useCallback, useMemo } from 'react'
import Editor, { OnMount, OnChange, loader } from '@monaco-editor/react'
import type { editor } from 'monaco-editor'

// Configure Monaco to use CDN
loader.config({
  paths: {
    vs: 'https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs',
  },
})

export type SupportedLanguage = 
  | 'json' 
  | 'xml' 
  | 'html' 
  | 'plaintext' 
  | 'javascript' 
  | 'typescript' 
  | 'shell'
  | 'python'
  | 'go'
  | 'java'
  | 'csharp'
  | 'ruby'
  | 'php'
  | 'swift'
  | 'kotlin'
  | 'rust'
  | 'c'
  | 'powershell'
  | 'clojure'
  | 'objective-c'
  | 'r'

interface CodeEditorProps {
  value: string
  onChange?: (value: string) => void
  language?: SupportedLanguage
  readOnly?: boolean
  height?: string | number
  minHeight?: number
  maxHeight?: number
  className?: string
  placeholder?: string
  theme?: 'light' | 'dark'
  showBorder?: boolean
  rounded?: boolean
  showLineNumbers?: boolean
}

// Helper to format JSON properly
function formatValue(value: string, language: string): string {
  if (language === 'json') {
    try {
      // Try to parse and re-stringify with proper formatting
      const parsed = JSON.parse(value)
      return JSON.stringify(parsed, null, 2)
    } catch {
      // If it's not valid JSON, return as-is
      return value
    }
  }
  return value
}

// Calculate height based on content lines
function calculateHeight(value: string, minHeight: number, maxHeight?: number): number {
  const lineHeight = 20 // Approximate line height in pixels
  const padding = 24 // Top + bottom padding
  const lines = value.split('\n').length
  const contentHeight = (lines * lineHeight) + padding
  
  let height = Math.max(contentHeight, minHeight)
  if (maxHeight) {
    height = Math.min(height, maxHeight)
  }
  return height
}

export function CodeEditor({
  value,
  onChange,
  language = 'json',
  readOnly = false,
  height = '100%',
  minHeight = 100,
  maxHeight,
  className = '',
  placeholder,
  theme = 'light',
  showBorder = true,
  rounded = true,
  showLineNumbers = true,
}: CodeEditorProps) {
  const editorRef = useRef<editor.IStandaloneCodeEditor | null>(null)

  // Format value for display
  const formattedValue = useMemo(() => formatValue(value, language), [value, language])

  const handleMount: OnMount = useCallback((editor) => {
    editorRef.current = editor
  }, [])

  const handleChange: OnChange = useCallback(
    (newValue) => {
      if (onChange && newValue !== undefined) {
        onChange(newValue)
      }
    },
    [onChange]
  )

  const monacoTheme = theme === 'dark' ? 'vs-dark' : 'vs'
  const bgColor = theme === 'dark' ? '!bg-[#1e1e1e]' : 'bg-white'

  // Calculate the actual height for Monaco
  const computedHeight = height === 'auto' 
    ? calculateHeight(formattedValue, minHeight, maxHeight)
    : (typeof height === 'number' ? height : height)

  const borderClass = showBorder ? 'border border-border' : ''
  const roundedClass = rounded ? 'rounded-sm' : ''

  const inlineStyle = {
    height: typeof computedHeight === 'number' ? `${computedHeight}px` : computedHeight,
    backgroundColor: theme === 'dark' ? '#1e1e1e' : undefined,
  }

  return (
    <div 
      className={`relative overflow-hidden ${borderClass} ${roundedClass} ${bgColor} ${className}`}
      style={inlineStyle}
    >
      {!formattedValue && placeholder && (
        <div className="absolute inset-0 flex items-center justify-center text-gray-500 text-sm z-10 pointer-events-none">
          {placeholder}
        </div>
      )}
      <Editor
        height="100%"
        language={language}
        value={formattedValue}
        onChange={handleChange}
        onMount={handleMount}
        theme={monacoTheme}
        options={{
          readOnly,
          domReadOnly: readOnly,
          contextmenu: !readOnly,
          minimap: { enabled: false },
          scrollBeyondLastLine: false,
          fontSize: 13,
          fontFamily: "'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, monospace",
          lineNumbers: showLineNumbers ? (readOnly ? 'on' : 'on') : 'off',
          renderLineHighlight: readOnly ? 'none' : 'line',
          scrollbar: {
            vertical: 'auto',
            horizontal: 'auto',
          },
          padding: { top: 12, bottom: 12 },
          wordWrap: 'on',
          automaticLayout: true,
          overviewRulerBorder: false,
          overviewRulerLanes: 0,
          hideCursorInOverviewRuler: true,
          guides: { indentation: !readOnly },
          cursorBlinking: readOnly ? 'solid' : 'smooth',
          lineDecorationsWidth: showLineNumbers ? 8 : 0,
          lineNumbersMinChars: showLineNumbers ? 3 : 0,
        }}
        loading={
          <div className="flex items-center justify-center h-full text-muted-foreground text-sm">
            Loading editor...
          </div>
        }
      />
    </div>
  )
}

// Lightweight read-only viewer version
interface CodeViewerProps {
  value: string
  language?: SupportedLanguage
  height?: string | number
  minHeight?: number
  maxHeight?: number
  className?: string
  theme?: 'light' | 'dark'
  showBorder?: boolean
  rounded?: boolean
  showLineNumbers?: boolean
}

export function CodeViewer({
  value,
  language = 'json',
  height = 'auto',
  minHeight = 100,
  maxHeight,
  className = '',
  theme = 'light',
  showBorder = false,
  rounded = false,
  showLineNumbers = true,
}: CodeViewerProps) {
  return (
    <CodeEditor
      value={value}
      language={language}
      readOnly={true}
      height={height}
      minHeight={minHeight}
      maxHeight={maxHeight}
      className={className}
      theme={theme}
      showBorder={showBorder}
      rounded={rounded}
      showLineNumbers={showLineNumbers}
    />
  )
}
