import { StateNode } from "tldraw"
import { ObsNoteShape } from "@/shapes/ObsNoteShapeUtil"
import { findNonOverlappingPosition } from "@/utils/shapeCollisionUtils"

export class ObsNoteTool extends StateNode {
  static override id = "ObsidianNote"
  static override initial = "idle"
  static override children = () => [ObsNoteIdle]

  onSelect() {
    // Check if there are existing ObsNote shapes on the canvas
    const allShapes = this.editor.getCurrentPageShapes()
    const obsNoteShapes = allShapes.filter(shape => shape.type === 'ObsNote')
    
    if (obsNoteShapes.length > 0) {
      // If ObsNote shapes exist, select them and center the view
      this.editor.setSelectedShapes(obsNoteShapes.map(shape => shape.id))
      this.editor.zoomToFit()
      
      // Add refresh all functionality
      this.addRefreshAllListener()
    }
  }

  private addRefreshAllListener() {
    // Listen for refresh-all-obsnotes event
    const handleRefreshAll = async () => {
      const shapeUtil = new ObsNoteShape(this.editor)
      shapeUtil.editor = this.editor
      
      const result = await shapeUtil.refreshAllFromVault()
      if (result.success > 0) {
        alert(`✅ Refreshed ${result.success} notes from vault!${result.failed > 0 ? ` (${result.failed} failed)` : ''}`)
      } else {
        alert('❌ Failed to refresh any notes. Check console for details.')
      }
    }

    window.addEventListener('refresh-all-obsnotes', handleRefreshAll)
    
    // Clean up listener when tool is deselected
    const cleanup = () => {
      window.removeEventListener('refresh-all-obsnotes', handleRefreshAll)
    }
    
    // Store cleanup function for later use
    ;(this as any).cleanup = cleanup
  }

  onExit() {
    // Clean up event listeners
    if ((this as any).cleanup) {
      ;(this as any).cleanup()
    }
  }
}

export class ObsNoteIdle extends StateNode {
  static override id = "idle"
  
  tooltipElement?: HTMLDivElement
  mouseMoveHandler?: (e: MouseEvent) => void

  override onEnter = () => {
    // Set cursor to cross (looks like +)
    this.editor.setCursor({ type: "cross", rotation: 0 })
    
    // Create tooltip element
    this.tooltipElement = document.createElement('div')
    this.tooltipElement.style.cssText = `
      position: fixed;
      background: rgba(0, 0, 0, 0.85);
      color: white;
      padding: 8px 12px;
      border-radius: 6px;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      font-size: 13px;
      white-space: nowrap;
      z-index: 10000;
      pointer-events: none;
      box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
      border: 1px solid rgba(255, 255, 255, 0.1);
    `
    this.tooltipElement.textContent = 'Click anywhere to place tool'
    
    // Add tooltip to DOM
    document.body.appendChild(this.tooltipElement)
    
    // Function to update tooltip position
    this.mouseMoveHandler = (e: MouseEvent) => {
      if (this.tooltipElement) {
        const x = e.clientX + 15
        const y = e.clientY - 35
        
        // Keep tooltip within viewport bounds
        const rect = this.tooltipElement.getBoundingClientRect()
        const viewportWidth = window.innerWidth
        const viewportHeight = window.innerHeight
        
        let finalX = x
        let finalY = y
        
        // Adjust if tooltip would go off the right edge
        if (x + rect.width > viewportWidth) {
          finalX = e.clientX - rect.width - 15
        }
        
        // Adjust if tooltip would go off the bottom edge
        if (y + rect.height > viewportHeight) {
          finalY = e.clientY - rect.height - 15
        }
        
        // Ensure tooltip doesn't go off the top or left
        finalX = Math.max(10, finalX)
        finalY = Math.max(10, finalY)
        
        this.tooltipElement.style.left = `${finalX}px`
        this.tooltipElement.style.top = `${finalY}px`
      }
    }
    
    // Add mouse move listener
    document.addEventListener('mousemove', this.mouseMoveHandler)
  }

  override onPointerDown = () => {
    // Get the click position in page coordinates
    const { currentPagePoint } = this.editor.inputs
    
    // Create an ObsidianBrowser shape on the canvas at the click location
    this.createObsidianBrowserShape(currentPagePoint.x, currentPagePoint.y)
  }
  
  override onExit = () => {
    this.cleanupTooltip()
    // Clean up event listeners
    if ((this as any).cleanup) {
      ;(this as any).cleanup()
    }
  }
  
  private cleanupTooltip = () => {
    // Remove mouse move listener
    if (this.mouseMoveHandler) {
      document.removeEventListener('mousemove', this.mouseMoveHandler)
      this.mouseMoveHandler = undefined
    }
    
    // Remove tooltip element
    if (this.tooltipElement) {
      document.body.removeChild(this.tooltipElement)
      this.tooltipElement = undefined
    }
  }

  private createObsidianBrowserShape(clickX?: number, clickY?: number) {
    try {
      // Check if ObsidianBrowser already exists
      const allShapes = this.editor.getCurrentPageShapes()
      const existingBrowserShapes = allShapes.filter(shape => shape.type === 'ObsidianBrowser')
      
      if (existingBrowserShapes.length > 0) {
        // If a browser already exists, just select it
        this.editor.setSelectedShapes([existingBrowserShapes[0].id])
        this.editor.setCurrentTool('select')
        return
      }

      // No existing browser, create a new one
      // Standardized size: 800x600
      const shapeWidth = 800
      const shapeHeight = 600
      
      let finalX: number
      let finalY: number
      
      if (clickX !== undefined && clickY !== undefined) {
        // User clicked - ALWAYS use that exact position (centered on click), no collision detection
        // This ensures the shape appears exactly where the user clicked, regardless of overlaps
        finalX = clickX - shapeWidth / 2 // Center the shape on click
        finalY = clickY - shapeHeight / 2 // Center the shape on click
      } else {
        // Fallback to viewport center if no click coordinates, with collision detection
        const viewport = this.editor.getViewportPageBounds()
        const centerX = viewport.x + viewport.w / 2
        const centerY = viewport.y + viewport.h / 2
        const baseX = centerX - shapeWidth / 2
        const baseY = centerY - shapeHeight / 2
        
        // Use collision detection for fallback case
        const position = findNonOverlappingPosition(
          this.editor,
          baseX,
          baseY,
          shapeWidth,
          shapeHeight
        )
        finalX = position.x
        finalY = position.y
      }

      const browserShape = this.editor.createShape({
        type: 'ObsidianBrowser',
        x: finalX,
        y: finalY,
        props: {
          w: shapeWidth,
          h: shapeHeight,
        }
      })

      // Select the new shape and switch to select tool
      this.editor.setSelectedShapes([`shape:${browserShape.id}`] as any)
      this.editor.setCurrentTool('select')

    } catch (error) {
      console.error('❌ Error creating ObsidianBrowser shape:', error)
    }
  }
}
