import React, { useState, useEffect, useRef } from 'react'
import Editor from '@monaco-editor/react'
import { ComponentDefinition } from '../../proxy/developerKit/componentInfo'
import { generateSingleComponentJSX, generateUniqueId } from '@/utils/codeParser'
import { FaCheck, FaCode, FaSpinner, FaMousePointer, FaSave, FaCog, FaTimes } from 'react-icons/fa'

interface CodeEditorProps {
  code: string
  onChange: (code: string) => void
  onApplyCodeChanges: (code: string) => void
  onResetCodeChanges: () => void
  language?: string
  theme?: 'vs-dark' | 'light'
  parseError?: string | null
  onCursorChange?: (componentId: string | null) => void
  onDrop?: (componentDef: ComponentDefinition, position: { line: number; column: number }) => void
  onComponentAdded?: (componentDef: ComponentDefinition) => void
  onComponentSave: () => void
}

export const CodeEditor: React.FC<CodeEditorProps> = ({
  code,
  onChange,
  onApplyCodeChanges,
  language = 'typescript',
  theme = 'vs-dark',
  onCursorChange,
  onComponentAdded,
  onComponentSave,
}) => {
  const [localCode, setLocalCode] = useState(code)
  const [hasChanges, setHasChanges] = useState(false)
  const [isFormatting, setIsFormatting] = useState(false)
  const [showSettings, setShowSettings] = useState(false)
  const [editorTheme, setEditorTheme] = useState(theme)
  const [fontSize, setFontSize] = useState(14)
  const [wordWrap, setWordWrap] = useState<'on' | 'off'>('on')
  const [minimap, setMinimap] = useState(true)
  const [showSuccessMessage, setShowSuccessMessage] = useState(false)
  const [isDragOver, setIsDragOver] = useState(false)
  const [dropIndicator, setDropIndicator] = useState<{
    show: boolean
    line: number
    column: number
  }>({ show: false, line: 0, column: 0 })

  const editorRef = useRef<any>(null)
  const containerRef = useRef<HTMLDivElement>(null)
  const cursorChangeTimeout = useRef<number | null>(null)

  useEffect(() => {
    setLocalCode(code)
    setHasChanges(false)
  }, [code])

  useEffect(() => {
    return () => {
      if (cursorChangeTimeout.current) {
        clearTimeout(cursorChangeTimeout.current)
      }
    }
  }, [])

  const findComponentIdAtPosition = (
    code: string,
    position: { lineNumber: number; column: number },
  ): string | null => {
    const lines = code.split('\n')
    const currentLineIndex = position.lineNumber - 1

    // Önce bulunduğu satırı kontrol et
    const line = lines[currentLineIndex] || ''
    const idMatch = line.match(/id=["']([\w-]+)["']/)
    if (idMatch) return idMatch[1]

    // Eğer bulunduğu satırda yoksa, yakındaki satırları kontrol et
    // Önce yukarı doğru ara, sonra aşağı doğru ara
    for (let distance = 1; distance <= 3; distance++) {
      // Yukarı ara
      if (currentLineIndex - distance >= 0) {
        const upLine = lines[currentLineIndex - distance] || ''
        // Component tag başlangıcını kontrol et
        const componentMatch = upLine.match(/<([A-Z][a-zA-Z]*)/)
        if (componentMatch) {
          // Bu component tag'inin ID'sini ara (aynı satırda veya sonraki satırlarda)
          for (
            let j = currentLineIndex - distance;
            j <= Math.min(lines.length - 1, currentLineIndex + 2);
            j++
          ) {
            const searchLine = lines[j] || ''
            const foundId = searchLine.match(/id=["']([\w-]+)["']/)
            if (foundId) return foundId[1]
          }
        }
      }

      // Aşağı ara
      if (currentLineIndex + distance < lines.length) {
        const downLine = lines[currentLineIndex + distance] || ''
        const componentMatch = downLine.match(/<([A-Z][a-zA-Z]*)/)
        if (componentMatch) {
          // Bu component tag'inin ID'sini ara
          for (
            let j = currentLineIndex + distance;
            j <= Math.min(lines.length - 1, currentLineIndex + distance + 2);
            j++
          ) {
            const searchLine = lines[j] || ''
            const foundId = searchLine.match(/id=["']([\w-]+)["']/)
            if (foundId) return foundId[1]
          }
        }
      }
    }

    // Hiçbir şey bulunamadıysa, cursor'ın bulunduğu satırda herhangi bir JSX tag var mı kontrol et
    const jsxMatch = line.match(/<\/?([A-Z][a-zA-Z]*)/)
    if (jsxMatch) {
      // Bu tag'e ait ID'yi bulabilir miyiz?
      const componentName = jsxMatch[1]
      for (
        let i = Math.max(0, currentLineIndex - 5);
        i <= Math.min(lines.length - 1, currentLineIndex + 5);
        i++
      ) {
        const searchLine = lines[i] || ''
        if (searchLine.includes(`<${componentName}`) && searchLine.includes('id=')) {
          const foundId = searchLine.match(/id=["']([\w-]+)["']/)
          if (foundId) return foundId[1]
        }
      }
    }

    return null
  }

  const handleEditorCursorChange = (_event: any) => {
    if (!editorRef.current) return
    const position = editorRef.current.getPosition()
    if (!position) return

    // Throttle the cursor change to avoid too many calls
    if (cursorChangeTimeout.current) {
      clearTimeout(cursorChangeTimeout.current)
    }
    const id = findComponentIdAtPosition(localCode, position)
    if (onCursorChange) onCursorChange(id)
  }

  const handleEditorDidMount = (editor: any, monaco: any) => {
    editorRef.current = editor

    monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
      target: monaco.languages.typescript.ScriptTarget.Latest,
      allowNonTsExtensions: true,
      moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
      module: monaco.languages.typescript.ModuleKind.CommonJS,
      noEmit: true,
      esModuleInterop: true,
      jsx: monaco.languages.typescript.JsxEmit.React,
      reactNamespace: 'React',
      allowJs: true,
      typeRoots: ['node_modules/@types'],
    })

    editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {
      handleApplyChanges()
    })

    editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KeyF, () => {
      handleFormatCode()
    })

    editor.onDidChangeCursorPosition(handleEditorCursorChange)
  }

  const handleCodeChange = (value: string | undefined) => {
    if (value !== undefined) {
      setLocalCode(value)
      setHasChanges(value !== code)
      onChange(value)
    }
  }

  const handleApplyChanges = () => {
    onApplyCodeChanges(localCode)
    setHasChanges(false)
    setShowSuccessMessage(true)
    handleFormatCode()
    setTimeout(() => setShowSuccessMessage(false), 3000)
  }

  const handleFormatCode = async () => {
    if (editorRef.current) {
      setIsFormatting(true)
      try {
        await editorRef.current.getAction('editor.action.formatDocument').run()
      } catch (error) {
        console.error('Kod formatlama hatası:', error)
      } finally {
        setIsFormatting(false)
      }
    }
  }

  const handleResetChanges = () => {
    setLocalCode(code)
    setHasChanges(false)
  }

  // Drag & Drop handlers for Code Editor
  const handleDragOver = (e: React.DragEvent) => {
    e.preventDefault()
    e.stopPropagation()

    if (!editorRef.current || !containerRef.current) return

    try {
      const hasComponentData = e.dataTransfer.types.some(
        (type) => type === 'application/json' || type === 'text/plain' || type === 'text',
      )

      if (hasComponentData) {
        e.dataTransfer.dropEffect = 'copy'
        setIsDragOver(true)

        // Get cursor position from mouse coordinates
        const rect = containerRef.current.getBoundingClientRect()
        const x = e.clientX - rect.left
        const y = e.clientY - rect.top

        // Convert to editor position
        const position = editorRef.current.getTargetAtClientPoint(x, y)
        if (position) {
          setDropIndicator({
            show: true,
            line: position.position.lineNumber,
            column: position.position.column,
          })
        }
      }
    } catch (err) {
      console.warn('Error handling drag over:', err)
    }
  }

  const handleDragLeave = (e: React.DragEvent) => {
    e.preventDefault()
    e.stopPropagation()

    if (!containerRef.current) return

    const rect = containerRef.current.getBoundingClientRect()
    const x = e.clientX
    const y = e.clientY

    if (x <= rect.left || x >= rect.right || y <= rect.top || y >= rect.bottom) {
      setIsDragOver(false)
      setDropIndicator({ show: false, line: 0, column: 0 })
    }
  }

  const handleDrop = (e: React.DragEvent) => {
    e.preventDefault()
    e.stopPropagation()

    setIsDragOver(false)
    setDropIndicator({ show: false, line: 0, column: 0 })

    if (!editorRef.current || !containerRef.current) return

    try {
      let componentDefData
      const formats = ['application/json', 'text/plain', 'text']

      // Sürüklenen bileşenin verisini al
      for (const format of formats) {
        const data = e.dataTransfer.getData(format)

        if (data) {
          componentDefData = data
          break
        }
      }

      if (!componentDefData) return

      let componentDef
      try {
        componentDef = JSON.parse(componentDefData)
      } catch (error) {
        console.error('Component verisi çözümlenemedi:', error)
        return
      }

      // 1. Component ID'sini oluştur
      const componentId = generateUniqueId()

      // 2. Props'ları adapt et ve ID'yi dahil et
      const adaptedProps = {
        ...(componentDef.properties || []).reduce(
          (acc: any, prop: any) => {
            acc[prop.name] = {
              type: prop.type,
              value: prop.value,
              ...(prop.options ? { options: prop.options } : {}),
            }
            return acc
          },
          {} as Record<string, any>,
        ),
        id: {
          type: 'string',
          value: componentId,
        },
      }

      // 3. JSX oluştur
      const componentJSX = generateSingleComponentJSX(componentDef.name, adaptedProps)

      // 4. Component tanımını ID ile genişlet
      const componentDefWithId = {
        ...componentDef,
        id: componentId,
        properties: [
          ...(componentDef.properties || []).filter((p: any) => p.name !== 'id'),
          {
            name: 'id',
            type: 'string',
            value: componentId,
            category: 'properties',
          },
        ],
      }

      // 5. Pozisyonu al
      let position = editorRef.current.getPosition()
      if (!position) {
        console.error('Geçersiz pozisyon tespit edildi. Yedek pozisyon kullanılıyor.')
        position = { lineNumber: 0, column: 0 }
      }

      // 6. JSX kodunu pozisyonda ekle
      const newCode = insertJSXAtPosition(localCode, componentJSX, position)
      setLocalCode(newCode)
      onChange(newCode)

      // 7. Parent'a bildirim gönder
      if (onComponentAdded) {
        onComponentAdded(componentDefWithId)
      }

      // 8. Uygulamayı tetikle
      setTimeout(() => {
        onApplyCodeChanges(newCode)
      }, 100)
    } catch (error) {
      console.error('Bileşen bırakılırken hata oluştu:', error)
    }
  }

  const insertJSXAtPosition = (
    code: string,
    jsx: string,
    position: { lineNumber: number; column: number },
  ): string => {
    const updatedCode = code
    const lines = updatedCode.split('\n')

    // Pozisyonu doğrula (import eklendiyse satır numaraları değişmiş olabilir)
    if (position.lineNumber < 1 || position.lineNumber > lines.length) {
      console.error('Geçersiz satır numarası:', position.lineNumber)
      position.lineNumber = lines.length // Geçersiz satırda son satıra ekle
    }

    const line = lines[position.lineNumber - 1] // 1 tabanlı indeks, 0 tabanlıya çevrilir

    if (!line) {
      console.error('Satır bulunamadı:', position.lineNumber)
      return updatedCode // Eğer satır yoksa, kodu değiştirmeden döndür
    }

    // Satırın indentasyonunu belirle
    const indentMatch = line.match(/^(\s*)/)
    const indent = indentMatch ? indentMatch[1] : '      ' // Default 6 boşluk

    // Component'i yeni satıra ekle (mevcut satırın altına)
    const formattedJSX = `${indent}${jsx}`
    lines.splice(position.lineNumber, 0, formattedJSX)

    return lines.join('\n') // Tüm satırları birleştir ve yeni kodu döndür
  }

  const handleDragEnter = (e: React.DragEvent) => {
    e.preventDefault()
    e.stopPropagation()
  }

  return (
    <div
      ref={containerRef}
      className={`w-full h-full flex flex-col min-h-0 max-h-full bg-gray-900 text-white relative ${
        isDragOver ? 'ring-2 ring-blue-500 ring-offset-2' : ''
      }`}
      style={{ flex: 1, minHeight: 0, maxHeight: '100vh' }}
      onDragOver={handleDragOver}
      onDragEnter={handleDragEnter}
      onDragLeave={handleDragLeave}
      onDrop={handleDrop}
    >
      {/* Drop Indicator */}
      {dropIndicator.show && (
        <div className="absolute inset-0 bg-blue-500 bg-opacity-10 border-2 border-dashed border-blue-500 rounded-lg flex items-center justify-center z-50 pointer-events-none">
          <div className="bg-blue-500 text-white px-4 py-2 rounded-lg font-medium shadow-lg">
            Bileşeni Line {dropIndicator.line}, Column {dropIndicator.column} konumuna bırak
          </div>
        </div>
      )}

      {/* Header */}
      <div className="bg-gray-800 border-b border-gray-700 p-4 flex items-end justify-between shrink-0">
        <div className="flex items-center gap-2">
          <button
            onClick={handleFormatCode}
            disabled={isFormatting}
            className="px-3 py-2 bg-gray-700 text-gray-300 rounded-lg text-xs font-medium hover:bg-gray-600 transition-colors flex items-center gap-2 disabled:opacity-50"
          >
            {isFormatting ? (
              <FaSpinner className="w-4 h-4 animate-spin" />
            ) : (
              <FaCode className="w-4 h-4" />
            )}
            Formatla
          </button>

          <button
            onClick={() => setShowSettings(!showSettings)}
            className={`px-3 py-2 rounded-lg text-xs font-medium transition-colors flex items-center gap-2 ${
              showSettings
                ? 'bg-blue-600 text-white'
                : 'bg-gray-700 text-gray-300 hover:bg-gray-600'
            }`}
          >
            <FaCog className="w-4 h-4" />
            Ayarlar
          </button>

          <button
            onClick={handleResetChanges}
            className="px-3 py-2 bg-red-600 text-white rounded-lg text-xs font-medium hover:bg-red-700 transition-colors flex items-center gap-2"
          >
            <FaTimes className="w-4 h-4" />
            Sıfırla
          </button>

          <button
            onClick={handleApplyChanges}
            className="px-3 py-2 bg-green-600 text-white rounded-lg text-xs font-medium hover:bg-green-700 transition-colors flex items-center gap-2"
          >
            <FaCheck className="w-4 h-4" />
            Uygula
          </button>
        </div>
        <div className="col-span-2 flex items-center justify-end">
          <button
            onClick={onComponentSave}
            className="flex items-center gap-2 bg-yellow-600 text-white px-4 py-2 rounded-lg hover:bg-yellow-700 transition-colors disabled:opacity-50 disabled:cursor-not-allowed shadow-sm"
          >
            <FaSave className="w-4 h-4" />
            Kaydet
          </button>
        </div>
      </div>

      {/* Settings Panel */}
      {showSettings && (
        <div className="bg-gray-800 border-b border-gray-700 p-4 shrink-0">
          <div className="grid grid-cols-4 gap-4">
            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">Tema</label>
              <select
                value={editorTheme}
                onChange={(e) => setEditorTheme(e.target.value as 'vs-dark' | 'light')}
                className="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
              >
                <option value="vs-dark">Koyu</option>
                <option value="light">Açık</option>
              </select>
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">Font Boyutu</label>
              <input
                type="number"
                min="10"
                max="24"
                value={fontSize}
                onChange={(e) => setFontSize(parseInt(e.target.value))}
                className="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
              />
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">
                Kelime Kaydırma
              </label>
              <select
                value={wordWrap}
                onChange={(e) => setWordWrap(e.target.value as 'on' | 'off')}
                className="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
              >
                <option value="on">Açık</option>
                <option value="off">Kapalı</option>
              </select>
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-300 mb-2">Mini Harita</label>
              <button
                onClick={() => setMinimap(!minimap)}
                className={`w-full px-3 py-2 rounded-md text-sm font-medium transition-colors ${
                  minimap ? 'bg-blue-600 text-white' : 'bg-gray-700 text-gray-300 hover:bg-gray-600'
                }`}
              >
                {minimap ? 'Etkin' : 'Devre Dışı'}
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Editor */}
      <div className="flex-1 h-full">
        <Editor
          height="100%"
          width="100%"
          language={language}
          theme={editorTheme}
          value={localCode}
          onChange={handleCodeChange}
          onMount={handleEditorDidMount}
          options={{
            fontSize: fontSize,
            wordWrap: wordWrap,
            minimap: { enabled: minimap },
            automaticLayout: true,
            scrollBeyondLastLine: false,
            renderWhitespace: 'selection',
            bracketPairColorization: { enabled: true },
            guides: {
              bracketPairs: true,
              indentation: true,
            },
            suggest: {
              showKeywords: true,
              showSnippets: true,
              showFunctions: true,
              showConstructors: true,
              showFields: true,
              showVariables: true,
              showClasses: true,
              showStructs: true,
              showInterfaces: true,
              showModules: true,
              showProperties: true,
              showEvents: true,
              showOperators: true,
              showUnits: true,
              showValues: true,
              showConstants: true,
              showEnums: true,
              showEnumMembers: true,
              showColors: true,
              showFiles: true,
              showReferences: true,
              showFolders: true,
              showTypeParameters: true,
              showUsers: true,
              showIssues: true,
            },
            quickSuggestions: {
              other: true,
              comments: true,
              strings: true,
            },
            parameterHints: {
              enabled: true,
            },
            hover: {
              enabled: true,
            },
            contextmenu: true,
            mouseWheelZoom: true,
            cursorBlinking: 'smooth',
            cursorSmoothCaretAnimation: 'on',
            smoothScrolling: true,
            folding: true,
            foldingStrategy: 'indentation',
            showFoldingControls: 'always',
            unfoldOnClickAfterEndOfLine: false,
            tabSize: 2,
            insertSpaces: true,
            detectIndentation: true,
            trimAutoWhitespace: true,
            formatOnPaste: true,
            formatOnType: true,
          }}
        />
      </div>

      {/* Status Bar */}
      <div className="bg-gray-800 border-t border-gray-700 px-4 py-2 flex items-center justify-between text-sm text-gray-400 shrink-0">
        <div className="flex items-center gap-4">
          <span>TypeScript React</span>
          <span>UTF-8</span>
          <span>LF</span>
        </div>
        <div className="flex items-center gap-4">
          <span>Satır 1, Sütun 1</span>
          <span>Boşluklar: 2</span>
          {hasChanges && <span className="text-orange-400">● Kaydedilmemiş değişiklikler</span>}
          {showSuccessMessage && (
            <span className="text-green-400 flex items-center gap-1">
              <FaCheck className="w-4 h-4" />
            </span>
          )}
          {isDragOver && (
            <span className="text-blue-400 flex items-center gap-1">
              <FaMousePointer className="w-4 h-4" />
              Bileşeni bırakmaya hazır
            </span>
          )}
        </div>
      </div>
    </div>
  )
}
