"use client";

import {
  BoldOutlined,
  ItalicOutlined,
  LinkOutlined,
  PictureOutlined,
  RedoOutlined,
  UnderlineOutlined,
  UnorderedListOutlined,
} from "@ant-design/icons";
import {
  Alert,
  Button,
  Card,
  Col,
  DatePicker,
  Form,
  Input,
  InputNumber,
  Modal,
  Row,
  Select,
  Space,
  Switch,
  Typography,
  message,
} from "antd";
import dayjs, { type Dayjs } from "dayjs";
import {
  type ClipboardEvent,
  type DragEvent,
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";

import DepartmentDropdown from "@/components/common/DepartmentDropdown";
import EmployeeDropdown from "@/components/common/EmployeeDropdown";
import { sanitizeVulnerabilityHtmlForDisplay } from "@/components/common/VulnerabilityHtml";
import {
  extractApiErrorMessage,
  getPickerReadsBlockedMessage,
  isPickerReadsBlockedError,
} from "@/lib/api/errors";
import { fetchEmployeeByEmail, type Employee } from "@/lib/api/employees";
import {
  fetchVulnerabilityConfig,
  type VulnerabilityConfig,
} from "@/lib/api/vulnerability-config";
import {
  confirmVulnerabilityUpload,
  fetchVulnerabilityAttachmentUrl,
  requestVulnerabilityUpload,
  type CreateVulnerabilityPayload,
  type UpdateVulnerabilityPayload,
  type VulnerabilityUploadResponse,
} from "@/lib/api/vulnerabilities";
import { useAuth } from "@/lib/hooks/use-auth";
import type { CriticalityLevel } from "@/types/models";

const { Paragraph, Text } = Typography;
const SIGNED_URL_REFRESH_SKEW_MS = 60_000;

const fieldIds = {
  title: "vulnerability-title",
  severity: "vulnerability-severity",
  discoverer: "vulnerability-discoverer",
  fixer: "vulnerability-fixer",
  owner: "vulnerability-owner",
  department: "vulnerability-department",
  vulnerabilityType: "vulnerability-type",
  application: "vulnerability-application",
  codeRepository: "vulnerability-code-repository",
  source: "vulnerability-source",
  discoveryChannel: "vulnerability-discovery-channel",
  discoveryPhase: "vulnerability-discovery-phase",
  networkEnv: "vulnerability-network-env",
  interfacePath: "vulnerability-interface-path",
  pocVerified: "vulnerability-poc-verified",
  thirdParty: "vulnerability-third-party",
  tags: "vulnerability-tags",
  affectedAssetsCount: "vulnerability-affected-assets-count",
  dependencyName: "vulnerability-dependency-name",
  dependencyVersion: "vulnerability-dependency-version",
  verificationSteps: "vulnerability-verification-steps",
  pocText: "vulnerability-poc-text",
  submittedAt: "vulnerability-submitted-at",
  slaDeadline: "vulnerability-sla-deadline",
  description: "vulnerability-description",
  descriptionToolbar: "vulnerability-description-toolbar",
  descriptionEditor: "vulnerability-description-editor",
  descriptionUpload: "vulnerability-description-upload",
} as const;

type FormValues = {
  title: string;
  severity_level: CriticalityLevel;
  vulnerability_type?: string;
  discoverer_employee_id?: number;
  fixer_employee_id?: number;
  owner_employee_id?: number;
  department_id?: string;
  application?: string;
  code_repository?: string;
  interface_path?: string;
  discovery_channel?: string;
  discovery_phase?: string;
  network_env?: string;
  source?: string;
  has_poc_verification?: boolean;
  is_third_party?: boolean;
  tags?: string[];
  affected_assets_count?: number | null;
  dependency_name?: string;
  dependency_version?: string;
  verification_steps?: string;
  poc_text?: string;
  submitted_at?: Dayjs;
  sla_deadline?: Dayjs;
};

type ApiLikeError = Error & {
  response?: {
    status?: number;
    data?: {
      message?: string;
    };
  };
};

export type VulnerabilityEditorInitialValues = Partial<{
  title: string;
  severity_level: CriticalityLevel;
  vulnerability_type: string;
  discoverer_employee_id: number | null;
  fixer_employee_id: number | null;
  owner_employee_id: number | null;
  department_id: string | null;
  application: string;
  code_repository: string;
  interface_path: string;
  discovery_channel: string;
  discovery_phase: string;
  network_env: string;
  source: string;
  has_poc_verification: boolean;
  is_third_party: boolean;
  tags: string[];
  affected_assets_count: number;
  dependency_name: string;
  dependency_version: string;
  verification_steps: string;
  poc_text: string;
  submitted_at: string | null;
  sla_deadline: string | null;
}>;

type VulnerabilityEditorFormProps = {
  mode: "create" | "edit";
  initialValues?: VulnerabilityEditorInitialValues;
  initialDescription?: string;
  editorResetKey?: string;
  loading?: boolean;
  submitLabel: string;
  onSubmit: (
    payload: CreateVulnerabilityPayload | UpdateVulnerabilityPayload,
  ) => Promise<void>;
  onCancel: () => void;
  cancelLabel?: string;
};

function uploadErrorMessage(
  error: unknown,
  stage: "presign" | "put" | "confirm",
) {
  const err = error as ApiLikeError | undefined;
  const responseMessage = err?.response?.data?.message?.toLowerCase() || "";
  const fallbackMessage = err?.message?.toLowerCase() || "";
  const messageText = responseMessage || fallbackMessage;

  if (messageText.includes("file uploads are not enabled")) {
    return "Image uploads are not enabled in this environment. Check the enterprise upload bucket and storage runtime config.";
  }
  if (messageText.includes("unsupported image type")) {
    return "This image type is not supported. Upload PNG, JPEG, JPG, WebP, or GIF files only.";
  }
  if (messageText.includes("image too large")) {
    return "This image is too large. The current limit is 10MB.";
  }
  if (messageText.includes("upload not found")) {
    return "The image reached storage, but confirmation failed. Check the upload bucket region, object path, and backend S3 permissions.";
  }
  if (stage === "put") {
    return "Direct upload to storage failed. Check the upload bucket CORS policy, bucket name, and network access, then try again.";
  }
  if (stage === "confirm") {
    return "Image upload completed, but the backend could not confirm it. Check the upload bucket and backend S3 access, then try again.";
  }
  return "Image upload could not start. Check whether uploads are enabled and the S3 runtime config is complete.";
}

function isImageFile(file: File) {
  return file.type.toLowerCase().startsWith("image/");
}

function isLikelyPresignedImageSrc(src: string) {
  const normalized = src.toLowerCase();
  return (
    normalized.includes("x-amz-signature=") ||
    normalized.includes("x-amz-algorithm=") ||
    normalized.includes("x-amz-credential=")
  );
}

function escapeHtmlAttribute(value: string) {
  return value
    .replace(/&/g, "&amp;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;");
}

function expiresAtFromSeconds(expiresIn: number): number | null {
  if (!expiresIn || expiresIn <= 0) return null;
  return Date.now() + expiresIn * 1000;
}

function refreshDelayFor(expiresAt: number): number {
  const ttlMs = Math.max(expiresAt - Date.now(), 0);
  if (ttlMs <= SIGNED_URL_REFRESH_SKEW_MS) {
    return Math.max(Math.floor(ttlMs / 2), 1_000);
  }
  return Math.max(ttlMs - SIGNED_URL_REFRESH_SKEW_MS, 1_000);
}

async function refreshEditorAttachmentImageUrls(
  container: HTMLDivElement,
): Promise<number[]> {
  const imgs = Array.from(
    container.querySelectorAll<HTMLImageElement>("img[data-sc-attachment-id]"),
  );
  if (!imgs.length) {
    return [];
  }

  const refreshableExpiresAt = await Promise.all(
    imgs.map(async (img) => {
      try {
        const attachmentId = Number(img.getAttribute("data-sc-attachment-id"));
        if (!attachmentId || Number.isNaN(attachmentId)) {
          return null;
        }

        img.style.maxWidth = "100%";
        img.style.height = "auto";
        const existingSrc = img.getAttribute("src") || "";
        if (existingSrc && !isLikelyPresignedImageSrc(existingSrc)) {
          return null;
        }

        const { url, expires_in: expiresIn } =
          await fetchVulnerabilityAttachmentUrl(attachmentId);
        img.src = url;
        return expiresAtFromSeconds(expiresIn);
      } catch (error) {
        console.error("Failed to refresh vulnerability image URL", error);
        return null;
      }
    }),
  );
  return refreshableExpiresAt.filter(
    (value): value is number => value !== null,
  );
}

function useEditor(options?: { onDirtyChange?: () => void }) {
  const editorRef = useRef<HTMLDivElement | null>(null);
  const [content, setContent] = useState<string>("");

  const markDirty = () => {
    options?.onDirtyChange?.();
  };

  const syncContentFromEditor = () => {
    setContent(editorRef.current?.innerHTML || "");
  };

  const applyCommand = (command: string, value?: string) => {
    if (!editorRef.current) return;
    editorRef.current.focus();
    document.execCommand(command, false, value);
    markDirty();
    syncContentFromEditor();
  };

  const insertLink = () => {
    const url = window.prompt("Enter URL");
    if (url) {
      applyCommand("createLink", url);
    }
  };

  const insertHtml = (html: string) => {
    if (!editorRef.current) return;
    editorRef.current.focus();
    document.execCommand("insertHTML", false, html);
    markDirty();
    syncContentFromEditor();
  };

  const setEditorContent = (html: string) => {
    if (editorRef.current) {
      editorRef.current.innerHTML = html;
    }
    setContent(html);
  };

  const clearContent = () => {
    markDirty();
    setEditorContent("");
  };

  return {
    editorRef,
    content,
    setContent,
    syncContentFromEditor,
    applyCommand,
    insertLink,
    insertHtml,
    setEditorContent,
    clearContent,
  };
}

function normalizeVulnerabilityHtmlForSave(html: string): string {
  if (!html) return "";
  try {
    const doc = new DOMParser().parseFromString(html, "text/html");
    doc
      .querySelectorAll("script, iframe, object, embed, link, meta")
      .forEach((node) => node.remove());

    doc.querySelectorAll("*").forEach((el) => {
      [...el.attributes].forEach((attr) => {
        const name = attr.name.toLowerCase();
        if (name.startsWith("on")) {
          el.removeAttribute(attr.name);
        }
      });
    });

    doc.querySelectorAll("img").forEach((img) => {
      const attachmentId = img.getAttribute("data-sc-attachment-id");
      const alt = img.getAttribute("alt") || "";
      if (!attachmentId) {
        img.remove();
        return;
      }
      [...img.attributes].forEach((attr) => img.removeAttribute(attr.name));
      img.setAttribute("data-sc-attachment-id", attachmentId);
      if (alt) img.setAttribute("alt", alt);
    });

    doc.querySelectorAll("a").forEach((a) => {
      const href = (a.getAttribute("href") || "").trim();
      [...a.attributes].forEach((attr) => a.removeAttribute(attr.name));
      if (!href || href.toLowerCase().startsWith("javascript:")) {
        a.removeAttribute("href");
      } else {
        a.setAttribute("href", href);
      }
      a.setAttribute("target", "_blank");
      a.setAttribute("rel", "noopener noreferrer");
    });

    doc.querySelectorAll("*").forEach((el) => {
      if (el.tagName.toLowerCase() === "a" || el.tagName.toLowerCase() === "img") {
        return;
      }
      [...el.attributes].forEach((attr) => el.removeAttribute(attr.name));
    });

    return doc.body.innerHTML;
  } catch {
    return html;
  }
}

function vulnerabilityHtmlIsBlank(html: string): boolean {
  if (!html) return true;
  try {
    const doc = new DOMParser().parseFromString(html, "text/html");
    doc.querySelectorAll("img[data-sc-attachment-id]").forEach((img) => {
      img.replaceWith(doc.createTextNode("attachment"));
    });
    return (doc.body.textContent || "").replace(/\u00a0/g, " ").trim() === "";
  } catch {
    return html.replace(/<[^>]*>/g, " ").replace(/&nbsp;/g, " ").trim() === "";
  }
}

function toFormValues(
  values?: VulnerabilityEditorInitialValues,
): Partial<FormValues> {
  if (!values) {
    return { severity_level: "medium", has_poc_verification: false };
  }
  return {
    title: values.title ?? "",
    severity_level: values.severity_level ?? "medium",
    vulnerability_type: values.vulnerability_type ?? undefined,
    discoverer_employee_id: values.discoverer_employee_id ?? undefined,
    fixer_employee_id: values.fixer_employee_id ?? undefined,
    owner_employee_id: values.owner_employee_id ?? undefined,
    department_id: values.department_id ?? undefined,
    application: values.application ?? undefined,
    code_repository: values.code_repository ?? undefined,
    interface_path: values.interface_path ?? undefined,
    discovery_channel: values.discovery_channel ?? undefined,
    discovery_phase: values.discovery_phase ?? undefined,
    network_env: values.network_env ?? undefined,
    source: values.source ?? undefined,
    has_poc_verification: values.has_poc_verification ?? false,
    is_third_party: values.is_third_party ?? false,
    tags: values.tags ?? [],
    affected_assets_count: values.affected_assets_count ?? null,
    dependency_name: values.dependency_name ?? undefined,
    dependency_version: values.dependency_version ?? undefined,
    verification_steps: values.verification_steps ?? undefined,
    poc_text: values.poc_text ?? undefined,
    submitted_at: values.submitted_at ? dayjs(values.submitted_at) : undefined,
    sla_deadline: values.sla_deadline ? dayjs(values.sla_deadline) : undefined,
  };
}

export function VulnerabilityEditorForm({
  mode,
  initialValues,
  initialDescription,
  editorResetKey,
  loading = false,
  submitLabel,
  onSubmit,
  onCancel,
  cancelLabel = "Back to list",
}: VulnerabilityEditorFormProps) {
  const { user } = useAuth();
  const [form] = Form.useForm<FormValues>();
  const [config, setConfig] = useState<VulnerabilityConfig | null>(null);
  const [loadingConfig, setLoadingConfig] = useState(true);
  const [submitting, setSubmitting] = useState(false);
  const [uploadingImage, setUploadingImage] = useState(false);
  const [draggingImage, setDraggingImage] = useState(false);
  const [descriptionRequiredError, setDescriptionRequiredError] =
    useState(false);
  const [resolvingFallbackDiscoverer, setResolvingFallbackDiscoverer] =
    useState(false);
  const [resolvedFallbackEmployee, setResolvedFallbackEmployee] =
    useState<Employee | null>(null);
  const fileInputRef = useRef<HTMLInputElement | null>(null);
  const autoResolveAttemptedRef = useRef(false);
  const lastHydratedEditorKeyRef = useRef<string>("");
  const isEditorDirtyRef = useRef(false);
  const editorDragDepthRef = useRef(0);
  const ownerManualOverrideRef = useRef(false);
  const departmentManualOverrideRef = useRef(false);
  const autoFilledOwnerEmployeeIdRef = useRef<number | null>(null);
  const autoFilledDepartmentIdRef = useRef<string | null>(null);
  const [editorElement, setEditorElement] = useState<HTMLDivElement | null>(
    null,
  );
  const discovererEmployeeId = Form.useWatch("discoverer_employee_id", form);
  const submissionRequiredFields = useMemo(
    () =>
      mode === "create"
        ? new Set(config?.submission_required_fields ?? [])
        : new Set<string>(),
    [config?.submission_required_fields, mode],
  );
  const isSubmissionFieldRequired = useCallback(
    (fieldKey: string) => submissionRequiredFields.has(fieldKey),
    [submissionRequiredFields],
  );
  const requiredRule = useCallback(
    (fieldKey: string, label: string) =>
      isSubmissionFieldRequired(fieldKey)
        ? [{ required: true, message: `${label} is required` }]
        : [],
    [isSubmissionFieldRequired],
  );

  const markEditorDirty = useCallback(() => {
    isEditorDirtyRef.current = true;
  }, []);

  const {
    editorRef,
    content,
    setContent,
    syncContentFromEditor,
    applyCommand: runEditorCommand,
    insertLink: openLinkPrompt,
    insertHtml: insertEditorHtml,
    setEditorContent,
    clearContent: clearEditorContent,
  } = useEditor({ onDirtyChange: markEditorDirty });

  const bindEditorRef = useCallback(
    (node: HTMLDivElement | null) => {
      editorRef.current = node;
      setEditorElement(node);
    },
    [editorRef],
  );

  const applyCommand = useCallback(
    (command: string, value?: string) => {
      runEditorCommand(command, value);
    },
    [runEditorCommand],
  );

  const insertLink = useCallback(() => {
    openLinkPrompt();
  }, [openLinkPrompt]);

  const insertHtml = useCallback(
    (html: string) => {
      insertEditorHtml(html);
    },
    [insertEditorHtml],
  );

  const clearContent = useCallback(() => {
    clearEditorContent();
    setDescriptionRequiredError(false);
  }, [clearEditorContent]);

  useEffect(() => {
    const loadConfig = async () => {
      setLoadingConfig(true);
      try {
        const data = await fetchVulnerabilityConfig();
        setConfig(data);
      } catch {
        message.error("Failed to load vulnerability config");
      } finally {
        setLoadingConfig(false);
      }
    };
    void loadConfig();
  }, []);

  useEffect(() => {
    const hydrationKey = `${mode}:${editorResetKey ?? "__default__"}`;
    if (!editorElement) {
      return;
    }
    if (lastHydratedEditorKeyRef.current === hydrationKey) {
      return;
    }

    const descriptionHtml = sanitizeVulnerabilityHtmlForDisplay(
      initialDescription || "",
    );

    isEditorDirtyRef.current = false;
    ownerManualOverrideRef.current = Boolean(
      initialValues?.owner_employee_id &&
        initialValues?.fixer_employee_id &&
        initialValues.owner_employee_id !== initialValues.fixer_employee_id,
    );
    departmentManualOverrideRef.current = Boolean(initialValues?.department_id);
    autoFilledOwnerEmployeeIdRef.current = null;
    autoFilledDepartmentIdRef.current = null;
    form.setFieldsValue(toFormValues(initialValues));
    editorElement.innerHTML = descriptionHtml;
    setContent(descriptionHtml);
    lastHydratedEditorKeyRef.current = hydrationKey;

    let cancelled = false;
    let refreshTimer: number | undefined;
    const scheduleNextImageUrlRefresh = (expiresAtValues: number[]) => {
      if (cancelled || !expiresAtValues.length) {
        return;
      }
      if (refreshTimer) {
        window.clearTimeout(refreshTimer);
      }
      const nextExpiresAt = Math.min(...expiresAtValues);
      refreshTimer = window.setTimeout(() => {
        if (
          cancelled ||
          lastHydratedEditorKeyRef.current !== hydrationKey ||
          !editorElement.isConnected
        ) {
          return;
        }
        void refreshEditorAttachmentImageUrls(editorElement)
          .then((nextExpiresAtValues) => {
            if (
              cancelled ||
              lastHydratedEditorKeyRef.current !== hydrationKey ||
              !editorElement.isConnected
            ) {
              return;
            }
            setContent(editorElement.innerHTML);
            scheduleNextImageUrlRefresh(nextExpiresAtValues);
          })
          .catch((error) => {
            console.error("Failed to refresh vulnerability image URLs", error);
          });
      }, refreshDelayFor(nextExpiresAt));
    };

    void refreshEditorAttachmentImageUrls(editorElement)
      .then((expiresAtValues) => {
        if (
          cancelled ||
          lastHydratedEditorKeyRef.current !== hydrationKey ||
          !editorElement.isConnected
        ) {
          return;
        }
        setContent(editorElement.innerHTML);
        scheduleNextImageUrlRefresh(expiresAtValues);
      })
      .catch((error) => {
        console.error("Failed to refresh vulnerability image URLs", error);
      });

    return () => {
      cancelled = true;
      if (refreshTimer) {
        window.clearTimeout(refreshTimer);
      }
    };
  }, [
    editorElement,
    editorResetKey,
    form,
    initialDescription,
    initialValues,
    mode,
    setContent,
  ]);

  useEffect(() => {
    if (mode !== "create") {
      return;
    }
    if (user?.employeeId && user.employeeLinkStatus === "linked") {
      form.setFieldValue("discoverer_employee_id", user.employeeId);
      setResolvedFallbackEmployee(null);
      return;
    }
    if (
      user?.employeeLinkStatus === "pending" ||
      user?.employeeLinkStatus === "failed"
    ) {
      form.setFieldValue("discoverer_employee_id", undefined);
    }
  }, [form, mode, user?.employeeId, user?.employeeLinkStatus]);

  useEffect(() => {
    if (mode !== "create") {
      return;
    }
    autoResolveAttemptedRef.current = false;
    setResolvedFallbackEmployee(null);
  }, [mode, user?.email, user?.employeeId, user?.employeeLinkStatus]);

  const resolveDiscovererFallback = useCallback(
    async (options?: { silent?: boolean }) => {
      if (!user?.email) {
        if (!options?.silent) {
          message.warning(
            "Current session does not expose an email to match against",
          );
        }
        return;
      }
      setResolvingFallbackDiscoverer(true);
      try {
        const emp = await fetchEmployeeByEmail(user.email);
        if (!emp?.id) {
          setResolvedFallbackEmployee(null);
          if (!options?.silent) {
            message.warning(
              "No employee record matched the current sign-in email",
            );
          }
          return;
        }
        form.setFieldValue("discoverer_employee_id", emp.id);
        setResolvedFallbackEmployee(emp);
        if (!options?.silent) {
          message.success("Matched discoverer from the current sign-in email");
        }
      } catch (error) {
        if (!options?.silent) {
          message.error(
            isPickerReadsBlockedError(error)
              ? getPickerReadsBlockedMessage()
              : (extractApiErrorMessage(error) ??
                  "Failed to resolve discoverer from the current sign-in email"),
          );
        }
      } finally {
        setResolvingFallbackDiscoverer(false);
      }
    },
    [form, user?.email],
  );

  const hasLinkedEmployee = Boolean(
    user?.employeeId && user.employeeLinkStatus === "linked",
  );
  const hasUnlinkedSession =
    mode === "create" &&
    !hasLinkedEmployee &&
    (user?.employeeLinkStatus === "pending" ||
      user?.employeeLinkStatus === "failed");
  const fallbackDiscovererResolved =
    Boolean(resolvedFallbackEmployee?.id) &&
    discovererEmployeeId === resolvedFallbackEmployee?.id;

  useEffect(() => {
    if (
      mode !== "create" ||
      !hasUnlinkedSession ||
      !user?.email ||
      discovererEmployeeId ||
      autoResolveAttemptedRef.current
    ) {
      return;
    }
    autoResolveAttemptedRef.current = true;
    void resolveDiscovererFallback({ silent: true });
  }, [
    discovererEmployeeId,
    hasUnlinkedSession,
    mode,
    resolveDiscovererFallback,
    user?.email,
  ]);

  const linkageAlert =
    mode === "create" && hasUnlinkedSession
      ? {
          type: (fallbackDiscovererResolved
            ? "warning"
            : user?.employeeLinkStatus === "failed"
              ? "error"
              : "warning") as "error" | "warning",
          title: fallbackDiscovererResolved
            ? "Discoverer matched from your current sign-in email"
            : user?.employeeLinkStatus === "failed"
              ? "Your sign-in account is not linked to an employee record"
              : "Employee link is still pending",
          description: fallbackDiscovererResolved
            ? "This submission can use the matched employee automatically, but your sign-in account is still not linked to an employee record. Ask an administrator to repair the user link so future workflows auto-fill cleanly."
            : user?.employeeLinkStatus === "failed"
              ? "This session cannot auto-fill discoverer details. Select the employee manually or use the explicit email match fallback before submitting."
              : "This session has not been linked to an employee record yet. Sensitive workflows should not guess your business identity; review the discoverer field before you submit.",
        }
      : null;

  const severityOptions = useMemo(
    () =>
      (config?.severity_levels ?? ["critical", "high", "medium", "low"]).map(
        (level) => ({
          label: level.toUpperCase(),
          value: level,
        }),
      ),
    [config?.severity_levels],
  );

  const sourceOptions = useMemo(
    () => (config?.sources ?? []).map((item) => ({ label: item, value: item })),
    [config?.sources],
  );

  const typeOptions = useMemo(
    () =>
      (config?.types ?? []).map((item) => ({
        label: `${item.name} (${item.default_severity.toUpperCase()})`,
        value: item.name,
      })),
    [config?.types],
  );

  const handleFormValuesChange = useCallback(
    (changedValues: Partial<FormValues>) => {
      if (
        Object.prototype.hasOwnProperty.call(
          changedValues,
          "owner_employee_id",
        )
      ) {
        ownerManualOverrideRef.current = true;
      }
      if (
        Object.prototype.hasOwnProperty.call(changedValues, "department_id")
      ) {
        departmentManualOverrideRef.current = true;
      }
    },
    [],
  );

  const syncDepartmentFromFixer = useCallback(
    (employee: Employee | null) => {
      const currentDepartmentId = form.getFieldValue("department_id");
      const autoFilledDepartmentId = autoFilledDepartmentIdRef.current;

      if (!employee) {
        if (
          !departmentManualOverrideRef.current &&
          currentDepartmentId &&
          currentDepartmentId === autoFilledDepartmentId
        ) {
          form.setFieldValue("department_id", undefined);
        }
        autoFilledDepartmentIdRef.current = null;
        return;
      }

      if (employee.department_id) {
        if (!departmentManualOverrideRef.current) {
          form.setFieldValue("department_id", employee.department_id);
          autoFilledDepartmentIdRef.current = employee.department_id;
        }
        return;
      }

      if (
        !departmentManualOverrideRef.current &&
        currentDepartmentId &&
        currentDepartmentId === autoFilledDepartmentId
      ) {
        form.setFieldValue("department_id", undefined);
      }
      autoFilledDepartmentIdRef.current = null;
    },
    [form],
  );

  const handleFixerEmployeeChange = useCallback(
    (employeeSelection: Employee | Employee[] | null) => {
      const employee = Array.isArray(employeeSelection)
        ? (employeeSelection[0] ?? null)
        : employeeSelection;

      syncDepartmentFromFixer(employee);

      const currentOwnerEmployeeId = form.getFieldValue("owner_employee_id");
      const autoFilledOwnerEmployeeId = autoFilledOwnerEmployeeIdRef.current;

      if (!employee) {
        if (
          !ownerManualOverrideRef.current &&
          currentOwnerEmployeeId &&
          currentOwnerEmployeeId === autoFilledOwnerEmployeeId
        ) {
          form.setFieldValue("owner_employee_id", undefined);
        }
        autoFilledOwnerEmployeeIdRef.current = null;
        return;
      }

      if (
        ownerManualOverrideRef.current &&
        currentOwnerEmployeeId !== employee.id
      ) {
        Modal.confirm({
          title: "Overwrite owner with selected fixer?",
          content:
            "The owner was changed manually. Overwrite it with the newly selected fixer?",
          okText: "Overwrite owner",
          cancelText: "Keep current owner",
          onOk: () => {
            form.setFieldValue("owner_employee_id", employee.id);
            ownerManualOverrideRef.current = false;
            autoFilledOwnerEmployeeIdRef.current = employee.id;
          },
        });
        return;
      }

      if (!ownerManualOverrideRef.current) {
        form.setFieldValue("owner_employee_id", employee.id);
        autoFilledOwnerEmployeeIdRef.current = employee.id;
      }
    },
    [form, syncDepartmentFromFixer],
  );

  const uploadImageFile = async (file: File) => {
    const presigned: VulnerabilityUploadResponse =
      await requestVulnerabilityUpload({
        filename: file.name,
        content_type: file.type || "application/octet-stream",
      });
    try {
      const putResponse = await fetch(presigned.upload_url, {
        method: "PUT",
        headers: {
          "Content-Type": file.type || "application/octet-stream",
        },
        body: file,
      });
      if (!putResponse.ok) {
        throw new Error(`Upload failed with status ${putResponse.status}`);
      }
    } catch (error) {
      throw new Error(uploadErrorMessage(error, "put"));
    }

    let confirmed;
    try {
      confirmed = await confirmVulnerabilityUpload({
        attachment_id: presigned.attachment_id,
      });
    } catch (error) {
      throw new Error(uploadErrorMessage(error, "confirm"));
    }

    const previewUrl =
      confirmed.view_url || presigned.view_url || URL.createObjectURL(file);
    insertHtml(
      `<p><img src="${escapeHtmlAttribute(previewUrl)}" data-sc-attachment-id="${presigned.attachment_id}" alt="${escapeHtmlAttribute(file.name)}" /></p>`,
    );
  };

  const handleImageFiles = async (files: File[]) => {
    const imageFiles = files.filter(isImageFile);
    const rejectedCount = files.length - imageFiles.length;

    if (rejectedCount > 0) {
      message.warning("Only image files can be uploaded here.");
    }
    if (imageFiles.length === 0) {
      return;
    }

    try {
      setUploadingImage(true);
      for (const imageFile of imageFiles) {
        await uploadImageFile(imageFile);
      }
      message.success(
        imageFiles.length > 1
          ? `${imageFiles.length} images uploaded`
          : "Image uploaded",
      );
    } catch (error) {
      console.error(error);
      message.error(
        error instanceof Error
          ? error.message
          : uploadErrorMessage(error, "presign"),
      );
    } finally {
      setUploadingImage(false);
      if (fileInputRef.current) {
        fileInputRef.current.value = "";
      }
    }
  };

  const handleImageUpload = async (file: File) => {
    await handleImageFiles([file]);
  };

  const hasDraggedFiles = (event: DragEvent<HTMLDivElement>) =>
    Array.from(event.dataTransfer.types).includes("Files");

  const resetEditorDragState = () => {
    editorDragDepthRef.current = 0;
    setDraggingImage(false);
  };

  const handleEditorDragEnter = (event: DragEvent<HTMLDivElement>) => {
    if (!hasDraggedFiles(event)) {
      return;
    }
    event.preventDefault();
    event.stopPropagation();
    editorDragDepthRef.current += 1;
    setDraggingImage(true);
  };

  const handleEditorDragOver = (event: DragEvent<HTMLDivElement>) => {
    if (!hasDraggedFiles(event)) {
      return;
    }
    event.preventDefault();
    event.stopPropagation();
    event.dataTransfer.dropEffect = "copy";
    setDraggingImage(true);
  };

  const handleEditorDragLeave = (event: DragEvent<HTMLDivElement>) => {
    if (!hasDraggedFiles(event)) {
      return;
    }
    event.preventDefault();
    event.stopPropagation();
    editorDragDepthRef.current = Math.max(editorDragDepthRef.current - 1, 0);
    if (editorDragDepthRef.current === 0) {
      setDraggingImage(false);
    }
  };

  const handleEditorDrop = (event: DragEvent<HTMLDivElement>) => {
    if (!hasDraggedFiles(event)) {
      return;
    }
    event.preventDefault();
    event.stopPropagation();
    resetEditorDragState();
    void handleImageFiles(Array.from(event.dataTransfer.files));
  };

  const handleEditorPaste = (event: ClipboardEvent<HTMLDivElement>) => {
    const files = Array.from(event.clipboardData.files);
    const itemFiles = Array.from(event.clipboardData.items)
      .filter((item) => item.kind === "file" && item.type.startsWith("image/"))
      .map((item) => item.getAsFile())
      .filter((file): file is File => Boolean(file));
    const pastedFiles = files.length > 0 ? files : itemFiles;

    if (!pastedFiles.some(isImageFile)) {
      return;
    }

    event.preventDefault();
    event.stopPropagation();
    void handleImageFiles(pastedFiles);
  };

  const handleSubmit = async (values: FormValues) => {
    setSubmitting(true);
    try {
      const description = normalizeVulnerabilityHtmlForSave(content);
      if (
        isSubmissionFieldRequired("description") &&
        vulnerabilityHtmlIsBlank(description)
      ) {
        setDescriptionRequiredError(true);
        message.error("Description is required");
        editorRef.current?.focus();
        return;
      }
      setDescriptionRequiredError(false);
      const basePayload: UpdateVulnerabilityPayload = {
        title: values.title,
        severity_level: values.severity_level,
        vulnerability_type: values.vulnerability_type,
        discoverer_employee_id: values.discoverer_employee_id as number,
        fixer_employee_id: values.fixer_employee_id ?? null,
        owner_employee_id: values.owner_employee_id ?? null,
        department_id: values.department_id ?? null,
        application: values.application,
        code_repository: values.code_repository,
        interface_path: values.interface_path,
        discovery_channel: values.discovery_channel,
        discovery_phase: values.discovery_phase,
        network_env: values.network_env,
        source: values.source,
        has_poc_verification: values.has_poc_verification ?? false,
        is_third_party: values.is_third_party ?? false,
        tags: values.tags ?? [],
        affected_assets_count: values.affected_assets_count ?? 0,
        dependency_name: values.dependency_name,
        dependency_version: values.dependency_version,
        description,
        verification_steps: values.verification_steps || "",
        poc_text: values.poc_text || "",
        submitted_at: values.submitted_at?.toISOString(),
        sla_deadline: values.sla_deadline?.toISOString(),
      };

      if (mode === "create") {
        const payload: CreateVulnerabilityPayload = {
          title: values.title,
          severity_level: values.severity_level,
          application: basePayload.application,
          code_repository: basePayload.code_repository,
          vulnerability_type: basePayload.vulnerability_type,
          discovery_channel: basePayload.discovery_channel,
          discovery_phase: basePayload.discovery_phase,
          network_env: basePayload.network_env,
          interface_path: basePayload.interface_path,
          source: basePayload.source,
          affected_assets_count: basePayload.affected_assets_count,
          tags: basePayload.tags,
          has_poc_verification: basePayload.has_poc_verification,
          is_third_party: basePayload.is_third_party,
          dependency_name: basePayload.dependency_name,
          dependency_version: basePayload.dependency_version,
          discoverer_employee_id: values.discoverer_employee_id as number,
          fixer_employee_id: values.fixer_employee_id ?? undefined,
          owner_employee_id: values.owner_employee_id ?? undefined,
          department_id: values.department_id ?? undefined,
	          description: basePayload.description,
	          verification_steps: basePayload.verification_steps,
	          poc_text: basePayload.poc_text,
	        };
        const numericSubmitter = Number(user?.id);
        if (!Number.isNaN(numericSubmitter)) {
          payload.submitter_user_id = numericSubmitter;
        }
        await onSubmit(payload);
      } else {
        await onSubmit(basePayload);
      }
    } catch (error) {
      console.error(error);
      message.error(
        extractApiErrorMessage(error) ??
          (mode === "create"
            ? "Failed to submit vulnerability"
            : "Failed to update vulnerability"),
      );
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Card loading={loading || loadingConfig}>
      <Form
        layout="vertical"
        form={form}
        onFinish={handleSubmit}
        onValuesChange={handleFormValuesChange}
        initialValues={{
          severity_level: "medium",
          has_poc_verification: false,
        }}
      >
        <Space direction="vertical" size={16} style={{ width: "100%" }}>
          <Card
            size="small"
            styles={{ body: { padding: 16 } }}
            title="Core details"
          >
            <Paragraph
              type="secondary"
              style={{ marginTop: 0, marginBottom: 16 }}
            >
              Start with a concise summary and severity so reviewers can triage
              quickly.
            </Paragraph>
            <Row gutter={[16, 16]}>
              <Col xs={24} md={16}>
                <Form.Item
                  name="title"
                  label="Title"
                  rules={requiredRule("title", "Title")}
                >
                  <Input
                    id={fieldIds.title}
                    name="title"
                    placeholder="Short, action-oriented summary"
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={8}>
                <Form.Item
                  name="severity_level"
                  label="Severity"
                  rules={requiredRule("severity_level", "Severity")}
                >
                  <Select id={fieldIds.severity} options={severityOptions} />
                </Form.Item>
              </Col>
              <Col xs={24} md={12}>
                <Form.Item
                  name="vulnerability_type"
                  label="Vulnerability Type"
                  rules={requiredRule("vulnerability_type", "Vulnerability Type")}
                >
                  <Select
                    id={fieldIds.vulnerabilityType}
                    allowClear
                    showSearch
                    placeholder="Select or search"
                    options={typeOptions}
                    optionFilterProp="label"
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={12}>
                <Form.Item
                  name="affected_assets_count"
                  label="Affected Assets Count"
                  rules={requiredRule("affected_assets_count", "Affected Assets Count")}
                >
                  <InputNumber
                    id={fieldIds.affectedAssetsCount}
                    min={0}
                    style={{ width: "100%" }}
                    placeholder="0"
                  />
                </Form.Item>
              </Col>
            </Row>
          </Card>

          <Card
            size="small"
            styles={{ body: { padding: 16 } }}
            title="Ownership and scope"
          >
            <Paragraph
              type="secondary"
              style={{ marginTop: 0, marginBottom: 16 }}
            >
              Capture the people and systems involved before diving into the
              discovery details.
            </Paragraph>
            {linkageAlert ? (
              <Alert
                showIcon
                type={linkageAlert.type}
                message={linkageAlert.title}
                description={
                  <Space direction="vertical" size={12}>
                    <Text>{linkageAlert.description}</Text>
                    <Space wrap>
                      <Button
                        onClick={() => void resolveDiscovererFallback()}
                        loading={resolvingFallbackDiscoverer}
                        disabled={!user?.email}
                      >
                        {fallbackDiscovererResolved
                          ? "Re-run email match"
                          : "Match discoverer from current email"}
                      </Button>
                      {fallbackDiscovererResolved &&
                      resolvedFallbackEmployee ? (
                        <Text type="secondary">
                          Matched employee: {resolvedFallbackEmployee.name} (
                          {resolvedFallbackEmployee.email})
                        </Text>
                      ) : null}
                      <Text type="secondary">
                        Session status: {user?.employeeLinkStatus}
                      </Text>
                    </Space>
                  </Space>
                }
                style={{ marginBottom: 16 }}
              />
            ) : null}
            <Row gutter={[16, 16]}>
              <Col xs={24} md={12}>
                <Form.Item
                  name="discoverer_employee_id"
                  label="Discoverer"
                  rules={requiredRule("discoverer_employee_id", "Discoverer")}
                >
                  <EmployeeDropdown
                    id={fieldIds.discoverer}
                    placeholder="Select discoverer"
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={12}>
                <Form.Item
                  name="fixer_employee_id"
                  label="Fixer"
                  rules={requiredRule("fixer_employee_id", "Fixer")}
                >
                  <EmployeeDropdown
                    id={fieldIds.fixer}
                    placeholder="Assign fixer (optional)"
                    allowClear
                    onEmployeeChange={handleFixerEmployeeChange}
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={12}>
                <Form.Item
                  name="owner_employee_id"
                  label="Owner"
                  rules={requiredRule("owner_employee_id", "Owner")}
                >
                  <EmployeeDropdown
                    id={fieldIds.owner}
                    placeholder="Assign owner (optional)"
                    allowClear
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={12}>
                <Form.Item
                  name="department_id"
                  label="Department"
                  rules={requiredRule("department_id", "Department")}
                >
                  <DepartmentDropdown
                    id={fieldIds.department}
                    placeholder="Select department"
                    allowClear
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={12}>
                <Form.Item
                  name="application"
                  label="Application/System"
                  rules={requiredRule("application", "Application/System")}
                >
                  <Input
                    id={fieldIds.application}
                    name="application"
                    placeholder="e.g., billing-api"
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={12}>
                <Form.Item
                  name="code_repository"
                  label="Code Repository"
                  rules={requiredRule("code_repository", "Code Repository")}
                >
                  <Input
                    id={fieldIds.codeRepository}
                    name="code_repository"
                    placeholder="e.g., https://github.com/org/repo"
                  />
                </Form.Item>
              </Col>
            </Row>
          </Card>

          <Card
            size="small"
            styles={{ body: { padding: 16 } }}
            title="Discovery context"
          >
            <Paragraph
              type="secondary"
              style={{ marginTop: 0, marginBottom: 16 }}
            >
              Use these fields to explain where the issue was found and how much
              exposure it has.
            </Paragraph>
            <Row gutter={[16, 16]}>
              <Col xs={24} md={12}>
                <Form.Item
                  name="source"
                  label="Source"
                  rules={requiredRule("source", "Source")}
                >
                  <Select
                    id={fieldIds.source}
                    allowClear
                    placeholder="Select source"
                    options={sourceOptions}
                    showSearch
                    filterOption={(input, option) =>
                      (option?.label as string)
                        ?.toLowerCase()
                        .includes(input.toLowerCase())
                    }
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={12}>
                <Form.Item
                  name="discovery_channel"
                  label="Discovery Channel"
                  extra="Record how the issue was found, such as manual review, a scanner, an alert, or a user report."
                  rules={requiredRule("discovery_channel", "Discovery Channel")}
                >
                  <Select
                    id={fieldIds.discoveryChannel}
                    allowClear
                    options={(config?.discovery_channels ?? []).map((item) => ({
                      label: item,
                      value: item,
                    }))}
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={8}>
                <Form.Item
                  name="discovery_phase"
                  label="Discovery Phase"
                  extra="Describe the lifecycle stage where the issue was observed, such as design, test, or runtime."
                  rules={requiredRule("discovery_phase", "Discovery Phase")}
                >
                  <Select
                    id={fieldIds.discoveryPhase}
                    allowClear
                    options={(config?.discovery_phases ?? []).map((item) => ({
                      label: item,
                      value: item,
                    }))}
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={8}>
                <Form.Item
                  name="network_env"
                  label="Network Environment"
                  extra="Note whether the issue is internet-facing, internal, staging, or another environment."
                  rules={requiredRule("network_env", "Network Environment")}
                >
                  <Select
                    id={fieldIds.networkEnv}
                    allowClear
                    options={(config?.network_envs ?? []).map((item) => ({
                      label: item,
                      value: item,
                    }))}
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={8}>
                <Form.Item
                  name="interface_path"
                  label="Interface Path"
                  extra="Use the affected URL, API route, RPC method, or admin path. Leave blank if the surface is not path-based."
                  rules={requiredRule("interface_path", "Interface Path")}
                >
                  <Input
                    id={fieldIds.interfacePath}
                    name="interface_path"
                    placeholder="e.g., /api/v1/login"
                  />
                </Form.Item>
              </Col>
            </Row>
          </Card>

          <Card
            size="small"
            styles={{ body: { padding: 16 } }}
            title="Evidence and triage"
          >
            <Paragraph
              type="secondary"
              style={{ marginTop: 0, marginBottom: 16 }}
            >
              Mark proof, ownership, dependency data, and tags before you write
              the full report.
            </Paragraph>
            <Row gutter={[16, 16]}>
              <Col xs={24} md={8}>
                <Form.Item
                  name="has_poc_verification"
                  label="POC Verified"
                  valuePropName="checked"
                >
                  <Switch id={fieldIds.pocVerified} aria-label="POC Verified" />
                </Form.Item>
              </Col>
              <Col xs={24} md={8}>
                <Form.Item
                  name="is_third_party"
                  label="Third-party Issue"
                  valuePropName="checked"
                  extra="Use this when the root cause or primary remediation belongs to a vendor, SaaS, library, or managed platform."
                >
                  <Switch
                    id={fieldIds.thirdParty}
                    aria-label="Third-party Issue"
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={8}>
                <Form.Item
                  name="tags"
                  label="Tags"
                  rules={requiredRule("tags", "Tags")}
                >
                  <Select
                    id={fieldIds.tags}
                    mode="tags"
                    placeholder="Add tags"
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={12}>
                <Form.Item
                  name="dependency_name"
                  label="Dependency Name"
                  rules={requiredRule("dependency_name", "Dependency Name")}
                >
                  <Input
                    id={fieldIds.dependencyName}
                    placeholder="e.g., lodash"
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={12}>
                <Form.Item
                  name="dependency_version"
                  label="Dependency Version"
                  rules={requiredRule("dependency_version", "Dependency Version")}
                >
                  <Input
                    id={fieldIds.dependencyVersion}
                    placeholder="e.g., 4.17.21"
                  />
                </Form.Item>
              </Col>
              {mode === "edit" ? (
                <>
                  <Col xs={24} md={12}>
                    <Form.Item name="submitted_at" label="Submitted At">
                      <DatePicker
                        id={fieldIds.submittedAt}
                        showTime
                        style={{ width: "100%" }}
                      />
                    </Form.Item>
                  </Col>
                  <Col xs={24} md={12}>
                    <Form.Item name="sla_deadline" label="SLA Deadline">
                      <DatePicker
                        id={fieldIds.slaDeadline}
                        showTime
                        style={{ width: "100%" }}
                      />
                    </Form.Item>
                  </Col>
                </>
              ) : null}
              <Col xs={24} md={12}>
                <Form.Item
                  name="verification_steps"
                  label="Verification Steps"
                  rules={requiredRule("verification_steps", "Verification Steps")}
                >
                  <Input.TextArea
                    id={fieldIds.verificationSteps}
                    rows={4}
                    placeholder="Document how to reproduce and verify the issue."
                  />
                </Form.Item>
              </Col>
              <Col xs={24} md={12}>
                <Form.Item
                  name="poc_text"
                  label="Proof of Concept"
                  rules={requiredRule("poc_text", "Proof of Concept")}
                >
                  <Input.TextArea
                    id={fieldIds.pocText}
                    rows={4}
                    placeholder="Add proof-of-concept notes or payloads."
                  />
                </Form.Item>
              </Col>
            </Row>

	            <Form.Item
	              label={
	                <span id={fieldIds.description}>Description (rich text)</span>
	              }
	              required={isSubmissionFieldRequired("description")}
	              validateStatus={descriptionRequiredError ? "error" : undefined}
	              help={descriptionRequiredError ? "Description is required" : undefined}
	              style={{ marginBottom: 0 }}
	            >
              <Card
                size="small"
                styles={{ body: { padding: 12 } }}
                title={
                  <Space
                    wrap
                    id={fieldIds.descriptionToolbar}
                    role="toolbar"
                    aria-label="Rich text formatting toolbar"
                  >
                    <Text strong>Formatting</Text>
                    <Button
                      aria-label="Bold"
                      icon={<BoldOutlined />}
                      size="small"
                      onClick={() => applyCommand("bold")}
                    />
                    <Button
                      aria-label="Italic"
                      icon={<ItalicOutlined />}
                      size="small"
                      onClick={() => applyCommand("italic")}
                    />
                    <Button
                      aria-label="Underline"
                      icon={<UnderlineOutlined />}
                      size="small"
                      onClick={() => applyCommand("underline")}
                    />
                    <Button
                      aria-label="Bulleted list"
                      icon={<UnorderedListOutlined />}
                      size="small"
                      onClick={() => applyCommand("insertUnorderedList")}
                    />
                    <Button
                      aria-label="Insert link"
                      icon={<LinkOutlined />}
                      size="small"
                      onClick={insertLink}
                    />
                    <Button
                      aria-label="Upload image"
                      icon={<PictureOutlined />}
                      size="small"
                      loading={uploadingImage}
                      onClick={() => fileInputRef.current?.click()}
                    >
                      Image
                    </Button>
                    <Button
                      aria-label="Clear description"
                      icon={<RedoOutlined />}
                      size="small"
                      onClick={clearContent}
                    >
                      Clear
                    </Button>
                  </Space>
                }
              >
                <div style={{ position: "relative" }}>
                  <div
                    id={fieldIds.descriptionEditor}
                    ref={bindEditorRef}
                    contentEditable
                    role="textbox"
                    aria-multiline="true"
                    aria-labelledby={fieldIds.description}
                    tabIndex={0}
                    suppressContentEditableWarning
                    onDragEnter={handleEditorDragEnter}
                    onDragOver={handleEditorDragOver}
                    onDragLeave={handleEditorDragLeave}
                    onDrop={handleEditorDrop}
                    onPaste={handleEditorPaste}
	                    onInput={() => {
	                      markEditorDirty();
	                      setDescriptionRequiredError(false);
	                      syncContentFromEditor();
	                    }}
	                    style={{
	                      minHeight: 220,
	                      border: draggingImage
	                        ? "1px solid #1677ff"
	                        : descriptionRequiredError
	                          ? "1px solid #ff4d4f"
	                        : "1px solid #e5e7eb",
                      borderRadius: 8,
                      padding: 12,
                      background: draggingImage ? "#f0f7ff" : undefined,
                      boxShadow: draggingImage
                        ? "0 0 0 3px rgba(22, 119, 255, 0.12)"
                        : undefined,
                      transition:
                        "border-color 0.2s ease, box-shadow 0.2s ease, background 0.2s ease",
                    }}
                  />
                  {(draggingImage || uploadingImage) && (
                    <div
                      aria-hidden="true"
                      style={{
                        position: "absolute",
                        inset: 8,
                        display: "flex",
                        alignItems: "center",
                        justifyContent: "center",
                        borderRadius: 8,
                        background: "rgba(255, 255, 255, 0.72)",
                        color: "#0958d9",
                        fontWeight: 600,
                        pointerEvents: "none",
                      }}
                    >
                      {uploadingImage
                        ? "Uploading image..."
                        : "Drop images to upload"}
                    </div>
                  )}
                </div>
                <input
                  id={fieldIds.descriptionUpload}
                  type="file"
                  accept="image/*"
                  ref={fileInputRef}
                  aria-label="Upload image attachment"
                  style={{ display: "none" }}
                  onChange={(event) => {
                    const file = event.target.files?.[0];
                    if (file) {
                      void handleImageUpload(file);
                    }
                  }}
                />
              </Card>
            </Form.Item>
          </Card>

          <Space>
            <Button type="primary" htmlType="submit" loading={submitting}>
              {submitLabel}
            </Button>
            <Button onClick={onCancel}>{cancelLabel}</Button>
          </Space>
        </Space>
      </Form>
    </Card>
  );
}
