"use client";

import type { AnyExtension } from "@tiptap/core";
import type { Editor } from "@tiptap/react";
import { type ComponentType, Suspense, useEffect, useMemo } from "react";
import { cn } from "../lib/utils";
import { type Collaborator, useEditorContext } from "./editor-provider";
import { retryableLazyEditor } from "./editor-lazy";
import { EditorLoadingPlaceholder } from "./editor-loading";
import { type CollaborationPeers, loadCollaborationPeers } from "./editor-peers";

/**
 * Props for TiptapEditor component.
 */
export interface TiptapEditorProps {
  /** Initial content for new documents (markdown string) */
  initialContent?: string;
  /** Placeholder text when editor is empty */
  placeholder?: string;
  /** Whether the editor is read-only */
  readOnly?: boolean;
  /** Whether to auto-focus on mount */
  autoFocus?: boolean;
  /** Custom className for the editor wrapper */
  className?: string;
  /** Custom className for the editor content area */
  contentClassName?: string;
  /** Callback when content changes */
  onUpdate?: (editor: Editor) => void;
  /** Callback when selection changes */
  onSelectionUpdate?: (editor: Editor) => void;
  /** Callback when editor is ready */
  onReady?: (editor: Editor) => void;
}

/**
 * Cursor colors with contrasting text.
 */
const cursorColors: Record<string, { background: string; text: string }> = {
  "#FF6B6B": { background: "#FF6B6B", text: "#FFFFFF" },
  "#4ECDC4": { background: "#4ECDC4", text: "#000000" },
  "#45B7D1": { background: "#45B7D1", text: "#000000" },
  "#96CEB4": { background: "#96CEB4", text: "#000000" },
  "#FFEAA7": { background: "#FFEAA7", text: "#000000" },
  "#DDA0DD": { background: "#DDA0DD", text: "#000000" },
  "#98D8C8": { background: "#98D8C8", text: "#000000" },
  "#F7DC6F": { background: "#F7DC6F", text: "#000000" },
  "#BB8FCE": { background: "#BB8FCE", text: "#000000" },
  "#85C1E9": { background: "#85C1E9", text: "#000000" },
};

/**
 * Get cursor label colors based on user color.
 */
function getCursorColors(color: string) {
  return cursorColors[color] ?? { background: color, text: "#FFFFFF" };
}

/**
 * Builds the collaborative editor against loaded tiptap namespaces. The peers
 * arrive as an argument so that this module reaches them through type-only
 * imports, which a bundler erases.
 */
