"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import {
  BookOpen,
  FileText,
  Folder,
  Hash,
  Pin,
  Plus,
  Search,
  Sparkles,
  SortAsc,
  X,
} from "lucide-react";
import { NoteCard } from "@/components/notes/note-card";
import { FolderTree } from "@/components/notes/folder-tree";
import { SavedViewsBar } from "@/components/tasks/saved-views-bar";
import { useNotes } from "@/hooks/use-notes";
import { useSavedViews } from "@/hooks/use-saved-views";
import { useTeamPermissions } from "@/hooks/use-team-permissions";
import { cn } from "@/lib/utils";

// Extract plain text from Tiptap ProseMirror JSON for full-text search
function extractText(node: unknown): string {
  if (!node || typeof node !== "object") return "";
  const n = node as Record<string, unknown>;
  if (n.type === "text" && typeof n.text === "string") return n.text;
  if (Array.isArray(n.content)) return (n.content as unknown[]).map(extractText).join(" ");
  return "";
}

type NoteFilterValues = {
  search: string;
  folderId: string;
  pinState: string;
};

const EMPTY_FILTERS: NoteFilterValues = {
  search: "",
  folderId: "",
  pinState: "",
};

const BUILT_IN_VIEWS = [
  { id: "all", label: "All notes", filters: {} },
  { id: "pinned", label: "Pinned", filters: { pinState: "pinned" } },
  { id: "unfiled", label: "No folder", filters: { folderId: "__none__" } },
] satisfies Array<{ id: string; label: string; filters: Partial<NoteFilterValues> }>;

/* ── Note template starters ─────────────────────────────────────────────────── */
type NoteTemplateId = "meeting" | "idea" | "weekly" | "research";

const NOTE_TEMPLATES = [
  { id: "meeting", icon: "📋", label: "Meeting notes", description: "Agenda, decisions, action items" },
  { id: "idea", icon: "💡", label: "Idea dump", description: "Capture thoughts before they escape" },
  { id: "weekly", icon: "📅", label: "Weekly review", description: "Wins, blockers, and next steps" },
  { id: "research", icon: "🔬", label: "Research note", description: "Sources, findings, conclusions" },
] satisfies Array<{ id: NoteTemplateId; icon: string; label: string; description: string }>;

function paragraph(text = "") {
  return {
    type: "paragraph",
    content: text ? [{ type: "text", text }] : [],
  };
}

function heading(text: string, level = 2) {
  return {
    type: "heading",
    attrs: { level },
    content: [{ type: "text", text }],
  };
}

function bulletList(items: string[]) {
  return {
    type: "bulletList",
    content: items.map((text) => ({
      type: "listItem",
      content: [paragraph(text)],
    })),
  };
}

function buildTemplateContent(templateId?: string): Record<string, unknown> | undefined {
  if (!templateId) return undefined;

  const templates: Record<NoteTemplateId, Record<string, unknown>> = {
    meeting: {
      type: "doc",
      content: [
        heading("Context"),
        bulletList(["Date / time:", "People:", "Goal of the meeting:"]),
        heading("Agenda"),
        bulletList(["Topic 1", "Topic 2", "Topic 3"]),
        heading("Decisions"),
        bulletList(["Decision:", "Owner:", "Deadline:"]),
        heading("Action Items"),
        bulletList(["[ ] Next action", "[ ] Follow-up", "[ ] Send summary"]),
      ],
    },
    idea: {
      type: "doc",
      content: [
        paragraph("Start writing. No structure needed yet."),
        paragraph(),
      ],
    },
    weekly: {
      type: "doc",
      content: [
        heading("Wins"),
        bulletList(["What went well?", "What moved forward?", "What gave energy?"]),
        heading("Blockers"),
        bulletList(["What slowed things down?", "What needs a decision?", "What can be simplified?"]),
        heading("Lessons"),
        bulletList(["What did I learn?", "What should I repeat?", "What should I stop doing?"]),
        heading("Next Week"),
        bulletList(["Top 3 priorities", "One thing to protect", "One thing to delegate or delete"]),
      ],
    },
    research: {
      type: "doc",
      content: [
        heading("Question"),
        paragraph("What am I trying to understand?"),
        heading("Sources"),
        bulletList(["Source / link:", "Source / link:", "Source / link:"]),
        heading("Findings"),
        bulletList(["Finding:", "Evidence:", "Confidence:"]),
        heading("Conclusion"),
        paragraph("What does this change or clarify?"),
        heading("Next Steps"),
        bulletList(["Verify", "Compare", "Apply"]),
      ],
    },
  };

  return templateId in templates ? templates[templateId as NoteTemplateId] : undefined;
}

