"use client";

import { useEffect, useState, useCallback, useMemo } from "react";
import { useParams, useRouter } from "next/navigation";
import {
  ArrowLeft,
  CheckSquare,
  Sparkles,
  Pin,
  PinOff,
  Trash2,
  PanelRightOpen,
  PanelRightClose,
} from "lucide-react";
import { createClient, getBrowserUser } from "@/lib/supabase/client";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { EmptyState } from "@/components/ui/empty-state";
import { NoteEditor } from "@/components/notes/editor";
import { NoteKnowledge } from "@/components/notes/note-knowledge";
import { NoteMeta } from "@/components/notes/note-meta";
import { CommentsPanel } from "@/components/comments/comments-panel";
import { AttachmentsPanel } from "@/components/attachments/attachments-panel";
import { RemindMeButton } from "@/components/reminders/remind-me-button";
import { useTags } from "@/hooks/use-tags";
import { useNoteKnowledge } from "@/hooks/use-note-knowledge";
import { useProjectGuests } from "@/hooks/use-project-guests";
import { useTeamPermissions } from "@/hooks/use-team-permissions";
import { useProjects } from "@/hooks/use-projects";
import { useWorkspaceStore } from "@/stores/workspace-store";
import type { Note, NoteFolder, Tag } from "@/types";

type TaskOption = { id: string; title: string };
type NoteOption = { id: string; title: string };

function extractPlainText(content: Record<string, unknown> | null | undefined): string {
  if (!content) return "";

  const parts: string[] = [];

  function walk(value: unknown) {
    if (!value || typeof value !== "object") return;
    const node = value as { content?: unknown[]; text?: unknown };
    if (typeof node.text === "string") {
      parts.push(node.text);
    }
    if (Array.isArray(node.content)) {
      node.content.forEach(walk);
    }
  }

  walk(content);
  return parts.join(" ").trim();
}

