import {
  codeBlockPlugin,
  codeMirrorPlugin,
  headingsPlugin,
  linkPlugin,
  listsPlugin,
  markdownShortcutPlugin,
  MDXEditor,
  quotePlugin,
  SandpackConfig,
  sandpackPlugin,
  thematicBreakPlugin,
} from "@mdxeditor/editor";
import { useEffect, useRef, useState } from "react";
import {
  folderApi,
  FolderCreate,
  FolderTreeNode,
  FolderTreeResponse,
  NoteRead,
} from "../api/folders";
import { NoteCreate, notesApi } from "../api/notes";
import "../main.css";
import {
  DndContext,
  DragEndEvent,
  PointerSensor,
  useSensor,
  useSensors,
} from "@dnd-kit/core";

import "@mdxeditor/editor/style.css";
import { DroppableFolder } from "../components/sidebar/DroppableFolder";
import { DraggableNote } from "../components/sidebar/DraggableNote";

const simpleSandpackConfig: SandpackConfig = {
  defaultPreset: "react",
  presets: [
    {
      label: "React",
      name: "react",
      meta: "live react",
      sandpackTemplate: "react",
      sandpackTheme: "dark",
      snippetFileName: "/App.js",
      snippetLanguage: "jsx",
    },
  ],
};

function Home() {
  const [folderTree, setFolderTree] = useState<FolderTreeResponse | null>(null);
  const [selectedNote, setSelectedNote] = useState<NoteRead | null>(null);
  const [title, setTitle] = useState("");
  const [content, setContent] = useState("#");
  const [newFolder, setNewFolder] = useState(false);
  const [newFolderText, setNewFolderText] = useState("");
  const [selectedFolder, setSelectedFolder] = useState<number | null>(null);
  const [encrypted, setEncrypted] = useState(false);
  const pointer = useSensor(PointerSensor, {
    activationConstraint: {
      distance: 30,
    },
  });
  const sensors = useSensors(pointer);
  useEffect(() => {
    loadFolderTree();
  }, []);

  const loadFolderTree = async () => {
    const data = await folderApi.tree();
    setFolderTree(data);
  };

  const handleCreate = async () => {
    if (!title.trim()) return;
    const newNote: NoteCreate = {
      title,
      content,
      folder_id: selectedFolder,
      encrypted,
    };
    await notesApi.create(newNote);
    setTitle("");
    setContent("#");
    loadFolderTree();
  };

  const handleCreateFolder = async () => {
    if (!newFolderText.trim()) return;
    const newFolderData: FolderCreate = {
      name: newFolderText,
      parent_id: null,
    };
    await folderApi.create(newFolderData);
    setNewFolderText("");
    loadFolderTree();
    setNewFolder(false);
  };

  const handleUpdate = async () => {
    if (!selectedNote) return;
    await notesApi.update(selectedNote.id, { title, content });
    setSelectedNote(null);
    setTitle("");
    setContent("#");
    loadFolderTree();
  };

  const handleDelete = async (id: number) => {
    await notesApi.delete(id);
    loadFolderTree();
  };

  const selectNote = (note: NoteRead) => {
    console.log(note);
    setSelectedNote(note);
    setTitle(note.title);
    setContent(note.content);
  };

  const clearSelection = () => {
    setSelectedNote(null);
    setTitle("");
    setContent("#");
  };

  const newFolderRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (newFolder && newFolderRef.current) {
      newFolderRef.current.focus();
    }
  }, [newFolder]);

  const renderFolder = (folder: FolderTreeNode, depth: number = 0) => (
    <div
      key={folder.id}
      style={{ marginLeft: depth > 0 ? "1rem" : "0" }}
      className="flex flex-col"
    >
      <DroppableFolder
        key={folder.id}
        folder={folder}
        setSelectedFolder={setSelectedFolder}
        selectedFolder={selectedFolder}
        selectedNote={selectedNote}
      />
      <div className="flex flex-col ml-5">
        {folder.notes.map((note) => (
          <DraggableNote
            key={note.id}
            note={note}
            selectNote={selectNote}
            selectedNote={selectedNote}
          />
        ))}
      </div>
      {folder.children.map((child) => renderFolder(child, depth + 1))}
    </div>
  );

  const handleDragEnd = async (event: DragEndEvent) => {
    const { active, over } = event;
    if (!over) return;

    console.log(active.data);
    console.log(over.data);

    await notesApi.update(active.id as number, {
      folder_id: over.id as number,
    });

    loadFolderTree();
  };

  return (
    <DndContext onDragEnd={handleDragEnd} autoScroll={false} sensors={sensors}>
      <div className="flex bg-ctp-base min-h-screen text-ctp-text">
        <div
          className="bg-ctp-mantle border-r-ctp-surface2 border-r overflow-hidden w-[300px] p-4 overflow-y-auto sm:block hidden"
          onDragOver={(e) => e.preventDefault()}
          onTouchMove={(e) => e.preventDefault()}
        >
          <h2>Notes</h2>
          <button
            onClick={clearSelection}
            style={{ marginBottom: "1rem", width: "100%" }}
          >
            New Note
          </button>
          <div className="flex gap-2 mb-2">
            <button
              onClick={() => {
                if (newFolder && newFolderRef.current) {
                  newFolderRef.current.focus();
                }
                setNewFolder(true);
              }}
              className="hover:bg-ctp-mauve group transition-colors rounded-md p-1 text-center flex"
            >
              <i className="fadr fa-folder-plus text-xl text-ctp-mauve group-hover:text-ctp-base transition-colors"></i>
            </button>
            <button
              onClick={clearSelection}
              className="hover:bg-ctp-mauve group transition-colors rounded-md p-1 text-center flex"
            >
              <i className="fadr fa-file-circle-plus text-xl text-ctp-mauve group-hover:text-ctp-base transition-colors"></i>
            </button>
          </div>

          {newFolder && (
            <div className="px-1 mb-1">
              <input
                onBlur={() => setNewFolder(false)}
                onChange={(e) => setNewFolderText(e.target.value)}
                value={newFolderText}
                type="text"
                placeholder="new folder"
                className="border-ctp-mauve border rounded-md px-2 w-full focus:outline-none focus:ring-1 focus:ring-ctp-mauve focus:border-ctp-mauve bg-ctp-base"
                ref={newFolderRef}
                onKeyDown={(e) => {
                  if (e.key === "Enter") {
                    handleCreateFolder();
                  }
                }}
              />
            </div>
          )}

          {/* Render folder tree */}
          {folderTree?.folders.map((folder) => renderFolder(folder))}

          {/* Render orphaned notes */}
          {folderTree?.orphaned_notes &&
            folderTree.orphaned_notes.length > 0 && (
              <div className="mt-4 flex flex-col">
                <div className="text-ctp-subtext0 text-sm mb-1">Unsorted</div>
                {folderTree.orphaned_notes.map((note) => (
                  <DraggableNote
                    key={note.id}
                    note={note}
                    selectNote={selectNote}
                    selectedNote={selectedNote}
                  />
                ))}
              </div>
            )}
        </div>

        <div className="flex flex-col w-full">
          <div className="w-full bg-ctp-crust h-4"></div>
          <input
            type="text"
            placeholder="Note title..."
            value={title}
            onChange={(e) => setTitle(e.target.value)}
            style={{
              padding: "0.5rem",
              marginBottom: "1rem",
              fontSize: "1.5rem",
              border: "1px solid #ccc",
            }}
          />
          <MDXEditor
            markdown={content}
            key={selectedNote?.id || "new"}
            onChange={setContent}
            className="prose text-ctp-text"
            plugins={[
              headingsPlugin(),
              listsPlugin(),
              quotePlugin(),
              thematicBreakPlugin(),
              linkPlugin(),
              codeBlockPlugin({ defaultCodeBlockLanguage: "js" }),
              sandpackPlugin({ sandpackConfig: simpleSandpackConfig }),
              codeMirrorPlugin({
                codeBlockLanguages: { js: "JavaScript", css: "CSS" },
              }),
              markdownShortcutPlugin(),
            ]}
          />
          <div style={{ marginTop: "1rem", display: "flex", gap: "0.5rem" }}>
            {selectedNote ? (
              <>
                <button onClick={handleUpdate}>Update Note</button>
                <button
                  onClick={() => handleDelete(selectedNote.id)}
                  className="bg-ctp-red rounded-md px-1 text-ctp-crust"
                >
                  Delete
                </button>
                <button onClick={clearSelection}>Cancel</button>
              </>
            ) : (
              <button onClick={handleCreate}>Create Note</button>
            )}
            <input
              type="checkbox"
              checked={encrypted}
              onChange={() => setEncrypted(!encrypted)}
            />
          </div>
        </div>
      </div>
    </DndContext>
  );
}

export default Home;