export default function NotesPage() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const {
    notes,
    folders,
    loading,
    createNote,
    deleteNote,
    togglePin,
    createFolder,
    renameFolder,
    deleteFolder,
  } = useNotes();
  const { views, createView, updateView, deleteView } = useSavedViews("notes");
  const { can } = useTeamPermissions();
  const canEditNotes = can("notes", "edit");

  const [filters, setFilters] = useState<NoteFilterValues>(EMPTY_FILTERS);
  const [showFolderSidebar, setShowFolderSidebar] = useState(true);
  const [sortBy, setSortBy] = useState<"updated" | "created" | "name">("updated");

  const selectedFolderId =
    filters.folderId && filters.folderId !== "__none__" ? filters.folderId : null;

  const handleCreate = useCallback(async (templateId?: string) => {
    const folderId = filters.folderId && filters.folderId !== "__none__" ? filters.folderId : null;
    // For templates, prepopulate a title
    const titleMap: Record<NoteTemplateId, string> = {
      meeting: "Meeting Notes",
      idea: "Idea Dump",
      weekly: "Weekly Review",
      research: "Research Note",
    };
    const typedTemplateId = templateId as NoteTemplateId | undefined;
    const note = await createNote({
      folder_id: folderId,
      title: typedTemplateId ? titleMap[typedTemplateId] ?? "" : undefined,
      content: buildTemplateContent(templateId),
    });
    router.push(`/notes/${note.id}`);
  }, [createNote, filters.folderId, router]);

  useEffect(() => {
    const savedViewId = searchParams.get("savedView");
    if (!savedViewId || views.length === 0) return;

    const matchedView = views.find((view) => view.id === savedViewId);
    if (!matchedView) return;

    const timer = window.setTimeout(() => {
      setFilters({
        ...EMPTY_FILTERS,
        ...Object.fromEntries(
          Object.entries(matchedView.filters).filter(([, value]) => typeof value === "string")
        ),
      });
    }, 0);

    return () => window.clearTimeout(timer);
  }, [searchParams, views]);

  useEffect(() => {
    const shouldCreate = searchParams.get("create");
    if (shouldCreate !== "1") return;

    const nextParams = new URLSearchParams(searchParams.toString());
    nextParams.delete("create");
    const nextQuery = nextParams.toString();
    router.replace(nextQuery ? `/notes?${nextQuery}` : "/notes", { scroll: false });

    if (canEditNotes) {
      void handleCreate();
    }
  }, [canEditNotes, handleCreate, router, searchParams]);

  /* ── Filter + sort — single source of truth, no duplicate sections ──────── */
  const filtered = useMemo(() => {
    let result = [...notes];

    // Folder filter
    if (filters.folderId === "__none__") {
      result = result.filter((n) => n.folder_id === null);
    } else if (filters.folderId) {
      result = result.filter((n) => n.folder_id === filters.folderId);
    }

    // Pin filter
    if (filters.pinState === "pinned") {
      result = result.filter((n) => n.is_pinned);
    }

    // Full-text search — title + note content
    if (filters.search.trim()) {
      const q = filters.search.toLowerCase();
      result = result.filter((n) => {
        if (n.title.toLowerCase().includes(q)) return true;
        const bodyText = extractText(n.content).toLowerCase();
        return bodyText.includes(q);
      });
    }

    // Sort
    if (sortBy === "updated") {
      result.sort((a, b) => new Date(b.updated_at).getTime() - new Date(a.updated_at).getTime());
    } else if (sortBy === "created") {
      result.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
    } else {
      result.sort((a, b) => a.title.localeCompare(b.title));
    }

    return result;
  }, [filters, notes, sortBy]);

  const pinnedNotes = useMemo(() => notes.filter((n) => n.is_pinned), [notes]);

  const noteCountByFolder = useMemo(() => {
    const counts: Record<string, number> = {};
    notes.forEach((n) => {
      if (n.folder_id) {
        counts[n.folder_id] = (counts[n.folder_id] || 0) + 1;
      }
    });
    return counts;
  }, [notes]);

  const activeFolder = filters.folderId && filters.folderId !== "__none__"
    ? folders.find(f => f.id === filters.folderId)
    : null;

  if (loading) {
    return (
      <div className="space-y-6">
        <div className="h-40 rounded-[28px] border border-white/[0.07] bg-white/[0.03] animate-pulse" />
        <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
          {Array.from({ length: 6 }).map((_, i) => (
            <div key={i} className="h-28 rounded-[20px] bg-white/[0.03] border border-white/[0.06] animate-pulse" />
          ))}
        </div>
      </div>
    );
  }

  return (
    <div className="space-y-6">

      {/* ── Hero header ─────────────────────────────────────────────────────── */}
      <div
        className="relative overflow-hidden rounded-[28px] border border-white/[0.07] bg-[#0e0c15] p-8"
        style={{
          backgroundImage:
            "radial-gradient(ellipse at 20% -30%, rgba(20,184,166,0.15) 0%, transparent 55%), radial-gradient(ellipse at 85% 110%, rgba(99,102,241,0.08) 0%, transparent 50%)",
        }}
      >
        <div className="flex flex-wrap items-start justify-between gap-4">
          <div>
            <div className="mb-3 inline-flex items-center gap-2 rounded-full border border-teal-500/20 bg-teal-500/[0.08] px-3 py-1">
              <BookOpen className="h-3.5 w-3.5 text-teal-400" />
              <span className="text-[10px] font-bold uppercase tracking-[0.18em] text-teal-300">Notes</span>
            </div>
            <h1 className="text-[28px] font-bold tracking-tight text-white">
              {notes.length} {notes.length === 1 ? "Note" : "Notes"}
            </h1>
            <p className="mt-1 text-[14px] text-white/40">
              Your thinking space — capture, organize, and connect your knowledge.
            </p>
          </div>

          <div className="flex flex-wrap items-center gap-2">
            <button
              onClick={() => setShowFolderSidebar((v) => !v)}
              className={cn(
                "inline-flex items-center gap-1.5 rounded-xl border px-3 py-2 text-[12px] font-semibold transition-all",
                showFolderSidebar
                  ? "border-teal-500/25 bg-teal-500/[0.10] text-teal-300"
                  : "border-white/[0.07] bg-white/[0.03] text-white/40 hover:text-white/65",
              )}
            >
              <Folder className="h-3.5 w-3.5" />
              Folders
            </button>
            <button
              onClick={() => void handleCreate()}
              disabled={!canEditNotes}
              className="inline-flex items-center gap-2 rounded-xl border border-teal-500/30 bg-teal-500/[0.15] px-4 py-2 text-[13px] font-bold text-teal-200 transition-all hover:border-teal-500/50 hover:bg-teal-500/[0.22] disabled:opacity-40"
            >
              <Plus className="h-3.5 w-3.5" />
              New note
            </button>
          </div>
        </div>

        {/* ── Stats ─────────────────────────────────────────────────────── */}
        <div className="mt-6 flex flex-wrap gap-3">
          <div className="flex items-center gap-2 rounded-xl border border-white/[0.05] bg-white/[0.025] px-3 py-2">
            <Pin className="h-3 w-3 text-teal-400/60" />
            <span className="text-[12px] font-semibold text-white/50">{pinnedNotes.length} pinned</span>
          </div>
          <div className="flex items-center gap-2 rounded-xl border border-white/[0.05] bg-white/[0.025] px-3 py-2">
            <Folder className="h-3 w-3 text-white/25" />
            <span className="text-[12px] font-semibold text-white/50">{folders.length} {folders.length === 1 ? "folder" : "folders"}</span>
          </div>
          <div className="flex items-center gap-2 rounded-xl border border-white/[0.05] bg-white/[0.025] px-3 py-2">
            <Hash className="h-3 w-3 text-white/25" />
            <span className="text-[12px] font-semibold text-white/50">
              {notes.filter(n => !n.folder_id).length} unfiled
            </span>
          </div>
        </div>
      </div>

      {/* ── Saved views ─────────────────────────────────────────────────────── */}
      <SavedViewsBar
        filters={filters}
        emptyFilters={EMPTY_FILTERS}
        views={views}
        builtInViews={BUILT_IN_VIEWS}
        title="Saved note views"
        description="Keep your favorite note lenses ready, from pinned thinking spaces to unfiled capture."
        onApply={setFilters}
        onCreate={async (name, nextFilters) => {
          await createView({ name, filters: { ...nextFilters } });
        }}
        onDelete={async (id) => {
          await deleteView(id);
        }}
        onToggleFavorite={async (id, isFavorite) => {
          await updateView(id, { is_favorite: isFavorite });
        }}
      />

      {/* ── Template starters ───────────────────────────────────────────────── */}
      {!filters.search && !filters.folderId && !filters.pinState && notes.length > 0 && (
        <div className="rounded-[22px] border border-white/[0.06] bg-white/[0.02] p-4">
          <div className="mb-3 flex items-center gap-2">
            <Sparkles className="h-3.5 w-3.5 text-white/25" />
            <span className="text-[10px] font-bold uppercase tracking-[0.16em] text-white/25">Start from a template</span>
          </div>
          <div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
            {NOTE_TEMPLATES.map((tpl) => (
              <button
                key={tpl.id}
                onClick={() => void handleCreate(tpl.id)}
                disabled={!canEditNotes}
                className="flex flex-col gap-1 rounded-[16px] border border-white/[0.06] bg-white/[0.025] p-3 text-left transition-all hover:border-white/[0.10] hover:bg-white/[0.05] disabled:opacity-40"
              >
                <span className="text-[18px]">{tpl.icon}</span>
                <span className="text-[12px] font-semibold text-white/70">{tpl.label}</span>
                <span className="text-[11px] text-white/30">{tpl.description}</span>
              </button>
            ))}
          </div>
        </div>
      )}

      {/* ── Main layout ─────────────────────────────────────────────────────── */}
      <div className="flex gap-6">

        {/* ── Folder sidebar ──────────────────────────────────────────────── */}
        {showFolderSidebar && (
          <aside className="hidden md:block w-52 shrink-0">
            <div className="rounded-[22px] border border-white/[0.06] bg-[#0e0c15] p-4">
              <FolderTree
                folders={folders}
                selectedFolderId={selectedFolderId}
                onSelect={(folderId) =>
                  setFilters((current) => ({
                    ...current,
                    folderId: folderId || "",
                  }))
                }
                noteCountByFolder={noteCountByFolder}
                totalNoteCount={notes.length}
                onCreate={async (name) => { await createFolder(name); }}
                onRename={renameFolder}
                onDelete={deleteFolder}
                canManage={canEditNotes}
              />
            </div>
          </aside>
        )}

        {/* ── Content area ────────────────────────────────────────────────── */}
        <div className="flex-1 min-w-0 space-y-4">

          {/* ── Filter + Sort bar ───────────────────────────────────────── */}
          <div className="flex flex-wrap items-center gap-2">

            {/* Search */}
            <div className="relative flex-1 min-w-[160px]">
              <Search className="absolute left-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-white/25" />
              <input
                value={filters.search}
                onChange={(e) => setFilters((c) => ({ ...c, search: e.target.value }))}
                placeholder="Notizen durchsuchen…"
                className="h-9 w-full rounded-xl border border-white/[0.07] bg-white/[0.04] pl-9 pr-3 text-[13px] text-white/80 placeholder:text-white/25 outline-none focus:border-white/[0.14] focus:bg-white/[0.06] transition-colors"
              />
            </div>

            {/* View tabs */}
            <div className="flex items-center rounded-xl border border-white/[0.07] bg-white/[0.03] p-0.5 gap-0.5">
              {[
                { id: "", label: "Alle", icon: null },
                { id: "pinned", label: "Angeheftet", icon: <Pin className="h-3 w-3" /> },
              ].map((tab) => (
                <button
                  key={tab.id}
                  onClick={() => setFilters((c) => ({ ...c, pinState: tab.id }))}
                  className={cn(
                    "inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-[12px] font-semibold transition-all",
                    filters.pinState === tab.id
                      ? "bg-white/[0.08] text-white/90 shadow-sm"
                      : "text-white/35 hover:text-white/60"
                  )}
                >
                  {tab.icon}
                  {tab.label}
                </button>
              ))}
            </div>

            {/* Mobile folder select */}
            <div className="md:hidden">
              <select
                value={filters.folderId}
                onChange={(e) => setFilters((c) => ({ ...c, folderId: e.target.value }))}
                className="h-9 rounded-xl border border-white/[0.07] bg-white/[0.04] px-3 text-[12px] text-white/70 outline-none"
              >
                <option value="">Alle ({notes.length})</option>
                <option value="__none__">Kein Ordner</option>
                {folders.map((f) => (
                  <option key={f.id} value={f.id}>
                    {f.name} ({noteCountByFolder[f.id] || 0})
                  </option>
                ))}
              </select>
            </div>

            {/* Sort */}
            <div className="flex items-center gap-1.5 rounded-xl border border-white/[0.07] bg-white/[0.03] px-3 py-1.5">
              <SortAsc className="h-3.5 w-3.5 text-white/25 shrink-0" />
              <select
                value={sortBy}
                onChange={(e) => setSortBy(e.target.value as typeof sortBy)}
                className="bg-transparent text-[12px] text-white/55 outline-none cursor-pointer"
              >
                <option value="updated">Zuletzt bearbeitet</option>
                <option value="created">Erstellt</option>
                <option value="name">Name A–Z</option>
              </select>
            </div>

            {/* Clear all filters */}
            {(filters.search || filters.folderId || filters.pinState) && (
              <button
                onClick={() => setFilters(EMPTY_FILTERS)}
                className="inline-flex items-center gap-1.5 rounded-xl border border-white/[0.06] px-3 py-1.5 text-[12px] text-white/30 transition-all hover:text-white/55"
              >
                <X className="h-3 w-3" />
                Zurücksetzen
              </button>
            )}
          </div>

          {/* ── Active folder indicator ──────────────────────────────────── */}
          {activeFolder && (
            <div className="flex items-center gap-2.5 rounded-[16px] border border-teal-500/15 bg-teal-500/[0.05] px-4 py-2.5">
              <Folder className="h-4 w-4 text-teal-400/60" />
              <span className="text-[13px] font-semibold text-teal-300/70">{activeFolder.name}</span>
              <span className="text-[12px] text-white/30">
                · {noteCountByFolder[activeFolder.id] || 0} Notes
              </span>
              <button
                onClick={() => setFilters((c) => ({ ...c, folderId: "" }))}
                className="ml-auto text-white/25 hover:text-white/50 transition-colors"
              >
                <X className="h-3.5 w-3.5" />
              </button>
            </div>
          )}

          {/* ── Results label ────────────────────────────────────────────── */}
          {notes.length > 0 && (
            <div className="flex items-center gap-2">
              {filters.pinState === "pinned"
                ? <Pin className="h-3.5 w-3.5 text-teal-400/50" />
                : <FileText className="h-3.5 w-3.5 text-white/20" />
              }
              <span className="text-[11px] font-bold uppercase tracking-[0.16em] text-white/25">
                {filtered.length} {filtered.length === 1 ? "Note" : "Notes"}
                {filters.pinState === "pinned" ? " · Angeheftet" : ""}
                {activeFolder ? ` · ${activeFolder.name}` : ""}
                {filters.search ? ` · "${filters.search}"` : ""}
              </span>
            </div>
          )}

          {/* ── Single unified grid ──────────────────────────────────────── */}
          {filtered.length === 0 ? (
            <div className="rounded-[24px] border border-dashed border-white/[0.07] bg-white/[0.01] p-12 text-center">
              <div className="mx-auto mb-4 flex h-16 w-16 items-center justify-center rounded-3xl border border-white/[0.08] bg-white/[0.04]">
                <FileText className="h-7 w-7 text-white/25" />
              </div>
              <p className="text-[16px] font-bold text-white/40">
                {notes.length === 0 ? "Noch keine Notizen" : "Keine passenden Notizen"}
              </p>
              <p className="mt-2 text-[13px] text-white/25">
                {notes.length === 0
                  ? "Erstelle deine erste Notiz."
                  : "Andere Filter oder Suche ausprobieren."}
              </p>
              {notes.length === 0 && (
                <div className="mt-5 space-y-4">
                  <button
                    onClick={() => void handleCreate()}
                    disabled={!canEditNotes}
                    className="inline-flex items-center gap-2 rounded-xl border border-teal-500/30 bg-teal-500/[0.15] px-4 py-2 text-[13px] font-bold text-teal-200 transition-all hover:border-teal-500/50 hover:bg-teal-500/[0.22] disabled:opacity-40"
                  >
                    <Plus className="h-3.5 w-3.5" />
                    Notiz erstellen
                  </button>
                  <div className="mx-auto grid max-w-3xl gap-2 sm:grid-cols-2 lg:grid-cols-4">
                    {NOTE_TEMPLATES.map((tpl) => (
                      <button
                        key={tpl.id}
                        onClick={() => void handleCreate(tpl.id)}
                        disabled={!canEditNotes}
                        className="flex flex-col gap-1 rounded-[16px] border border-white/[0.06] bg-white/[0.025] p-3 text-left transition-all hover:border-white/[0.10] hover:bg-white/[0.05] disabled:opacity-40"
                      >
                        <span className="text-[18px]">{tpl.icon}</span>
                        <span className="text-[12px] font-semibold text-white/70">{tpl.label}</span>
                        <span className="text-[11px] text-white/30">{tpl.description}</span>
                      </button>
                    ))}
                  </div>
                </div>
              )}
            </div>
          ) : (
            <div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-3">
              {filtered.map((note) => (
                <NoteCard
                  key={note.id}
                  note={note}
                  onTogglePin={() => togglePin(note.id, note.is_pinned)}
                  onDelete={() => deleteNote(note.id)}
                  canManage={canEditNotes}
                />
              ))}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}
