import { TrackControls } from '@/components/sequencer/TrackControls'
import { TimelineControls } from '@/components/sequencer/TimelineControls'
import { SoundLibrary } from '@/components/sequencer/SoundLibrary'
import { SequencerCanvas } from '@/components/sequencer/SequencerCanvas'
import { AppLayout } from '@/components/AppLayout'
import { DndContext, type DragEndEvent, type DragStartEvent, PointerSensor, useSensors, useSensor } from '@dnd-kit/core'
import { useState, useRef, useCallback, useEffect } from 'react'

export interface Track {
  id: string
  name: string
  sounds: PlacedSound[]
}

export interface PlacedSound {
  id: string
  soundId: number
  name: string
  duration: number // in seconds
  startTime: number // in seconds
  trackId: string
}

interface SequencerState {
  tracks: Track[]
  duration: number
  zoom: number
  currentTime: number
  isPlaying: boolean
}

const INITIAL_DURATION = 30 // 30 seconds
const INITIAL_ZOOM = 40 // 40 pixels per second
const MIN_ZOOM = 10
const MAX_ZOOM = 200

export function SequencerPage() {
  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 8,
      },
    })
  )

  const [state, setState] = useState<SequencerState>({
    tracks: [
      {
        id: 'track-1',
        name: 'Track 1',
        sounds: [],
      },
    ],
    duration: INITIAL_DURATION,
    zoom: INITIAL_ZOOM,
    currentTime: 0,
    isPlaying: false,
  })

  const [draggedItem, setDraggedItem] = useState<any>(null)
  const [dragOverInfo, setDragOverInfo] = useState<{trackId: string, x: number} | null>(null)
  const [currentMousePos, setCurrentMousePos] = useState<{x: number, y: number} | null>(null)
  
  const trackControlsRef = useRef<HTMLDivElement>(null)
  const sequencerCanvasRef = useRef<HTMLDivElement>(null)

  const handleDragStart = useCallback((event: DragStartEvent) => {
    setDraggedItem(event.active.data.current)
    
    // Start tracking mouse position globally
    const handleMouseMove = (e: MouseEvent) => {
      setCurrentMousePos({ x: e.clientX, y: e.clientY })
    }
    
    document.addEventListener('mousemove', handleMouseMove)
    
    // Store cleanup function
    ;(window as any).dragMouseCleanup = () => {
      document.removeEventListener('mousemove', handleMouseMove)
    }
  }, [])

  // Update drag over info based on current mouse position and over target
  useEffect(() => {
    if (draggedItem && currentMousePos && (draggedItem.type === 'sound' || draggedItem.type === 'placed-sound')) {
      // Find which track the mouse is currently over
      for (const track of state.tracks) {
        const trackElement = document.getElementById(`track-${track.id}`)
        if (trackElement) {
          const rect = trackElement.getBoundingClientRect()
          if (
            currentMousePos.x >= rect.left &&
            currentMousePos.x <= rect.right &&
            currentMousePos.y >= rect.top &&
            currentMousePos.y <= rect.bottom
          ) {
            const x = currentMousePos.x - rect.left
            setDragOverInfo({ trackId: track.id, x: Math.max(0, x) })
            return
          }
        }
      }
      // Mouse is not over any track
      setDragOverInfo(null)
    } else {
      setDragOverInfo(null)
    }
  }, [draggedItem, currentMousePos, state.tracks])

  const handleDragEnd = useCallback((event: DragEndEvent) => {
    const { active, over } = event
    const dragData = active.data.current
    const overData = over?.data.current

    // Handle sound drop from library to track
    if (dragData?.type === 'sound' && overData?.type === 'track') {
      // Use precise drop position if available
      let startTime = 0
      if (dragOverInfo && dragOverInfo.trackId === overData.trackId) {
        startTime = Math.max(0, dragOverInfo.x / state.zoom)
      }

      const newPlacedSound: PlacedSound = {
        id: `placed-${Date.now()}-${Math.random()}`,
        soundId: dragData.sound.id,
        name: dragData.sound.name || dragData.sound.filename,
        duration: dragData.sound.duration / 1000, // Convert from ms to seconds
        startTime,
        trackId: overData.trackId,
      }

      setState(prev => ({
        ...prev,
        tracks: prev.tracks.map(track =>
          track.id === overData.trackId
            ? { ...track, sounds: [...track.sounds, newPlacedSound] }
            : track
        ),
      }))
    }

    // Handle moving placed sounds within tracks
    if (dragData?.type === 'placed-sound' && overData?.type === 'track') {
      console.log('Moving placed sound:', dragData, 'to track:', overData.trackId)
      
      // Use precise drop position if available
      let startTime = dragData.startTime || 0
      if (dragOverInfo && dragOverInfo.trackId === overData.trackId) {
        startTime = Math.max(0, dragOverInfo.x / state.zoom)
      }

      const sourceTrackId = dragData.trackId
      const targetTrackId = overData.trackId
      
      console.log('Source track:', sourceTrackId, 'Target track:', targetTrackId, 'New start time:', startTime)

      setState(prev => ({
        ...prev,
        tracks: prev.tracks.map(track => {
          if (track.id === sourceTrackId && sourceTrackId === targetTrackId) {
            // Moving within the same track - just update position
            console.log('Moving within same track')
            const updatedSound: PlacedSound = {
              ...dragData,
              startTime,
              trackId: targetTrackId,
            }
            return {
              ...track,
              sounds: track.sounds.map(s => 
                s.id === dragData.id ? updatedSound : s
              ),
            }
          } else if (track.id === sourceTrackId) {
            // Remove from source track (different track move)
            console.log('Removing sound from source track:', track.id, 'sounds before:', track.sounds.length)
            const filtered = track.sounds.filter(s => s.id !== dragData.id)
            console.log('Sounds after removal:', filtered.length)
            return {
              ...track,
              sounds: filtered,
            }
          } else if (track.id === targetTrackId) {
            // Add to target track (different track move)
            console.log('Adding sound to target track:', track.id, 'sounds before:', track.sounds.length)
            const updatedSound: PlacedSound = {
              ...dragData,
              startTime,
              trackId: targetTrackId,
            }
            console.log('Updated sound:', updatedSound)
            const newSounds = [...track.sounds, updatedSound]
            console.log('Sounds after addition:', newSounds.length)
            return {
              ...track,
              sounds: newSounds,
            }
          }
          return track
        }),
      }))
    }
    
    // Clear state
    setDraggedItem(null)
    setDragOverInfo(null)
    setCurrentMousePos(null)
    
    // Clean up mouse tracking
    if ((window as any).dragMouseCleanup) {
      (window as any).dragMouseCleanup()
      delete (window as any).dragMouseCleanup
    }
  }, [dragOverInfo, state.zoom])

  const handleAddTrack = () => {
    const newTrackNumber = state.tracks.length + 1
    const newTrack: Track = {
      id: `track-${Date.now()}`,
      name: `Track ${newTrackNumber}`,
      sounds: [],
    }
    setState(prev => ({ ...prev, tracks: [...prev.tracks, newTrack] }))
  }

  const handleRemoveTrack = (trackId: string) => {
    setState(prev => ({
      ...prev,
      tracks: prev.tracks.filter(track => track.id !== trackId),
    }))
  }

  const handleUpdateTrackName = (trackId: string, name: string) => {
    setState(prev => ({
      ...prev,
      tracks: prev.tracks.map(track =>
        track.id === trackId ? { ...track, name } : track
      ),
    }))
  }

  const handlePlay = () => {
    setState(prev => ({ ...prev, isPlaying: !prev.isPlaying }))
  }

  const handleStop = () => {
    setState(prev => ({ ...prev, isPlaying: false, currentTime: 0 }))
  }

  const handleReset = () => {
    setState(prev => ({ ...prev, currentTime: 0 }))
  }

  const handleZoomChange = (value: number) => {
    setState(prev => ({ ...prev, zoom: value }))
  }

  const handleDurationChange = (duration: number) => {
    setState(prev => ({ ...prev, duration }))
  }

  const handleVerticalScroll = useCallback(() => {
    if (trackControlsRef.current && sequencerCanvasRef.current) {
      const canvasScrollTop = sequencerCanvasRef.current.scrollTop
      if (Math.abs(trackControlsRef.current.scrollTop - canvasScrollTop) > 1) {
        trackControlsRef.current.scrollTop = canvasScrollTop
      }
    }
  }, [])

  // Simple playhead animation
  useEffect(() => {
    if (state.isPlaying) {
      const interval = setInterval(() => {
        setState(prev => {
          const newTime = prev.currentTime + 0.1
          if (newTime >= prev.duration) {
            return { ...prev, currentTime: prev.duration, isPlaying: false }
          }
          return { ...prev, currentTime: newTime }
        })
      }, 100)
      return () => clearInterval(interval)
    }
  }, [state.isPlaying, state.duration])

  return (
    <AppLayout 
      breadcrumb={{
        items: [
          { label: 'Home', href: '/' },
          { label: 'Sequencer' }
        ]
      }}
    >
      <div className="h-[calc(100vh-8rem)] flex flex-col">
        {/* Main Content */}
        <div className="flex-1 flex overflow-hidden">
        <DndContext
          sensors={sensors}
          onDragStart={handleDragStart}
          onDragEnd={handleDragEnd}
        >
          {/* Left Sidebar - Sound Library */}
          <div className="w-80 border-r bg-muted/30 flex flex-col">
            <div className="p-4 h-full">
              <SoundLibrary />
            </div>
          </div>

          {/* Center Content - Tracks */}
          <div className="flex-1 flex flex-col overflow-hidden">
            {/* Timeline Controls */}
            <div className="p-4 border-b bg-muted/30">
              <TimelineControls
                duration={state.duration}
                zoom={state.zoom}
                onDurationChange={handleDurationChange}
                onZoomChange={handleZoomChange}
                minZoom={MIN_ZOOM}
                maxZoom={MAX_ZOOM}
              />
            </div>

            {/* Track Area */}
            <div className="flex-1 flex overflow-hidden">
              {/* Track Controls */}
              <div className="w-40 border-r">
                <TrackControls
                  ref={trackControlsRef}
                  tracks={state.tracks}
                  onAddTrack={handleAddTrack}
                  onRemoveTrack={handleRemoveTrack}
                  onUpdateTrackName={handleUpdateTrackName}
                  onScroll={handleVerticalScroll}
                />
              </div>

              {/* Sequencer Canvas */}
              <div className="flex-1 min-w-0 overflow-hidden">
                <SequencerCanvas
                  ref={sequencerCanvasRef}
                  tracks={state.tracks}
                  duration={state.duration}
                  zoom={state.zoom}
                  currentTime={state.currentTime}
                  isPlaying={state.isPlaying}
                  onScroll={handleVerticalScroll}
                  draggedItem={draggedItem}
                  dragOverInfo={dragOverInfo}
                />
              </div>
            </div>
          </div>
        </DndContext>
        </div>
      </div>
    </AppLayout>
  )
}