import { useState, useEffect, useCallback, useRef, useContext } from "react";
import axios from "axios";
import { apiClient } from "@/utils/apiClient";
import { useForm, Controller } from "react-hook-form";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Textarea } from "@/components/ui/textarea";
import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { Loader2, X, Copy, Maximize2, Minus, Store, Terminal, ExternalLink, Sparkles } from "lucide-react";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { useInlineAiValidation } from "@/components/product-import/steps/ValidationStep/hooks/useInlineAiValidation";
import { AiSuggestionBadge } from "@/components/product-import/steps/ValidationStep/components/AiSuggestionBadge";
import { AiDescriptionCompare } from "@/components/ai/AiDescriptionCompare";
import { submitProductEdit, submitImageChanges, submitTaxonomySet, type ImageChanges } from "@/services/productEditor";
import { createProductEditorAuditLog } from "@/services/productEditorAuditLog";
import { AuthContext } from "@/contexts/AuthContext";
import { EditableComboboxField } from "./EditableComboboxField";
import { EditableInput } from "./EditableInput";
import { EditableMultiSelect } from "./EditableMultiSelect";
import { useProductSuggestions } from "./useProductSuggestions";
import { ImageManager, MiniImagePreview } from "./ImageManager";
import type {
  SearchProduct,
  FieldOptions,
  FieldOption,
  LineOption,
  ProductImage,
  ProductFormValues,
} from "./types";

// Simple in-memory cache for lines/sublines to avoid duplicate requests across forms
const linesCache = new Map<string, Promise<LineOption[]>>();
const sublinesCache = new Map<string, Promise<LineOption[]>>();

function fetchLinesCached(companyId: string, signal?: AbortSignal): Promise<LineOption[]> {
  const cached = linesCache.get(companyId);
  if (cached) return cached;
  const p = apiClient
    .get(`/api/import/product-lines/${companyId}`, { signal })
    .then((res) => res.data as LineOption[])
    .catch(() => {
      linesCache.delete(companyId);
      return [] as LineOption[];
    });
  linesCache.set(companyId, p);
  return p;
}

function fetchSublinesCached(lineId: string, signal?: AbortSignal): Promise<LineOption[]> {
  const cached = sublinesCache.get(lineId);
  if (cached) return cached;
  const p = apiClient
    .get(`/api/import/sublines/${lineId}`, { signal })
    .then((res) => res.data as LineOption[])
    .catch(() => {
      sublinesCache.delete(lineId);
      return [] as LineOption[];
    });
  sublinesCache.set(lineId, p);
  return p;
}

// --- Field configuration types ---

type FieldType = "input" | "combobox" | "multiselect" | "textarea";

interface FieldConfig {
  key: keyof ProductFormValues;
  label: string;
  type: FieldType;
  placeholder?: string;
  searchPlaceholder?: string;
  maxLength?: number;
  rows?: number;
  copyable?: boolean;
  /** For combobox: key into fieldOptions, or "lines"/"sublines" for dynamic */
  optionsKey?: keyof FieldOptions | "lines" | "sublines";
  /** For combobox: disable when this other field is empty */
  disabledUnless?: keyof ProductFormValues;
  /** For multiselect colors field */
  showColors?: boolean;
  /** Format value for display (editing shows raw value) */
  formatDisplay?: (val: string) => string;
  /** Number of grid columns this field spans (default 1) */
  colSpan?: number;
}

interface FieldGroup {
  label?: string;
  cols: number;
  fields: FieldConfig[];
}

// --- Layout modes ---

export type LayoutMode = "full" | "minimal" | "shop" | "backend";

export const LAYOUT_ICONS: { mode: LayoutMode; label: string; icon: React.ComponentType<{ className?: string }> }[] = [
  { mode: "full", label: "Full", icon: Maximize2 },
  { mode: "minimal", label: "Minimal", icon: Minus },
  { mode: "shop", label: "Shop", icon: Store },
  { mode: "backend", label: "Backend", icon: Terminal },
];

// --- Field registry (all available fields) ---

