import React, { useState, useCallback } from 'react'
import { ReactFlow, Controls, Background, useNodesState, useEdgesState, addEdge, BackgroundVariant, getNodesBounds } from '@xyflow/react'
import { toSvg } from 'html-to-image'
import '@xyflow/react/dist/style.css'
import './App.css'
import Toolbar from './components/Toolbar';
import ControlPanel from './components/ControlPanel';
import CustomBlock from './components/CustomBlock';

const nodeTypes = {
  fbdBlock: CustomBlock
}

const EDGE_STYLES = {
  bool: { stroke: '#000', strokeWidth: 2 },
  a: { stroke: '#000', strokeWidth: 2, strokeDasharray: '4 4' },     // Пунктир
  b: { stroke: '#D8000A', strokeWidth: 2 },                          // Красная
  c: { stroke: '#000', strokeWidth: 2, strokeDasharray: '1 3' },     // Точечная
  d: { stroke: '#008000', strokeWidth: 2 },                          // Зеленая
  e: { stroke: '#1717D8', strokeWidth: 2 }                           // Синяя
};

function App() {
  const [nodes, setNodes, onNodesChange] = useNodesState([])
  const [edges, setEdges, onEdgesChange] = useEdgesState([])
  const [flowInstance, setFlowInstance] = useState(null)
  const [edgeType, setEdgeType] = useState('bool')

  const onConnect = useCallback(
    (params) => setEdges((edge) => {
      const currentStyle = EDGE_STYLES[edgeType] || EDGE_STYLES['bool']
      return addEdge({
        ...params,
        type: 'smoothstep',
        style: currentStyle,
        data: {type: edgeType}
      }, edge)
    }), [setEdges, edgeType]
  )

  const onDragOver = useCallback((event) => {
    event.preventDefault()
    event.dataTransfer.dropEffect = 'move'
  }, [])

  const onDrop = useCallback(
    (event) => {
      event.preventDefault()
      if (!flowInstance)
        return

      const dataStr = event.dataTransfer.getData('application/reactflow')
      if (!dataStr)
        return

      const {type, label, inputCount, outputCount} = JSON.parse(dataStr)
      const position = flowInstance.screenToFlowPosition({
        x: event.clientX,
        y: event.clientY
      })

      const newNode = {
        id: `block_${Date.now()}`,
        type: 'fbdBlock',
        position,
        data: {type, label, inputCount, outputCount}
      }
      setNodes((currentNodes) => [...currentNodes, newNode])
    }, [flowInstance, setNodes]
  )

  function handleClear() {
    if ((nodes.length > 0 || edges.length > 0) && window.confirm("Очистить холст?")) {
      setNodes([])
      setEdges([])
    }
  }

  const handleExportSvg = useCallback(() => {
    const reactFlowViewport = document.querySelector('.react-flow__viewport')
    if (!reactFlowViewport || !nodes.length > 0) {
      alert('Не удалось найти холст для экспорта')
      return
    }

    const bounds = getNodesBounds(nodes)
    const padding = 30
    const widthExportWindow = bounds.width + padding * 2
    const heightExportWindow = bounds.height + padding * 2

    toSvg(reactFlowViewport, {
      backgroundColor: 'white',
      width: widthExportWindow,
      height: heightExportWindow,
      style: {
        width: `${widthExportWindow}px`,
        height: `${heightExportWindow}px`,
        transform: `translate(${-bounds.x + padding}px, ${-bounds.y + padding}px) scale(1)`,
        transformOrigin: 'top left'
      }
    }).then(async (dataUrl) => {
      if ('showSaveFilePicker' in window) {
        try {
          const handle = await window.showSaveFilePicker({
            suggestedName: 'fbd-scheme.svg',
            types: [{
              description: 'Векторная диаграмма SVG',
              accept: {'image/svg+xml': ['.svg']}
            }]
          })

          const writable = await handle.createWritable()
          const scheme = await fetch(dataUrl)
          const file = await scheme.blob()
          await writable.write(file)
          await writable.close()
        }
        catch (err) { console.log('Пользователь отменил сохранение или произошла ошибка: ', err) }
      }
      else {
        const link = document.createElement('a')
        link.download = 'fbd-scheme.svg'
        link.href = dataUrl
        link.click()
      }
    }).catch((error) => {
      console.error('Ошибка генерации SVG-файла: ', error)
      alert('Не удалось сгененировать SVG-файл')
    })
  }, [nodes])


  return(
    <div className="App">
      <ControlPanel
        onClear = {handleClear}
        onExportSvg = {handleExportSvg}
      />
      <div className = "main-container">
        <Toolbar
          activeEdgeType = {edgeType}
          onChangeEdgeType = {setEdgeType}
        />
        <div className = "main-canvas-container">
          <div className="canvas-container">
            <ReactFlow
              nodes = {nodes}
              edges = {edges}
              onNodesChange = {onNodesChange}
              onEdgesChange = {onEdgesChange}
              onConnect = {onConnect}
              nodeTypes = {nodeTypes}
              onInit = {setFlowInstance}
              onDrop = {onDrop}
              onDragOver = {onDragOver}
              //fitView
            >
              <Controls/>
              <Background variant = {BackgroundVariant.Lines} color = "#eee" gap = {10}/>
            </ReactFlow>
          </div>
        </div>
      </div>
    </div>
  )
}

export default App