export function createTiptapEditor(
  peers: CollaborationPeers,
): ComponentType<TiptapEditorProps> {
  const { EditorContent, useEditor } = peers.react;
  const StarterKit = peers.starterKit.default;
  const Collaboration = peers.collaboration.default;
  const CollaborationCaret = peers.collaborationCaret.default;

  return function TiptapEditor({
    initialContent,
    placeholder = "Start writing...",
    readOnly = false,
    autoFocus = false,
    className,
    contentClassName,
    onUpdate,
    onSelectionUpdate,
    onReady,
  }: TiptapEditorProps) {
    const { doc, provider, connectionState } = useEditorContext();

    // Y.js fragment for the editor content
    const fragment = useMemo(() => doc.getXmlFragment("prosemirror"), [doc]);

    // Configure Tiptap extensions
    const extensions = useMemo(() => {
      const baseExtensions: AnyExtension[] = [
        StarterKit.configure({
          // Disable history - Y.js handles undo/redo
          ...({ history: false } as any),
          // Configure code block for syntax highlighting placeholder
          codeBlock: {
            HTMLAttributes: {
              class: "hljs",
            },
          },
        }),
        Collaboration.configure({
          fragment,
        }),
      ];

      // Add collaboration cursor if provider is available
      if (provider?.awareness) {
        baseExtensions.push(
          CollaborationCaret.configure({
            provider,
            user: provider.awareness.getLocalState()?.user ?? {
              name: "Anonymous",
              color: "#808080",
            },
            render: (user: { name: string; color: string }) => {
              const { background, text } = getCursorColors(user.color);

              const cursor = document.createElement("span");
              cursor.className = "collaboration-cursor";
              cursor.style.borderColor = background;

              const label = document.createElement("span");
              label.className = "collaboration-cursor-label";
              label.style.backgroundColor = background;
              label.style.color = text;
              label.textContent = user.name;

              cursor.appendChild(label);
              return cursor;
            },
          }),
        );
      }

      return baseExtensions;
    }, [fragment, provider]);

    // Initialize Tiptap editor
    const editor = useEditor({
      extensions,
      editable: !readOnly,
      autofocus: autoFocus,
      editorProps: {
        attributes: {
          class: cn(
            "prose prose-sm sm:prose-base dark:prose-invert max-w-none",
            "focus:outline-none",
            contentClassName,
          ),
          "data-placeholder": placeholder,
        },
      },
      onUpdate: ({ editor: ed }) => {
        onUpdate?.(ed);
      },
      onSelectionUpdate: ({ editor: ed }) => {
        onSelectionUpdate?.(ed);
      },
      onCreate: ({ editor: ed }) => {
        onReady?.(ed);
      },
    });

    // Update editable state when readOnly changes
    useEffect(() => {
      if (editor) {
        editor.setEditable(!readOnly);
      }
    }, [editor, readOnly]);

    // Handle initial content (only for new documents)
    useEffect(() => {
      if (
        editor &&
        initialContent &&
        connectionState === "synced" &&
        editor.isEmpty
      ) {
        editor.commands.setContent(initialContent);
      }
    }, [editor, initialContent, connectionState]);

    return (
      <div
        className={cn(
          "relative min-h-[200px] w-full rounded-lg border border-border",
          "bg-background",
          className,
        )}
      >
        {/* Connection status indicator */}
        <div className="absolute top-2 right-2 z-10">
          <ConnectionIndicator state={connectionState} />
        </div>

        {/* Editor content */}
        <div className="p-4 pt-10">
          <EditorContent editor={editor} />
        </div>

        {/* Placeholder when empty */}
        <style>{`
        .ProseMirror p.is-editor-empty:first-child::before {
          content: attr(data-placeholder);
          float: left;
          color: var(--muted-foreground, #999);
          pointer-events: none;
          height: 0;
        }

        .collaboration-cursor {
          position: relative;
          border-left: 2px solid;
          margin-left: -1px;
          margin-right: -1px;
          pointer-events: none;
          word-break: normal;
        }

        .collaboration-cursor-label {
          position: absolute;
          top: -1.4em;
          left: -1px;
          font-size: 12px;
          font-style: normal;
          font-weight: 600;
          line-height: normal;
          padding: 2px 6px;
          border-radius: 4px 4px 4px 0;
          white-space: nowrap;
          user-select: none;
        }

        .ProseMirror pre {
          background: var(--muted, #f4f4f5);
          border-radius: 0.375rem;
          padding: 0.75rem 1rem;
          font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
          font-size: 0.875rem;
          overflow-x: auto;
        }

        .dark .ProseMirror pre {
          background: var(--muted, #27272a);
        }

        .ProseMirror code {
          background: var(--muted, #f4f4f5);
          border-radius: 0.25rem;
          padding: 0.125rem 0.25rem;
          font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
          font-size: 0.875em;
        }

        .dark .ProseMirror code {
          background: var(--muted, #27272a);
        }

        .ProseMirror pre code {
          background: transparent;
          padding: 0;
          font-size: inherit;
        }
      `}</style>
      </div>
    );
  };
}

const lazyTiptapEditor = retryableLazyEditor(async () =>
  createTiptapEditor(await loadCollaborationPeers()),
);

/**
 * TiptapEditor - Collaborative markdown editor with Y.js sync.
 * Must be used within an EditorProvider. Loads its tiptap, Hocuspocus and
 * yjs peers on first render.
 */
export function TiptapEditor(props: TiptapEditorProps) {
  const LazyTiptapEditor = lazyTiptapEditor();
  return (
    <Suspense
      fallback={
        <EditorLoadingPlaceholder className={cn("min-h-[200px]", props.className)} />
      }
    >
      <LazyTiptapEditor {...props} />
    </Suspense>
  );
}

/**
 * Connection status indicator component.
 */
function ConnectionIndicator({
  state,
}: {
  state: "disconnected" | "connecting" | "connected" | "synced";
}) {
  const config = {
    disconnected: {
      color: "bg-red-500",
      label: "Disconnected",
    },
    connecting: {
      color: "bg-yellow-500 animate-pulse",
      label: "Connecting...",
    },
    connected: {
      color: "bg-blue-500",
      label: "Connected",
    },
    synced: {
      color: "bg-green-500",
      label: "Synced",
    },
  }[state];

  return (
    <div className="flex items-center gap-1.5 text-muted-foreground text-xs">
      <span className={cn("h-2 w-2 rounded-full", config.color)} />
      <span>{config.label}</span>
    </div>
  );
}

/**
 * Collaborators list component.
 * Shows active users in the document.
 */
export function CollaboratorsList({
  collaborators,
  className,
}: {
  collaborators: Collaborator[];
  className?: string;
}) {
  if (collaborators.length === 0) {
    return null;
  }

  return (
    <div className={cn("flex items-center gap-1", className)}>
      {collaborators.slice(0, 5).map((collab) => (
        <div
          key={collab.clientId}
          className="flex h-6 w-6 items-center justify-center rounded-full font-medium text-xs"
          style={{ backgroundColor: collab.user.color }}
          title={collab.user.name}
        >
          {collab.user.name.charAt(0).toUpperCase()}
        </div>
      ))}
      {collaborators.length > 5 && (
        <div className="flex h-6 w-6 items-center justify-center rounded-full bg-muted font-medium text-xs">
          +{collaborators.length - 5}
        </div>
      )}
    </div>
  );
}

export { EditorToolbar } from "./editor-toolbar";