export default function NoteEditorPage() {
  const params = useParams();
  const router = useRouter();
  const noteId = params.id as string;
  const supabase = createClient();
  const activeTeamId = useWorkspaceStore((state) => state.activeTeamId);
  const setActiveTeamId = useWorkspaceStore((state) => state.setActiveTeamId);
  const [note, setNote] = useState<Note | null>(null);

  const { tags, createTag } = useTags();
  const { projects } = useProjects();
  const { can } = useTeamPermissions(note?.team_id ?? null);
  const { currentGuestRole, userId: guestViewerId } = useProjectGuests(
    note?.project_id ?? null
  );
  const [noteTags, setNoteTags] = useState<Tag[]>([]);
  const [folders, setFolders] = useState<NoteFolder[]>([]);
  const [tasks, setTasks] = useState<TaskOption[]>([]);
  const [noteOptions, setNoteOptions] = useState<NoteOption[]>([]);
  const [loading, setLoading] = useState(true);
  const [title, setTitle] = useState("");
  const [showMeta, setShowMeta] = useState(false);
  const [creatingLinkedTask, setCreatingLinkedTask] = useState(false);
  const [aiActionLoading, setAiActionLoading] = useState(false);
  const [aiActionMode, setAiActionMode] = useState<"summary" | "action_items" | null>(null);
  const [aiActionResult, setAiActionResult] = useState<string | null>(null);
  const isPersonalOwner =
    !note?.team_id && !!note?.user_id && note.user_id === guestViewerId;
  const guestCanEdit = currentGuestRole === "edit";
  const guestCanComment =
    currentGuestRole === "comment" || currentGuestRole === "edit";
  const canEditNote = (note?.team_id ? can("notes", "edit") : isPersonalOwner) || guestCanEdit;
  const canCommentNote =
    (note?.team_id ? can("comments", "comment") : isPersonalOwner) || guestCanComment;
  const knowledgeTagIds = useMemo(() => noteTags.map((tag) => tag.id), [noteTags]);
  const noteKnowledge = useNoteKnowledge({
    noteId,
    teamId: note?.team_id ?? null,
    projectId: note?.project_id ?? null,
    tagIds: knowledgeTagIds,
  });

  // Fetch note + related data
  useEffect(() => {
    async function load() {
      const noteRes = await supabase
        .from("notes")
        .select("*, note_tags(tag_id, tags:tags(*))")
        .eq("id", noteId)
        .single();

      if (noteRes.data) {
        const n = noteRes.data;
        const workspaceTeamId = n.team_id ?? null;

        if (workspaceTeamId !== activeTeamId) {
          setActiveTeamId(workspaceTeamId);
        }

        const foldersQuery = workspaceTeamId
          ? supabase
              .from("note_folders")
              .select("*")
              .eq("team_id", workspaceTeamId)
              .order("sort_order")
              .order("name")
          : supabase
              .from("note_folders")
              .select("*")
              .is("team_id", null)
              .order("sort_order")
              .order("name");

        const tasksQuery = workspaceTeamId
          ? supabase
              .from("tasks")
              .select("id, title")
              .eq("team_id", workspaceTeamId)
              .is("parent_task_id", null)
              .order("created_at", { ascending: false })
              .limit(100)
          : supabase
              .from("tasks")
              .select("id, title")
              .is("team_id", null)
              .is("parent_task_id", null)
              .order("created_at", { ascending: false })
              .limit(100);

        const relatedNotesQuery = workspaceTeamId
          ? supabase
              .from("notes")
              .select("id, title")
              .eq("team_id", workspaceTeamId)
              .neq("id", noteId)
              .order("updated_at", { ascending: false })
              .limit(120)
          : supabase
              .from("notes")
              .select("id, title")
              .is("team_id", null)
              .neq("id", noteId)
              .order("updated_at", { ascending: false })
              .limit(120);

        const [foldersRes, tasksRes, relatedNotesRes] = await Promise.all([
          foldersQuery,
          tasksQuery,
          relatedNotesQuery,
        ]);

        setNote(n);
        setTitle(n.title);
        setNoteTags(
          (n.note_tags as Array<{ tags: Tag }>)
            ?.map((nt) => nt.tags)
            .filter(Boolean) || []
        );
        setFolders(foldersRes.data || []);
        setTasks(tasksRes.data || []);
        setNoteOptions(relatedNotesRes.data || []);
      }
      setLoading(false);
    }
    void load();
  }, [activeTeamId, noteId, setActiveTeamId, supabase]);

  // Save title (debounced via onBlur)
  const saveTitle = useCallback(
    async (newTitle: string) => {
      if (!note || !canEditNote || newTitle === note.title) return;
      await supabase.from("notes").update({ title: newTitle }).eq("id", noteId);
      setNote((prev) => (prev ? { ...prev, title: newTitle } : prev));
    },
    [canEditNote, note, noteId, supabase]
  );

  // Save content
  const saveContent = useCallback(
    async (content: Record<string, unknown>) => {
      if (!canEditNote) return;
      await supabase.from("notes").update({ content }).eq("id", noteId);
      setNote((prev) => (prev ? { ...prev, content } : prev));
    },
    [canEditNote, noteId, supabase]
  );

  // Toggle pin
  async function togglePin() {
    if (!note || !canEditNote) return;
    const newPinned = !note.is_pinned;
    await supabase.from("notes").update({ is_pinned: newPinned }).eq("id", noteId);
    setNote((prev) => (prev ? { ...prev, is_pinned: newPinned } : prev));
  }

  // Delete
  async function handleDelete() {
    if (!canEditNote) return;
    await supabase.from("notes").delete().eq("id", noteId);
    router.push("/notes");
  }

  async function handleCreateLinkedTask() {
    if (!note || !canEditNote || note.linked_task_id || creatingLinkedTask) return;

    setCreatingLinkedTask(true);
    const user = await getBrowserUser();

    if (!user) {
      setCreatingLinkedTask(false);
      return;
    }

    const { data } = await supabase
      .from("tasks")
      .insert({
        user_id: user.id,
        team_id: note.team_id,
        title: note.title || "Follow up note",
        description: `Created from note: ${note.title || "Untitled"}`,
        status: "todo",
        priority: "none",
        project_id: note.project_id,
      })
      .select("id")
      .single();

    if (data?.id) {
      await supabase
        .from("notes")
        .update({ linked_task_id: data.id })
        .eq("id", noteId);
      setNote((prev) => (prev ? { ...prev, linked_task_id: data.id } : prev));
      setTasks((prev) =>
        [{ id: data.id, title: note.title || "Follow up note" }, ...prev]
      );
    }

    setCreatingLinkedTask(false);
  }

  async function handleGenerateMeetingSummary() {
    if (!note || aiActionLoading) return;

    setAiActionLoading(true);
    setAiActionMode("summary");
    setAiActionResult(null);

    const prompt = [
      `Review note_id "${note.id}".`,
      `The note title is "${note.title}".`,
      `Project id: ${note.project_id || "none"}.`,
      `Team id: ${note.team_id || "none"}.`,
      "Use get_note_context to read the note first.",
      "Then produce a concise meeting-style summary with key topics, decisions, blockers, and next steps.",
      "If this is not a meeting note, still give a sharp structured summary without creating tasks.",
    ].join(" ");

    try {
      const res = await fetch("/api/ai/chat", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          message: prompt,
          messages: [{ role: "user", content: prompt }],
          workspaceTeamId: note.team_id,
        }),
      });

      const data = await res.json();
      setAiActionResult(data.text || "Meeting summary generated.");
    } catch {
      setAiActionResult("AI meeting summary failed.");
    } finally {
      setAiActionLoading(false);
      setAiActionMode(null);
    }
  }

  async function handleGenerateActionItems() {
    if (!note || aiActionLoading || !canEditNote) return;

    setAiActionLoading(true);
    setAiActionMode("action_items");
    setAiActionResult(null);

    const prompt = [
      `Review note_id "${note.id}".`,
      `The note title is "${note.title}".`,
      `Project id: ${note.project_id || "none"}.`,
      `Team id: ${note.team_id || "none"}.`,
      "Use get_note_context to read the note first.",
      "Then extract the concrete action items from the note.",
      "If there are real next steps, create 3 to 7 useful tasks in the same workspace, linked to the note's project when available.",
      "Prefer create_tasks_batch when creating several tasks.",
      "Afterwards, briefly summarize the created tasks. If the note is only reference material, say that clearly and do not create tasks.",
    ].join(" ");

    try {
      const res = await fetch("/api/ai/chat", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          message: prompt,
          messages: [{ role: "user", content: prompt }],
          workspaceTeamId: note.team_id,
        }),
      });

      const data = await res.json();
      setAiActionResult(data.text || "Action items processed.");
    } catch {
      setAiActionResult("AI action item generation failed.");
    } finally {
      setAiActionLoading(false);
      setAiActionMode(null);
    }
  }

  // Meta updates
  async function updateMeta(
    field: string,
    value: string | null | string[]
  ) {
    if (!note || !canEditNote) return;

    if (field === "tag_ids") {
      const tagIds = value as string[];
      await supabase.from("note_tags").delete().eq("note_id", noteId);
      if (tagIds.length > 0) {
        await supabase
          .from("note_tags")
          .insert(tagIds.map((tag_id) => ({ note_id: noteId, tag_id })));
      }
      setNoteTags(tags.filter((t) => tagIds.includes(t.id)));
    } else {
      await supabase
        .from("notes")
        .update({ [field]: value })
        .eq("id", noteId);
      setNote((prev) => (prev ? { ...prev, [field]: value } : prev));
    }
  }

  if (loading) {
    return (
      <div className="space-y-4">
        <Skeleton className="h-8 w-48" />
        <Skeleton className="h-[400px] rounded-xl" />
      </div>
    );
  }

  if (!note) {
    return (
      <EmptyState
        title="Note not found"
        description="This note may have been deleted."
        action={
          <Button variant="outline" onClick={() => router.push("/notes")}>
            Back to notes
          </Button>
        }
      />
    );
  }

  return (
    <div className="flex flex-col lg:flex-row gap-0 -mx-4 sm:-mx-6 lg:-mx-8 -my-6">
      {/* Editor area */}
      <div className="flex-1 min-w-0 px-4 sm:px-6 lg:px-8 py-6">
        {/* Top bar */}
        <div className="flex items-center gap-2 mb-4">
          <Button
            variant="ghost"
            size="icon"
            onClick={() => router.push("/notes")}
          >
            <ArrowLeft className="h-4 w-4" />
          </Button>

          <div className="flex-1" />

          <RemindMeButton
            body={extractPlainText(note.content).slice(0, 240)}
            className="border-border bg-transparent text-foreground hover:bg-accent"
            label="Remind me"
            sourceId={note.id}
            sourceTitle={note.title || "Untitled note"}
            sourceType="note"
            sourceUrl={`/notes/${note.id}`}
          />

          <Button
            variant="ghost"
            size="icon"
            onClick={togglePin}
            disabled={!canEditNote}
          >
            {note.is_pinned ? (
              <PinOff className="h-4 w-4" />
            ) : (
              <Pin className="h-4 w-4" />
            )}
          </Button>

          {!note.linked_task_id && (
            <Button
              variant="ghost"
              size="sm"
              onClick={handleCreateLinkedTask}
              disabled={creatingLinkedTask || !canEditNote}
            >
              <CheckSquare className="h-4 w-4" />
              {creatingLinkedTask ? "Creating..." : "Create linked task"}
            </Button>
          )}

          <Button
            variant="ghost"
            size="sm"
            onClick={handleGenerateMeetingSummary}
            disabled={aiActionLoading}
          >
            <Sparkles className="h-4 w-4" />
            {aiActionLoading && aiActionMode === "summary" ? "Summarizing..." : "Meeting summary"}
          </Button>

          <Button
            variant="ghost"
            size="sm"
            onClick={handleGenerateActionItems}
            disabled={aiActionLoading || !canEditNote}
          >
            <Sparkles className="h-4 w-4" />
            {aiActionLoading && aiActionMode === "action_items" ? "Analyzing..." : "AI action items"}
          </Button>

          <Button
            variant="ghost"
            size="icon"
            onClick={() => setShowMeta(!showMeta)}
            className="lg:hidden"
          >
            {showMeta ? (
              <PanelRightClose className="h-4 w-4" />
            ) : (
              <PanelRightOpen className="h-4 w-4" />
            )}
          </Button>

          <Button variant="ghost" size="icon" onClick={handleDelete} disabled={!canEditNote}>
            <Trash2 className="h-4 w-4 text-destructive" />
          </Button>
        </div>

        {/* Title */}
        <input
          value={title}
          onChange={(e) => setTitle(e.target.value)}
          disabled={!canEditNote}
          onBlur={() => saveTitle(title)}
          onKeyDown={(e) => {
            if (e.key === "Enter") {
              e.preventDefault();
              (e.target as HTMLInputElement).blur();
            }
          }}
          placeholder="Untitled"
          className="w-full text-3xl font-bold tracking-tight bg-transparent outline-none placeholder:text-muted-foreground/40 mb-4"
        />

        {/* Pinned indicator */}
        {note.is_pinned && (
          <div className="flex items-center gap-1.5 text-xs text-primary mb-4">
            <Pin className="h-3 w-3 fill-primary" />
            Pinned
          </div>
        )}

        {aiActionResult && (
          <div className="mb-4 rounded-xl border border-border/60 bg-muted/30 px-4 py-3 text-sm whitespace-pre-wrap">
            {aiActionResult}
          </div>
        )}

        {/* Editor */}
        {(note.team_id || note.project_id) && !canEditNote && (
          <div className="mb-4 rounded-xl border border-border/60 bg-muted/30 px-4 py-3 text-sm text-muted-foreground">
            This is a shared note in read-only mode for your role. You can still follow the discussion below.
          </div>
        )}

        <NoteEditor content={note.content} onChange={saveContent} editable={canEditNote} />

        <NoteKnowledge
          outbound={noteKnowledge.outbound}
          backlinks={noteKnowledge.backlinks}
          relatedNotes={noteKnowledge.relatedNotes}
          loading={noteKnowledge.loading}
          noteOptions={noteOptions}
          taskOptions={tasks}
          projectOptions={projects.map((project) => ({
            id: project.id,
            name: project.name,
            icon: project.icon,
          }))}
          onAddRelation={noteKnowledge.createRelation}
          onDeleteRelation={noteKnowledge.deleteRelation}
          disabled={!canEditNote}
        />

        <div className="mt-6">
          <AttachmentsPanel
            entityType="note"
            entityId={note.id}
            projectId={note.project_id}
            teamId={note.team_id}
            editable={canEditNote}
          />
        </div>

        {(note.team_id || note.project_id) && (
          <div className="mt-6">
            <CommentsPanel
              entityType="note"
              entityId={note.id}
              teamId={note.team_id}
              title="Team discussion"
              allowCommentOverride={canCommentNote}
              placeholderOverride="Write an update, question, or handoff for everyone working in this note..."
            />
          </div>
        )}
      </div>

      {/* Meta sidebar — always visible on lg, toggle on mobile */}
      <div
        className={`w-full lg:w-72 shrink-0 ${
          showMeta ? "block" : "hidden lg:block"
        }`}
      >
        <NoteMeta
          folderId={note.folder_id}
          projectId={note.project_id}
          linkedTaskId={note.linked_task_id}
          tagIds={noteTags.map((t) => t.id)}
          folders={folders}
          projects={projects}
          tags={tags}
          tasks={tasks}
          onFolderChange={(id) => updateMeta("folder_id", id)}
          onProjectChange={(id) => updateMeta("project_id", id)}
          onLinkedTaskChange={(id) => updateMeta("linked_task_id", id)}
          onTagsChange={(ids) => updateMeta("tag_ids", ids)}
          onCreateTag={createTag}
          disabled={!canEditNote}
        />
      </div>
    </div>
  );
}
