import { useMutation, useQuery } from "@tanstack/react-query";
import {
  AlertCircle,
  CheckCircle2,
  Download,
  FileText,
  Loader2,
  Upload,
} from "lucide-react";
import * as React from "react";
import { Button } from "../../../components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "../../../components/ui/dialog";
import { DropdownMenuItem } from "../../../components/ui/dropdown-menu";
import { ScrollArea } from "../../../components/ui/scroll-area";
import {
  type BulkUserItem,
  type BulkUserResult,
  bulkCreateUsers,
  createTenant,
  fetchAllTenants,
  fetchUsers,
} from "../../../lib/adminApi";
import { t } from "../../../lib/i18n";
import {
  buildTenantImportPreview,
  type TenantCSVRow,
  type TenantImportPreviewRow,
} from "../../tenants/utils/tenantCsvImport";
import { isHanmacFamilyTenant, isHanmacFamilyUser } from "../orgChartPicker";
import { parseUserCSV } from "../utils/csvParser";
import { applyGeneralPlanningOfficePriority } from "../utils/generalPlanningOfficePriority";
import {
  buildHanmacImportEmailPreview,
  type HanmacImportEmailPreview,
} from "../utils/hanmacImportEmail";

interface UserBulkUploadModalProps {
  onSuccess?: () => void;
  variant?: "button" | "dropdown" | "custom";
  open?: boolean;
  onOpenChange?: (open: boolean) => void;
}

function buildUserTenantPreviewRows(
  users: BulkUserItem[],
  tenants: Parameters<typeof buildTenantImportPreview>[1],
) {
  const rowsByKey = new Map<string, TenantCSVRow>();

  users.forEach((user, index) => {
    const key = tenantImportKeyFromUser(user);
    if (!key || rowsByKey.has(key)) {
      return;
    }

    rowsByKey.set(key, {
      rowNumber: index + 2,
      tenantId: user.tenantImport?.sourceTenantId ?? "",
      name: user.tenantImport?.name || user.tenantSlug || key,
      type: user.tenantImport?.type || "COMPANY",
      parentTenantId: user.tenantImport?.parentTenantId ?? "",
      parentTenantSlug: user.tenantImport?.parentTenantSlug ?? "",
      slug: user.tenantImport?.slug || user.tenantSlug || key,
      memo: user.tenantImport?.memo ?? "",
      emailDomain: user.tenantImport?.emailDomain ?? "",
      visibility: "public",
      orgUnitType: "node",
      worksmobileSync: "yes",
    });
  });

  return buildTenantImportPreview([...rowsByKey.values()], tenants);
}

function tenantImportKeyFromUser(user: BulkUserItem) {
  return (
    user.tenantImport?.sourceTenantId ||
    user.tenantImport?.slug ||
    user.tenantSlug ||
    user.tenantImport?.name ||
    ""
  );
}

function tenantImportKeyFromRow(row: TenantCSVRow) {
  return row.tenantId || row.slug || row.name;
}

function splitTenantImportDomains(value: string) {
  return value
    .replaceAll("\n", ";")
    .replaceAll(",", ";")
    .split(";")
    .map((domain) => domain.trim().toLowerCase())
    .filter(Boolean);
}

function emailLocalPart(email: string) {
  return email.trim().toLowerCase().split("@")[0] || "";
}

function hanmacEmailStatusLabel(preview?: HanmacImportEmailPreview) {
  if (!preview) return "";
  if (preview.status === "suggested") return "제안";
  if (preview.status === "needsReview") return "확인 필요";
  if (preview.status === "ruleMismatch") return "규칙 확인";
  if (preview.status === "blockingError") return "오류";
  return "";
}

function userImportErrorLabel(user: BulkUserItem) {
  if (!user.importErrors?.includes("duplicateEmail")) {
    return "";
  }
  return "중복 이메일";
}

function hanmacEmailStatusClass(preview?: HanmacImportEmailPreview) {
  if (!preview) return "text-muted-foreground";
  if (preview.status === "blockingError") return "text-destructive";
  if (preview.status === "ruleMismatch" || preview.status === "needsReview") {
    return "text-amber-600";
  }
  if (preview.status === "suggested") return "text-blue-600";
  return "text-muted-foreground";
}

