import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { AlertCircle, CheckCircle2, X } from "lucide-react";
import type { ComponentRecord } from "../types";
import type { ContentPlaceholderVars } from "@/lib/contentPlaceholders";
import {
  PASTE_COMPONENT_EMPTY_ERROR,
  PASTE_COMPONENT_EXAMPLE_JSON,
  PASTE_VALIDATION_LABELS,
  parsePastedComponentJson,
  type ParsePasteResult,
} from "@/lib/pasteComponent";
import { pasteDebug, pasteLogError } from "@/lib/pasteDebug";
import { normalizePastedText, readPasteText } from "@/lib/pasteText";
import PasteComponentPreviewPanel from "./PasteComponentPreviewPanel";

export type PasteComponentTarget = {
  sectionIndex?: number;
  slotIndex?: number;
};

export type PasteComponentJsonModalProps = {
  open: boolean;
  components: ComponentRecord[];
  placeholderVars: ContentPlaceholderVars;
  siteChromeKey: string;
  showGlobalFooter: boolean;
  target: PasteComponentTarget | null;
  initialText?: string;
  initialError?: string;
  initialStep?: "paste" | "preview";
  onClose: () => void;
  onApply: (text: string) => boolean | { error: string };
};

function buildPlacementLabel(target: PasteComponentTarget | null): string {
  if (target?.sectionIndex === undefined) return "New section on this page";
  if (target.slotIndex !== undefined) {
    return `Section ${target.sectionIndex + 1}, slot ${target.slotIndex + 1}`;
  }
  return `Section ${target.sectionIndex + 1} (next available slot)`;
}

function ValidationFeedback({ result }: { result: ParsePasteResult | null }) {
  if (!result) return null;

  if (result.ok) {
    return (
      <div
        style={{
          display: "flex",
          alignItems: "flex-start",
          gap: 10,
          marginTop: 12,
          padding: "10px 14px",
          background: "#f0fdf4",
          border: "1px solid #bbf7d0",
          borderRadius: 10,
          color: "#166534",
          fontSize: 14,
          lineHeight: 1.5,
        }}
      >
        <CheckCircle2 size={18} style={{ flexShrink: 0, marginTop: 1 }} />
        <div>
          <strong>Valid component JSON.</strong> Review the preview before applying.
          {result.warnings.length > 0 && (
            <span> {result.warnings.length} note{result.warnings.length === 1 ? "" : "s"} to review.</span>
          )}
        </div>
      </div>
    );
  }

  return (
    <div
      style={{
        display: "flex",
        alignItems: "flex-start",
        gap: 10,
        marginTop: 12,
        padding: "10px 14px",
        background: "#fef2f2",
        border: "1px solid #fecaca",
        borderRadius: 10,
        color: "#991b1b",
        fontSize: 14,
        lineHeight: 1.5,
      }}
    >
      <AlertCircle size={18} style={{ flexShrink: 0, marginTop: 1 }} />
      <div>
        <strong>{PASTE_VALIDATION_LABELS[result.category]}</strong>
        {result.field ? (
          <span>
            {" "}
            — check <code style={{ fontSize: 12 }}>{result.field}</code>
          </span>
        ) : null}
        <div style={{ marginTop: 4 }}>{result.error}</div>
      </div>
    </div>
  );
}

