"use client";

import * as React from "react";
import { Loader2, X, ImagePlus } from "lucide-react";
import { cn } from "@/lib/utils";
import Image from "next/image";
import { Button } from "@/components/ui/button";
import { uploadDealNoteImageMultipart } from "@/api/client";
import { toast } from "sonner";
import { NoteContent } from "@/components/deals/deal-note-composer";

export type BusinessDealNotesRichFieldHandle = {
  getStorageValue: () => string;
};

type Props = {
  value: string;
  disabled: boolean;
  /**
   * When set, upload uses POST /deals/:id/notes/upload-image (business deal id, lead id, etc.).
   * When null, uses POST /deals/note-image-upload (authenticated draft; e.g. new deal with customer only).
   */
  uploadDealId: string | null;
  apiBaseUrl: string;
};

/**
 * Rich notes editor for business deals: same storage shape as lead notes (HTML + img tags, relative /media URLs).
 */
export const BusinessDealNotesRichField = React.forwardRef<
  BusinessDealNotesRichFieldHandle,
  Props
>(function BusinessDealNotesRichField(
  { value, disabled, uploadDealId, apiBaseUrl },
  ref,
) {
  const editorRef = React.useRef<HTMLDivElement>(null);
  const fileInputRef = React.useRef<HTMLInputElement>(null);
  const [attachedImages, setAttachedImages] = React.useState<string[]>([]);
  const [uploading, setUploading] = React.useState(false);

  const base = apiBaseUrl.replace(/\/$/, "");

  const buildStorageHtml = React.useCallback(() => {
    const el = editorRef.current;
    const html = (el?.innerHTML ?? "").trim();
    const imgTags = attachedImages
      .map((url) => {
        const rel = url.startsWith(base)
          ? url.slice(base.length).replace(/^(?!\/)/, "/")
          : url;
        return `<img src="${rel.replace(/"/g, "&quot;")}" loading="lazy" class="w-[150px] h-[150px] object-cover rounded-lg border-2 border-gray-200 shadow-sm" alt="" />`;
      })
      .join("");
    const combined =
      html && imgTags ? `${html}<br/>${imgTags}` : html || imgTags;
    return combined.replace(
      new RegExp(base.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"),
      "",
    );
  }, [attachedImages, base]);

  React.useImperativeHandle(ref, () => ({
    getStorageValue: () => {
      if (disabled) return value ?? "";
      return buildStorageHtml();
    },
  }));

  React.useEffect(() => {
    if (disabled) return;
    const el = editorRef.current;
    if (!el) return;
    el.innerHTML = value ?? "";
    setAttachedImages([]);
  }, [value, disabled]);

  const uploadFile = React.useCallback(
    async (file: File) => {
      if (!file.type.startsWith("image/")) {
        toast.error("Please choose an image file");
        return;
      }
      setUploading(true);
      try {
        let res: { url: string };
        try {
          res = await uploadDealNoteImageMultipart(file, uploadDealId);
        } catch (first) {
          const status = (first as { status?: number }).status;
          if (uploadDealId && (status === 403 || status === 404)) {
            res = await uploadDealNoteImageMultipart(file, null);
          } else {
            throw first;
          }
        }
        const url = res.url.startsWith("http") ? res.url : `${base}${res.url}`;
        setAttachedImages((prev) => [...prev, url]);
      } catch (e) {
        const description =
          e instanceof Error ? e.message : "Image upload failed";
        toast.error("Image upload failed", { description });
      } finally {
        setUploading(false);
      }
    },
    [uploadDealId, base],
  );

  const handlePaste = (e: React.ClipboardEvent) => {
    if (disabled) return;
    const items = e.clipboardData?.items;
    if (!items) return;
    for (const item of items) {
      if (item.type.indexOf("image") !== -1) {
        e.preventDefault();
        const file = item.getAsFile();
        if (file) void uploadFile(file);
        return;
      }
    }
  };

  const removeAttachedImage = (index: number) => {
    setAttachedImages((prev) => prev.filter((_, i) => i !== index));
  };

  if (disabled) {
    return (
      <div className="min-h-[220px] rounded-xl border border-gray-200 bg-muted/30 p-4">
        {value?.trim() ? (
          <NoteContent text={value} apiBaseUrl={apiBaseUrl} />
        ) : (
          <p className="text-sm text-muted-foreground">No notes.</p>
        )}
      </div>
    );
  }

  return (
    <div className="space-y-2">
      <div className="flex flex-wrap items-center gap-2">
        <input
          ref={fileInputRef}
          type="file"
          accept="image/*"
          className="hidden"
          onChange={(e) => {
            const f = e.target.files?.[0];
            e.target.value = "";
            if (f) void uploadFile(f);
          }}
        />
        <Button
          type="button"
          variant="outline"
          size="sm"
          className="h-9 gap-1.5 rounded-lg text-xs"
          disabled={uploading}
          onClick={() => fileInputRef.current?.click()}
        >
          {uploading ? (
            <Loader2 className="size-3.5 animate-spin" />
          ) : (
            <ImagePlus className="size-3.5" />
          )}
          Add image
        </Button>
        <span className="text-xs text-muted-foreground">
          Or paste an image from the clipboard.
        </span>
      </div>

      {attachedImages.length > 0 ? (
        <div className="flex gap-2 overflow-x-auto pb-1">
          {attachedImages.map((url, i) => (
            <div
              key={`${url}-${i}`}
              className="relative h-[72px] w-[72px] shrink-0 overflow-hidden rounded-lg border-2 border-gray-200 bg-gray-100 shadow-sm group"
            >
              <Image
                src={url}
                alt=""
                fill
                loading="lazy"
                sizes="(max-width: 768px) 100px, 100px"
                className="size-full object-cover"
              />
              <button
                type="button"
                onClick={() => removeAttachedImage(i)}
                className="absolute top-0.5 right-0.5 flex size-5 items-center justify-center rounded-full bg-black/60 text-white opacity-0 transition-opacity group-hover:opacity-100 focus:opacity-100"
                aria-label="Remove image"
              >
                <X className="size-3" />
              </button>
            </div>
          ))}
        </div>
      ) : null}

      <div
        ref={editorRef}
        contentEditable
        onPaste={handlePaste}
        data-placeholder="Add context, next steps, or meeting outcomes… (paste images like lead notes)"
        className={cn(
          "min-h-[200px] rounded-xl border border-gray-200 bg-gray-50/80 px-4 py-3 text-[15px] leading-relaxed outline-none focus:border-[#6C63FF]/50 focus:ring-2 focus:ring-[#6C63FF]/20",
          "empty:before:text-muted-foreground empty:before:content-[attr(data-placeholder)]",
        )}
        suppressContentEditableWarning
      />
      {uploading && attachedImages.length === 0 ? (
        <p className="flex items-center gap-1.5 text-xs text-muted-foreground">
          <Loader2 className="size-3 animate-spin" />
          Uploading…
        </p>
      ) : null}
    </div>
  );
});
