import { useCallback, useEffect, useState, useRef } from 'react'
import ReactFlow, {
  Node,
  Edge,
  Controls,
  Background,
  MiniMap,
  useNodesState,
  useEdgesState,
  addEdge,
  Connection,
  MarkerType,
  NodeTypes,
  Panel
} from 'reactflow'
import 'reactflow/dist/style.css'
import { api } from '../services/api'
import { OrganizationalUnit, OrganizationalUnitType } from '@skillmate/shared'
import { Upload } from 'lucide-react'

// Custom Node Component
const OrganizationNode = ({ data }: { data: any }) => {
  const getTypeIcon = (type: OrganizationalUnitType) => {
    const icons = {
      direktion: '🏛️',
      abteilung: '🏢',
      dezernat: '📁',
      sachgebiet: '📋',
      teildezernat: '🔧',
      fuehrungsstelle: '⭐',
      stabsstelle: '🎯',
      sondereinheit: '🛡️'
    }
    return icons[type] || '📄'
  }

  const getGradient = (level: number) => {
    const gradients = [
      'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
      'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
      'linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)',
      'linear-gradient(135deg, #43e97b 0%, #38f9d7 100%)',
      'linear-gradient(135deg, #fa709a 0%, #fee140 100%)',
      'linear-gradient(135deg, #30cfd0 0%, #330867 100%)'
    ]
    return gradients[level % gradients.length]
  }

  return (
    <div className="bg-white rounded-lg shadow-lg border-2 border-gray-200 min-w-[250px]">
      <div 
        className="p-2 text-white rounded-t-md"
        style={{ background: getGradient(data.level || 0) }}
      >
        <div className="flex items-center justify-between">
          <span className="text-lg">{getTypeIcon(data.type)}</span>
          <span className="text-xs opacity-90">{data.code}</span>
        </div>
      </div>
      <div className="p-3">
        <h4 className="font-semibold text-gray-800 text-sm">{data.name}</h4>
        {data.employeeCount !== undefined && (
          <p className="text-xs text-gray-600 mt-1">
            👥 {data.employeeCount} Mitarbeiter
          </p>
        )}
        {data.hasFuehrungsstelle && (
          <span className="inline-block px-2 py-1 mt-2 text-xs bg-yellow-100 text-yellow-800 rounded">
            FüSt
          </span>
        )}
      </div>
    </div>
  )
}

const nodeTypes: NodeTypes = {
  organization: OrganizationNode
}