export default function PasteComponentJsonModal({
  open,
  components,
  placeholderVars,
  siteChromeKey,
  showGlobalFooter,
  target,
  initialText = "",
  initialError = "",
  initialStep = "paste",
  onClose,
  onApply,
}: PasteComponentJsonModalProps) {
  const [step, setStep] = useState<"paste" | "preview">("paste");
  const [pasteText, setPasteText] = useState("");
  const [hasText, setHasText] = useState(false);
  const [pasteError, setPasteError] = useState("");
  const [parseResult, setParseResult] = useState<ParsePasteResult | null>(null);
  const [pasteModalKey, setPasteModalKey] = useState(0);
  const textareaRef = useRef<HTMLTextAreaElement>(null);
  const latestTextRef = useRef("");

  const placementLabel = useMemo(() => buildPlacementLabel(target), [target]);

  const syncPasteText = useCallback((text: string) => {
    latestTextRef.current = text;
    setPasteText(text);
    setHasText(Boolean(normalizePastedText(text)));
    if (textareaRef.current && textareaRef.current.value !== text) {
      textareaRef.current.value = text;
    }
    setPasteError("");
  }, []);

  const getCurrentText = useCallback(() => {
    const fromDom = textareaRef.current?.value ?? "";
    return latestTextRef.current.trim() || fromDom.trim() || pasteText;
  }, [pasteText]);

  useEffect(() => {
    if (!open) return;
    setStep(initialStep);
    setPasteError(initialError);
    latestTextRef.current = initialText;
    setPasteText(initialText);
    setHasText(Boolean(normalizePastedText(initialText)));
    if (!initialText) {
      setPasteModalKey((key) => key + 1);
    }
  }, [open, initialText, initialError, initialStep]);

  useEffect(() => {
    if (!open) {
      setParseResult(null);
      return;
    }
    const text = normalizePastedText(pasteText);
    if (!text) {
      setParseResult(null);
      return;
    }
    setParseResult(parsePastedComponentJson(text, components));
  }, [open, pasteText, components]);

  useEffect(() => {
    if (!open) return;
    const frame = window.requestAnimationFrame(() => {
      const textarea = textareaRef.current;
      const text = latestTextRef.current;
      if (textarea && textarea.value !== text) {
        textarea.value = text;
      }
      if (step === "paste") textarea?.focus();
    });
    return () => window.cancelAnimationFrame(frame);
  }, [open, pasteModalKey, step]);

  useEffect(() => {
    if (!open || step !== "paste") return;

    const onDocumentPaste = (event: ClipboardEvent) => {
      void (async () => {
        const text = await readPasteText(event);
        if (!normalizePastedText(text)) return;

        const textarea = textareaRef.current;
        const focusedInModal = textarea && document.activeElement === textarea;
        if (!focusedInModal) {
          event.preventDefault();
          syncPasteText(text);
          textarea?.focus();
          pasteDebug("modal:document-paste", { length: text.length });
        }
      })();
    };

    window.addEventListener("paste", onDocumentPaste, true);
    return () => window.removeEventListener("paste", onDocumentPaste, true);
  }, [open, step, syncPasteText]);

  const goToPreview = () => {
    const text = getCurrentText();
    if (!normalizePastedText(text)) {
      setPasteError(PASTE_COMPONENT_EMPTY_ERROR);
      return;
    }
    const result = parsePastedComponentJson(text, components);
    setParseResult(result);
    if (result.ok === false) {
      setPasteError(result.error);
      return;
    }
    setPasteError("");
    setStep("preview");
  };

  const applyComponent = () => {
    const text = getCurrentText();
    if (!normalizePastedText(text)) {
      setPasteError(PASTE_COMPONENT_EMPTY_ERROR);
      setStep("paste");
      return;
    }
    const result = parsePastedComponentJson(text, components);
    if (result.ok === false) {
      setParseResult(result);
      setPasteError(result.error);
      setStep("paste");
      return;
    }
    const applied = onApply(text);
    if (applied === true) {
      onClose();
      return;
    }
    if (typeof applied === "object" && applied.error) {
      setPasteError(applied.error);
    }
  };

  if (!open) return null;

  const isValid = parseResult?.ok === true;
  const textareaBorder = pasteError
    ? "#fca5a5"
    : parseResult?.ok === false
      ? "#fca5a5"
      : parseResult?.ok
        ? "#86efac"
        : "#e5e7eb";

  return (
    <div
      style={{
        position: "fixed",
        inset: 0,
        zIndex: 50,
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        background: "rgba(0,0,0,0.4)",
        padding: 24,
      }}
    >
      <div
        role="dialog"
        aria-modal="true"
        aria-labelledby="paste-component-json-title"
        style={{
          background: "#fff",
          borderRadius: 20,
          boxShadow: "0 24px 48px rgba(0,0,0,0.15)",
          maxWidth: step === "preview" ? 760 : 640,
          width: "100%",
          maxHeight: "90vh",
          overflow: "auto",
        }}
      >
        <div
          style={{
            display: "flex",
            alignItems: "center",
            justifyContent: "space-between",
            padding: "20px 24px",
            borderBottom: "1px solid #e5e7eb",
          }}
        >
          <div>
            <h2 id="paste-component-json-title" style={{ margin: 0, fontSize: 18, fontWeight: 700 }}>
              {step === "paste" ? "Paste component JSON" : "Preview component"}
            </h2>
            <p style={{ margin: "4px 0 0", fontSize: 13, color: "#64748b" }}>
              {step === "paste"
                ? "Paste component JSON copied from the Component Library. Review the preview before applying."
                : "Confirm this is the component you want to add to the page."}
            </p>
          </div>
          <button
            type="button"
            onClick={onClose}
            aria-label="Close"
            style={{ padding: 8, border: "none", background: "none", cursor: "pointer", color: "#64748b" }}
          >
            <X size={20} />
          </button>
        </div>

        {step === "paste" ? (
          <div style={{ padding: 24 }}>
            <p style={{ margin: "0 0 12px", fontSize: 14, color: "#64748b", lineHeight: 1.5 }}>
              Copy JSON using the <strong>Copy</strong> button in the Components module or on a page block. Plain text,
              emojis, and rich text from other apps are not supported.
            </p>
            <details style={{ margin: "0 0 16px", fontSize: 13, color: "#64748b" }}>
              <summary style={{ cursor: "pointer", fontWeight: 600, color: "#334155", marginBottom: 8 }}>
                Example valid component JSON
              </summary>
              <pre
                style={{
                  margin: 0,
                  padding: "12px 14px",
                  background: "#f8fafc",
                  border: "1px solid #e2e8f0",
                  borderRadius: 10,
                  fontSize: 12,
                  lineHeight: 1.5,
                  overflow: "auto",
                  whiteSpace: "pre-wrap",
                  wordBreak: "break-word",
                }}
              >
                {PASTE_COMPONENT_EXAMPLE_JSON}
              </pre>
            </details>
            <textarea
              key={`paste-modal-${pasteModalKey}`}
              ref={textareaRef}
              defaultValue=""
              onInput={(event) => syncPasteText(event.currentTarget.value)}
              onPaste={(event) => {
                event.preventDefault();
                void (async () => {
                  const pasted = await readPasteText(event);
                  if (!normalizePastedText(pasted)) {
                    setPasteError(PASTE_COMPONENT_EMPTY_ERROR);
                    pasteLogError("modal:paste-empty", {
                      clipboardTypes: Array.from(event.clipboardData?.types ?? []),
                    });
                    return;
                  }
                  syncPasteText(pasted);
                  pasteDebug("modal:paste-event", { length: pasted.length });
                })();
              }}
              rows={12}
              placeholder={PASTE_COMPONENT_EXAMPLE_JSON}
              style={{
                width: "100%",
                padding: "12px 14px",
                border: `1px solid ${textareaBorder}`,
                borderRadius: 10,
                boxSizing: "border-box",
                fontFamily: "monospace",
                fontSize: 13,
                outline: "none",
              }}
            />
            <ValidationFeedback result={parseResult} />
            {pasteError && (
              <p style={{ color: "#b91c1c", margin: "10px 0 0", fontSize: 14, lineHeight: 1.5 }}>{pasteError}</p>
            )}
          </div>
        ) : (
          parseResult?.ok === true && (
            <div style={{ padding: 24 }}>
              <PasteComponentPreviewPanel
                key={getCurrentText()}
                block={parseResult.block}
                summary={parseResult.summary}
                components={components}
                placeholderVars={placeholderVars}
                siteChromeKey={siteChromeKey}
                showGlobalFooter={showGlobalFooter}
                placementLabel={placementLabel}
                warnings={parseResult.warnings}
              />
              {pasteError && (
                <p style={{ color: "#b91c1c", margin: "12px 0 0", fontSize: 14, lineHeight: 1.5 }}>{pasteError}</p>
              )}
            </div>
          )
        )}

        <div
          style={{
            padding: "16px 24px",
            borderTop: "1px solid #e5e7eb",
            display: "flex",
            justifyContent: "flex-end",
            gap: 12,
            flexWrap: "wrap",
          }}
        >
          <button
            type="button"
            onClick={onClose}
            style={{
              padding: "10px 20px",
              background: "#f1f5f9",
              border: "none",
              borderRadius: 10,
              cursor: "pointer",
              fontWeight: 500,
            }}
          >
            Cancel
          </button>
          {step === "preview" ? (
            <>
              <button
                type="button"
                onClick={() => {
                  setPasteError("");
                  setStep("paste");
                }}
                style={{
                  padding: "10px 20px",
                  background: "#fff",
                  border: "1px solid #e2e8f0",
                  borderRadius: 10,
                  cursor: "pointer",
                  fontWeight: 500,
                }}
              >
                Edit JSON
              </button>
              <button
                type="button"
                onClick={applyComponent}
                disabled={!isValid}
                style={{
                  padding: "10px 20px",
                  background: isValid ? "#0f172a" : "#cbd5e1",
                  color: "#fff",
                  border: "none",
                  borderRadius: 10,
                  cursor: isValid ? "pointer" : "not-allowed",
                  fontWeight: 600,
                }}
              >
                Apply component
              </button>
            </>
          ) : (
            <button
              type="button"
              onClick={goToPreview}
              disabled={!hasText || !isValid}
              style={{
                padding: "10px 20px",
                background: hasText && isValid ? "#0f172a" : "#cbd5e1",
                color: "#fff",
                border: "none",
                borderRadius: 10,
                cursor: hasText && isValid ? "pointer" : "not-allowed",
                fontWeight: 600,
              }}
            >
              Review preview
            </button>
          )}
        </div>
      </div>
    </div>
  );
}
