"use client";

import { API_BASE_URL, API_ENDPOINTS } from "@/api/constant";
import { getAccessToken } from "@/lib/auth-cookies";
import Image from "@tiptap/extension-image";
import TiptapLink from "@tiptap/extension-link";
import Placeholder from "@tiptap/extension-placeholder";
import Underline from "@tiptap/extension-underline";
import { EditorContent, useEditor } from "@tiptap/react";
import StarterKit from "@tiptap/starter-kit";
import { Loader2 } from "lucide-react";
import { useCallback, useEffect, useRef, useState } from "react";
import { toast } from "react-hot-toast";

interface RichTextEditorProps {
  value: string;
  onChange: (html: string) => void;
  placeholder?: string;
  height?: string;
  borderLess?: boolean;
  isFullscreen?: boolean;
  onToggleFullscreen?: () => void;
}

const MAX_IMAGE_SIZE = 1 * 1024 * 1024; // 1 MB

const RichTextEditor = ({
  value,
  onChange,
  placeholder = "Write your answer",
  height = "h-[280px]",
  borderLess = false,
  isFullscreen = false,
  onToggleFullscreen,
}: RichTextEditorProps) => {
  const fileInputRef = useRef<HTMLInputElement>(null);
  const [uploadingImage, setUploadingImage] = useState(false);

  const editor = useEditor({
    immediatelyRender: false,
    extensions: [
      StarterKit,
      Underline,
      TiptapLink.configure({ openOnClick: false }),
      Image.configure({ inline: false, allowBase64: false }),
      Placeholder.configure({ placeholder }),
    ],
    content: value ?? "",
    onUpdate: ({ editor }) => {
      onChange(editor.getHTML());
    },
    editorProps: {
      attributes: {
        class:
          "tiptap rte-body px-3 py-2.5 focus:outline-none text-[14px] leading-[1.7] min-h-[140px] text-gray-900",
      },
    },
  });

  // Sync external `value` changes into the editor (e.g. parent loads a draft
  // after mount). Skip when the editor already matches to avoid loops.
  useEffect(() => {
    if (!editor) return;
    const incoming = value ?? "";
    if (incoming !== editor.getHTML()) {
      editor.commands.setContent(incoming, { emitUpdate: false });
    }
  }, [editor, value]);

  const btn = (active: boolean, disabled = false) =>
    `p-1.5 rounded transition-colors ${
      disabled
        ? "text-gray-300 cursor-not-allowed"
        : active
          ? "bg-gray-300 text-gray-900"
          : "text-gray-500 hover:bg-gray-200 cursor-pointer"
    }`;

  const addLink = () => {
    const url = prompt("URL");
    if (url) editor?.chain().focus().setLink({ href: url }).run();
  };

  const handleImageUpload = useCallback(
    async (file: File) => {
      if (file.size > MAX_IMAGE_SIZE) {
        alert("Image must be smaller than 1 MB.");
        return;
      }

      const formData = new FormData();
      formData.append("file", file);

      setUploadingImage(true);
      try {
        const token = getAccessToken();
        const res = await fetch(`${API_BASE_URL}${API_ENDPOINTS.attachment}`, {
          method: "POST",
          headers: token ? { Authorization: `Bearer ${token}` } : {},
          body: formData,
        });

        if (!res.ok) throw new Error("Upload failed");

        const json = await res.json();
        const filePath: string = json?.responseData?.filePath ?? json?.filePath;

        if (filePath) {
          editor?.chain().focus().setImage({ src: filePath }).run();
        }
      } catch {
        toast.error("Failed to upload image. Please try again.");
      } finally {
        setUploadingImage(false);
        if (fileInputRef.current) fileInputRef.current.value = "";
      }
    },
    [editor],
  );

  const Divider = () => (
    <div className="w-px h-4 bg-gray-300 mx-0.5 self-center shrink-0" />
  );

  return (
    <div
      className={`flex flex-col w-full overflow-hidden ${
        borderLess ? "bg-white" : "border border-gray-285 rounded-[7px] bg-gray-150"
      } ${height}`}
    >
      {/* Sticky toolbar */}
      <div className="rte-toolbar">
        <button
          type="button"
          onClick={() => editor?.chain().focus().toggleBold().run()}
          className={`rte-btn ${editor?.isActive("bold") ? "active" : ""}`}
          title="Bold"
        >
          <b>B</b>
        </button>
        <button
          type="button"
          onClick={() => editor?.chain().focus().toggleItalic().run()}
          className={`rte-btn ${editor?.isActive("italic") ? "active" : ""}`}
          title="Italic"
          style={{ fontStyle: "italic", fontWeight: 400 }}
        >
          I
        </button>
        <button
          type="button"
          onClick={() => editor?.chain().focus().toggleUnderline().run()}
          className={`rte-btn ${editor?.isActive("underline") ? "active" : ""}`}
          title="Underline"
          style={{ textDecoration: "underline" }}
        >
          U
        </button>
        <button
          type="button"
          onClick={() => editor?.chain().focus().toggleStrike().run()}
          className={`rte-btn ${editor?.isActive("strike") ? "active" : ""}`}
          title="Strikethrough"
          style={{ textDecoration: "line-through" }}
        >
          S
        </button>

        <div className="rte-sep" />

        <button
          type="button"
          onClick={() => editor?.chain().focus().toggleBulletList().run()}
          className={`rte-btn ${editor?.isActive("bulletList") ? "active" : ""}`}
          title="Bullet list"
        >
          <svg width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" />
          </svg>
        </button>
        <button
          type="button"
          onClick={() => editor?.chain().focus().toggleOrderedList().run()}
          className={`rte-btn ${editor?.isActive("orderedList") ? "active" : ""}`}
          title="Numbered list"
        >
          <svg width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" d="M10 6h11M10 12h11M10 18h11M4 6h.01M4 12l-1 1h2m-2 0v1h2v1H3M3.5 18h1a.5.5 0 010 1H3v1h2" />
          </svg>
        </button>

        <div className="rte-sep" />

        <button
          type="button"
          onClick={addLink}
          className={`rte-btn ${editor?.isActive("link") ? "active" : ""}`}
          title="Add link"
        >
          <svg width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" d="M10 13a5 5 0 007.54.54l3-3a5 5 0 00-7.07-7.07l-1.72 1.71" />
            <path strokeLinecap="round" strokeLinejoin="round" d="M14 11a5 5 0 00-7.54-.54l-3 3a5 5 0 007.07 7.07l1.71-1.71" />
          </svg>
        </button>
        <button
          type="button"
            onClick={() => editor?.chain().focus().unsetLink().run()}
            className="rte-btn"
            title="Remove link"
          >
            <svg width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" d="M18.364 5.636a5 5 0 010 7.07l-3 3a5 5 0 01-7.07 0M5.636 18.364a5 5 0 000-7.07l3-3" />
              <line x1="2" y1="2" x2="22" y2="22" strokeLinecap="round" />
            </svg>
          </button>

        <div className="rte-sep" />

        <button
          type="button"
          onClick={() => editor?.chain().focus().toggleBlockquote().run()}
          className={`rte-btn ${editor?.isActive("blockquote") ? "active" : ""}`}
          title="Quote"
          style={{ fontSize: "13px", fontWeight: 700 }}
        >
          “”
        </button>

        <div className="rte-sep" />

        <button
          type="button"
          onClick={() => fileInputRef.current?.click()}
          disabled={uploadingImage}
          className="rte-btn"
          style={{ opacity: uploadingImage ? 0.5 : 1 }}
          title="Upload image (max 1 MB)"
        >
          {uploadingImage ? (
            <Loader2 size={14} className="animate-spin" />
          ) : (
            <svg width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
              <rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
              <circle cx="8.5" cy="8.5" r="1.5" />
              <polyline points="21 15 16 10 5 21" />
            </svg>
          )}
        </button>

        <input
          ref={fileInputRef}
          type="file"
          accept="image/*"
          className="hidden"
          onChange={(e) => {
            const file = e.target.files?.[0];
            if (file) handleImageUpload(file);
          }}
        />

        {onToggleFullscreen && (
          <>
            <div className="rte-sep" />
            <button
              type="button"
              onClick={onToggleFullscreen}
              className={`rte-btn ${isFullscreen ? "active" : ""}`}
              title={isFullscreen ? "Minimize editor" : "Expand editor"}
            >
              {isFullscreen ? (
                <svg width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" d="M4 14h6v6m0-6l-7 7M20 10h-6V4m0 6l7-7" />
                </svg>
              ) : (
                <svg width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" d="M15 3h6m0 0v6m0-6l-7 7M9 21H3m0 0v-6m0 6l7-7" />
                </svg>
              )}
            </button>
          </>
        )}
      </div>

      {/* Scrollable editor body */}
      <div className="flex-1 overflow-y-auto">
        <EditorContent editor={editor} className="h-full" />
      </div>
    </div>
  );
};

export default RichTextEditor;
