/**
 * Minimal hook for HTML5 drag-and-drop events.
 * Only captures events and pushes to LiveView - no business logic.
 */

interface DragData {
  type: "site" | "device"
  id: string
  siteId: string
  position: number
}

export const DeviceListReorder = {
  draggedElement: null as HTMLElement | null,
  dragData: null as DragData | null,
  handleDragStart: null as ((e: DragEvent) => void) | null,
  handleDragEnd: null as ((e: DragEvent) => void) | null,
  handleDragOver: null as ((e: DragEvent) => void) | null,
  handleDrop: null as ((e: DragEvent) => void) | null,
  dragHandleListeners: [] as Array<{ element: Element; handler: (e: Event) => void }>,

  mounted(this: any) {
    // Capture drag start
    this.handleDragStart = (e: DragEvent) => {
      const target = (e.target as HTMLElement).closest("[data-site-id]") as HTMLElement
      if (!target) return

      // Check if element is actually draggable
      if (target.getAttribute("draggable") !== "true") return

      const siteId = target.dataset.siteId
      const position = parseInt(target.dataset.sitePosition || target.dataset.devicePosition || "0")

      if (target.classList.contains("site-header")) {
        this.draggedElement = target
        this.dragData = { type: "site", id: siteId!, siteId: siteId!, position }
        target.classList.add("opacity-50")
      } else if (target.classList.contains("device-row")) {
        const deviceId = target.dataset.deviceId
        this.draggedElement = target
        this.dragData = { type: "device", id: deviceId!, siteId: siteId!, position }
        target.classList.add("opacity-50")
      }

      e.dataTransfer!.effectAllowed = "move"
    }

    // Clean up on drag end
    this.handleDragEnd = (_e: DragEvent) => {
      if (this.draggedElement) {
        this.draggedElement.classList.remove("opacity-50")
        this.draggedElement = null
      }
      this.dragData = null

      // Remove drop indicators
      this.el.querySelectorAll(".border-blue-500").forEach((el: Element) => {
        el.classList.remove("border-blue-500", "border-t-4", "border-b-4")
      })
    }

    // Show drop indicator
    this.handleDragOver = (e: DragEvent) => {
      e.preventDefault()
      if (!this.dragData) return

      const target = (e.target as HTMLElement).closest("[data-site-id], [data-device-id]") as HTMLElement
      if (!target || target === this.draggedElement) return

      // Check if in bottom half of element
      const rect = target.getBoundingClientRect()
      const middleY = rect.top + (rect.height / 2)
      const isBottomHalf = e.clientY > middleY

      // Visual feedback - show border on top or bottom depending on drop position
      this.el.querySelectorAll(".border-blue-500").forEach((el: Element) => {
        el.classList.remove("border-blue-500", "border-t-4", "border-b-4")
      })
      target.classList.add("border-blue-500", isBottomHalf ? "border-b-4" : "border-t-4")
    }

    // Handle drop
    this.handleDrop = (e: DragEvent) => {
      e.preventDefault()
      if (!this.dragData) return

      const target = (e.target as HTMLElement).closest("[data-site-id], [data-device-id]") as HTMLElement
      if (!target || target === this.draggedElement) return

      const dropSiteId = target.dataset.siteId
      let dropPosition = parseInt(target.dataset.sitePosition || target.dataset.devicePosition || "0")

      // Check if dropping in bottom half of element - if so, insert after instead of before
      const rect = target.getBoundingClientRect()
      const middleY = rect.top + (rect.height / 2)
      if (e.clientY > middleY) {
        dropPosition += 1
      }

      // Push to LiveView based on type
      if (this.dragData.type === "site" && target.classList.contains("site-header")) {
        this.pushEvent("reorder_site", {
          site_id: this.dragData.id,
          new_position: dropPosition
        })
      } else if (this.dragData.type === "device" && target.classList.contains("device-row")) {
        // Only allow within same site
        if (dropSiteId === this.dragData.siteId) {
          this.pushEvent("reorder_device", {
            device_id: this.dragData.id,
            new_position: dropPosition
          })
        }
      }

      // Clean up
      this.el.querySelectorAll(".border-blue-500").forEach((el: Element) => {
        el.classList.remove("border-blue-500", "border-t-4", "border-b-4")
      })
    }

    // Add event listeners
    this.el.addEventListener("dragstart", this.handleDragStart)
    this.el.addEventListener("dragend", this.handleDragEnd)
    this.el.addEventListener("dragover", this.handleDragOver)
    this.el.addEventListener("drop", this.handleDrop)

    // Prevent drag handle from triggering row click
    this.dragHandleListeners = []
    this.el.querySelectorAll(".drag-handle").forEach((handle: Element) => {
      const handler = (e: Event) => {
        e.stopPropagation()
      }
      handle.addEventListener("click", handler)
      this.dragHandleListeners.push({ element: handle, handler })
    })
  },

  destroyed(this: any) {
    // Remove main event listeners
    if (this.handleDragStart) {
      this.el.removeEventListener("dragstart", this.handleDragStart)
      this.handleDragStart = null
    }
    if (this.handleDragEnd) {
      this.el.removeEventListener("dragend", this.handleDragEnd)
      this.handleDragEnd = null
    }
    if (this.handleDragOver) {
      this.el.removeEventListener("dragover", this.handleDragOver)
      this.handleDragOver = null
    }
    if (this.handleDrop) {
      this.el.removeEventListener("drop", this.handleDrop)
      this.handleDrop = null
    }

    // Remove drag handle listeners
    this.dragHandleListeners.forEach(({ element, handler }) => {
      element.removeEventListener("click", handler)
    })
    this.dragHandleListeners = []

    // Clean up state
    this.draggedElement = null
    this.dragData = null
  }
}