export default function OrganizationEditor() {
  const [nodes, setNodes, onNodesChange] = useNodesState([])
  const [edges, setEdges, onEdgesChange] = useEdgesState([])
  const [loading, setLoading] = useState(true)
  const [selectedNode, setSelectedNode] = useState<Node | null>(null)
  const [showAddDialog, setShowAddDialog] = useState(false)
  const [showImportDialog, setShowImportDialog] = useState(false)
  const [uploadProgress, setUploadProgress] = useState<string | null>(null)
  const fileInputRef = useRef<HTMLInputElement>(null)
  const [formData, setFormData] = useState({
    name: '',
    code: '',
    type: 'dezernat' as OrganizationalUnitType,
    level: 2,
    parentId: '',
    description: ''
  })

  // Load organizational units
  useEffect(() => {
    loadOrganization()
  }, [])

  const loadOrganization = async () => {
    try {
      setLoading(true)
      const response = await api.get('/organization/hierarchy')
      
      if (response.data.success) {
        const units = response.data.data
        const { nodes: flowNodes, edges: flowEdges } = convertToFlowElements(units)
        setNodes(flowNodes)
        setEdges(flowEdges)
      }
    } catch (error) {
      console.error('Failed to load organization:', error)
    } finally {
      setLoading(false)
    }
  }

  const convertToFlowElements = (units: any[], parentPosition = { x: 0, y: 0 }, level = 0): { nodes: Node[], edges: Edge[] } => {
    const nodes: Node[] = []
    const edges: Edge[] = []
    const levelHeight = 150
    const nodeWidth = 300

    units.forEach((unit, index) => {
      const nodeId = unit.id
      const xPos = parentPosition.x + index * nodeWidth
      const yPos = level * levelHeight

      // Use persisted positions if available, otherwise compute defaults
      const persistedX = (typeof unit.positionX === 'number'
        ? unit.positionX
        : (unit.positionX != null && !isNaN(Number(unit.positionX)) ? Number(unit.positionX) : undefined))
      const persistedY = (typeof unit.positionY === 'number'
        ? unit.positionY
        : (unit.positionY != null && !isNaN(Number(unit.positionY)) ? Number(unit.positionY) : undefined))

      nodes.push({
        id: nodeId,
        type: 'organization',
        position: { x: persistedX ?? xPos, y: persistedY ?? yPos },
        data: {
          ...unit,
          level
        }
      })

      // Create edge to parent if exists
      if (unit.parentId) {
        edges.push({
          id: `e-${unit.parentId}-${nodeId}`,
          source: unit.parentId,
          target: nodeId,
          type: 'smoothstep',
          animated: false,
          markerEnd: {
            type: MarkerType.ArrowClosed,
            width: 20,
            height: 20,
            color: '#94a3b8'
          },
          style: {
            strokeWidth: 2,
            stroke: '#94a3b8'
          }
        })
      }

      // Process children recursively
      if (unit.children && unit.children.length > 0) {
        const childElements = convertToFlowElements(
          unit.children,
          { x: xPos, y: yPos },
          level + 1
        )
        nodes.push(...childElements.nodes)
        edges.push(...childElements.edges)
      }
    })

    return { nodes, edges }
  }

  const onConnect = useCallback(
    (params: Connection) => {
      setEdges((eds) => addEdge({
        ...params,
        type: 'smoothstep',
        animated: false,
        markerEnd: {
          type: MarkerType.ArrowClosed,
          width: 20,
          height: 20,
          color: '#94a3b8'
        }
      }, eds))
    },
    [setEdges]
  )

  const onNodeClick = useCallback((_: any, node: Node) => {
    setSelectedNode(node)
  }, [])

  const onNodeDragStop = useCallback(async (_: any, node: Node) => {
    try {
      await api.put(`/organization/units/${node.id}`, {
        positionX: node.position.x,
        positionY: node.position.y
      })
    } catch (error) {
      console.error('Failed to update position:', error)
    }
  }, [])

  const handleAddUnit = async () => {
    try {
      // Build payload and attach selected node as parent if present
      const payload: any = {
        name: formData.name,
        code: formData.code || undefined,
        type: formData.type,
        level: selectedNode ? ((selectedNode.data?.level ?? 0) + 1) : formData.level,
        description: formData.description || undefined,
      }
      if (selectedNode?.id) payload.parentId = selectedNode.id

      const response = await api.post('/organization/units', payload)
      if (response.data.success) {
        await loadOrganization()
        setShowAddDialog(false)
        setFormData({
          name: '',
          code: '',
          type: 'dezernat',
          level: 2,
          parentId: '',
          description: ''
        })
      }
    } catch (error) {
      console.error('Failed to add unit:', error)
    }
  }

  const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0]
    if (!file) return

    if (file.type !== 'application/pdf') {
      alert('Bitte laden Sie nur PDF-Dateien hoch.')
      return
    }

    const formData = new FormData()
    formData.append('pdf', file)
    formData.append('clearExisting', 'false') // Don't clear existing by default

    setUploadProgress('PDF wird hochgeladen...')

    try {
      const response = await api.post('/organization/import-pdf', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      })

      if (response.data.success) {
        setUploadProgress(`Erfolgreich! ${response.data.data.unitsImported} Einheiten importiert.`)
        await loadOrganization()
        setTimeout(() => {
          setShowImportDialog(false)
          setUploadProgress(null)
        }, 2000)
      }
    } catch (error: any) {
      console.error('PDF import failed:', error)
      setUploadProgress(`Fehler: ${error.response?.data?.error?.message || 'Upload fehlgeschlagen'}`)
    }
  }

  if (loading) {
    return (
      <div className="flex items-center justify-center h-screen">
        <div className="text-lg">Lade Organigramm...</div>
      </div>
    )
  }

  return (
    <div className="h-screen w-full">
      <ReactFlow
        nodes={nodes}
        edges={edges}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
        onConnect={onConnect}
        onNodeClick={onNodeClick}
        onNodeDragStop={onNodeDragStop}
        nodeTypes={nodeTypes}
        fitView
        attributionPosition="bottom-left"
      >
        <Controls />
        <MiniMap 
          nodeColor={(node) => {
            const gradients = ['#667eea', '#f093fb', '#4facfe', '#43e97b', '#fa709a', '#30cfd0']
            return gradients[node.data?.level % gradients.length] || '#94a3b8'
          }}
        />
        <Background variant="dots" gap={12} size={1} />
        
        <Panel position="top-left" className="bg-white p-4 rounded-lg shadow-lg">
          <h2 className="text-xl font-bold mb-4">LKA NRW Organigramm</h2>
          <div className="space-y-2">
            <button
              onClick={() => setShowAddDialog(true)}
              className="w-full px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
            >
              + Einheit hinzufügen
            </button>
            <button
              onClick={() => setShowImportDialog(true)}
              className="w-full px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700 flex items-center justify-center gap-2"
            >
              <Upload size={16} />
              PDF importieren
            </button>
          </div>
        </Panel>

        <Panel position="top-right" className="bg-white p-4 rounded-lg shadow-lg max-w-sm">
          {selectedNode ? (
            <>
              <h3 className="font-bold mb-2">{selectedNode.data.name}</h3>
              {selectedNode.data.code && (
                <p className="text-sm text-gray-600">Code: {selectedNode.data.code}</p>
              )}
              <p className="text-sm text-gray-600">Typ: {selectedNode.data.type}</p>
              <p className="text-sm text-gray-600">Ebene: {selectedNode.data.level}</p>
              {selectedNode.data.description && (
                <p className="text-sm mt-2">{selectedNode.data.description}</p>
              )}
            </>
          ) : (
            <p className="text-gray-500">Klicken Sie auf eine Einheit für Details</p>
          )}
        </Panel>
      </ReactFlow>

      {/* Import PDF Dialog */}
      {showImportDialog && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6 max-w-md w-full">
            <h2 className="text-xl font-bold mb-4">PDF Organigramm importieren</h2>
            
            <div className="space-y-4">
              <div className="border-2 border-dashed border-gray-300 rounded-lg p-8 text-center">
                <Upload className="mx-auto h-12 w-12 text-gray-400 mb-4" />
                <p className="text-sm text-gray-600 mb-4">
                  Laden Sie ein PDF-Dokument mit der Organisationsstruktur hoch.
                  Das System extrahiert automatisch die Hierarchie.
                </p>
                
                <input
                  ref={fileInputRef}
                  type="file"
                  accept=".pdf"
                  onChange={handleFileUpload}
                  className="hidden"
                />
                
                <button
                  onClick={() => fileInputRef.current?.click()}
                  className="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700"
                  disabled={!!uploadProgress}
                >
                  PDF auswählen
                </button>
              </div>
              
              {uploadProgress && (
                <div className="p-3 bg-blue-50 text-blue-700 rounded">
                  {uploadProgress}
                </div>
              )}
            </div>

            <div className="flex justify-end gap-2 mt-6">
              <button
                onClick={() => {
                  setShowImportDialog(false)
                  setUploadProgress(null)
                }}
                className="px-4 py-2 text-gray-600 hover:text-gray-800"
              >
                Schließen
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Add Unit Dialog */}
      {showAddDialog && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg p-6 max-w-md w-full">
            <h2 className="text-xl font-bold mb-4">Neue Einheit hinzufügen</h2>
            
            <div className="space-y-4">
              <div>
                <label className="block text-sm font-medium mb-1">Name *</label>
                <input
                  type="text"
                  value={formData.name}
                  onChange={(e) => setFormData({ ...formData, name: e.target.value })}
                  className="w-full px-3 py-2 border rounded"
                  required
                />
              </div>

              {selectedNode && (
                <div className="text-xs text-gray-600">
                  Wird unterhalb von: <span className="font-semibold">{selectedNode.data?.name}</span> eingefügt
                </div>
              )}

              <div>
                <label className="block text-sm font-medium mb-1">Code *</label>
                <input
                  type="text"
                  value={formData.code}
                  onChange={(e) => setFormData({ ...formData, code: e.target.value })}
                  className="w-full px-3 py-2 border rounded"
                  placeholder="z.B. ZA 1"
                  required
                />
              </div>

              <div>
                <label className="block text-sm font-medium mb-1">Typ *</label>
                <select
                  value={formData.type}
                  onChange={(e) => setFormData({ ...formData, type: e.target.value as OrganizationalUnitType })}
                  className="w-full px-3 py-2 border rounded"
                >
                  <option value="direktion">Direktion</option>
                  <option value="abteilung">Abteilung</option>
                  <option value="dezernat">Dezernat</option>
                  <option value="sachgebiet">Sachgebiet</option>
                  <option value="teildezernat">Teildezernat</option>
                  <option value="stabsstelle">Stabsstelle</option>
                  <option value="sondereinheit">Sondereinheit</option>
                  <option value="fuehrungsstelle">Führungsstelle</option>
                </select>
              </div>

              <div>
                <label className="block text-sm font-medium mb-1">Ebene *</label>
                <input
                  type="number"
                  value={formData.level}
                  onChange={(e) => setFormData({ ...formData, level: parseInt(e.target.value) })}
                  className="w-full px-3 py-2 border rounded"
                  min="0"
                  max="10"
                />
              </div>

              <div>
                <label className="block text-sm font-medium mb-1">Beschreibung</label>
                <textarea
                  value={formData.description}
                  onChange={(e) => setFormData({ ...formData, description: e.target.value })}
                  className="w-full px-3 py-2 border rounded"
                  rows={3}
                />
              </div>
            </div>

            <div className="flex justify-end gap-2 mt-6">
              <button
                onClick={() => setShowAddDialog(false)}
                className="px-4 py-2 text-gray-600 hover:text-gray-800"
              >
                Abbrechen
              </button>
              <button
                onClick={handleAddUnit}
                className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
              >
                Hinzufügen
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  )
}
