import { useState, useEffect, useCallback, useMemo, useRef } from "react";
import { apiFetch } from '@/utils/api';
import axios from "axios";
import { apiClient } from "@/utils/apiClient";
import { toast } from "sonner";
import { Loader2, Sparkles, Save } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Progress } from "@/components/ui/progress";
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
  PaginationEllipsis,
} from "@/components/ui/pagination";
import { ProductSearch } from "@/components/product-editor/ProductSearch";
import {
  BulkEditRow,
  FIELD_OPTIONS,
  AI_FIELDS,
  INITIAL_ROW_STATE,
  getFieldValue,
  getSubmitFieldKey,
  type BulkEditFieldChoice,
  type RowAiState,
} from "@/components/bulk-edit/BulkEditRow";
import { submitProductEdit } from "@/services/productEditor";
import type { SearchProduct, FieldOptions, FieldOption, LineOption, LandingExtra } from "@/components/product-editor/types";

const PER_PAGE = 20;
const PROD_IMG_HOST = "https://sbing.com";

/** Strip all HTML tags for use in plain text contexts */
function stripHtml(html: string): string {
  return html.replace(/<[^>]*>/g, "");
}

export default function BulkEdit() {
  // Product loading state (mirrors ProductEditor)
  const [allProducts, setAllProducts] = useState<SearchProduct[]>([]);
  const [fieldOptions, setFieldOptions] = useState<FieldOptions | null>(null);
  const [isLoadingOptions, setIsLoadingOptions] = useState(true);
  const [isLoadingProducts, setIsLoadingProducts] = useState(false);
  const [page, _setPage] = useState(1);
  const topRef = useRef<HTMLDivElement>(null);
  const setPage = useCallback((v: number | ((p: number) => number)) => {
    _setPage(v);
    setTimeout(() => topRef.current?.scrollIntoView({ behavior: "smooth" }), 0);
  }, []);
  const [activeTab, setActiveTab] = useState("new");
  const [loadedTab, setLoadedTab] = useState<string | null>(null);

  // Line picker state
  const [lineCompany, setLineCompany] = useState<string>("");
  const [lineLine, setLineLine] = useState<string>("");
  const [lineSubline, setLineSubline] = useState<string>("");
  const [lineOptions, setLineOptions] = useState<LineOption[]>([]);
  const [sublineOptions, setSublineOptions] = useState<LineOption[]>([]);
  const [isLoadingLines, setIsLoadingLines] = useState(false);
  const [isLoadingSublines, setIsLoadingSublines] = useState(false);

  // Landing extras state
  const [landingExtras, setLandingExtras] = useState<Record<string, LandingExtra[]>>({});
  const [isLoadingExtras, setIsLoadingExtras] = useState(false);
  const [activeLandingItem, setActiveLandingItem] = useState<string | null>(null);

  // Abort controller
  const abortRef = useRef<AbortController | null>(null);

  // Bulk edit state
  const [selectedField, setSelectedField] = useState<BulkEditFieldChoice>("description");
  const [aiStates, setAiStates] = useState<Map<number, RowAiState>>(new Map());
  const [productImages, setProductImages] = useState<Map<number, string | null>>(new Map());

  // Validation progress
  const [validationProgress, setValidationProgress] = useState<{
    done: number;
    total: number;
  } | null>(null);

  // Save progress
  const [saveProgress, setSaveProgress] = useState<{
    done: number;
    total: number;
  } | null>(null);

  const isAiField = AI_FIELDS.includes(selectedField);

  const totalPages = Math.ceil(allProducts.length / PER_PAGE);
  const pageProducts = useMemo(
    () => allProducts.slice((page - 1) * PER_PAGE, page * PER_PAGE),
    [allProducts, page]
  );

  // Get select options for the current field
  const currentFieldSelectOptions = useMemo((): FieldOption[] | undefined => {
    if (!fieldOptions) return undefined;
    switch (selectedField) {
      case "tax_cat": return fieldOptions.taxCategories;
      case "size_cat": return fieldOptions.sizes;
      case "ship_restrictions": return fieldOptions.shippingRestrictions;
      default: return undefined;
    }
  }, [fieldOptions, selectedField]);

  // Load field options on mount (but don't auto-load products)
  useEffect(() => {
    apiClient
      .get("/api/import/field-options")
      .then((res) => setFieldOptions(res.data))
      .catch((err) => {
        console.error("Failed to load field options:", err);
        toast.error("Failed to load field options");
      })
      .finally(() => setIsLoadingOptions(false));
  }, []);

  // Load lines when company changes
  useEffect(() => {
    setLineLine("");
    setLineSubline("");
    setLineOptions([]);
    setSublineOptions([]);
    if (!lineCompany) return;
    setIsLoadingLines(true);
    apiClient
      .get(`/api/import/product-lines/${lineCompany}`)
      .then((res) => setLineOptions(res.data))
      .catch(() => setLineOptions([]))
      .finally(() => setIsLoadingLines(false));
  }, [lineCompany]);

  // Load sublines when line changes
  useEffect(() => {
    setLineSubline("");
    setSublineOptions([]);
    if (!lineLine) return;
    setIsLoadingSublines(true);
    apiClient
      .get(`/api/import/sublines/${lineLine}`)
      .then((res) => setSublineOptions(res.data))
      .catch(() => setSublineOptions([]))
      .finally(() => setIsLoadingSublines(false));
  }, [lineLine]);

  const loadedPids = useMemo(
    () => new Set(allProducts.map((p) => Number(p.pid))),
    [allProducts]
  );

  // ── Product loading (same patterns as ProductEditor) ──

  const handleSearchSelect = useCallback((product: SearchProduct) => {
    setAllProducts((prev) => {
      if (prev.some((p) => p.pid === product.pid)) return prev;
      return [product, ...prev];
    });
    setPage(1);
  }, []);

  const handleNewSearch = useCallback(() => {
    setAllProducts([]);
    setPage(1);
  }, []);

  const handleLoadAllSearch = useCallback(async (pids: number[]) => {
    const hadExisting = allProducts.length > 0;
    setIsLoadingProducts(true);
    try {
      const res = await apiClient.get("/api/import/search-products", {
        params: { pid: pids.join(",") },
      });
      const fetched = res.data as SearchProduct[];
      setAllProducts((prev) => {
        const existingPids = new Set(prev.map((p) => p.pid));
        const newProducts = fetched.filter((p) => !existingPids.has(p.pid));
        return [...prev, ...newProducts];
      });
      setPage(1);
      if (fetched.length > 1) {
        toast.success(
          hadExisting
            ? `Loaded remaining ${fetched.length} products`
            : "Loaded all products"
        );
      }
    } catch {
      toast.error("Failed to load products");
    } finally {
      setIsLoadingProducts(false);
    }
  }, []);

  const loadFeedProducts = useCallback(async (endpoint: string, label: string) => {
    abortRef.current?.abort();
    const controller = new AbortController();
    abortRef.current = controller;
    setAllProducts([]);
    setIsLoadingProducts(true);
    try {
      const res = await apiClient.get(`/api/import/${endpoint}`, { signal: controller.signal });
      setAllProducts(res.data);
      setPage(1);
      toast.success(`Loaded ${res.data.length} ${label} products`);
    } catch (e) {
      if (!axios.isCancel(e)) toast.error(`Failed to load ${label} products`);
    } finally {
      setIsLoadingProducts(false);
    }
  }, []);

  const loadLandingExtras = useCallback(async (catId: number, tabKey: string) => {
    if (landingExtras[tabKey]) return;
    setIsLoadingExtras(true);
    try {
      const res = await apiClient.get("/api/import/landing-extras", {
        params: { catId, sid: 0 },
      });
      setLandingExtras((prev) => ({ ...prev, [tabKey]: res.data }));
    } catch {
      console.error("Failed to load landing extras");
    } finally {
      setIsLoadingExtras(false);
    }
  }, [landingExtras]);

  const handleLandingClick = useCallback(async (extra: LandingExtra) => {
    abortRef.current?.abort();
    const controller = new AbortController();
    abortRef.current = controller;
    setActiveLandingItem(extra.path);
    setAllProducts([]);
    setIsLoadingProducts(true);
    try {
      const res = await apiClient.get("/api/import/path-products", {
        params: { path: extra.path },
        signal: controller.signal,
      });
      setAllProducts(res.data);
      setPage(1);
      toast.success(`Loaded ${res.data.length} products for ${stripHtml(extra.name)}`);
    } catch (e) {
      if (!axios.isCancel(e)) toast.error("Failed to load products for " + stripHtml(extra.name));
    } finally {
      setIsLoadingProducts(false);
      setActiveLandingItem(null);
    }
  }, []);

  const handleTabChange = useCallback((tab: string) => {
    setActiveTab(tab);
    if (tab === "new" && loadedTab !== "new") {
      setLoadedTab("new");
      loadFeedProducts("new-products", "new");
      loadLandingExtras(-2, "new");
    } else if (tab === "preorder" && loadedTab !== "preorder") {
      setLoadedTab("preorder");
      loadFeedProducts("preorder-products", "pre-order");
      loadLandingExtras(-16, "preorder");
    } else if (tab === "hidden" && loadedTab !== "hidden") {
      setLoadedTab("hidden");
      loadFeedProducts("hidden-new-products", "hidden");
    } else if (tab === "search" || tab === "by-line") {
      abortRef.current?.abort();
      setAllProducts([]);
      setPage(1);
    }
  }, [loadedTab, loadFeedProducts, loadLandingExtras]);

  const loadLineProducts = useCallback(async () => {
    if (!lineCompany || !lineLine) return;
    abortRef.current?.abort();
    const controller = new AbortController();
    abortRef.current = controller;
    setAllProducts([]);
    setIsLoadingProducts(true);
    try {
      const params: Record<string, string> = { company: lineCompany, line: lineLine };
      if (lineSubline) params.subline = lineSubline;
      const res = await apiClient.get("/api/import/line-products", { params, signal: controller.signal });
      setAllProducts(res.data);
      setPage(1);
      toast.success(`Loaded ${res.data.length} products`);
    } catch (e) {
      if (!axios.isCancel(e)) toast.error("Failed to load line products");
    } finally {
      setIsLoadingProducts(false);
    }
  }, [lineCompany, lineLine, lineSubline]);

  // ── Image loading ──

  // Load first image for current page products
  useEffect(() => {
    const pidsNeedingImages = pageProducts
      .filter((p) => !productImages.has(p.pid))
      .map((p) => p.pid);

    if (pidsNeedingImages.length === 0) return;

    pidsNeedingImages.forEach((pid) => {
      apiClient
        .get(`/api/import/product-images/${pid}`)
        .then((res) => {
          const images = res.data;
          let url: string | null = null;
          if (Array.isArray(images) && images.length > 0) {
            // Get smallest size for thumbnail
            const first = images[0];
            const sizes = first.sizes || {};
            const smallKey = Object.keys(sizes).find((k) => k.includes("175") || k.includes("small"));
            const anyKey = Object.keys(sizes)[0];
            const chosen = sizes[smallKey ?? anyKey];
            url = chosen?.url ?? null;
          }
          setProductImages((prev) => new Map(prev).set(pid, url));
        })
        .catch(() => {
          setProductImages((prev) => new Map(prev).set(pid, null));
        });
    });
  }, [pageProducts, productImages]);

  // ── AI Validation ──

  const triggerValidation = useCallback(
    (products: SearchProduct[]) => {
      if (!isAiField) return;

      const total = products.length;
      let done = 0;

      // Mark all as validating
      setAiStates((prev) => {
        const next = new Map(prev);
        products.forEach((p) => {
          const existing = next.get(p.pid) ?? { ...INITIAL_ROW_STATE };
          next.set(p.pid, { ...existing, status: "validating" });
        });
        return next;
      });

      setValidationProgress({ done: 0, total });

      const endpoint =
        selectedField === "name"
          ? "/api/ai/validate/inline/name"
          : "/api/ai/validate/inline/description";

      // Fire all requests at once
      products.forEach(async (product) => {
        const payload: Record<string, unknown> = {};

        if (selectedField === "name") {
          payload.name = product.title;
          payload.company_name = product.brand;
          payload.company_id = product.brand_id;
          payload.line_name = product.line;
          payload.subline_name = product.subline;
          // Gather sibling names from products in same brand + line
          const siblings = allProducts
            .filter(
              (p) =>
                p.pid !== product.pid &&
                p.brand_id === product.brand_id &&
                p.line_id === product.line_id
            )
            .map((p) => p.title)
            .filter(Boolean);
          if (siblings.length > 0) payload.siblingNames = siblings;
        } else {
          payload.name = product.title;
          payload.description = product.description ?? "";
          payload.company_name = product.brand;
          payload.company_id = product.brand_id;
        }

        try {
          const response = await apiFetch(endpoint, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({ product: payload }),
          });

          const result = await response.json();

          setAiStates((prev) => {
            const next = new Map(prev);
            const existing = next.get(product.pid) ?? { ...INITIAL_ROW_STATE };
            next.set(product.pid, {
              ...existing,
              status: "done",
              result: {
                isValid: result.isValid ?? true,
                suggestion: result.suggestion || null,
                issues: result.issues || [],
              },
              editedSuggestion: result.suggestion || null,
            });
            return next;
          });
        } catch (err) {
          console.error(`Validation error for PID ${product.pid}:`, err);
          setAiStates((prev) => {
            const next = new Map(prev);
            const existing = next.get(product.pid) ?? { ...INITIAL_ROW_STATE };
            next.set(product.pid, {
              ...existing,
              status: "done",
              result: { isValid: true, issues: [] },
            });
            return next;
          });
        } finally {
          done++;
          setValidationProgress((prev) =>
            prev ? { ...prev, done } : null
          );
          if (done >= total) {
            // Clear progress after a short delay
            setTimeout(() => setValidationProgress(null), 500);
          }
        }
      });
    },
    [selectedField, isAiField, allProducts]
  );

  const handleValidateAll = useCallback(() => {
    if (!isAiField) return;
    triggerValidation(pageProducts);
  }, [isAiField, pageProducts, triggerValidation]);

  // ── Row actions ──

  const handleAccept = useCallback((pid: number, value: string) => {
    setAiStates((prev) => {
      const next = new Map(prev);
      const existing = next.get(pid) ?? { ...INITIAL_ROW_STATE };
      next.set(pid, {
        ...existing,
        decision: "accepted",
        editedSuggestion: value,
        manualEdit: value,
      });
      return next;
    });
  }, []);

  const handleDismiss = useCallback((pid: number) => {
    setAiStates((prev) => {
      const next = new Map(prev);
      const existing = next.get(pid) ?? { ...INITIAL_ROW_STATE };
      next.set(pid, { ...existing, decision: "dismissed" });
      return next;
    });
  }, []);

  const handleManualEdit = useCallback((pid: number, value: string) => {
    setAiStates((prev) => {
      const next = new Map(prev);
      const existing = next.get(pid) ?? { ...INITIAL_ROW_STATE };
      next.set(pid, { ...existing, manualEdit: value });
      return next;
    });
  }, []);

  const handleEditSuggestion = useCallback((pid: number, value: string) => {
    setAiStates((prev) => {
      const next = new Map(prev);
      const existing = next.get(pid) ?? { ...INITIAL_ROW_STATE };
      next.set(pid, { ...existing, editedSuggestion: value });
      return next;
    });
  }, []);

  // ── Save ──

  const getChangedRows = useCallback((): { pid: number; value: string }[] => {
    const changed: { pid: number; value: string }[] = [];
    for (const product of allProducts) {
      const state = aiStates.get(product.pid);
      if (!state) continue;

      // Accepted AI suggestion
      if (state.decision === "accepted" && state.editedSuggestion != null) {
        if (state.saveStatus !== "saved") {
          changed.push({ pid: product.pid, value: state.editedSuggestion });
        }
        continue;
      }

      // Manual edit (non-AI fields or user-modified field)
      if (state.manualEdit != null) {
        const original = getFieldValue(product, selectedField);
        if (state.manualEdit !== original && state.saveStatus !== "saved") {
          changed.push({ pid: product.pid, value: state.manualEdit });
        }
      }
    }
    return changed;
  }, [allProducts, aiStates, selectedField]);

  const changedCount = useMemo(() => getChangedRows().length, [getChangedRows]);

  const handleSaveAll = useCallback(async () => {
    const rows = getChangedRows();
    if (rows.length === 0) {
      toast.info("No changes to save");
      return;
    }

    const submitKey = getSubmitFieldKey(selectedField);
    let done = 0;
    let successCount = 0;
    let errorCount = 0;

    setSaveProgress({ done: 0, total: rows.length });

    for (const row of rows) {
      // Mark as saving
      setAiStates((prev) => {
        const next = new Map(prev);
        const existing = next.get(row.pid) ?? { ...INITIAL_ROW_STATE };
        next.set(row.pid, { ...existing, saveStatus: "saving", saveError: null });
        return next;
      });

      try {
        const result = await submitProductEdit({
          pid: row.pid,
          changes: { [submitKey]: row.value },
          environment: "prod",
        });

        if (result.success) {
          successCount++;
          setAiStates((prev) => {
            const next = new Map(prev);
            const existing = next.get(row.pid) ?? { ...INITIAL_ROW_STATE };
            next.set(row.pid, { ...existing, saveStatus: "saved" });
            return next;
          });
        } else {
          errorCount++;
          const errorMsg = result.message || "Save failed";
          setAiStates((prev) => {
            const next = new Map(prev);
            const existing = next.get(row.pid) ?? { ...INITIAL_ROW_STATE };
            next.set(row.pid, { ...existing, saveStatus: "error", saveError: errorMsg });
            return next;
          });
        }
      } catch (err) {
        errorCount++;
        const errorMsg = err instanceof Error ? err.message : "Save failed";
        setAiStates((prev) => {
          const next = new Map(prev);
          const existing = next.get(row.pid) ?? { ...INITIAL_ROW_STATE };
          next.set(row.pid, { ...existing, saveStatus: "error", saveError: errorMsg });
          return next;
        });
      }

      done++;
      setSaveProgress({ done, total: rows.length });
    }

    setTimeout(() => setSaveProgress(null), 500);

    if (errorCount === 0) {
      toast.success(`Saved ${successCount} product${successCount === 1 ? "" : "s"}`);
    } else {
      toast.error(`Saved ${successCount}, failed ${errorCount}`);
    }
  }, [getChangedRows, selectedField]);

  // ── Clear AI states when field changes ──

  const handleFieldChange = useCallback((field: BulkEditFieldChoice) => {
    setSelectedField(field);
    setAiStates(new Map());
  }, []);

  // ── Landing extras render ──

  const renderLandingExtras = (tabKey: string) => {
    const extras = landingExtras[tabKey];
    if (!extras || extras.length === 0) return null;

    return (
      <div className="mb-4">
        <div className="flex gap-3 overflow-x-auto pb-2 items-start">
          {extras.map((extra) => (
            <button
              key={extra.extra_id}
              onClick={() => handleLandingClick(extra)}
              disabled={activeLandingItem === extra.path}
              className="flex-shrink-0 group relative w-28 text-left"
            >
              <div className="aspect-square w-full overflow-hidden rounded-lg border bg-card hover:bg-accent transition-colors relative">
                {extra.image && (
                  <img
                    src={extra.image.startsWith("/") ? PROD_IMG_HOST + extra.image : extra.image}
                    alt={stripHtml(extra.name)}
                    className="w-full h-full object-cover group-hover:scale-105 transition-transform"
                    loading="lazy"
                  />
                )}
                {activeLandingItem === extra.path && (
                  <div className="absolute inset-0 flex items-center justify-center bg-background/60">
                    <Loader2 className="h-4 w-4 animate-spin" />
                  </div>
                )}
              </div>
              <div className="pt-1 text-center">
                {(() => {
                  const parts = extra.name.split(/<br\s*\/?>/i).map(stripHtml);
                  return (
                    <div className="text-xs leading-snug">
                      {parts[0] && <span className="font-semibold">{parts[0]}</span>}
                      {parts[1] && <><br /><span className="font-normal">{parts[1]}</span></>}
                    </div>
                  );
                })()}
              </div>
            </button>
          ))}
        </div>
      </div>
    );
  };

  // ── Pagination ──

  const renderPagination = () => {
    if (totalPages <= 1) return null;

    const getPageNumbers = () => {
      const pages: (number | "ellipsis")[] = [];
      if (totalPages <= 7) {
        for (let i = 1; i <= totalPages; i++) pages.push(i);
      } else {
        pages.push(1);
        if (page > 3) pages.push("ellipsis");
        for (let i = Math.max(2, page - 1); i <= Math.min(totalPages - 1, page + 1); i++) {
          pages.push(i);
        }
        if (page < totalPages - 2) pages.push("ellipsis");
        pages.push(totalPages);
      }
      return pages;
    };

    return (
      <Pagination>
        <PaginationContent>
          <PaginationItem>
            <PaginationPrevious
              onClick={() => setPage((p) => Math.max(1, p - 1))}
              className={page === 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}
            />
          </PaginationItem>
          {getPageNumbers().map((p, i) =>
            p === "ellipsis" ? (
              <PaginationItem key={`e${i}`}>
                <PaginationEllipsis />
              </PaginationItem>
            ) : (
              <PaginationItem key={p}>
                <PaginationLink
                  isActive={p === page}
                  onClick={() => setPage(p)}
                  className="cursor-pointer"
                >
                  {p}
                </PaginationLink>
              </PaginationItem>
            )
          )}
          <PaginationItem>
            <PaginationNext
              onClick={() => setPage((p) => Math.min(totalPages, p + 1))}
              className={page === totalPages ? "pointer-events-none opacity-50" : "cursor-pointer"}
            />
          </PaginationItem>
        </PaginationContent>
      </Pagination>
    );
  };

  if (isLoadingOptions) {
    return (
      <div className="flex items-center justify-center h-64">
        <Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
      </div>
    );
  }

  return (
    <div className="container mx-auto py-6 max-w-5xl space-y-6">
      {/* Header */}
      <div className="flex items-center justify-between flex-wrap gap-3">
        <h1 className="text-2xl font-bold">Bulk Edit</h1>

        <div className="flex items-center gap-3">
          <span className="text-sm text-muted-foreground">Field:</span>
          <Select value={selectedField} onValueChange={(v) => handleFieldChange(v as BulkEditFieldChoice)}>
            <SelectTrigger className="w-48">
              <SelectValue />
            </SelectTrigger>
            <SelectContent>
              {FIELD_OPTIONS.map((opt) => (
                <SelectItem key={opt.value} value={opt.value}>
                  <span className="flex items-center gap-1.5">
                    {opt.label}
                    {opt.ai && <Sparkles className="h-3 w-3 text-purple-500" />}
                  </span>
                </SelectItem>
              ))}
            </SelectContent>
          </Select>

          {isAiField && (
            <Button
              onClick={handleValidateAll}
              variant="secondary"
              size="sm"
              disabled={pageProducts.length === 0 || validationProgress !== null}
            >
              <Sparkles className="h-4 w-4 mr-1" />
              Validate Page
            </Button>
          )}

          <Button
            onClick={handleSaveAll}
            size="sm"
            disabled={changedCount === 0 || saveProgress !== null}
          >
            <Save className="h-4 w-4 mr-1" />
            Save{changedCount > 0 ? ` (${changedCount})` : " All"}
          </Button>
        </div>
      </div>

      {/* Product loading tabs */}
      <Tabs value={activeTab} onValueChange={handleTabChange}>
        <TabsList>
          <TabsTrigger value="new">New</TabsTrigger>
          <TabsTrigger value="preorder">Pre-Order</TabsTrigger>
          <TabsTrigger value="hidden">Hidden (New)</TabsTrigger>
          <TabsTrigger value="by-line">By Line</TabsTrigger>
          <TabsTrigger value="search">Search</TabsTrigger>
        </TabsList>

        <TabsContent value="search" className="mt-4">
          <ProductSearch
            onSelect={handleSearchSelect}
            onLoadAll={handleLoadAllSearch}
            onNewSearch={handleNewSearch}
            loadedPids={loadedPids}
          />
        </TabsContent>

        <TabsContent value="new" className="mt-4">
          {isLoadingExtras && !landingExtras["new"] && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground mb-3">
              <Loader2 className="h-4 w-4 animate-spin" />
              Loading featured lines...
            </div>
          )}
          {renderLandingExtras("new")}
          {isLoadingProducts && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <Loader2 className="h-4 w-4 animate-spin" />
              Loading products...
            </div>
          )}
        </TabsContent>

        <TabsContent value="preorder" className="mt-4">
          {isLoadingExtras && !landingExtras["preorder"] && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground mb-3">
              <Loader2 className="h-4 w-4 animate-spin" />
              Loading featured lines...
            </div>
          )}
          {renderLandingExtras("preorder")}
          {isLoadingProducts && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <Loader2 className="h-4 w-4 animate-spin" />
              Loading products...
            </div>
          )}
        </TabsContent>

        <TabsContent value="hidden" className="mt-4">
          {isLoadingProducts && (
            <div className="flex items-center gap-2 text-sm text-muted-foreground">
              <Loader2 className="h-4 w-4 animate-spin" />
              Loading products...
            </div>
          )}
        </TabsContent>

        <TabsContent value="by-line" className="mt-4">
          <div className="flex items-center gap-3">
            <Select value={lineCompany} onValueChange={setLineCompany}>
              <SelectTrigger className="w-52">
                <SelectValue placeholder="Select company..." />
              </SelectTrigger>
              <SelectContent>
                {fieldOptions?.companies.map((c) => (
                  <SelectItem key={c.value} value={c.value}>{c.label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
            <Select value={lineLine} onValueChange={setLineLine} disabled={!lineCompany || isLoadingLines}>
              <SelectTrigger className="w-52">
                <SelectValue placeholder={isLoadingLines ? "Loading..." : "Select line..."} />
              </SelectTrigger>
              <SelectContent>
                {lineOptions.map((l) => (
                  <SelectItem key={l.value} value={l.value}>{l.label}</SelectItem>
                ))}
              </SelectContent>
            </Select>
            {sublineOptions.length > 0 && (
              <Select value={lineSubline} onValueChange={setLineSubline} disabled={isLoadingSublines}>
                <SelectTrigger className="w-52">
                  <SelectValue placeholder={isLoadingSublines ? "Loading..." : "All sublines"} />
                </SelectTrigger>
                <SelectContent>
                  {sublineOptions.map((s) => (
                    <SelectItem key={s.value} value={s.value}>{s.label}</SelectItem>
                  ))}
                </SelectContent>
              </Select>
            )}
            <Button onClick={loadLineProducts} disabled={!lineLine || isLoadingProducts}>
              {isLoadingProducts && <Loader2 className="h-4 w-4 animate-spin mr-2" />}
              Load
            </Button>
          </div>
        </TabsContent>
      </Tabs>

      {/* Progress bars */}
      {validationProgress && (
        <div className="space-y-1">
          <div className="flex justify-between text-xs text-muted-foreground">
            <span>Validating...</span>
            <span>
              {validationProgress.done} / {validationProgress.total}
            </span>
          </div>
          <Progress
            value={(validationProgress.done / validationProgress.total) * 100}
            className="h-1.5"
          />
        </div>
      )}

      {saveProgress && (
        <div className="space-y-1">
          <div className="flex justify-between text-xs text-muted-foreground">
            <span>Saving...</span>
            <span>
              {saveProgress.done} / {saveProgress.total}
            </span>
          </div>
          <Progress
            value={(saveProgress.done / saveProgress.total) * 100}
            className="h-1.5"
          />
        </div>
      )}

      <div ref={topRef} />
      {renderPagination()}

      {/* Product rows */}
      {pageProducts.length > 0 && (
        <div className="space-y-2">
          {pageProducts.map((product) => (
            <BulkEditRow
              key={product.pid}
              product={product}
              field={selectedField}
              state={aiStates.get(product.pid) ?? INITIAL_ROW_STATE}
              imageUrl={productImages.get(product.pid) ?? null}
              selectOptions={currentFieldSelectOptions}
              onAccept={handleAccept}
              onDismiss={handleDismiss}
              onManualEdit={handleManualEdit}
              onEditSuggestion={handleEditSuggestion}
            />
          ))}
        </div>
      )}

      {renderPagination()}
    </div>
  );
}