export const downloadUserTemplate = () => {
  const headers =
    "email,sub_email,name,phone,role,tenant_slug,department,grade,position,jobTitle,employee_id,tenant_slug1,department1,grade1,position1,jobTitle1,employee_id1";
  const example =
    "user1@example.com,sub1@test.com;sub2@test.com,홍길동,010-1234-5678,user,tenant-slug,개발팀,수석,팀장,프론트엔드,EMP001,second-tenant,센터,책임,,Architecture,EMP002";
  const blob = new Blob([`${headers}\n${example}`], {
    type: "text/csv;charset=utf-8;",
  });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = "user_bulk_template.csv";
  a.click();
  URL.revokeObjectURL(url);
};

export function UserBulkUploadModal({
  onSuccess,
  variant = "button",
  open: controlledOpen,
  onOpenChange: controlledOnOpenChange,
}: UserBulkUploadModalProps) {
  const [localOpen, setLocalOpen] = React.useState(false);
  const open = controlledOpen !== undefined ? controlledOpen : localOpen;
  const setOpen = (val: boolean) => {
    setLocalOpen(val);
    controlledOnOpenChange?.(val);
  };
  const [file, setFile] = React.useState<File | null>(null);
  const [parsing, setParsing] = React.useState(false);
  const [previewData, setPreviewData] = React.useState<BulkUserItem[]>([]);
  const [tenantPreviewRows, setTenantPreviewRows] = React.useState<
    TenantImportPreviewRow[]
  >([]);
  const [selectedTenantMatches, setSelectedTenantMatches] = React.useState<
    Record<number, string>
  >({});
  const [selectedTenantCreateSlugs, setSelectedTenantCreateSlugs] =
    React.useState<Record<number, string>>({});
  const [results, setResults] = React.useState<BulkUserResult[] | null>(null);
  const [preparing, setPreparing] = React.useState(false);
  const fileInputRef = React.useRef<HTMLInputElement>(null);

  const tenantQuery = useQuery({
    queryKey: ["tenants", "user-bulk-import"],
    queryFn: () => fetchAllTenants(),
  });

  const usersQuery = useQuery({
    queryKey: ["users", "user-bulk-import-email-policy"],
    queryFn: () => fetchUsers(10000, 0),
    enabled: open,
  });

  const mutation = useMutation({
    mutationFn: bulkCreateUsers,
    onSuccess: (data) => {
      setResults(data.results);
      onSuccess?.();
    },
  });

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const selectedFile = e.target.files?.[0];
    if (selectedFile) {
      setFile(selectedFile);
      parseCSV(selectedFile);
    }
  };

  const parseCSV = (file: File) => {
    setParsing(true);
    const reader = new FileReader();
    reader.onload = (e) => {
      const text = e.target?.result as string;
      const data = parseUserCSV(text);
      setPreviewData(data);
      const tenantRows = buildUserTenantPreviewRows(
        data,
        tenantQuery.data?.items ?? [],
      );
      setTenantPreviewRows(tenantRows);
      setSelectedTenantMatches(
        Object.fromEntries(
          tenantRows.map((row) => [
            row.row.rowNumber,
            row.defaultTenantId || "__create__",
          ]),
        ),
      );
      setSelectedTenantCreateSlugs(
        Object.fromEntries(
          tenantRows.map((row) => [row.row.rowNumber, row.defaultCreateSlug]),
        ),
      );
      setParsing(false);
    };
    reader.readAsText(file);
  };

  const handleUpload = async () => {
    if (previewData.length > 0) {
      setPreparing(true);
      try {
        const users = await resolveUserImportTenants();
        mutation.mutate(users);
      } finally {
        setPreparing(false);
      }
    }
  };

  const resolveUserImportTenants = async () => {
    const tenants = tenantQuery.data?.items ?? [];
    const tenantByKey = new Map<
      string,
      { id: string; slug: string; emailDomain: string }
    >();

    for (const preview of tenantPreviewRows) {
      const key = tenantImportKeyFromRow(preview.row);
      const selected =
        selectedTenantMatches[preview.row.rowNumber] ?? "__create__";
      if (selected !== "__create__") {
        const tenant = tenants.find((item) => item.id === selected);
        if (tenant) {
          tenantByKey.set(key, {
            id: tenant.id,
            slug: tenant.slug,
            emailDomain: preview.row.emailDomain,
          });
        }
        continue;
      }

      const created = await createTenant({
        name: preview.row.name || preview.row.slug,
        slug:
          selectedTenantCreateSlugs[preview.row.rowNumber] ||
          preview.defaultCreateSlug,
        type: preview.row.type || "COMPANY",
        parentId: preview.row.parentTenantId || undefined,
        description: preview.row.memo,
        domains: splitTenantImportDomains(preview.row.emailDomain),
        status: "active",
      });
      tenantByKey.set(key, {
        id: created.id,
        slug: created.slug,
        emailDomain: preview.row.emailDomain,
      });
    }

    return previewData.map((user, index) => {
      const finalUser = applyGeneralPlanningOfficePriority(user, tenants);

      const key = tenantImportKeyFromUser(finalUser);
      const resolvedTenant = key ? tenantByKey.get(key) : undefined;
      const emailPreview = hanmacEmailPreviews[index];
      const { tenantImport: _tenantImport, ...payload } = finalUser;
      return {
        ...payload,
        email: emailPreview?.finalEmail ?? payload.email,
        tenantId: resolvedTenant?.id ?? payload.tenantId,
        tenantSlug: resolvedTenant?.slug ?? payload.tenantSlug,
        emailDomain: resolvedTenant?.emailDomain ?? payload.emailDomain,
      };
    });
  };

  const reset = () => {
    setFile(null);
    setPreviewData([]);
    setTenantPreviewRows([]);
    setSelectedTenantMatches({});
    setSelectedTenantCreateSlugs({});
    setResults(null);
    if (fileInputRef.current) fileInputRef.current.value = "";
  };

  const successCount = results?.filter((r) => r.success).length ?? 0;
  const failCount = results ? results.length - successCount : 0;
  const tenants = tenantQuery.data?.items ?? [];
  const existingHanmacLocalParts = React.useMemo(() => {
    const values = new Set<string>();
    for (const user of usersQuery.data?.items ?? []) {
      if (!isHanmacFamilyUser(user, tenants)) {
        continue;
      }
      const localPart = emailLocalPart(user.email);
      if (localPart) values.add(localPart);
    }
    return values;
  }, [tenants, usersQuery.data?.items]);
  const hanmacEmailPreviews = React.useMemo(() => {
    const batchLocalParts = new Set<string>();
    return previewData.map((user) => {
      const tenant = tenants.find(
        (item) =>
          item.slug.toLowerCase() === user.tenantSlug?.trim().toLowerCase(),
      );
      if (!isHanmacFamilyTenant(tenant, tenants)) {
        return undefined;
      }
      return buildHanmacImportEmailPreview(
        user,
        existingHanmacLocalParts,
        batchLocalParts,
      );
    });
  }, [existingHanmacLocalParts, previewData, tenants]);
  const hasBlockingHanmacEmailRows = hanmacEmailPreviews.some(
    (preview) => preview?.status === "blockingError",
  );
  const hasBlockingImportRows = previewData.some(
    (user) => (user.importErrors?.length ?? 0) > 0,
  );

  const triggerProps = {
    disabled: mutation.isPending,
    "data-testid": "bulk-import-btn",
  };

  const triggerNode =
    variant === "dropdown" ? (
      <DropdownMenuItem
        onClick={() => setOpen(true)}
        className="cursor-pointer"
        {...triggerProps}
      >
        <Upload size={16} className="mr-2 opacity-50" />
        {t("ui.admin.users.list.bulk_import", "일괄 등록 (CSV)")}
      </DropdownMenuItem>
    ) : variant === "custom" ? null : (
      <DialogTrigger asChild>
        <Button variant="outline" className="gap-2" {...triggerProps}>
          <Upload size={16} />
          {t("ui.admin.users.list.bulk_import", "일괄 등록 (CSV)")}
        </Button>
      </DialogTrigger>
    );

  return (
    <>
      {variant === "dropdown" ? triggerNode : null}
      <Dialog
        open={open}
        onOpenChange={(val) => {
          setOpen(val);
          if (!val) reset();
        }}
      >
        {variant !== "dropdown" && variant !== "custom" && triggerNode}
        <DialogContent className="max-w-2xl">
          <DialogHeader>
            <DialogTitle data-testid="bulk-upload-title">
              {t("ui.admin.users.bulk.title", "사용자 일괄 등록")}
            </DialogTitle>
            <DialogDescription>
              {t(
                "msg.admin.users.bulk.description",
                "CSV 파일을 업로드하여 여러 사용자를 한 번에 등록합니다.",
              )}
            </DialogDescription>
          </DialogHeader>

          {!results ? (
            <div className="space-y-4 py-4">
              <div className="flex justify-between items-center">
                <Button
                  variant="ghost"
                  size="sm"
                  onClick={downloadUserTemplate}
                  className="gap-2"
                >
                  <Download size={14} />
                  {t(
                    "ui.admin.users.bulk.download_template",
                    "템플릿 다운로드",
                  )}
                </Button>
                <Button asChild variant="secondary" className="cursor-pointer">
                  <label>
                    {file
                      ? t("ui.common.change_file", "파일 변경")
                      : t("ui.common.select_file", "파일 선택")}
                    <input
                      name="user-bulk-upload-file"
                      type="file"
                      accept=".csv"
                      className="hidden"
                      ref={fileInputRef}
                      onChange={handleFileChange}
                      onClick={(e) => {
                        // Allow picking the same file again if it was cleared
                        (e.target as HTMLInputElement).value = "";
                      }}
                    />
                  </label>
                </Button>
              </div>

              {file && (
                <div className="rounded-lg border p-4 bg-muted/20">
                  <div className="flex items-center gap-3 mb-2">
                    <FileText className="text-primary" />
                    <span className="font-medium">{file.name}</span>
                    <span className="text-xs text-muted-foreground">
                      ({(file.size / 1024).toFixed(1)} KB)
                    </span>
                  </div>
                  {parsing ? (
                    <div className="flex items-center gap-2 text-sm text-muted-foreground">
                      <Loader2 size={14} className="animate-spin" />
                      {t("msg.common.parsing", "파싱 중...")}
                    </div>
                  ) : (
                    <div className="text-sm text-muted-foreground">
                      {t(
                        "msg.admin.users.bulk.parsed_count",
                        "{{count}}명의 사용자가 감지되었습니다.",
                        { count: previewData.length },
                      )}
                    </div>
                  )}
                </div>
              )}

              {tenantPreviewRows.length > 0 && (
                <div
                  className="rounded-md border p-3 text-sm"
                  data-testid="user-import-tenant-resolution"
                >
                  <div className="mb-2 font-medium">
                    {t("ui.admin.users.bulk.tenant_resolution", "테넌트 매핑")}
                  </div>
                  <div className="space-y-2">
                    {tenantPreviewRows.map((preview) => (
                      <div
                        key={preview.row.rowNumber}
                        className="grid gap-2 sm:grid-cols-[1fr_1fr]"
                      >
                        <div>
                          <div className="font-medium">{preview.row.name}</div>
                          <div className="font-mono text-xs text-muted-foreground">
                            {preview.row.slug}
                          </div>
                        </div>
                        <div className="space-y-2">
                          <select
                            id={`user-bulk-tenant-match-${preview.row.rowNumber}`}
                            name={`user-bulk-tenant-match-${preview.row.rowNumber}`}
                            className="h-9 w-full rounded-md border border-input bg-background px-3 text-sm"
                            value={
                              selectedTenantMatches[preview.row.rowNumber] ??
                              "__create__"
                            }
                            onChange={(event) =>
                              setSelectedTenantMatches((prev) => ({
                                ...prev,
                                [preview.row.rowNumber]: event.target.value,
                              }))
                            }
                          >
                            <option value="__create__">
                              {t(
                                "ui.admin.users.bulk.create_missing_tenant",
                                "신규 생성",
                              )}
                            </option>
                            {preview.candidates.map((candidate) => (
                              <option
                                key={candidate.tenantId}
                                value={candidate.tenantId}
                              >
                                {candidate.name} ({candidate.slug})
                              </option>
                            ))}
                          </select>
                          {(selectedTenantMatches[preview.row.rowNumber] ??
                            "__create__") === "__create__" && (
                            <input
                              id={`user-bulk-tenant-create-slug-${preview.row.rowNumber}`}
                              name={`user-bulk-tenant-create-slug-${preview.row.rowNumber}`}
                              className="h-9 w-full rounded-md border border-input bg-background px-3 font-mono text-sm"
                              value={
                                selectedTenantCreateSlugs[
                                  preview.row.rowNumber
                                ] ?? ""
                              }
                              onChange={(event) =>
                                setSelectedTenantCreateSlugs((prev) => ({
                                  ...prev,
                                  [preview.row.rowNumber]: event.target.value,
                                }))
                              }
                            />
                          )}
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
              )}

              {previewData.length > 0 && (
                <ScrollArea className="h-[200px] rounded-md border">
                  <table className="w-full text-sm">
                    <thead className="bg-muted sticky top-0">
                      <tr>
                        <th className="p-2 text-left">Email</th>
                        <th className="p-2 text-left">Name</th>
                        <th className="p-2 text-left">Tenant</th>
                        <th className="p-2 text-left">Status</th>
                      </tr>
                    </thead>
                    <tbody>
                      {previewData.slice(0, 10).map((u, index) => (
                        <tr
                          key={`${u.email}-${u.tenantSlug ?? ""}-${u.name}`}
                          className="border-t"
                        >
                          <td className="p-2">
                            <input
                              id={`user-bulk-email-preview-${index}`}
                              name={`user-bulk-email-preview-${index}`}
                              className="h-8 w-full min-w-[180px] rounded-md border border-input bg-background px-2 font-mono text-xs"
                              value={
                                hanmacEmailPreviews[index]?.finalEmail ??
                                u.email
                              }
                              onChange={(event) =>
                                setPreviewData((prev) =>
                                  prev.map((item, itemIndex) =>
                                    itemIndex === index
                                      ? { ...item, email: event.target.value }
                                      : item,
                                  ),
                                )
                              }
                            />
                          </td>
                          <td className="p-2">{u.name}</td>
                          <td className="p-2">{u.tenantSlug || "-"}</td>
                          <td
                            className={`p-2 text-xs ${
                              u.importErrors?.length
                                ? "text-destructive"
                                : hanmacEmailStatusClass(
                                    hanmacEmailPreviews[index],
                                  )
                            }`}
                          >
                            {u.importErrors?.length
                              ? "오류"
                              : hanmacEmailStatusLabel(
                                  hanmacEmailPreviews[index],
                                )}
                            {u.importErrors?.length ? (
                              <div>{userImportErrorLabel(u)}</div>
                            ) : null}
                            {hanmacEmailPreviews[index]?.reason && (
                              <div>{hanmacEmailPreviews[index]?.reason}</div>
                            )}
                          </td>
                        </tr>
                      ))}
                      {previewData.length > 10 && (
                        <tr>
                          <td
                            colSpan={4}
                            className="p-2 text-center text-muted-foreground italic"
                          >
                            ... and {previewData.length - 10} more users
                          </td>
                        </tr>
                      )}
                    </tbody>
                  </table>
                </ScrollArea>
              )}
            </div>
          ) : (
            <div className="space-y-4 py-4">
              <div className="flex items-center gap-4 p-4 rounded-lg bg-muted/30 border">
                {results.some((r) => r.success && r.status === "created") && (
                  <>
                    <div className="flex-1 text-center">
                      <div className="text-2xl font-bold text-green-600">
                        {
                          results.filter(
                            (r) => r.success && r.status === "created",
                          ).length
                        }
                      </div>
                      <div className="text-xs text-muted-foreground uppercase">
                        {t("ui.common.status.new", "신규")}
                      </div>
                    </div>
                    <div className="w-px h-10 bg-border" />
                  </>
                )}
                {results.some((r) => r.success && r.status === "updated") && (
                  <>
                    <div className="flex-1 text-center">
                      <div className="text-2xl font-bold text-blue-600">
                        {
                          results.filter(
                            (r) => r.success && r.status === "updated",
                          ).length
                        }
                      </div>
                      <div className="text-xs text-muted-foreground uppercase">
                        {t("ui.common.status.updated", "수정")}
                      </div>
                    </div>
                    <div className="w-px h-10 bg-border" />
                  </>
                )}
                {results.some((r) => r.success && r.status === "unchanged") && (
                  <>
                    <div className="flex-1 text-center">
                      <div className="text-2xl font-bold text-slate-500">
                        {
                          results.filter(
                            (r) => r.success && r.status === "unchanged",
                          ).length
                        }
                      </div>
                      <div className="text-xs text-muted-foreground uppercase">
                        {t("ui.common.status.unchanged", "동일")}
                      </div>
                    </div>
                    <div className="w-px h-10 bg-border" />
                  </>
                )}
                {!results.some((r) => r.success && r.status) &&
                  successCount > 0 && (
                    <>
                      <div className="flex-1 text-center">
                        <div className="text-2xl font-bold text-green-600">
                          {successCount}
                        </div>
                        <div className="text-xs text-muted-foreground uppercase">
                          {t("ui.common.success", "성공")}
                        </div>
                      </div>
                      <div className="w-px h-10 bg-border" />
                    </>
                  )}
                <div className="flex-1 text-center">
                  <div className="text-2xl font-bold text-destructive">
                    {failCount}
                  </div>
                  <div className="text-xs text-muted-foreground uppercase">
                    {t("ui.common.fail", "실패")}
                  </div>
                </div>
              </div>

              <ScrollArea className="h-[250px] rounded-md border">
                <div className="p-2 space-y-2">
                  {results.map((r) => (
                    <div
                      key={r.email}
                      className="flex items-start gap-3 p-2 rounded border bg-card text-sm"
                    >
                      {r.success ? (
                        <CheckCircle2
                          size={16}
                          className="text-green-500 mt-0.5"
                        />
                      ) : (
                        <AlertCircle
                          size={16}
                          className="text-destructive mt-0.5"
                        />
                      )}
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center gap-2">
                          <div className="font-medium truncate">{r.email}</div>
                          {r.success && r.status === "created" && (
                            <span className="px-1.5 py-0.5 rounded-full bg-green-100 text-green-700 text-[10px] font-bold">
                              {t("ui.common.status.new", "신규")}
                            </span>
                          )}
                          {r.success && r.status === "updated" && (
                            <span className="px-1.5 py-0.5 rounded-full bg-blue-100 text-blue-700 text-[10px] font-bold">
                              {t("ui.common.status.updated", "수정")}
                            </span>
                          )}
                          {r.success && r.status === "unchanged" && (
                            <span className="px-1.5 py-0.5 rounded-full bg-slate-100 text-slate-600 text-[10px] font-bold">
                              {t("ui.common.status.unchanged", "동일")}
                            </span>
                          )}
                          {r.success && !r.status && (
                            <span className="px-1.5 py-0.5 rounded-full bg-green-100 text-green-700 text-[10px] font-bold">
                              {t("ui.common.success", "성공")}
                            </span>
                          )}
                        </div>
                        {r.success && r.status === "updated" && (
                          <div className="mt-1 text-[10px] text-muted-foreground flex flex-wrap gap-1 items-center">
                            <span className="font-medium">
                              {t(
                                "ui.admin.users.bulk.modified_fields",
                                "수정 항목:",
                              )}
                            </span>
                            {r.modifiedFields &&
                              r.modifiedFields.length > 0 &&
                              r.modifiedFields.map((field) => (
                                <span
                                  key={field}
                                  className="px-1 py-0.5 rounded bg-blue-50 text-blue-600 border border-blue-100"
                                >
                                  {t(
                                    `ui.admin.users.field.${field.toLowerCase()}`,
                                    field,
                                  )}
                                </span>
                              ))}
                          </div>
                        )}
                        {r.success && r.status === "unchanged" && (
                          <div className="mt-1 text-[10px] text-muted-foreground italic">
                            {t(
                              "ui.admin.users.bulk.no_changes",
                              "기존 데이터와 동일 (변경 사항 없음)",
                            )}
                          </div>
                        )}
                        {!r.success && (
                          <div className="text-xs text-destructive">
                            {r.message}
                          </div>
                        )}
                      </div>
                    </div>
                  ))}
                </div>
              </ScrollArea>
            </div>
          )}

          <DialogFooter>
            {!results ? (
              <Button
                onClick={handleUpload}
                disabled={
                  previewData.length === 0 ||
                  mutation.isPending ||
                  preparing ||
                  hasBlockingHanmacEmailRows ||
                  hasBlockingImportRows
                }
                className="w-full sm:w-auto"
                data-testid="bulk-start-btn"
              >
                {(mutation.isPending || preparing) && (
                  <Loader2 size={16} className="mr-2 animate-spin" />
                )}
                {t("ui.admin.users.bulk.start_upload", "등록 시작")}
              </Button>
            ) : (
              <Button
                onClick={() => setOpen(false)}
                className="w-full sm:w-auto"
                data-testid="bulk-close-dialog-btn"
              >
                {t("ui.common.close", "닫기")}
              </Button>
            )}
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </>
  );
}
