import { useEffect, useState, useCallback } from 'react';
import ReactFlow, {
  addEdge,
  Background,
  Controls,
  useNodesState,
  useEdgesState,
} from 'reactflow';
import 'reactflow/dist/style.css';
import {
  fetchDiagramByName,
  saveDiagramByName,
  listDiagrams,
  deleteDiagramByName,
} from '../services/api';
import CustomNode from './CustomNode';
import IconSelector from './IconSelector';
import { toast } from 'react-toastify';

const nodeTypes = {
  custom: CustomNode,
};

function Diagram() {
  const [nodes, setNodes, onNodesChange] = useNodesState([]);
  const [edges, setEdges, onEdgesChange] = useEdgesState([]);
  const [selectedNode, setSelectedNode] = useState(null);
  const [showForm, setShowForm] = useState(false);
  const [newLabel, setNewLabel] = useState('');
  const [selectedIcon, setSelectedIcon] = useState('');
  const [selectedEdge, setSelectedEdge] = useState(null);
  const [diagramName, setDiagramName] = useState(null);
  const [diagramList, setDiagramList] = useState([]);
  const isIframe = window.self !== window.top;

  useEffect(() => {
    let isMounted = true;

    const load = async () => {
      try {
        const { diagrams } = await listDiagrams();
        if (isMounted) {
          setDiagramList(diagrams);

          if (diagrams.length > 0) {
            setDiagramName((prev) => prev || diagrams[0]);
          } else {
            setDiagramName(null);
          }
        }
      } catch (err) {
        console.error(err);
        setDiagramList([]);
        setDiagramName(null);
      }
    };

    load();
    return () => {
      isMounted = false;
    };
  }, []);

  useEffect(() => {
    let isMounted = true;

    const loadDiagram = async () => {
      if (!diagramName) {
        setNodes([]);
        setEdges([]);
        return;
      }
      try {
        const data = await fetchDiagramByName(diagramName);
        if (isMounted) {
          setNodes(data.nodes || []);
          const sanitizedEdges = (data.edges || []).map(({ id, source, target, animated }) => ({
            id,
            source,
            target,
            animated: !!animated,
          }));
          setEdges(sanitizedEdges);
          setSelectedNode(null);
          setSelectedEdge(null);
        }
      } catch (err) {
        console.error(err);
        toast.error(`❌ Failed to load diagram "${diagramName}"`);
        setNodes([]);
        setEdges([]);
      }
    };

    loadDiagram();
    return () => {
      isMounted = false;
    };
  }, [diagramName, setNodes, setEdges]);

  const handleSave = async () => {
    if (!diagramName) return;
    const cleanedEdges = edges.map(({ id, source, target, animated }) => ({
      id,
      source,
      target,
      animated: !!animated,
    }));
    await saveDiagramByName(diagramName, { nodes, edges: cleanedEdges });
    toast.success(`✅ Diagram "${diagramName}" saved!`);
  };

  const handleAddNode = () => {
    setShowForm(true);
  };

  const handleSubmitNode = () => {
    const id = (nodes.length + 1).toString();
    const label = newLabel || `Node ${id}`;
    const icon = selectedIcon || 'https://s3.dvirlabs.com/lab-icons/default.svg';

    const newNode = {
      id,
      type: 'custom',
      data: { label, icon },
      position: { x: Math.random() * 400, y: Math.random() * 300 },
    };

    setNodes((nds) => [...nds, newNode]);
    toast.success(`🟢 Node "${label}" added`);
    setShowForm(false);
    setNewLabel('');
    setSelectedIcon('');
  };

  const handleDeleteNode = () => {
    if (!selectedNode) return;
    setNodes((nds) => nds.filter((n) => n.id !== selectedNode.id));
    setEdges((eds) => eds.filter((e) => e.source !== selectedNode.id && e.target !== selectedNode.id));
    toast.error(`🗑️ Node "${selectedNode.data.label}" deleted`);
    setSelectedNode(null);
  };

  const onEdgeClick = (_, edge) => {
    setSelectedEdge(edge);
    setSelectedNode(null);
  };

  const handleDeleteEdge = () => {
    if (!selectedEdge) return;
    setEdges((eds) => eds.filter((e) => e.id !== selectedEdge.id));
    toast.error(`🗑️ Edge "${selectedEdge.id}" deleted`);
    setSelectedEdge(null);
  };

  const onConnect = useCallback(
    (params) => setEdges((eds) => addEdge({ ...params, animated: true }, eds)),
    [setEdges]
  );

  const handleNodeDoubleClick = (event, node) => {
    const newLabel = prompt('Enter new name:', node.data.label);
    if (newLabel !== null) {
      setNodes((nds) =>
        nds.map((n) =>
          n.id === node.id ? { ...n, data: { ...n.data, label: newLabel } } : n
        )
      );
      toast.info(`✏️ Node renamed to "${newLabel}"`);
    }
  };

  const onNodeClick = (_, node) => {
    setSelectedNode(node);
  };

  const handleDeleteDiagram = async () => {
    if (!diagramName || diagramName === 'default') {
      toast.warn("❌ Cannot delete 'default' diagram or nothing selected.");
      return;
    }

    const confirmDelete = confirm(`Are you sure you want to delete diagram "${diagramName}"?`);
    if (!confirmDelete) return;

    try {
      await deleteDiagramByName(diagramName);
      const updatedList = diagramList.filter(name => name !== diagramName);
      setDiagramList(updatedList);
      const newSelected = updatedList[0] || null;
      setDiagramName(newSelected);
      setNodes([]);
      setEdges([]);
      toast.success(`🗑️ Diagram "${diagramName}" deleted`);
    } catch (err) {
      toast.error(`❌ Failed to delete diagram "${diagramName}"`);
    }
  };

  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <div style={{ position: 'absolute', zIndex: 10, right: 10, top: 10, display: 'flex', alignItems: 'center', gap: '10px', height: '48px' }}>
        <div style={{ position: 'relative', display: 'flex', alignItems: 'center' }}>
          <select
            value={diagramName || ''}
            onChange={(e) => setDiagramName(e.target.value)}
            style={{
              padding: '10px 16px',
              height: '48px',
              fontSize: '16px',
              fontWeight: 'bold',
              borderRadius: '12px',
              border: 'none',
              background: '#111',
              color: 'white',
              cursor: 'pointer',
              appearance: 'none',
              width: 180,
              paddingRight: 32,
            }}
          >
            {diagramList.map((name) => (
              <option key={name} value={name} style={{ color: 'white', font: 'bold 16px Arial' }}>
                📌 {name}
              </option>
            ))}
          </select>
          <div
            style={{
              position: 'absolute',
              right: 12,
              top: '50%',
              transform: 'translateY(-50%)',
              pointerEvents: 'none',
              fontSize: 16,
              color: 'white',
            }}
          >
            ⏷
          </div>
        </div>

        {!isIframe && (
          <>
            <button className="btn" style={{ background: '#d28519' }} onClick={() => {
              const newName = prompt("Enter new diagram name:");
              if (newName) {
                if (!diagramList.includes(newName)) {
                  const updatedList = [...diagramList, newName];
                  setDiagramList(updatedList);
                }
                setDiagramName(newName);
                setNodes([]);
                setEdges([]);
                setSelectedNode(null);
                setSelectedEdge(null);
              }
            }}>🆕 New Diagram</button>

            <button className="btn" onClick={handleSave} style={{ background: 'green' }}>💾 Save</button>
            <button className="btn" onClick={handleAddNode} style={{ background: 'blue' }}>➕ Add Node</button>

            <button className="btn" onClick={handleDeleteNode} style={{ background: selectedNode ? '#b81a1a' : '#ccc', color: selectedNode ? 'white' : '#666', cursor: selectedNode ? 'pointer' : 'not-allowed' }} disabled={!selectedNode}>🗑️ Delete Node</button>

            <button className="btn" onClick={handleDeleteEdge} style={{ background: selectedEdge ? '#b81a1a' : '#ccc', color: selectedEdge ? 'white' : '#666', cursor: selectedEdge ? 'pointer' : 'not-allowed' }} disabled={!selectedEdge}>🗑️ Delete Edge</button>

            <button className="btn" onClick={handleDeleteDiagram} style={{ background: 'red' }}>🗑️ Delete Diagram</button>
          </>
        )}
      </div>

      {showForm && (
        <div style={{ position: 'absolute', zIndex: 20, right: 10, top: 80, background: '#e6f0fa', padding: '16px', borderRadius: '12px', boxShadow: '0 4px 8px rgba(0,0,0,0.15)', width: 280 }}>
          <h4 style={{ color: '#125ea8', marginBottom: 12, fontSize: 18, display: 'flex', alignItems: 'center', gap: 8 }}>🧩 Add New Node</h4>
          <label style={{ fontWeight: 'bold', marginBottom: 4, display: 'block', color: '#333' }}>Label:</label>
          <input
            type="text"
            placeholder="Enter label"
            value={newLabel}
            onChange={(e) => setNewLabel(e.target.value)}
            style={{ padding: '6px', width: '100%', borderRadius: 6, border: '1px solid #ccc', marginBottom: 12 }}
          />
          <IconSelector onSelect={setSelectedIcon} />
          <div style={{ marginTop: 12 }}>
            <button className="btn" onClick={handleSubmitNode}>✅ Add</button>
            <button className="btn" style={{ marginLeft: 8, background: '#ccc', color: '#333' }} onClick={() => setShowForm(false)}>❌ Cancel</button>
          </div>
        </div>
      )}

      <ReactFlow
        nodes={nodes}
        edges={edges}
        onNodesChange={onNodesChange}
        onEdgesChange={onEdgesChange}
        onConnect={onConnect}
        onNodeClick={onNodeClick}
        onNodeDoubleClick={handleNodeDoubleClick}
        onEdgeClick={onEdgeClick}
        onPaneClick={() => {
          setSelectedNode(null);
          setSelectedEdge(null);
        }}
        nodeTypes={nodeTypes}
        fitView
      >
        <Background />
        <Controls />
      </ReactFlow>
    </div>
  );
}

export default Diagram;