const F: Record<string, FieldConfig> = {
  company:      { key: "company", label: "Company", type: "combobox", optionsKey: "companies", searchPlaceholder: "Search companies..." },
  line:         { key: "line", label: "Line", type: "combobox", optionsKey: "lines", searchPlaceholder: "Search lines...", disabledUnless: "company" },
  subline:      { key: "subline", label: "Subline", type: "combobox", optionsKey: "sublines", searchPlaceholder: "Search sublines...", disabledUnless: "line" },
  artist:       { key: "artist", label: "Artist", type: "combobox", optionsKey: "artists", searchPlaceholder: "Search artists..." },
  tax_cat:      { key: "tax_cat", label: "Tax Cat", type: "combobox", optionsKey: "taxCategories" },
  ship:         { key: "ship_restrictions", label: "Shipping", type: "combobox", optionsKey: "shippingRestrictions" },
  msrp:         { key: "msrp", label: "MSRP", type: "input", formatDisplay: (v) => { const n = parseFloat(v); return isNaN(n) ? v : n.toFixed(2); } },
  cur_price:    { key: "current_price", label: "Current", type: "input", formatDisplay: (v) => { const n = parseFloat(v); return isNaN(n) ? v : n.toFixed(2); } },
  cost:         { key: "cost_each", label: "Cost", type: "input", formatDisplay: (v) => { const n = parseFloat(v); return isNaN(n) ? v : n.toFixed(2); } },
  min_qty:      { key: "qty_per_unit", label: "Min Qty", type: "input" },
  case_qty:     { key: "case_qty", label: "Case Pack", type: "input" },
  weight:       { key: "weight", label: "Weight (oz)", type: "input" },
  length:       { key: "length", label: "Length (in)", type: "input" },
  width:        { key: "width", label: "Width (in)", type: "input" },
  height:       { key: "height", label: "Height (in)", type: "input" },
  size_cat:     { key: "size_cat", label: "Size Cat", type: "combobox", optionsKey: "sizes" },
  coo:          { key: "coo", label: "Country of Origin", type: "input", placeholder: "2-letter code", maxLength: 2 },
  hts_code:     { key: "hts_code", label: "HTS Code", type: "input" },
  categories:   { key: "categories", label: "Categories", type: "multiselect", optionsKey: "categories", searchPlaceholder: "Search categories..." },
  themes:       { key: "themes", label: "Themes", type: "multiselect", optionsKey: "themes", searchPlaceholder: "Search themes..." },
  colors:       { key: "colors", label: "Colors", type: "multiselect", optionsKey: "colors", searchPlaceholder: "Search colors...", showColors: true },
  supplier:     { key: "supplier", label: "Supplier", type: "combobox", optionsKey: "suppliers", searchPlaceholder: "Search suppliers..." },
  description:  { key: "description", label: "Description", type: "textarea", rows: 8 },
  priv_notes:   { key: "priv_notes", label: "Private Notes", type: "textarea", rows: 2 },
};

// --- Per-mode layouts with fields combined into sensible rows ---

interface ModeLayout {
  /** Number of leading groups to render beside images (max cols 2 in sidebar) */
  sidebarGroups: number;
  /** Max visible rows in the image grid */
  imageRows?: number;
  /** Override description textarea rows */
  descriptionRows?: number;
  groups: FieldGroup[];
}

const MODE_LAYOUTS: Record<LayoutMode, ModeLayout> = {
  full: {
    sidebarGroups: 3,
    groups: [
      { label: "Taxonomy", cols: 2, fields: [F.supplier,F.company, F.line, F.subline] },
      { cols: 2, fields: [F.artist, F.size_cat] },
      { label: "Description", cols: 1, fields: [F.description] },
      { label: "Pricing", cols: 5, fields: [F.msrp, F.cur_price, F.cost, F.min_qty, F.case_qty] },
      { label: "Dimensions", cols: 4, fields: [F.weight, F.length, F.width, F.height] },
      { cols: 4, fields: [ F.tax_cat, F.ship,F.coo, F.hts_code] },
      { label: "Classification", cols: 3, fields: [F.categories, F.themes, F.colors] },
      { label: "Notes", cols: 1, fields: [F.priv_notes] },
    ],
  },
  shop: {
    sidebarGroups: 3,
    descriptionRows: 8,
    groups: [
      { label: "Taxonomy", cols: 7, fields: [{ ...F.company, colSpan: 3 }, { ...F.msrp, colSpan: 2 }, { ...F.cur_price, colSpan: 2 }] },
      { cols: 2, fields: [F.line, F.subline, F.artist, F.size_cat] },
      { label: "Description", cols: 1, fields: [F.description] },
      { label: "Classification", cols: 3, fields: [F.categories, F.themes, F.colors] },
    ],
  },
  backend: {
    sidebarGroups: 6,
    groups: [
      { label: "Pricing", cols: 2, fields: [F.supplier, F.min_qty] },
      { cols: 3, fields: [F.cost, F.cur_price, F.msrp] },
      { cols: 3, fields: [F.case_qty, F.size_cat, F.weight] },
      { label: "Dimensions", cols: 3, fields: [F.length, F.width, F.height] },
      { cols: 2, fields: [F.tax_cat, F.ship, F.coo, F.hts_code] },
      { label: "Notes", cols: 1, fields: [F.priv_notes] },
    ],
  },
  minimal: {
    sidebarGroups: 3,
    imageRows: 2.2,
    descriptionRows: 5,
    groups: [
      { cols: 2, fields: [F.company, F.msrp, F.line, F.subline] },
      { label: "Description", cols: 1, fields: [F.description] },
    ],
  },
};

