import { NodeViewWrapper } from "@tiptap/react";
import { useCallback, useRef, useState } from "react";
import type { NodeViewProps } from "@tiptap/react";
import { uploadImage } from "./upload";

export function ImageUploadView({ editor, getPos }: NodeViewProps) {
  const [dragging, setDragging] = useState(false);
  const [uploading, setUploading] = useState(false);
  const [urlMode, setUrlMode] = useState(false);
  const [urlValue, setUrlValue] = useState("");
  const fileRef = useRef<HTMLInputElement>(null);

  const replaceWithImage = useCallback(
    (src: string) => {
      const pos = getPos();
      if (pos === undefined) return;
      editor
        .chain()
        .focus()
        .deleteRange({ from: pos, to: pos + 1 })
        .insertContentAt(pos, {
          type: "image",
          attrs: { src },
        })
        .run();
    },
    [editor, getPos],
  );

  const handleFiles = useCallback(
    (files: FileList | File[]) => {
      const file = Array.from(files).find((f) => f.type.startsWith("image/"));
      if (!file) return;
      setUploading(true);
      uploadImage(file)
        .then((url) => replaceWithImage(url))
        .catch((err) => {
          console.error("[image-upload]", err);
          setUploading(false);
        });
    },
    [replaceWithImage],
  );

  const onDrop = useCallback(
    (e: React.DragEvent) => {
      e.preventDefault();
      setDragging(false);
      if (e.dataTransfer.files.length) handleFiles(e.dataTransfer.files);
    },
    [handleFiles],
  );

  const onDragOver = useCallback((e: React.DragEvent) => {
    e.preventDefault();
    setDragging(true);
  }, []);

  const onDragLeave = useCallback(() => setDragging(false), []);

  const submitUrl = useCallback(() => {
    const src = urlValue.trim();
    if (src) replaceWithImage(src);
  }, [urlValue, replaceWithImage]);

  return (
    <NodeViewWrapper>
      <div
        className={`image-upload-card${dragging ? " dragging" : ""}`}
        onDrop={onDrop}
        onDragOver={onDragOver}
        onDragLeave={onDragLeave}
        contentEditable={false}
      >
        <input
          ref={fileRef}
          type="file"
          accept="image/*"
          style={{ display: "none" }}
          onChange={(e) => {
            if (e.target.files?.length) handleFiles(e.target.files);
          }}
        />

        {uploading ? (
          <>
            <div className="image-upload-card-icon" style={{ opacity: 0.5 }}>
              <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
                <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>
            </div>
            <p className="image-upload-card-hint">Uploading...</p>
          </>
        ) : !urlMode ? (
          <>
            <div className="image-upload-card-icon">
              <svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
                <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>
            </div>
            <div className="image-upload-card-actions">
              <button
                className="image-upload-btn primary"
                onClick={() => fileRef.current?.click()}
              >
                Upload image
              </button>
              <button
                className="image-upload-btn secondary"
                onClick={() => setUrlMode(true)}
              >
                Embed link
              </button>
            </div>
            <p className="image-upload-card-hint">
              Drag & drop an image, or click to upload
            </p>
          </>
        ) : (
          <div className="image-upload-card-url">
            <input
              type="text"
              className="image-upload-url-input"
              placeholder="Paste image URL..."
              value={urlValue}
              onChange={(e) => setUrlValue(e.target.value)}
              onKeyDown={(e) => {
                if (e.key === "Enter") submitUrl();
                if (e.key === "Escape") setUrlMode(false);
              }}
              autoFocus
            />
            <div className="image-upload-card-actions">
              <button className="image-upload-btn primary" onClick={submitUrl}>
                Embed
              </button>
              <button
                className="image-upload-btn secondary"
                onClick={() => setUrlMode(false)}
              >
                Cancel
              </button>
            </div>
          </div>
        )}
      </div>
    </NodeViewWrapper>
  );
}
