import { useState, useRef, useEffect, useCallback } from 'react';
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { ArrowLeft, Trash2, MoreHorizontal, Sparkles } from 'lucide-react';
import { SidebarTrigger } from '@/components/ui/sidebar';
import { Separator } from '@/components/ui/separator';
import { useFormatPrefs, formatDateTime } from '@/lib/date';
import { Button } from '@/components/ui/button';
import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
} from '@/components/ui/alert-dialog';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { ScrollArea } from '@/components/ui/scroll-area';
import { trpc } from '@/lib/trpc';
import { useNotify } from '@/hooks/useNotify';
import { MilkdownEditor } from '@/components/notes/MilkdownEditor';
import { PendingEditBlock } from '@/components/notes/PendingEditBlock';
import { useFloatingChat } from '@/context/FloatingChatContext';

export const Route = createFileRoute('/notes/$noteId')({
  component: NoteDetailPage,
});

function NoteDetailPage() {
  const { noteId } = Route.useParams();
  const navigate = useNavigate();
  const utils = trpc.useUtils();
  const prefs = useFormatPrefs();
  const { data: note, isLoading } = trpc.notes.get.useQuery({ id: noteId });
  const { data: pendingEdits = [] } = trpc.noteEdits.listPending.useQuery({ noteId });

  const editorRef = useRef<HTMLDivElement>(null);
  const { registerSection, unregisterSection } = useFloatingChat();
  const noteProjectId = note?.projectId ?? undefined;
  useEffect(() => {
    registerSection({
      id: 'note-editor',
      label: 'Note Editor',
      ref: editorRef,
      projectId: noteProjectId,
      anchorMode: 'right-margin',
    });
    return () => unregisterSection('note-editor');
  }, [noteId, noteProjectId, registerSection, unregisterSection]);

  const [title, setTitle] = useState('');
  const [isSaving, setIsSaving] = useState(false);
  const [deleteOpen, setDeleteOpen] = useState(false);
  const debounceTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const pendingContentRef = useRef<string | null>(null);

  const { notify, notifyError } = useNotify();

  const approveEdit = trpc.noteEdits.approve.useMutation({
    onSuccess: () => {
      void utils.noteEdits.listPending.invalidate({ noteId });
      void utils.notes.get.invalidate({ id: noteId });
    },
    onError: (err) => notifyError('toast.note.deleteError', err),
  });

  const rejectEdit = trpc.noteEdits.reject.useMutation({
    onSuccess: () => void utils.noteEdits.listPending.invalidate({ noteId }),
    onError: (err) => notifyError('toast.note.deleteError', err),
  });

  const updateNote = trpc.notes.update.useMutation({
    onSuccess: () => {
      void utils.notes.get.invalidate({ id: noteId });
      void utils.notes.list.invalidate();
    },
    onSettled: () => {
      setIsSaving(false);
    },
    onError: (err) => notifyError('toast.note.deleteError', err),
  });

  const deleteNote = trpc.notes.delete.useMutation({
    onSuccess: () => {
      notify('warning', 'toast.note.deleted');
      void utils.notes.list.invalidate();
      void navigate({ to: '/projects', search: { projectId: note?.projectId, tab: 'notes' } });
    },
    onError: (err) => notifyError('toast.note.deleteError', err),
  });

  useEffect(() => {
    if (note) {
      setTitle(note.title);
    }
  }, [note]);

  useEffect(() => {
    return () => {
      if (debounceTimerRef.current) {
        clearTimeout(debounceTimerRef.current);
      }
    };
  }, []);

  const handleContentChange = useCallback(
    (markdown: string) => {
      setIsSaving(true);
      pendingContentRef.current = markdown;

      if (debounceTimerRef.current) {
        clearTimeout(debounceTimerRef.current);
      }

      debounceTimerRef.current = setTimeout(() => {
        pendingContentRef.current = null;
        updateNote.mutate({ id: noteId, content: markdown });
      }, 2000);
    },
    [noteId, updateNote]
  );

  const handleTitleBlur = () => {
    const trimmed = title.trim();
    if (trimmed && note && trimmed !== note.title) {
      setIsSaving(true);
      updateNote.mutate({ id: noteId, title: trimmed });
    }
  };

  const handleTitleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      e.currentTarget.blur();
    }
  };

  const goBackToProject = useCallback(() => {
    void navigate({
      to: '/projects',
      search: { projectId: note?.projectId, tab: 'notes' },
    });
  }, [navigate, note?.projectId]);

  const handleBack = () => {
    if (debounceTimerRef.current) {
      clearTimeout(debounceTimerRef.current);
      debounceTimerRef.current = null;
    }
    if (pendingContentRef.current !== null) {
      updateNote.mutate({ id: noteId, content: pendingContentRef.current });
      pendingContentRef.current = null;
    }
    goBackToProject();
  };

  const handleDelete = () => {
    if (debounceTimerRef.current) {
      clearTimeout(debounceTimerRef.current);
      debounceTimerRef.current = null;
    }
    pendingContentRef.current = null;
    deleteNote.mutate({ id: noteId });
  };

  if (isLoading) {
    return (
      <div className="flex h-full items-center justify-center">
        <p className="text-muted-foreground text-sm">Loading note...</p>
      </div>
    );
  }

  if (!note) {
    return (
      <div className="flex h-full items-center justify-center">
        <p className="text-muted-foreground text-sm">Note not found.</p>
      </div>
    );
  }

  return (
    <div className="flex h-full min-h-0 flex-col">
      {/* Minimal top bar */}
      <div className="flex h-14 shrink-0 items-center gap-1 px-3">
        <SidebarTrigger />
        <Separator orientation="vertical" className="data-[orientation=vertical]:h-4" />
        <Button variant="ghost" size="icon" className="h-7 w-7" onClick={handleBack}>
          <ArrowLeft className="h-4 w-4" />
        </Button>
        <div className="ml-auto flex items-center gap-2">
          {isSaving && (
            <span className="text-muted-foreground text-xs">Saving…</span>
          )}
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button variant="ghost" size="icon" className="h-7 w-7">
                <MoreHorizontal className="h-4 w-4" />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
              <DropdownMenuItem
                className="text-destructive focus:text-destructive"
                onClick={() => setDeleteOpen(true)}
              >
                <Trash2 className="h-4 w-4" />
                Delete note
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      </div>

      {/* Notion-style content area */}
      <ScrollArea ref={editorRef} data-ai-section="note-editor" className="flex-1 min-h-0">
        <div className="mx-auto max-w-3xl pb-32 pt-14">
          {/* Title styled to match the project page h1 */}
          <input
            value={title}
            onChange={(e) => setTitle(e.target.value)}
            onBlur={handleTitleBlur}
            onKeyDown={handleTitleKeyDown}
            className="mb-1 w-full bg-transparent pl-18 pr-6 text-3xl font-semibold leading-tight tracking-tight text-foreground outline-none placeholder:text-muted-foreground/40"
            placeholder="Untitled"
          />
          {/* Metadata */}
          <p className="mb-8 pl-18 text-xs text-muted-foreground">
            Last edited {formatDateTime(note.updatedAt, prefs)}
          </p>
          {/* AI pending edits banner */}
          {pendingEdits.length > 0 && (
            <div className="mb-6 flex flex-col gap-3">
              <div className="flex items-center gap-2 text-sm text-muted-foreground pl-18">
                <Sparkles className="h-4 w-4 text-primary" />
                <span>
                  {pendingEdits.length === 1
                    ? '1 AI suggestion pending'
                    : `${pendingEdits.length} AI suggestions pending`}
                </span>
              </div>
              <div className="flex flex-col gap-2 pl-18 pr-6">
                {pendingEdits.map((edit) => (
                  <PendingEditBlock
                    key={edit.id}
                    edit={edit}
                    onApprove={() => approveEdit.mutate({ id: edit.id })}
                    onReject={() => rejectEdit.mutate({ id: edit.id })}
                    isPending={approveEdit.isPending || rejectEdit.isPending}
                  />
                ))}
              </div>
            </div>
          )}

          {/* Editor */}
          <MilkdownEditor
            key={noteId}
            initialContent={note.content}
            onChange={handleContentChange}
          />
        </div>
      </ScrollArea>

      <AlertDialog open={deleteOpen} onOpenChange={setDeleteOpen}>
        <AlertDialogContent>
          <AlertDialogHeader>
            <AlertDialogTitle>Delete note</AlertDialogTitle>
            <AlertDialogDescription>
              Are you sure you want to delete &quot;{title || 'Untitled'}&quot;? This action cannot be undone.
            </AlertDialogDescription>
          </AlertDialogHeader>
          <AlertDialogFooter>
            <AlertDialogCancel>Cancel</AlertDialogCancel>
            <AlertDialogAction variant="destructive" onClick={handleDelete}>
              Delete
            </AlertDialogAction>
          </AlertDialogFooter>
        </AlertDialogContent>
      </AlertDialog>
    </div>
  );
}
