import { useState, useCallback, useRef, useEffect } from "react";
import type { Editor } from "@tiptap/react";
import { AlertCircle } from "lucide-react";
import { trpc } from "@/lib/trpc";
import { useAutoSave } from "@/hooks/useAutoSave";
import { TiptapEditor } from "./TiptapEditor";
import { PageTitleProvider } from "./PageTitleContext";
import { PageTree } from "./PageTree";
import { RefineAgentPanel } from "./RefineAgentPanel";
import { DeleteSubpageDialog } from "./DeleteSubpageDialog";
import { Skeleton } from "@/components/Skeleton";
import { Button } from "@/components/ui/button";

interface ContentTabProps {
  initiativeId: string;
  initiativeName: string;
}

interface DeleteConfirmation {
  pageId: string;
  redo: () => void;
}

export function ContentTab({ initiativeId, initiativeName }: ContentTabProps) {
  const utils = trpc.useUtils();
  const { save, flush, isSaving } = useAutoSave();

  // Get or create root page
  const rootPageQuery = trpc.getRootPage.useQuery({ initiativeId });
  const allPagesQuery = trpc.listPages.useQuery({ initiativeId });
  const createPageMutation = trpc.createPage.useMutation();
  const deletePageMutation = trpc.deletePage.useMutation();
  const updateInitiativeMutation = trpc.updateInitiative.useMutation();
  const initiativeNameTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const pendingInitiativeNameRef = useRef<string | null>(null);

  const [activePageId, setActivePageId] = useState<string | null>(null);
  const [deleteConfirm, setDeleteConfirm] = useState<DeleteConfirmation | null>(null);
  const [pageTitle, setPageTitle] = useState("");

  // Keep a ref to the current editor so subpage creation can insert links
  const editorRef = useRef<Editor | null>(null);

  // Resolve active page: use explicit selection, or fallback to root
  const resolvedActivePageId =
    activePageId ?? rootPageQuery.data?.id ?? null;

  const isRootPage = resolvedActivePageId != null && resolvedActivePageId === rootPageQuery.data?.id;

  // Fetch active page content
  const activePageQuery = trpc.getPage.useQuery(
    { id: resolvedActivePageId! },
    { enabled: !!resolvedActivePageId },
  );

  const handleEditorUpdate = useCallback(
    (json: string) => {
      if (resolvedActivePageId) {
        save(resolvedActivePageId, { content: json });
      }
    },
    [resolvedActivePageId, save],
  );

  // Sync title from server when active page changes
  useEffect(() => {
    if (activePageQuery.data) {
      setPageTitle(isRootPage ? initiativeName : activePageQuery.data.title);
    }
  }, [activePageQuery.data?.id, isRootPage, initiativeName]); // eslint-disable-line react-hooks/exhaustive-deps

  const handleTitleChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const newTitle = e.target.value;
      setPageTitle(newTitle);
      if (isRootPage) {
        // Debounce initiative name updates
        pendingInitiativeNameRef.current = newTitle;
        if (initiativeNameTimerRef.current) {
          clearTimeout(initiativeNameTimerRef.current);
        }
        initiativeNameTimerRef.current = setTimeout(() => {
          pendingInitiativeNameRef.current = null;
          updateInitiativeMutation.mutate({ id: initiativeId, name: newTitle });
          initiativeNameTimerRef.current = null;
        }, 1000);
      } else if (resolvedActivePageId) {
        save(resolvedActivePageId, { title: newTitle });
      }
    },
    [isRootPage, resolvedActivePageId, save, initiativeId, updateInitiativeMutation],
  );

  // Flush pending initiative name save on unmount
  useEffect(() => {
    return () => {
      if (initiativeNameTimerRef.current) {
        clearTimeout(initiativeNameTimerRef.current);
        initiativeNameTimerRef.current = null;
      }
      if (pendingInitiativeNameRef.current != null) {
        updateInitiativeMutation.mutate({ id: initiativeId, name: pendingInitiativeNameRef.current });
        pendingInitiativeNameRef.current = null;
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const handleTitleKeyDown = useCallback(
    (e: React.KeyboardEvent<HTMLInputElement>) => {
      if (e.key === "Enter") {
        e.preventDefault();
        // Focus the Tiptap editor below
        const el = (e.target as HTMLElement)
          .closest(".flex-1")
          ?.querySelector<HTMLElement>("[contenteditable]");
        el?.focus();
      }
    },
    [],
  );

  const handleCreateChild = useCallback(
    (parentPageId: string) => {
      createPageMutation.mutate({
        initiativeId,
        parentPageId,
        title: "Untitled",
      });
    },
    [initiativeId, createPageMutation],
  );

  const handleNavigate = useCallback((pageId: string) => {
    setActivePageId(pageId);
  }, []);

  // Slash command: /subpage -- creates a page and inserts a link at cursor
  const handleSubpageCreate = useCallback(
    async (editor: Editor) => {
      editorRef.current = editor;
      try {
        const page = await createPageMutation.mutateAsync({
          initiativeId,
          parentPageId: resolvedActivePageId,
          title: "Untitled",
        });
        // Insert page link at current cursor position
        editor.commands.insertPageLink({ pageId: page.id });
        // Wait for auto-save to persist the link before navigating
        await flush();
        // Update the query cache so navigating back shows content with the link
        utils.getPage.setData(
          { id: resolvedActivePageId! },
          (old) => old ? { ...old, content: JSON.stringify(editor.getJSON()) } : undefined,
        );
        // Navigate directly to the newly created subpage
        setActivePageId(page.id);
      } catch {
        // Mutation errors surfaced via React Query state
      }
    },
    [initiativeId, resolvedActivePageId, createPageMutation, flush, utils],
  );

  // Detect when a page link is deleted from the editor (already undone by plugin)
  const handlePageLinkDeleted = useCallback(
    (pageId: string, redo: () => void) => {
      // Don't prompt for pages that don't exist in our tree
      const allPages = allPagesQuery.data ?? [];
      const exists = allPages.some((p) => p.id === pageId);
      if (!exists) {
        // Page doesn't exist -- redo the deletion so the stale link is removed
        redo();
        return;
      }

      setDeleteConfirm({ pageId, redo });
    },
    [allPagesQuery.data],
  );

  const confirmDeleteSubpage = useCallback(() => {
    if (deleteConfirm) {
      // Re-delete the page link from the editor, then delete the page from DB
      deleteConfirm.redo();
      deletePageMutation.mutate({ id: deleteConfirm.pageId });
      setDeleteConfirm(null);
    }
  }, [deleteConfirm, deletePageMutation]);

  const dismissDeleteConfirm = useCallback(() => {
    setDeleteConfirm(null);
  }, []);

  const allPages = allPagesQuery.data ?? [];

  // Loading
  if (rootPageQuery.isLoading) {
    return (
      <div className="flex gap-4">
        <Skeleton className="h-64 w-48" />
        <Skeleton className="h-64 flex-1" />
      </div>
    );
  }

  // Error -- server likely needs restart or migration hasn't applied
  if (rootPageQuery.isError) {
    return (
      <div className="flex flex-col items-center justify-center gap-3 py-12 text-center">
        <AlertCircle className="h-6 w-6 text-destructive" />
        <p className="text-sm text-destructive">
          Failed to load editor: {rootPageQuery.error.message}
        </p>
        <p className="text-xs text-muted-foreground">
          Make sure the backend server is running with the latest code.
        </p>
        <Button
          variant="outline"
          size="sm"
          onClick={() => void rootPageQuery.refetch()}
        >
          Retry
        </Button>
      </div>
    );
  }

  return (
    <>
      <PageTitleProvider pages={allPages}>
      <div className="flex gap-4 pt-4">
        {/* Page tree sidebar */}
        <div className="w-48 shrink-0 border-r border-border pr-3">
          <div className="flex items-center justify-between mb-2">
            <span className="text-xs font-medium text-muted-foreground uppercase tracking-wider">
              Pages
            </span>
          </div>
          <PageTree
            pages={allPages}
            activePageId={resolvedActivePageId ?? ""}
            onNavigate={handleNavigate}
            onCreateChild={handleCreateChild}
          />
        </div>

        {/* Editor area */}
        <div className="flex-1 min-w-0">
          {/* Refine agent panel -- sits above editor */}
          <RefineAgentPanel initiativeId={initiativeId} />

          {resolvedActivePageId && (
            <>
              {(isSaving || updateInitiativeMutation.isPending) && (
                <div className="flex justify-end mb-2">
                  <span className="text-xs text-muted-foreground">
                    Saving...
                  </span>
                </div>
              )}
              {activePageQuery.isSuccess && (
                <input
                  value={pageTitle}
                  onChange={handleTitleChange}
                  onKeyDown={handleTitleKeyDown}
                  placeholder="Untitled"
                  className="w-full text-3xl font-bold bg-transparent border-none outline-none placeholder:text-muted-foreground/40 pl-11 mb-2"
                />
              )}
              {activePageQuery.isSuccess && (
                <TiptapEditor
                  key={resolvedActivePageId}
                  entityId={resolvedActivePageId}
                  content={activePageQuery.data?.content ?? null}
                  onUpdate={handleEditorUpdate}
                  onPageLinkClick={handleNavigate}
                  onSubpageCreate={handleSubpageCreate}
                  onPageLinkDeleted={handlePageLinkDeleted}
                />
              )}
              {activePageQuery.isLoading && (
                <Skeleton className="h-64 w-full" />
              )}
              {activePageQuery.isError && (
                <div className="flex items-center gap-2 py-4 text-sm text-destructive">
                  <AlertCircle className="h-4 w-4" />
                  Failed to load page: {activePageQuery.error.message}
                </div>
              )}
            </>
          )}
        </div>
      </div>

      {/* Delete subpage confirmation dialog */}
      <DeleteSubpageDialog
        open={deleteConfirm !== null}
        pageName={
          allPages.find((p) => p.id === deleteConfirm?.pageId)?.title ??
          "Untitled"
        }
        onConfirm={confirmDeleteSubpage}
        onCancel={dismissDeleteConfirm}
      />
      </PageTitleProvider>
    </>
  );
}
