'use client'

import { Note } from '@/lib/types'
import { NoteCard } from './note-card'
import { useState, useMemo, useEffect } from 'react'
import { NoteEditor } from './note-editor'
import { reorderNotes, getNotes } from '@/app/actions/notes'
import {
  DndContext,
  DragEndEvent,
  DragOverlay,
  DragStartEvent,
  MouseSensor,
  TouchSensor,
  useSensor,
  useSensors,
  closestCenter,
  PointerSensor,
} from '@dnd-kit/core'
import {
  SortableContext,
  rectSortingStrategy,
  useSortable,
  arrayMove,
} from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { useRouter } from 'next/navigation'

interface NoteGridProps {
  notes: Note[]
}

function SortableNote({ note, onEdit }: { note: Note; onEdit: (note: Note) => void }) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id: note.id })

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    opacity: isDragging ? 0.5 : 1,
    zIndex: isDragging ? 1000 : 1,
  }

  return (
    <div
      ref={setNodeRef}
      style={style}
      {...attributes}
      {...listeners}
      data-note-id={note.id}
      data-draggable="true"
    >
      <NoteCard note={note} onEdit={onEdit} isDragging={isDragging} />
    </div>
  )
}

export function NoteGrid({ notes }: NoteGridProps) {
  const router = useRouter()
  const [editingNote, setEditingNote] = useState<Note | null>(null)
  const [activeId, setActiveId] = useState<string | null>(null)
  const [localPinnedNotes, setLocalPinnedNotes] = useState<Note[]>([])
  const [localUnpinnedNotes, setLocalUnpinnedNotes] = useState<Note[]>([])

  // Sync local state with props
  useEffect(() => {
    setLocalPinnedNotes(notes.filter(note => note.isPinned).sort((a, b) => a.order - b.order))
    setLocalUnpinnedNotes(notes.filter(note => !note.isPinned).sort((a, b) => a.order - b.order))
  }, [notes])

  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 8,
      },
    }),
    useSensor(MouseSensor, {
      activationConstraint: {
        distance: 8,
      },
    }),
    useSensor(TouchSensor, {
      activationConstraint: {
        delay: 200,
        tolerance: 6,
      },
    })
  )

  const handleDragStart = (event: DragStartEvent) => {
    console.log('[DND-DEBUG] Drag started:', {
      activeId: event.active.id,
      activeData: event.active.data.current
    })
    setActiveId(event.active.id as string)
  }

  const handleDragEnd = async (event: DragEndEvent) => {
    const { active, over } = event
    console.log('[DND-DEBUG] Drag ended:', {
      activeId: active.id,
      overId: over?.id,
      hasOver: !!over
    })
    setActiveId(null)

    if (!over || active.id === over.id) {
      console.log('[DND-DEBUG] Drag cancelled: no valid drop target or same element')
      return
    }

    const activeIdStr = active.id as string
    const overIdStr = over.id as string

    // Determine which section the dragged note belongs to
    const isInPinned = localPinnedNotes.some(n => n.id === activeIdStr)
    const targetIsInPinned = localPinnedNotes.some(n => n.id === overIdStr)

    console.log('[DND-DEBUG] Section check:', {
      activeIdStr,
      overIdStr,
      isInPinned,
      targetIsInPinned,
      pinnedNotesCount: localPinnedNotes.length,
      unpinnedNotesCount: localUnpinnedNotes.length
    })

    // Only allow reordering within the same section
    if (isInPinned !== targetIsInPinned) {
      console.log('[DND-DEBUG] Drag cancelled: crossing sections (pinned/unpinned)')
      return
    }

    if (isInPinned) {
      // Reorder pinned notes
      const oldIndex = localPinnedNotes.findIndex(n => n.id === activeIdStr)
      const newIndex = localPinnedNotes.findIndex(n => n.id === overIdStr)
      
      console.log('[DND-DEBUG] Pinned reorder:', { oldIndex, newIndex })
      
      if (oldIndex !== -1 && newIndex !== -1) {
        const newOrder = arrayMove(localPinnedNotes, oldIndex, newIndex)
        setLocalPinnedNotes(newOrder)
        console.log('[DND-DEBUG] Calling reorderNotes for pinned notes')
        await reorderNotes(activeIdStr, overIdStr)
        
        // Refresh notes from server to sync state
        console.log('[DND-DEBUG] Refreshing notes from server after reorder')
        await refreshNotesFromServer()
      } else {
        console.log('[DND-DEBUG] Invalid indices for pinned reorder')
      }
    } else {
      // Reorder unpinned notes
      const oldIndex = localUnpinnedNotes.findIndex(n => n.id === activeIdStr)
      const newIndex = localUnpinnedNotes.findIndex(n => n.id === overIdStr)
      
      console.log('[DND-DEBUG] Unpinned reorder:', { oldIndex, newIndex })
      
      if (oldIndex !== -1 && newIndex !== -1) {
        const newOrder = arrayMove(localUnpinnedNotes, oldIndex, newIndex)
        setLocalUnpinnedNotes(newOrder)
        console.log('[DND-DEBUG] Calling reorderNotes for unpinned notes')
        await reorderNotes(activeIdStr, overIdStr)
        
        // Refresh notes from server to sync state
        console.log('[DND-DEBUG] Refreshing notes from server after reorder')
        await refreshNotesFromServer()
      } else {
        console.log('[DND-DEBUG] Invalid indices for unpinned reorder')
      }
    }
  }

  // Function to refresh notes from server without full page reload
  const refreshNotesFromServer = async () => {
    console.log('[DND-DEBUG] Fetching fresh notes from server...')
    const freshNotes = await getNotes()
    console.log('[DND-DEBUG] Received fresh notes:', freshNotes.length)
    
    // Update local state with fresh data
    const pinned = freshNotes.filter(note => note.isPinned).sort((a, b) => a.order - b.order)
    const unpinned = freshNotes.filter(note => !note.isPinned).sort((a, b) => a.order - b.order)
    
    setLocalPinnedNotes(pinned)
    setLocalUnpinnedNotes(unpinned)
    
    console.log('[DND-DEBUG] Local state updated with fresh server data')
  }

  // Find active note from either section
  const activeNote = activeId
    ? localPinnedNotes.find(n => n.id === activeId) || localUnpinnedNotes.find(n => n.id === activeId)
    : null

  return (
    <>
      <div className="space-y-8">
        <DndContext
          sensors={sensors}
          collisionDetection={closestCenter}
          onDragStart={handleDragStart}
          onDragEnd={handleDragEnd}
        >
          {localPinnedNotes.length > 0 && (
            <div>
              <h2 className="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide mb-3 px-2">
                Pinned
              </h2>
              <SortableContext items={localPinnedNotes.map(n => n.id)} strategy={rectSortingStrategy}>
                <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 auto-rows-max">
                  {localPinnedNotes.map((note) => (
                    <SortableNote key={note.id} note={note} onEdit={setEditingNote} />
                  ))}
                </div>
              </SortableContext>
            </div>
          )}
          
          {localUnpinnedNotes.length > 0 && (
            <div>
              {localPinnedNotes.length > 0 && (
                <h2 className="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide mb-3 px-2">
                  Others
                </h2>
              )}
              <SortableContext items={localUnpinnedNotes.map(n => n.id)} strategy={rectSortingStrategy}>
                <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 gap-4 auto-rows-max">
                  {localUnpinnedNotes.map((note) => (
                    <SortableNote key={note.id} note={note} onEdit={setEditingNote} />
                  ))}
                </div>
              </SortableContext>
            </div>
          )}

          <DragOverlay>
            {activeNote ? (
              <div className="opacity-90 rotate-2 scale-105 shadow-2xl">
                <NoteCard
                  note={activeNote}
                  onEdit={() => {}}
                  isDragging={true}
                />
              </div>
            ) : null}
          </DragOverlay>
        </DndContext>
        
        {notes.length === 0 && (
          <div className="text-center py-16">
            <p className="text-gray-500 dark:text-gray-400 text-lg">No notes yet</p>
            <p className="text-gray-400 dark:text-gray-500 text-sm mt-2">Create your first note to get started</p>
          </div>
        )}
      </div>

      {editingNote && (
        <NoteEditor note={editingNote} onClose={() => setEditingNote(null)} />
      )}
    </>
  )
}
