"use client";

import * as React from "react";
import { useDropzone } from "react-dropzone";
import {
  Download,
  Upload,
  Upload as UploadIcon,
  Redo2,
  Undo2,
  X,
  ListChecks,
} from "lucide-react";
import { toast } from "sonner";

import {
  DealImportVirtualGrid,
  type DealImportVirtualGridColumn,
} from "@/components/deals/deal-import-virtual-grid";
import { GridIcon } from "@/components/deals/deal-form-helpers";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { Label } from "@/components/ui/label";
import { cn } from "@/lib/utils";
import { downloadBlob } from "@/lib/download-blob";
import { isEditableShortcutTarget } from "@/lib/is-editable-element";
import { useAppDispatch, useAppSelector } from "@/store/hooks";
import {
  clearDealImportGridHistory,
  commitDealImportGridSnapshot,
  redoDealImportGrid,
  replaceDealImportGridSnapshot,
  resetDealImportGridSession,
  selectDealImportGridSession,
  undoDealImportGrid,
} from "@/store/slices/deal-import-grid-slice";
import {
  CUSTOMER_IMPORT_CHUNK_SIZE,
  CUSTOMER_IMPORT_MAX_ROWS,
} from "@/features/customers/api/customer-import-limits";
import { normalizeCustomerImportRow } from "@/features/customers/api/normalize-customer-import-row";
import {
  buildCustomerImportErrorRowsFromGrid,
  downloadCustomerImportErrorExcel,
} from "@/features/customers/api/export-customer-import-errors";
import { fetchCustomersImportSampleClient } from "@/features/customers/api/fetch-customers-import-sample-client";
import {
  getCustomerImportValidationError,
  getCustomerImportValidationErrors,
  type CustomerImportValidationOptions,
} from "@/features/customers/api/validate-customer-import-row";
import { useBulkCreateCustomersMutation } from "@/features/customers/hooks/use-bulk-create-customers-mutation";
import { useGetBrandsQuery } from "@/api/endpoints/brands-api";
import type {
  ExcelParseRequest,
  ExcelParseResponse,
} from "@/workers/excel-import.worker";

const SESSION_KEY = "customer-import";

type GridRow = { isImported?: boolean; error?: string } & Record<string, unknown>;

function yieldToMainThread() {
  return new Promise<void>((resolve) => {
    setTimeout(resolve, 0);
  });
}

function parseApiRowErrorIndex(error: string): number | null {
  const match = /^Row (\d+):/.exec(error.trim());
  if (!match) return null;
  const rowNum = parseInt(match[1], 10);
  return Number.isFinite(rowNum) ? rowNum - 1 : null;
}

function stripApiRowErrorPrefix(error: string): string {
  return error.replace(/^Row \d+:\s*/, "").trim();
}

export type CustomerImportDialogProps = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onSuccess?: () => void;
};