export function ProductEditForm({
  product,
  fieldOptions,
  layoutMode,
  initialImages,
  onClose,
}: {
  product: SearchProduct;
  fieldOptions: FieldOptions;
  layoutMode: LayoutMode;
  initialImages?: ProductImage[];
  onClose: () => void;
}) {
  const { user } = useContext(AuthContext);
  const [lineOptions, setLineOptions] = useState<LineOption[]>([]);
  const [sublineOptions, setSublineOptions] = useState<LineOption[]>([]);
  const [productImages, setProductImages] = useState<ProductImage[]>([]);
  const [isLoadingImages, setIsLoadingImages] = useState(false);
  const [isSubmitting, setIsSubmitting] = useState(false);

  const originalValuesRef = useRef<ProductFormValues | null>(null);
  const originalImagesRef = useRef<ProductImage[]>([]);

  const {
    register,
    control,
    handleSubmit,
    reset,
    watch,
    setValue,
    getValues,
    formState: { dirtyFields },
  } = useForm<ProductFormValues>();

  const watchCompany = watch("company");
  const watchLine = watch("line");
  const watchDescription = watch("description");

  // Populate form on mount
  useEffect(() => {
    const formValues: ProductFormValues = {
      name: product.title ?? "",
      company: String(product.brand_id ?? ""),
      line: String(product.line_id ?? ""),
      subline: String(product.subline_id ?? ""),
      supplier: String(product.supplier ?? ""),
      upc: product.barcode ?? "",
      item_number: product.sku ?? "",
      supplier_no: product.vendor_reference ?? "",
      notions_no: product.notions_reference ?? "",
      msrp: String(product.regular_price ?? ""),
      current_price: String(product.price ?? ""),
      cost_each: String(product.cost_price ?? ""),
      qty_per_unit: String(product.moq ?? ""),
      case_qty: String(product.case_qty ?? ""),
      tax_cat: String(product.tax_code ?? ""),
      artist: String(product.artist_id ?? ""),
      weight: product.weight?.toString() ?? "",
      length: product.length?.toString() ?? "",
      width: product.width?.toString() ?? "",
      height: product.height?.toString() ?? "",
      ship_restrictions: product.shipping_restrictions ?? "",
      coo: product.country_of_origin ?? "",
      hts_code: product.harmonized_tariff_code ?? "",
      size_cat: product.size_cat ?? "",
      description: product.description ?? "",
      priv_notes: "",
      categories: [],
      themes: [],
      colors: [],
    };

    originalValuesRef.current = { ...formValues };
    reset(formValues);

    // Fetch categories (and images if not pre-fetched) with abort support
    const controller = new AbortController();
    const { signal } = controller;

    if (initialImages) {
      setProductImages(initialImages);
      originalImagesRef.current = initialImages;
    } else {
      setIsLoadingImages(true);
      apiClient
        .get(`/api/import/product-images/${product.pid}`, { signal })
        .then((res) => {
          setProductImages(res.data);
          originalImagesRef.current = res.data;
        })
        .catch((e) => { if (!axios.isCancel(e)) toast.error("Failed to load product images"); })
        .finally(() => setIsLoadingImages(false));
    }

    apiClient
      .get(`/api/import/product-categories/${product.pid}`, { signal })
      .then((res) => {
        const cats: string[] = [];
        const themes: string[] = [];
        for (const item of res.data) {
          const t = Number(item.type);
          if (t >= 10 && t <= 13) cats.push(String(item.value));
          else if (t >= 20 && t <= 21) themes.push(String(item.value));
        }
        if (originalValuesRef.current) {
          originalValuesRef.current.categories = cats;
          originalValuesRef.current.themes = themes;
        }
        setValue("categories", cats);
        setValue("themes", themes);
      })
      .catch(() => {
        // Non-critical — just leave arrays empty
      });

    return () => controller.abort();
  }, [product, reset]);

  // Apply batch-fetched images when they arrive after mount
  useEffect(() => {
    if (initialImages && productImages.length === 0 && !isLoadingImages) {
      setProductImages(initialImages);
      originalImagesRef.current = initialImages;
    }
  }, [initialImages]);

  // Load lines when company changes (cached across forms)
  useEffect(() => {
    if (!watchCompany) {
      setLineOptions([]);
      return;
    }
    const controller = new AbortController();
    fetchLinesCached(watchCompany, controller.signal).then(setLineOptions);
    return () => controller.abort();
  }, [watchCompany]);

  // Load sublines when line changes (cached across forms)
  useEffect(() => {
    if (!watchLine) {
      setSublineOptions([]);
      return;
    }
    const controller = new AbortController();
    fetchSublinesCached(watchLine, controller.signal).then(setSublineOptions);
    return () => controller.abort();
  }, [watchLine]);

  const computeImageChanges = useCallback((): ImageChanges | null => {
    const original = originalImagesRef.current;
    const current = productImages;

    const originalIds = original.map((img) => img.iid);
    const currentIds = current.map((img) => img.iid);
    const originalExistingIds = originalIds.filter((id): id is number => typeof id === "number");
    const currentExistingIds = currentIds.filter((id): id is number => typeof id === "number");

    const toDelete = originalExistingIds.filter((id) => !currentIds.includes(id));
    const hidden = current.filter((img) => img.hidden).map((img) => img.iid).filter((id): id is number => typeof id === "number");
    const show = current.filter((img) => !img.hidden).map((img) => img.iid).filter((id): id is number => typeof id === "number");
    const add: Record<string, string> = {};
    for (const img of current) {
      if (img.isNew && img.imageUrl) {
        add[String(img.iid)] = img.imageUrl;
      }
    }

    const order = current.map((img) => img.iid);

    const originalHidden = original
      .filter((img) => img.hidden)
      .map((img) => img.iid)
      .filter((id): id is number => typeof id === "number");
    const orderChanged = JSON.stringify(currentExistingIds) !== JSON.stringify(originalExistingIds);
    const hiddenChanged = JSON.stringify([...hidden].sort()) !== JSON.stringify([...(originalHidden as number[])].sort());
    const hasDeleted = toDelete.length > 0;
    const hasAdded = Object.keys(add).length > 0;

    if (!orderChanged && !hiddenChanged && !hasDeleted && !hasAdded) {
      return null;
    }

    return { order, hidden, show, delete: toDelete, add };
  }, [productImages]);

  const onSubmit = useCallback(
    async (data: ProductFormValues) => {
      if (!originalValuesRef.current) return;

      const original = originalValuesRef.current;
      const changes: Record<string, unknown> = {};

      for (const key of Object.keys(data) as (keyof ProductFormValues)[]) {
        const cur = data[key];
        const orig = original[key];
        if (Array.isArray(cur) && Array.isArray(orig)) {
          if (JSON.stringify([...cur].sort()) !== JSON.stringify([...orig].sort())) {
            changes[key] = cur;
          }
        } else if (cur !== orig) {
          changes[key] = cur;
        }
      }

      const imageChanges = computeImageChanges();

      // Extract taxonomy changes for separate API calls
      const taxonomyCalls: { type: "cats" | "themes" | "colors"; ids: number[]; previousIds: number[] }[] = [];
      if ("categories" in changes) {
        taxonomyCalls.push({ type: "cats", ids: (changes.categories as string[]).map(Number), previousIds: (original.categories as string[] ?? []).map(Number) });
        delete changes.categories;
      }
      if ("themes" in changes) {
        taxonomyCalls.push({ type: "themes", ids: (changes.themes as string[]).map(Number), previousIds: (original.themes as string[] ?? []).map(Number) });
        delete changes.themes;
      }
      if ("colors" in changes) {
        taxonomyCalls.push({ type: "colors", ids: (changes.colors as string[]).map(Number), previousIds: (original.colors as string[] ?? []).map(Number) });
        delete changes.colors;
      }

      const hasFieldChanges = Object.keys(changes).length > 0;

      // Build previous values for changed fields (for audit trail)
      const previousValues: Record<string, unknown> = {};
      for (const key of Object.keys(changes)) {
        previousValues[key] = original[key as keyof ProductFormValues];
      }

      if (!hasFieldChanges && !imageChanges && taxonomyCalls.length === 0) {
        toast.info("No changes to submit");
        return;
      }

      setIsSubmitting(true);
      try {
        // Helper: call an API function, time it, fire audit log
        const audited = async <T extends { success: boolean; error?: unknown; message?: string }>(
          action: 'product_edit' | 'image_changes' | 'taxonomy_set',
          targetEndpoint: string,
          requestPayload: unknown,
          fn: () => Promise<T>,
        ): Promise<T> => {
          const start = Date.now();
          try {
            const result = await fn();
            createProductEditorAuditLog({
              user_id: user?.id ?? 0,
              username: user?.username,
              pid: product.pid,
              action,
              request_payload: requestPayload,
              target_endpoint: targetEndpoint,
              success: result.success,
              response_payload: result,
              error_message: result.success ? undefined : (
                typeof result.error === 'string' ? result.error
                : Array.isArray(result.error) ? result.error.join('; ')
                : result.message
              ),
              duration_ms: Date.now() - start,
            });
            return result;
          } catch (err) {
            createProductEditorAuditLog({
              user_id: user?.id ?? 0,
              username: user?.username,
              pid: product.pid,
              action,
              request_payload: requestPayload,
              target_endpoint: targetEndpoint,
              success: false,
              error_message: err instanceof Error ? err.message : 'Unknown error',
              duration_ms: Date.now() - start,
            });
            throw err;
          }
        };

        const promises: Promise<{ success: boolean; error?: unknown; message?: string }>[] = [];

        if (hasFieldChanges) {
          promises.push(audited('product_edit', '/apiv2/product/edit', { pid: product.pid, changes, previous_values: previousValues },
            () => submitProductEdit({ pid: product.pid, changes, environment: "prod" })));
        }
        if (imageChanges) {
          promises.push(audited('image_changes', '/apiv2/product/image_changes', { pid: product.pid, imageChanges },
            () => submitImageChanges({ pid: product.pid, imageChanges, environment: "prod" })));
        }
        for (const { type, ids, previousIds } of taxonomyCalls) {
          promises.push(audited('taxonomy_set', `/apiv2/product/${type}/${product.pid}/set`, { pid: product.pid, type, ids, previous_ids: previousIds },
            () => submitTaxonomySet({ pid: product.pid, type, ids, environment: "prod" })));
        }

        const results = await Promise.all(promises);
        const failed = results.find((r) => !r.success);

        if (failed) {
          const errorDetail = Array.isArray(failed.error)
            ? failed.error.filter((e) => e !== "Errors").join("; ")
            : typeof failed.error === "string"
              ? failed.error
              : null;
          toast.error(errorDetail || failed.message || "Failed to update product");
        } else {
          toast.success("Product updated successfully");
          originalValuesRef.current = { ...data };
          if (imageChanges) {
            try {
              const res = await apiClient.get(`/api/import/product-images/${product.pid}`);
              originalImagesRef.current = res.data;
              setProductImages(res.data);
            } catch {
              const submittedImages = productImages.map((img) => ({
                ...img,
                isNew: false,
              }));
              originalImagesRef.current = submittedImages;
              setProductImages(submittedImages);
            }
          } else {
            originalImagesRef.current = [...productImages];
          }
          reset(data);
        }
      } catch (err) {
        toast.error(
          err instanceof Error ? err.message : "Failed to update product"
        );
      } finally {
        setIsSubmitting(false);
      }
    },
    [product.pid, reset, computeImageChanges, productImages, user]
  );

  // Resolve options for a field config
  const getOptions = useCallback(
    (optionsKey?: string): FieldOption[] => {
      if (!optionsKey) return [];
      if (optionsKey === "lines") return lineOptions;
      if (optionsKey === "sublines") return sublineOptions;
      return (fieldOptions[optionsKey as keyof FieldOptions] as FieldOption[]) ?? [];
    },
    [fieldOptions, lineOptions, sublineOptions]
  );

  // --- AI inline validation ---
  const [validatingField, setValidatingField] = useState<"name" | "description" | null>(null);
  const [descDialogOpen, setDescDialogOpen] = useState(false);
  const {
    validateName,
    validateDescription,
    nameResult,
    descriptionResult,
    clearNameResult,
    clearDescriptionResult,
  } = useInlineAiValidation();

  const handleValidateName = useCallback(async () => {
    const values = getValues();
    if (!values.name?.trim()) return;
    clearNameResult();
    setValidatingField("name");
    const companyLabel = fieldOptions.companies.find((c) => c.value === values.company)?.label;
    const lineLabel = lineOptions.find((l) => l.value === values.line)?.label;
    const sublineLabel = sublineOptions.find((s) => s.value === values.subline)?.label;
    const result = await validateName({
      name: values.name,
      company_name: companyLabel,
      company_id: values.company,
      line_name: lineLabel,
      subline_name: sublineLabel,
    });
    setValidatingField((prev) => (prev === "name" ? null : prev));
    if (result && result.isValid && !result.suggestion) {
      toast.success("Name looks good!");
    }
  }, [getValues, fieldOptions, lineOptions, sublineOptions, validateName, clearNameResult]);

  const handleValidateDescription = useCallback(async () => {
    const values = getValues();
    if (!values.description?.trim() || values.description.trim().length < 10) return;
    clearDescriptionResult();
    setValidatingField("description");
    const companyLabel = fieldOptions.companies.find((c) => c.value === values.company)?.label;
    const categoryLabels = values.categories
      ?.map((id) => fieldOptions.categories.find((c) => c.value === id)?.label)
      .filter(Boolean)
      .join(", ");
    const result = await validateDescription({
      name: values.name,
      description: values.description,
      company_name: companyLabel,
      company_id: values.company,
      categories: categoryLabels || undefined,
    });
    setValidatingField((prev) => (prev === "description" ? null : prev));
    if (result && result.isValid && !result.suggestion) {
      toast.success("Description looks good!");
    }
  }, [getValues, fieldOptions, validateDescription, clearDescriptionResult]);

  // --- Embedding-based taxonomy suggestions ---
  const {
    categories: categorySuggestions,
    themes: themeSuggestions,
    colors: colorSuggestions,
    isLoading: isSuggestionsLoading,
    triggerFetch: triggerSuggestions,
  } = useProductSuggestions({
    name: product.title,
    description: product.description,
    company_name: product.brand,
    line_name: product.line,
  });

  const hasImageChanges = computeImageChanges() !== null;
  const changedCount = Object.keys(dirtyFields).length;

  const renderFieldGroup = (group: FieldGroup, gi: number) => (
    <div
      key={gi}
      className="grid gap-x-2 gap-y-2 p-1 rounded-md"
      style={{ gridTemplateColumns: `repeat(${group.cols}, minmax(0, 1fr))` }}
    >
      {group.fields.map((fc) => {
        const wrapSpan = (node: React.ReactNode) =>
          fc.colSpan && fc.colSpan > 1
            ? <div key={fc.key} style={{ gridColumn: `span ${fc.colSpan}` }}>{node}</div>
            : node;

        if (fc.type === "input") {
          return wrapSpan(
            <Controller
              key={fc.key}
              name={fc.key}
              control={control}
              render={({ field }) => (
                <EditableInput
                  label={fc.label}
                  value={field.value as string}
                  onChange={field.onChange}
                  onBlur={field.onBlur}
                  placeholder={fc.placeholder ?? "—"}
                  maxLength={fc.maxLength}
                  copyable={fc.copyable}
                  formatDisplay={fc.formatDisplay}
                />
              )}
            />
          );
        }
        if (fc.type === "combobox") {
          return wrapSpan(
            <Controller
              key={fc.key}
              name={fc.key}
              control={control}
              render={({ field }) => (
                <EditableComboboxField
                  label={fc.label}
                  options={getOptions(fc.optionsKey)}
                  value={field.value as string}
                  onChange={field.onChange}
                  placeholder="—"
                  searchPlaceholder={fc.searchPlaceholder}
                  disabled={fc.disabledUnless ? !watch(fc.disabledUnless) : false}
                />
              )}
            />
          );
        }
        if (fc.type === "multiselect") {
          const fieldSuggestions =
            fc.key === "categories" ? categorySuggestions :
            fc.key === "themes" ? themeSuggestions :
            fc.key === "colors" ? colorSuggestions :
            undefined;
          return wrapSpan(
            <Controller
              key={fc.key}
              name={fc.key}
              control={control}
              render={({ field }) => (
                <EditableMultiSelect
                  label={fc.label}
                  options={getOptions(fc.optionsKey)}
                  value={(field.value as string[]) ?? []}
                  onChange={field.onChange}
                  placeholder="—"
                  searchPlaceholder={fc.searchPlaceholder}
                  showColors={fc.showColors}
                  suggestions={fieldSuggestions}
                  isLoadingSuggestions={isSuggestionsLoading}
                  onOpen={triggerSuggestions}
                />
              )}
            />
          );
        }
        if (fc.type === "textarea") {
          const isDescription = fc.key === "description";
          return (
            <div key={fc.key} className="col-span-full flex flex-col gap-0.5 rounded-md border border-muted-foreground/50 bg-transparent px-3 py-1 text-sm hover:border-input hover:bg-muted/50 transition-colors">
              <div className="flex items-center justify-between relative">
                <span className="text-muted-foreground text-xs shrink-0">{fc.label}</span>
                {isDescription && (watchDescription?.trim().length ?? 0) >= 10 && (
                  descriptionResult?.suggestion ? (
                    <button
                      type="button"
                      onClick={() => setDescDialogOpen(true)}
                      className="flex items-center gap-1 px-1.5 -mr-1.5 py-0.5 rounded bg-purple-100 hover:bg-purple-200 dark:bg-purple-900/50 dark:hover:bg-purple-800/50 text-purple-600 dark:text-purple-400 text-xs transition-colors shrink-0"
                      title="View AI suggestion"
                    >
                      <Sparkles className="h-3.5 w-3.5" />
                      <span>{descriptionResult.issues.length}</span>
                    </button>
                  ) : (
                    <Tooltip>
                      <TooltipTrigger asChild>
                        <button
                          type="button"
                          className="shrink-0 absolute top-0.5 -right-1 text-purple-500 hover:text-purple-600 transition-colors p-0.5"
                          onClick={handleValidateDescription}
                          disabled={validatingField === "description"}
                        >
                          {validatingField === "description"
                            ? <Loader2 className="h-4 w-4 animate-spin" />
                            : <Sparkles className="h-4 w-4" />
                          }
                        </button>
                      </TooltipTrigger>
                      <TooltipContent side="top">AI validate description</TooltipContent>
                    </Tooltip>
                  )
                )}
              </div>
              <Textarea {...register(fc.key)} rows={(fc.key === "description" && MODE_LAYOUTS[layoutMode].descriptionRows) || fc.rows || 3} className="border-0 p-0 h-auto shadow-none focus-visible:ring-0 resize-y text-sm min-h-0" />
            </div>
          );
        }
        return null;
      })}
    </div>
  );

  return (
    <Card>
      <CardHeader>
        <div className="flex items-start justify-between">
          <div className="flex-1 min-w-0 flex items-start gap-1">
            <div className="flex-1 min-w-0">
              <Controller
                name="name"
                control={control}
                render={({ field }) => (
                  <EditableInput
                    value={field.value}
                    onChange={field.onChange}
                    onBlur={field.onBlur}
                    placeholder="Product name"
                    className="text-base font-semibold"
                    inputClassName="text-base font-semibold"
                    rightAction={
                      <Tooltip>
                        <TooltipTrigger asChild>
                          <button
                            type="button"
                            className="shrink-0 text-purple-500 hover:text-purple-600 transition-colors"
                            onClick={(e) => { e.stopPropagation(); handleValidateName(); }}
                            disabled={validatingField === "name"}
                          >
                            {validatingField === "name"
                              ? <Loader2 className="h-4 w-4 animate-spin" />
                              : <Sparkles className="h-4 w-4" />
                            }
                          </button>
                        </TooltipTrigger>
                        <TooltipContent side="bottom">AI validate name</TooltipContent>
                      </Tooltip>
                    }
                  />
                )}
              />
              {nameResult?.suggestion && (
                <AiSuggestionBadge
                  suggestion={nameResult.suggestion}
                  issues={nameResult.issues}
                  onAccept={(editedValue) => {
                    setValue("name", editedValue, { shouldDirty: true });
                    clearNameResult();
                  }}
                  onDismiss={clearNameResult}
                  onRevalidate={handleValidateName}
                  isRevalidating={validatingField === "name"}
                  compact
                  className="mt-1"
                />
              )}
            </div>
            <Tooltip>
              <TooltipTrigger asChild>
                <Button
                  variant="outline"
                  size="icon"
                  asChild
                >
                  <a
                    href={`https://backend.acherryontop.com/product/${product.pid}`}
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    <ExternalLink className="h-5 w-5" />
                  </a>
                </Button>
              </TooltipTrigger>
              <TooltipContent side="bottom">View in Backend</TooltipContent>
            </Tooltip>
          </div>
          <div className="flex items-center justify-end mb-3 ml-1">
          <Tooltip>
            <TooltipTrigger asChild>
              <Button variant="outline" size="icon" onClick={onClose}>
                <X className="h-5 w-5" />
              </Button>
            </TooltipTrigger>
            <TooltipContent side="bottom">Hide this product</TooltipContent>
          </Tooltip>
        </div>
        </div>
        <div className="flex flex-wrap gap-2 items-center justify-start">
              <Badge
                variant="secondary"
                className="gap-1 cursor-pointer hover:bg-muted text-xs px-2.5 h-[22px] font-normal"
                onClick={() => {
                  navigator.clipboard.writeText(String(product.pid));
                  toast.success("Copied PID");
                }}
              >
                <span className="text-muted-foreground text-xs">PID</span> {product.pid}
                <Copy className="h-3 w-3 opacity-50" />
              </Badge>
              {(["item_number", "upc", "supplier_no", "notions_no"] as const).map((key) => (
                <Controller
                  key={key}
                  name={key}
                  control={control}
                  render={({ field }) => (
                    <EditableInput
                      label={{ item_number: "Item #", upc: "UPC", supplier_no: "Supplier #", notions_no: "Notions #" }[key]}
                      value={field.value as string}
                      onChange={field.onChange}
                      onBlur={field.onBlur}
                      placeholder="—"
                      copyable
                      alwaysShowCopy
                      className="w-auto border-none py-0 px-2.5 text-xs h-[22px] rounded-full bg-secondary hover:bg-muted"
                      inputClassName="text-xs"
                    />
                  )}
                />
              ))}
            </div>
      </CardHeader>
      <CardContent>
       
        <form onSubmit={handleSubmit(onSubmit)} className="space-y-1">
          {/* Images + sidebar fields */}
          <div className="flex gap-2">
            <div className="shrink-0">
              {layoutMode === "minimal" ? (
                <MiniImagePreview images={productImages} isLoading={isLoadingImages} />
              ) : (
                <ImageManager
                  images={productImages}
                  setImages={setProductImages}
                  isLoading={isLoadingImages}
                  maxRows={MODE_LAYOUTS[layoutMode].imageRows}
                />
              )}
            </div>
            {MODE_LAYOUTS[layoutMode].sidebarGroups > 0 && (
              <div className="flex-1 min-w-0 space-y-1">
                {MODE_LAYOUTS[layoutMode].groups.slice(0, MODE_LAYOUTS[layoutMode].sidebarGroups).map((group, gi) =>
                  renderFieldGroup(group, gi)
                )}
              </div>
            )}
          </div>

          {/* Remaining field groups */}
          {MODE_LAYOUTS[layoutMode].groups.slice(MODE_LAYOUTS[layoutMode].sidebarGroups).map((group, gi) =>
            renderFieldGroup(group, gi + MODE_LAYOUTS[layoutMode].sidebarGroups)
          )}

          {/* AI Description Review Dialog */}
          {descriptionResult?.suggestion && (
            <Dialog open={descDialogOpen} onOpenChange={setDescDialogOpen}>
              <DialogContent className="sm:max-w-4xl max-h-[85vh] overflow-y-auto">
                <DialogHeader>
                  <DialogTitle className="flex items-center gap-2">
                    <Sparkles className="h-4 w-4 text-purple-500" />
                    AI Description Review
                  </DialogTitle>
                </DialogHeader>
                <AiDescriptionCompare
                  currentValue={getValues("description")}
                  onCurrentChange={(v) => setValue("description", v, { shouldDirty: true })}
                  suggestion={descriptionResult.suggestion}
                  issues={descriptionResult.issues}
                  productName={getValues("name")}
                  onAccept={(text) => {
                    setValue("description", text, { shouldDirty: true });
                    clearDescriptionResult();
                    setDescDialogOpen(false);
                  }}
                  onDismiss={() => {
                    clearDescriptionResult();
                    setDescDialogOpen(false);
                  }}
                  onRevalidate={handleValidateDescription}
                  isRevalidating={validatingField === "description"}
                />
              </DialogContent>
            </Dialog>
          )}

          {/* Submit */}
          <div className="flex items-center justify-end gap-3 pt-2">
            <Button
              type="button"
              variant="outline"
              size="sm"
              onClick={() => {
                if (originalValuesRef.current) {
                  reset(originalValuesRef.current);
                }
              }}
            >
              Reset Changes
            </Button>
            <Button
              type="submit"
              disabled={isSubmitting || (changedCount === 0 && !hasImageChanges)}
              size="sm"
            >
              {isSubmitting && (
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
              )}
              Submit{" "}
              {changedCount > 0 || hasImageChanges
                ? `(${changedCount} field${changedCount !== 1 ? "s" : ""}${hasImageChanges ? " + images" : ""})`
                : ""}
            </Button>
          </div>
        </form>
      </CardContent>
    </Card>
  );
}
