<template>
  <g>

    <!-- Main edge path -->
    <BaseEdge
      :id="id"
      :path="edgePath"
      :style="{
        stroke: selected ? '#ff6b6b' : edgeStyle.stroke || '#555',
        strokeWidth: selected ? 3 : edgeStyle.strokeWidth || 2,
        ...edgeStyle
      }"
      :marker-end="selected ? 'url(#arrow-selected)' : 'url(#arrow)'"
      :class="{
        'vue-flow__edge-path': true,
        'custom-edge': true,
        'selected': selected,
        'animated': animated
      }"
    />

    <!-- Interactive control points for path adjustment -->
    <g v-if="selected && showControlPoints" class="edge-control-points">
      <!-- Mid-point control for path bending -->
      <circle
        :cx="labelX"
        :cy="labelY"
        r="4"
        fill="#3b82f6"
        stroke="white"
        stroke-width="2"
        class="edge-control-point"
        style="cursor: move;"
        @mousedown="onControlPointMouseDown"
        @touchstart="onControlPointMouseDown"
      />
      
      <!-- Visual indicator for draggable control -->
      <circle
        :cx="labelX"
        :cy="labelY"
        r="8"
        fill="rgba(59, 130, 246, 0.2)"
        class="edge-control-indicator"
        style="pointer-events: none;"
      />
    </g>

    <!-- Edge label using EdgeLabelRenderer for HTML content -->
    <EdgeLabelRenderer v-if="label">
      <div
        :style="{
          position: 'absolute',
          transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
          pointerEvents: 'all',
          fontSize: '12px',
          fontWeight: '500'
        }"
        class="edge-label-container nodrag nopan"
      >
        <div class="edge-label">
          {{ label }}
        </div>
      </div>
    </EdgeLabelRenderer>
  </g>
</template>

<script setup>
import { computed, ref, inject } from 'vue'
import { BaseEdge, EdgeLabelRenderer, getBezierPath, getSmoothStepPath, getStraightPath } from '@vue-flow/core'
import { useEdge } from '@vue-flow/core'

const props = defineProps({
  id: String,
  sourceX: Number,
  sourceY: Number,
  targetX: Number,
  targetY: Number,
  sourcePosition: String,
  targetPosition: String,
  selected: Boolean,
  animated: Boolean,
  label: String,
  style: Object,
  type: {
    type: String,
    default: 'smoothstep'
  },
  data: Object,
  markerEnd: String,
  markerStart: String
})

// Get edge instance for updating
const { edge } = useEdge()

// Control state
const showControlPoints = ref(true)
const isDragging = ref(false)
const pathOffset = ref({ x: 0, y: 0 })

// Computed edge style
const edgeStyle = computed(() => ({
  stroke: '#555',
  strokeWidth: 2,
  ...props.style
}))

// Calculate edge path based on type with optional offset for custom positioning
const edgePath = computed(() => {
  try {
    const offsetX = pathOffset.value.x || 0
    const offsetY = pathOffset.value.y || 0
    
    // Apply offset to create custom path curvature
    const centerX = (props.sourceX + props.targetX) / 2 + offsetX
    const centerY = (props.sourceY + props.targetY) / 2 + offsetY
    
    switch (props.type) {
      case 'straight':
        return getStraightPath(props.sourceX, props.sourceY, props.targetX, props.targetY)[0]
      case 'smoothstep':
      case 'custom':
        return getSmoothStepPath(
          props.sourceX,
          props.sourceY,
          props.sourcePosition,
          props.targetX,
          props.targetY,
          props.targetPosition,
          centerX,
          centerY,
          20, // offset
          8   // border radius
        )[0]
      case 'bezier':
      default:
        return getBezierPath({
          sourceX: props.sourceX,
          sourceY: props.sourceY,
          sourcePosition: props.sourcePosition,
          targetX: props.targetX,
          targetY: props.targetY,
          targetPosition: props.targetPosition,
          curvature: 0.25
        })[0]
    }
  } catch (error) {
    console.error('Error calculating edge path:', error)
    // Fallback to a simple straight line
    return `M ${props.sourceX} ${props.sourceY} L ${props.targetX} ${props.targetY}`
  }
})

// Calculate label position
const labelX = computed(() => {
  return (props.sourceX + props.targetX) / 2 + pathOffset.value.x
})

const labelY = computed(() => {
  return (props.sourceY + props.targetY) / 2 + pathOffset.value.y
})

// Control point drag handling
const onControlPointMouseDown = (event) => {
  event.preventDefault()
  event.stopPropagation()
  
  isDragging.value = true
  const startX = event.clientX || event.touches[0].clientX
  const startY = event.clientY || event.touches[0].clientY
  const startOffsetX = pathOffset.value.x
  const startOffsetY = pathOffset.value.y
  
  const onMouseMove = (moveEvent) => {
    if (!isDragging.value) return
    
    const currentX = moveEvent.clientX || moveEvent.touches[0].clientX
    const currentY = moveEvent.clientY || moveEvent.touches[0].clientY
    
    const deltaX = currentX - startX
    const deltaY = currentY - startY
    
    // Update path offset for custom positioning
    pathOffset.value = {
      x: startOffsetX + deltaX,
      y: startOffsetY + deltaY
    }
    
    // Store the custom path in edge data for persistence
    if (edge.value) {
      edge.value.data = {
        ...edge.value.data,
        customPath: pathOffset.value
      }
    }
  }
  
  const onMouseUp = () => {
    isDragging.value = false
    document.removeEventListener('mousemove', onMouseMove)
    document.removeEventListener('mouseup', onMouseUp)
    document.removeEventListener('touchmove', onMouseMove)
    document.removeEventListener('touchend', onMouseUp)
  }
  
  document.addEventListener('mousemove', onMouseMove)
  document.addEventListener('mouseup', onMouseUp)
  document.addEventListener('touchmove', onMouseMove)
  document.addEventListener('touchend', onMouseUp)
}

// Initialize path offset from saved data
try {
  if (edge.value && edge.value.data && edge.value.data.customPath) {
    pathOffset.value = edge.value.data.customPath
  }
} catch (error) {
  console.log('Edge data not available yet, using default path')
}
</script>

<script>
export default {
  name: 'CustomEdge',
  inheritAttrs: false
}
</script>

<style scoped>
.edge-label-container {
  z-index: 1000;
}

.edge-label {
  background: white;
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 11px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  border: 1px solid #e2e8f0;
  white-space: nowrap;
  pointer-events: none;
}

.edge-control-point {
  cursor: move;
  transition: r 0.2s ease;
}

.edge-control-point:hover {
  r: 5;
  fill: #2563eb;
}

.custom-edge {
  transition: stroke-width 0.2s ease, stroke 0.2s ease;
}

.custom-edge.animated {
  stroke-dasharray: 5;
  animation: dash 1s linear infinite;
}

.custom-edge.selected {
  filter: drop-shadow(0 0 4px rgba(255, 107, 107, 0.5));
}

@keyframes dash {
  to {
    stroke-dashoffset: -10;
  }
}

/* Hide control points when not selected */
.edge-control-points {
  opacity: 0;
  transition: opacity 0.2s ease;
}

.selected .edge-control-points {
  opacity: 1;
}
</style> 