export function CustomerImportDialog({
  open,
  onOpenChange,
  onSuccess,
}: CustomerImportDialogProps) {
  const dispatch = useAppDispatch();
  const importSession = useAppSelector((state) =>
    selectDealImportGridSession(state, SESSION_KEY),
  );
  const bulkCreateCustomers = useBulkCreateCustomersMutation();
  const {
    data: brands = [],
    isLoading: brandsLoading,
    isFetching: brandsFetching,
  } = useGetBrandsQuery(undefined, { skip: !open });

  const excelWorkerRef = React.useRef<Worker | null>(null);
  const pendingParseRef = React.useRef<{
    resolve: (result: { headers: string[]; rows: Record<string, string>[] }) => void;
    reject: (err: Error) => void;
  } | null>(null);
  const importFileInputRef = React.useRef<HTMLInputElement>(null);

  const [isParsingFile, setIsParsingFile] = React.useState(false);
  const [sampleDownloading, setSampleDownloading] = React.useState(false);
  const [importedFileName, setImportedFileName] = React.useState<string | null>(null);
  const [skipDuplicates, setSkipDuplicates] = React.useState(false);
  const [importProgress, setImportProgress] = React.useState<{
    processed: number;
    total: number;
  } | null>(null);
  const [bulkImportActive, setBulkImportActive] = React.useState(false);
  const [selectedPosition, setSelectedPosition] = React.useState<{
    rowIdx: number;
    colIdx: number;
  } | null>(null);

  const gridHeaders = importSession.present.headers;
  const gridRows = importSession.present.rows as GridRow[];
  const gridReady = importSession.present.gridReady;
  const canUndo = importSession.past.length > 0;
  const canRedo = importSession.future.length > 0;

  const importUiLocked =
    bulkCreateCustomers.isPending ||
    importProgress != null ||
    bulkImportActive ||
    isParsingFile;

  const gridRowsRef = React.useRef(gridRows);
  React.useEffect(() => {
    gridRowsRef.current = gridRows;
  }, [gridRows]);

  function getExcelWorker(): Worker {
    if (!excelWorkerRef.current) {
      excelWorkerRef.current = new Worker(
        new URL("@/workers/excel-import.worker.ts", import.meta.url),
        { type: "module" },
      );

      excelWorkerRef.current.onmessage = (
        event: MessageEvent<ExcelParseResponse>,
      ) => {
        const msg = event.data;
        const pending = pendingParseRef.current;
        if (!pending) return;

        if (msg.type === "PARSE_SUCCESS") {
          pending.resolve({ headers: msg.headers, rows: msg.rows });
        } else if (msg.type === "PARSE_ERROR") {
          pending.reject(new Error(msg.message));
        }

        pendingParseRef.current = null;
        setIsParsingFile(false);
      };

      excelWorkerRef.current.onerror = (err) => {
        const pending = pendingParseRef.current;
        if (pending) {
          pending.reject(
            new Error("Excel worker failed: " + (err?.message || String(err))),
          );
          pendingParseRef.current = null;
        }
        setIsParsingFile(false);
      };
    }
    return excelWorkerRef.current;
  }

  React.useEffect(() => {
    return () => {
      if (excelWorkerRef.current) {
        excelWorkerRef.current.terminate();
        excelWorkerRef.current = null;
      }
      pendingParseRef.current = null;
    };
  }, []);

  React.useEffect(() => {
    if (!open) return;
    return () => {
      dispatch(resetDealImportGridSession({ sessionKey: SESSION_KEY }));
    };
  }, [dispatch, open]);

  const replaceGridSnapshot = React.useCallback(
    (snapshot: { headers: string[]; rows: GridRow[]; gridReady: boolean }) => {
      dispatch(
        replaceDealImportGridSnapshot({
          sessionKey: SESSION_KEY,
          snapshot,
        }),
      );
    },
    [dispatch],
  );

  const commitGridSnapshot = React.useCallback(
    (snapshot: { headers: string[]; rows: GridRow[]; gridReady: boolean }) => {
      dispatch(
        commitDealImportGridSnapshot({
          sessionKey: SESSION_KEY,
          snapshot,
        }),
      );
    },
    [dispatch],
  );

  const buildCurrentGridSnapshot = React.useCallback(
    (rows: GridRow[]) => ({
      headers: gridHeaders,
      rows,
      gridReady,
    }),
    [gridHeaders, gridReady],
  );

  const customerImportValidationReady = !brandsLoading && !brandsFetching;

  const customerImportValidationOptions =
    React.useMemo((): CustomerImportValidationOptions => {
      const validBrandLabels = new Set<string>();
      for (const brand of brands) {
        const name = String(brand.name ?? "").trim();
        if (name) validBrandLabels.add(name.toLowerCase());
      }
      return { validBrandLabels };
    }, [brands]);

  const getGridRowCheckpointError = React.useCallback(
    (row: GridRow): string | null => {
      if (row.isImported) return null;

      if (!customerImportValidationReady) {
        return "Waiting for brand validation";
      }

      const { isImported, error, ...rest } = row;
      const clientError = getCustomerImportValidationError(
        rest as Record<string, unknown>,
        customerImportValidationOptions,
      );
      if (clientError) return clientError;
      return typeof error === "string" && error.trim() ? error : null;
    },
    [customerImportValidationOptions, customerImportValidationReady],
  );

  const errorReviewRowCount = React.useMemo(
    () =>
      gridRows.filter((row) => !row.isImported && getGridRowCheckpointError(row))
        .length,
    [getGridRowCheckpointError, gridRows],
  );

  const allRowsImported =
    gridRows.length > 0 && gridRows.every((row) => row.isImported);

  const buildColumns = React.useCallback(
    (headers: string[]): DealImportVirtualGridColumn<GridRow>[] => [
      {
        key: "__rowNum__",
        name: "#",
        width: 48,
        frozen: true,
        renderHeaderCell: () => (
          <div className="flex h-full w-full items-center justify-center font-bold text-[11px]">
            #
          </div>
        ),
        renderCell: ({ rowIdx, row }) => (
          <div className="relative flex h-full flex-col items-center justify-center">
            <span
              style={{
                fontSize: 11,
                color: row.isImported ? "#10b981" : "#9ca3af",
                fontWeight: row.isImported ? "bold" : "normal",
              }}
            >
              {rowIdx + 1}
            </span>
            {row.isImported && (
              <div className="absolute -top-1 -right-1 h-2 w-2 rounded-full border border-white bg-emerald-500" />
            )}
          </div>
        ),
      },
      ...headers.map((h) => ({
        key: h,
        name: h,
        width: 160,
        minWidth: 120,
        editable: true,
        renderCell: ({ row }: { row: GridRow }) => {
          const val = row[h];
          const displayVal = val != null ? String(val) : "";
          return (
            <div className="flex h-full items-center truncate px-2">{displayVal}</div>
          );
        },
      })),
      {
        key: "__status__",
        name: "Status",
        width: 240,
        renderCell: ({ row, globalRowIdx }) => {
          const checkpointError = getGridRowCheckpointError(row);
          const rowHeader =
            row["Full Name"] ||
            row.fullName ||
            row["Company Name"] ||
            row.companyName ||
            row.Email ||
            row.email ||
            `Row ${globalRowIdx + 1}`;
          const statusText = row.isImported
            ? "Imported"
            : checkpointError
              ? `[${rowHeader}] ${checkpointError}`
              : "Ready to import";
          const statusClass = row.isImported
            ? "text-emerald-600"
            : checkpointError
              ? "text-red-600"
              : "text-gray-500";
          return (
            <div
              className={cn(
                "flex h-full w-full cursor-help items-center truncate px-1 text-[12px] font-medium",
                statusClass,
              )}
              title={statusText}
            >
              {!row.isImported && checkpointError && (
                <span className="mr-1.5 shrink-0">⚠</span>
              )}
              <span className="truncate">{statusText}</span>
            </div>
          );
        },
      },
    ],
    [getGridRowCheckpointError],
  );

  const finalColumns = React.useMemo(
    () => (gridReady ? buildColumns(gridHeaders) : []),
    [buildColumns, gridHeaders, gridReady],
  );

  const parseFileToGrid = async (file: File) => {
    if (isParsingFile) return;
    setIsParsingFile(true);

    try {
      const buf = await file.arrayBuffer();
      const worker = getExcelWorker();

      const result = await new Promise<{
        headers: string[];
        rows: Record<string, string>[];
      }>((resolve, reject) => {
        pendingParseRef.current = { resolve, reject };
        const request: ExcelParseRequest = { type: "PARSE_EXCEL", buffer: buf };
        worker.postMessage(request, [buf]);
      });

      if (result.rows.length > CUSTOMER_IMPORT_MAX_ROWS) {
        toast.error(
          `This file has ${result.rows.length.toLocaleString()} rows. Maximum is ${CUSTOMER_IMPORT_MAX_ROWS.toLocaleString()} per import.`,
        );
        return;
      }

      const gridRowsParsed: GridRow[] = result.rows.map((r) => ({ ...r }));

      replaceGridSnapshot({
        headers: result.headers,
        rows: gridRowsParsed,
        gridReady: true,
      });
      dispatch(clearDealImportGridHistory({ sessionKey: SESSION_KEY }));
      setImportedFileName(file.name);
    } catch (err: unknown) {
      console.error("Excel parse failed", err);
      toast.error(err instanceof Error ? err.message : "Failed to parse Excel file");
    } finally {
      setIsParsingFile(false);
    }
  };

  const handleGridFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;
    await parseFileToGrid(file);
    if (importFileInputRef.current) importFileInputRef.current.value = "";
  };

  const downloadSampleExcel = async (rows = 10) => {
    setSampleDownloading(true);
    try {
      const { blob, filename } = await fetchCustomersImportSampleClient(rows);
      downloadBlob(blob, filename);
    } catch (err) {
      toast.error(
        err instanceof Error ? err.message : "Failed to download sample",
      );
    } finally {
      setSampleDownloading(false);
    }
  };

  const handleDownloadErrorReport = async () => {
    try {
      const errorRows = buildCustomerImportErrorRowsFromGrid({
        rows: gridRows,
        getErrorMessage: (row) => getGridRowCheckpointError(row as GridRow),
      });

      if (!errorRows.length) {
        toast.error("No customer errors to export");
        return;
      }

      const toastId = toast.loading("Preparing error report…");
      await downloadCustomerImportErrorExcel({
        headers: gridHeaders,
        rows: errorRows,
        sourceFileName: importedFileName ?? undefined,
      });
      toast.success(
        `Downloaded error report for ${errorRows.length} row${errorRows.length === 1 ? "" : "s"}`,
        { id: toastId },
      );
    } catch (err) {
      toast.error(
        err instanceof Error ? err.message : "Could not download error report",
      );
    }
  };

  const handleBulkImport = async () => {
    const unimportedRows = gridRows
      .map((row, index) => ({ ...row, originalIdx: index }))
      .filter((row) => !row.isImported);

    if (!unimportedRows.length) {
      toast.error("No customers left to import");
      return;
    }

    if (gridRows.length > CUSTOMER_IMPORT_MAX_ROWS) {
      toast.error(
        `Cannot import more than ${CUSTOMER_IMPORT_MAX_ROWS.toLocaleString()} rows at once`,
      );
      return;
    }

    const nextRows = [...gridRows];
    const preflightInvalidRows: Array<{
      row: GridRow;
      originalIdx: number;
      errors: string[];
      rowNumber: number;
    }> = [];

    for (let rowIndex = 0; rowIndex < unimportedRows.length; rowIndex += 1) {
      const row = unimportedRows[rowIndex] as GridRow & { originalIdx: number };
      if (rowIndex > 0 && rowIndex % 64 === 0) {
        await yieldToMainThread();
      }

      const { isImported, originalIdx, error, ...rest } = row;
      const validationErrors = getCustomerImportValidationErrors(
        rest as Record<string, unknown>,
        customerImportValidationOptions,
      );

      if (validationErrors.length > 0) {
        nextRows[originalIdx] = {
          ...nextRows[originalIdx],
          error: validationErrors.join("; "),
        };
        preflightInvalidRows.push({
          row: nextRows[originalIdx],
          originalIdx,
          errors: validationErrors,
          rowNumber: originalIdx + 1,
        });
        continue;
      }

      nextRows[originalIdx] = {
        ...nextRows[originalIdx],
        error: undefined,
      };
    }

    if (preflightInvalidRows.length > 0) {
      commitGridSnapshot(buildCurrentGridSnapshot([...nextRows]));
      try {
        await downloadCustomerImportErrorExcel({
          headers: gridHeaders,
          rows: preflightInvalidRows.map(({ row, errors, rowNumber }) => ({
            row,
            errors,
            rowNumber,
          })),
          sourceFileName: importedFileName ?? undefined,
        });
      } catch (err) {
        console.error("Failed to auto-download import error report", err);
      }
      toast.error(
        `${preflightInvalidRows.length} row${preflightInvalidRows.length === 1 ? "" : "s"} have missing or invalid required fields. No customers were imported. An error report was downloaded.`,
      );
      return;
    }

    setBulkImportActive(true);
    const totalUnimported = unimportedRows.length;
    setImportProgress({ processed: 0, total: totalUnimported });
    dispatch(clearDealImportGridHistory({ sessionKey: SESSION_KEY }));

    let successfulCount = 0;
    let failedCount = 0;
    let skippedCount = 0;
    let processedCount = 0;

    try {
      for (let i = 0; i < unimportedRows.length; i += CUSTOMER_IMPORT_CHUNK_SIZE) {
        const chunk = unimportedRows.slice(i, i + CUSTOMER_IMPORT_CHUNK_SIZE);
        const validChunkRows = chunk.map((row) => {
          const { isImported, originalIdx, error, ...rest } = row;
          return normalizeCustomerImportRow(rest as Record<string, unknown>);
        });

        setImportProgress((prev) =>
          prev ? { ...prev, processed: processedCount } : null,
        );

        try {
          const result = await bulkCreateCustomers.mutateAsync({
            customers: validChunkRows,
            skipDuplicates,
          });

          const chunkErrorsByIndex = new Map<number, string>();
          for (const errMsg of result.errors ?? []) {
            const idx = parseApiRowErrorIndex(errMsg);
            if (idx == null || idx < 0 || idx >= chunk.length) continue;
            chunkErrorsByIndex.set(idx, stripApiRowErrorPrefix(errMsg));
          }

          chunk.forEach((row, rowIndex) => {
            const apiError = chunkErrorsByIndex.get(rowIndex);
            if (apiError) {
              const isSkipped = apiError.toLowerCase().startsWith("skipped");
              if (isSkipped) {
                skippedCount += 1;
              } else {
                failedCount += 1;
              }
              nextRows[row.originalIdx] = {
                ...nextRows[row.originalIdx],
                error: apiError,
              };
              return;
            }

            successfulCount += 1;
            nextRows[row.originalIdx] = {
              ...nextRows[row.originalIdx],
              isImported: true,
              error: undefined,
            };
          });

          processedCount = successfulCount + failedCount + skippedCount;
          commitGridSnapshot(buildCurrentGridSnapshot([...nextRows]));
          setImportProgress((prev) =>
            prev ? { ...prev, processed: processedCount } : null,
          );
        } catch (err: unknown) {
          const msg = err instanceof Error ? err.message : "Batch import failed";
          toast.error(msg);

          chunk.forEach((row) => {
            nextRows[row.originalIdx] = {
              ...nextRows[row.originalIdx],
              error: msg,
            };
          });
          failedCount += chunk.length;
          processedCount = successfulCount + failedCount + skippedCount;
          commitGridSnapshot(buildCurrentGridSnapshot([...nextRows]));
          setImportProgress((prev) =>
            prev ? { ...prev, processed: processedCount } : null,
          );
          break;
        }
      }

      setImportProgress(null);

      if (successfulCount > 0) {
        toast.success(
          `Imported ${successfulCount} customer${successfulCount === 1 ? "" : "s"}${skippedCount > 0 ? `; ${skippedCount} skipped` : ""}${failedCount > 0 ? `; ${failedCount} failed` : ""}`,
        );
        onSuccess?.();
      } else if (skippedCount > 0 && failedCount === 0) {
        toast.warning(`${skippedCount} row${skippedCount === 1 ? "" : "s"} skipped (duplicates)`);
      } else if (failedCount > 0) {
        toast.error(
          `Import failed for ${failedCount} row${failedCount === 1 ? "" : "s"}`,
        );
      }
    } finally {
      setBulkImportActive(false);
    }
  };

  const { getRootProps, getInputProps, isDragActive } = useDropzone({
    disabled: importUiLocked,
    accept: {
      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": [
        ".xlsx",
      ],
      "application/vnd.ms-excel": [".xls"],
    },
    maxFiles: 1,
    onDrop: async (acceptedFiles) => {
      const file = acceptedFiles[0];
      if (file) await parseFileToGrid(file);
    },
    onDropRejected: () => {
      toast.error("Please upload an Excel file (.xlsx or .xls)");
    },
  });

  React.useEffect(() => {
    if (!gridReady || !open) return;

    const handleKeyDown = (event: KeyboardEvent) => {
      if (importUiLocked) return;
      if (isEditableShortcutTarget(event.target)) return;

      const isModifierPressed = event.ctrlKey || event.metaKey;
      if (!isModifierPressed || event.altKey) return;

      const key = event.key.toLowerCase();
      const shouldRedo = key === "y" || (key === "z" && event.shiftKey);
      const shouldUndo = key === "z" && !event.shiftKey;

      if (shouldUndo && canUndo) {
        event.preventDefault();
        dispatch(undoDealImportGrid({ sessionKey: SESSION_KEY }));
        return;
      }

      if (shouldRedo && canRedo) {
        event.preventDefault();
        dispatch(redoDealImportGrid({ sessionKey: SESSION_KEY }));
      }
    };

    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [canRedo, canUndo, dispatch, gridReady, importUiLocked, open]);

  const handleOpenChange = (nextOpen: boolean) => {
    if (!nextOpen && importUiLocked) return;
    if (!nextOpen) {
      dispatch(resetDealImportGridSession({ sessionKey: SESSION_KEY }));
      setImportedFileName(null);
      setImportProgress(null);
    }
    onOpenChange(nextOpen);
  };

  return (
    <Dialog open={open} onOpenChange={handleOpenChange}>
      <DialogContent
        className="sm:max-w-[1120px] w-full h-full sm:h-[95vh] sm:max-h-[95vh] p-0 overflow-hidden bg-white rounded-none sm:rounded-3xl shadow-2xl flex flex-col border-none"
        showCloseButton={!importUiLocked}
        onPointerDownOutside={(e) => {
          if (importUiLocked) e.preventDefault();
        }}
        onInteractOutside={(e) => {
          if (importUiLocked) e.preventDefault();
        }}
        onEscapeKeyDown={(e) => {
          if (importUiLocked) e.preventDefault();
        }}
      >
        <DialogHeader className="shrink-0 border-b border-gray-100 px-5 py-4 md:px-7">
          <DialogTitle className="text-[18px] font-extrabold font-['Lexend']">
            Import customers
          </DialogTitle>
          <p className="text-[12px] text-gray-500 font-medium mt-1">
            Upload an Excel file, review and edit rows in the grid, then import.
            At least one of{" "}
            <span className="font-semibold text-gray-700">Full Name</span>,{" "}
            <span className="font-semibold text-gray-700">Company Name</span>, or{" "}
            <span className="font-semibold text-gray-700">Email</span> is required
            per row, and <span className="font-semibold text-gray-700">Brand</span>{" "}
            is required. Maximum {CUSTOMER_IMPORT_MAX_ROWS} rows per file.
          </p>
        </DialogHeader>

        <div className="flex flex-1 min-h-0 flex-col">
          <input
            ref={importFileInputRef}
            type="file"
            accept=".xlsx,.xls"
            className="hidden"
            onChange={handleGridFileChange}
          />

          <div className="shrink-0 border-b border-gray-100 px-5 py-3 md:px-7">
            <div className="flex flex-col gap-3 xl:flex-row xl:items-center xl:justify-between">
              <div className="flex min-w-0 flex-wrap items-center gap-2">
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  onClick={() => void downloadSampleExcel(10)}
                  disabled={sampleDownloading || importUiLocked}
                  className="h-8 gap-2 rounded-xl border-gray-200 text-[11px] md:h-9 md:text-[12px]"
                >
                  <Download size={14} />
                  {sampleDownloading ? "Downloading…" : "Sample (10 rows)"}
                </Button>
                <Button
                  type="button"
                  variant="outline"
                  size="sm"
                  onClick={() => importFileInputRef.current?.click()}
                  disabled={importUiLocked}
                  className="h-8 gap-2 rounded-xl border-dashed border-[#6C63FF] text-[11px] text-[#6C63FF] hover:bg-[#6C63FF]/5 md:h-9 md:text-[12px]"
                >
                  <Upload size={14} />
                  {gridReady ? "Replace file" : "Upload file"}
                </Button>
                {gridReady && (
                  <>
                    <Button
                      type="button"
                      variant="ghost"
                      size="sm"
                      onClick={() =>
                        dispatch(undoDealImportGrid({ sessionKey: SESSION_KEY }))
                      }
                      disabled={importUiLocked || !canUndo}
                      className="h-8 gap-1.5 rounded-xl text-[11px] md:h-9 md:text-[12px]"
                    >
                      <Undo2 size={14} /> Undo
                    </Button>
                    <Button
                      type="button"
                      variant="ghost"
                      size="sm"
                      onClick={() =>
                        dispatch(redoDealImportGrid({ sessionKey: SESSION_KEY }))
                      }
                      disabled={importUiLocked || !canRedo}
                      className="h-8 gap-1.5 rounded-xl text-[11px] md:h-9 md:text-[12px]"
                    >
                      <Redo2 size={14} /> Redo
                    </Button>
                    <Button
                      type="button"
                      variant="ghost"
                      size="sm"
                      onClick={() => {
                        replaceGridSnapshot({
                          headers: [],
                          rows: [],
                          gridReady: false,
                        });
                        setImportedFileName(null);
                      }}
                      disabled={importUiLocked}
                      className="h-8 gap-1.5 rounded-xl text-[11px] text-red-500 hover:bg-red-50 md:h-9 md:text-[12px]"
                    >
                      <X size={14} /> Clear
                    </Button>
                  </>
                )}
              </div>

              <div className="flex flex-wrap items-center gap-3">
                <div className="flex items-center gap-2">
                  <Checkbox
                    id="skip-duplicates"
                    checked={skipDuplicates}
                    onCheckedChange={(checked) =>
                      setSkipDuplicates(checked === true)
                    }
                    disabled={importUiLocked}
                  />
                  <Label
                    htmlFor="skip-duplicates"
                    className="text-[12px] font-medium text-gray-600 cursor-pointer"
                  >
                    Skip duplicates (email + brand)
                  </Label>
                </div>
                <Button
                  type="button"
                  size="sm"
                  onClick={() => void handleBulkImport()}
                  disabled={
                    importUiLocked ||
                    !gridRows.length ||
                    !customerImportValidationReady ||
                    allRowsImported
                  }
                  className={cn(
                    "gap-2 rounded-xl font-bold text-[12px] h-9 px-5 shadow-sm",
                    allRowsImported
                      ? "bg-emerald-50 text-emerald-600 border border-emerald-100 shadow-none cursor-default"
                      : "bg-[#6C63FF] hover:bg-[#5a52e0] text-white shadow-[#6C63FF]/20",
                  )}
                >
                  {allRowsImported ? (
                    <>
                      <ListChecks size={16} /> All imported
                    </>
                  ) : (
                    <>
                      <Upload size={16} />
                      {importUiLocked
                        ? "Importing…"
                        : `Import ${gridRows.filter((r) => !r.isImported).length} customers`}
                    </>
                  )}
                </Button>
              </div>
            </div>
          </div>

          <div className="flex-1 min-h-0 overflow-hidden flex flex-col">
            {!gridReady ? (
              <div
                {...getRootProps()}
                className="flex flex-col items-center justify-center h-full gap-4 text-center px-8 py-12 cursor-pointer border-2 border-dashed border-gray-300 rounded-xl m-4 hover:border-[#6C63FF] hover:bg-[#6C63FF]/5 transition-colors"
              >
                <input {...getInputProps()} />
                <div className="w-16 h-16 rounded-2xl bg-[#6C63FF]/10 flex items-center justify-center">
                  {isDragActive ? (
                    <UploadIcon size={24} className="text-[#6C63FF]" />
                  ) : (
                    <GridIcon />
                  )}
                </div>
                <div>
                  <p className="text-[14px] font-bold text-gray-800 mb-1">
                    {isDragActive
                      ? "Drop Excel file here"
                      : isParsingFile
                        ? "Parsing Excel…"
                        : "No data loaded"}
                  </p>
                  <p className="text-[12px] text-gray-500 max-w-sm">
                    {isDragActive
                      ? "Release to upload the file"
                      : isParsingFile
                        ? "Reading spreadsheet. Please wait."
                        : "Drag & drop an .xlsx file here, or click to browse. Download a sample template to get started."}
                  </p>
                </div>
                <Button
                  type="button"
                  size="sm"
                  onClick={(e) => {
                    e.stopPropagation();
                    importFileInputRef.current?.click();
                  }}
                  disabled={importUiLocked}
                  className="gap-2 rounded-xl bg-[#6C63FF] hover:bg-[#5a52e0] text-white font-semibold text-[12px] h-9 px-5"
                >
                  <UploadIcon size={14} /> Browse files
                </Button>
              </div>
            ) : (
              <div className="h-full flex flex-col min-h-0">
                <div className="px-5 md:px-7 py-3 bg-gray-50/50 border-b border-gray-100 shrink-0">
                  <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
                    <div className="flex min-w-0 flex-col gap-0.5">
                      <h4 className="flex min-w-0 items-baseline gap-1 text-[13px] font-bold text-gray-800">
                        <span className="shrink-0">Review data</span>
                        {importedFileName ? (
                          <span
                            className="min-w-0 truncate font-medium text-gray-500"
                            title={importedFileName}
                          >
                            · {importedFileName}
                          </span>
                        ) : null}
                      </h4>
                      <div className="flex flex-col">
                        <p className="text-[11px] text-gray-500 font-medium">
                          Double-click any cell to edit.
                        </p>
                        {(() => {
                          const errorRows = gridRows.filter(
                            (row) =>
                              !row.isImported && getGridRowCheckpointError(row),
                          );
                          const count = errorRows.length;
                          if (count === 0) return null;
                          const firstMsg = getGridRowCheckpointError(errorRows[0]);
                          return (
                            <p className="text-[11px] text-red-600 font-bold mt-0.5 flex items-center gap-1">
                              <span className="shrink-0">⚠</span>
                              <span className="truncate max-w-[400px]">
                                {count} row{count > 1 ? "s" : ""} need
                                {count === 1 ? "s" : ""} review: {firstMsg}
                              </span>
                            </p>
                          );
                        })()}
                      </div>
                    </div>
                    {errorReviewRowCount > 0 ? (
                      <Button
                        type="button"
                        size="sm"
                        variant="outline"
                        onClick={() => void handleDownloadErrorReport()}
                        disabled={importUiLocked}
                        className="gap-2 rounded-xl border-amber-200 bg-amber-50 text-amber-900 hover:bg-amber-100 text-[12px] h-9 px-4 shrink-0"
                        title="Download one Excel file listing each row and its errors"
                      >
                        <Download size={14} />
                        Download errors ({errorReviewRowCount})
                      </Button>
                    ) : null}
                  </div>
                </div>

                <div className="relative flex min-h-0 flex-1 flex-col overflow-hidden">
                  {importUiLocked && (
                    <div className="absolute inset-0 bg-white/70 backdrop-blur-[2px] z-[100] flex flex-col items-center justify-center gap-4 text-center">
                      <div className="relative">
                        <div className="w-16 h-16 rounded-full border-4 border-[#6C63FF]/10 border-t-[#6C63FF] animate-spin" />
                        <div className="absolute inset-0 flex items-center justify-center">
                          <Upload className="text-[#6C63FF] animate-bounce" size={20} />
                        </div>
                      </div>
                      <div className="space-y-1">
                        <p className="text-[16px] font-extrabold text-gray-900 tracking-tight">
                          Importing customers…
                        </p>
                        {importProgress ? (
                          <p className="text-[12px] text-gray-500 font-medium">
                            Processing {importProgress.processed} of{" "}
                            {importProgress.total} customers. Please wait.
                          </p>
                        ) : (
                          <p className="text-[12px] text-gray-500 font-medium">
                            Wait a moment while we process your request.
                          </p>
                        )}
                      </div>
                      {importProgress && (
                        <div className="w-48 h-1.5 bg-gray-100 rounded-full overflow-hidden">
                          <div
                            className="h-full bg-[#6C63FF] transition-all duration-300"
                            style={{
                              width: `${Math.min(100, (importProgress.processed / importProgress.total) * 100)}%`,
                            }}
                          />
                        </div>
                      )}
                    </div>
                  )}

                  <DealImportVirtualGrid
                    columns={finalColumns}
                    rows={gridRows}
                    locked={importUiLocked}
                    selectedPosition={selectedPosition}
                    onSelectedCellChange={setSelectedPosition}
                    onRowsChange={(rows) => {
                      commitGridSnapshot(
                        buildCurrentGridSnapshot(rows as GridRow[]),
                      );
                    }}
                    getRowClassName={(row) =>
                      row.isImported
                        ? "bg-emerald-50/40"
                        : getGridRowCheckpointError(row)
                          ? "bg-red-50"
                          : ""
                    }
                    isRowEditable={(row) => !row.isImported}
                  />
                </div>
              </div>
            )}
          </div>

          {gridReady ? (
            <div className="shrink-0 border-t border-gray-100 bg-gray-50 px-5 py-3 md:px-7 flex flex-col md:flex-row items-center justify-between gap-4">
              <div className="flex flex-wrap items-center justify-center md:justify-start gap-x-4 gap-y-2 text-[11px] text-gray-500">
                <span>
                  Total:{" "}
                  <span className="font-bold text-gray-800">
                    {gridRows.length}
                  </span>{" "}
                  customers
                </span>
                <span className="text-gray-300">|</span>
                <span>
                  Imported:{" "}
                  <span className="font-bold text-emerald-600">
                    {gridRows.filter((row) => row.isImported).length}
                  </span>
                </span>
                <span className="text-gray-300">|</span>
                <span>
                  Remaining:{" "}
                  <span className="font-bold text-amber-600">
                    {gridRows.filter((row) => !row.isImported).length}
                  </span>
                </span>
                <span className="text-gray-300">|</span>
                <span>
                  Needs review:{" "}
                  <span className="font-bold text-red-600">
                    {
                      gridRows.filter((row) =>
                        Boolean(getGridRowCheckpointError(row)),
                      ).length
                    }
                  </span>
                </span>
              </div>
              <div className="text-[11px] text-gray-400 font-medium whitespace-nowrap">
                Up to {CUSTOMER_IMPORT_MAX_ROWS.toLocaleString()} rows per file ·
                Click cell to edit · Ctrl+Z undo · Ctrl+Y redo
              </div>
            </div>
          ) : null}
        </div>
      </DialogContent>
    </Dialog>
  );
}
