'use client';

import { useMemo, useState, useTransition } from 'react';
import * as XLSX from 'xlsx';
import { AlertCircle, CheckCircle2, Download, FileSpreadsheet, Loader2, RefreshCw, Upload } from 'lucide-react';
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { useToast } from '@/hooks/use-toast';
import { handleBulkImportMaterials } from '@/lib/actions';
import type { ItemGroup, ProductionItem } from '@/lib/types';

type ImportFieldKey =
  | 'name'
  | 'itemNumber'
  | 'itemSymbolName'
  | 'globalReferenceNumber'
  | 'barcode'
  | 'secondaryBarcode'
  | 'additionalDetails'
  | 'salePrice'
  | 'purchasePrice'
  | 'groupName'
  | 'itemCategory'
  | 'primaryUnit'
  | 'secondaryUnit'
  | 'secondaryUnitQuantity';

type ColumnOption = {
  id: string;
  label: string;
  index: number;
};

type ParsedSheet = {
  name: string;
  columns: ColumnOption[];
  rows: string[][];
};

type ImportAnalysisRow = {
  rowNumber: number;
  values: Partial<Record<ImportFieldKey, string>>;
  issues: string[];
  payload: Record<string, unknown>;
  existingItemId?: string;
  autoGeneratedBarcode?: boolean;
  predictedItemNumber?: string;
};

type ImportResultRow = {
  rowNumber: number;
  name: string;
  barcode: string;
  predictedItemNumber: string;
  assignedItemNumber: string;
  status: 'نجح' | 'تحديث' | 'فشل';
  error?: string;
};

type ImportReport = {
  importedCount: number;
  updatedCount: number;
  failedRows: Array<{ rowNumber: number; message: string }>;
  failedTotal: number;
};

type Props = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  itemGroups: ItemGroup[];
  currentItems: ProductionItem[];
  onImported: () => void;
};

const IMPORT_FIELDS: Array<{ key: ImportFieldKey; label: string; required?: boolean }> = [
  { key: 'name', label: 'اسم العنصر', required: true },
  { key: 'itemNumber', label: 'رقم الصنف' },
  { key: 'itemSymbolName', label: 'اسم رمز الصنف' },
  { key: 'globalReferenceNumber', label: 'رقم مرجع عالمي' },
  { key: 'barcode', label: 'الباركود' },
  { key: 'secondaryBarcode', label: 'باركود الوحدة الفرعية' },
  { key: 'additionalDetails', label: 'تفاصيل إضافية' },
  { key: 'salePrice', label: 'سعر البيع' },
  { key: 'purchasePrice', label: 'سعر الشراء' },
  { key: 'groupName', label: 'اسم المجموعة' },
  { key: 'itemCategory', label: 'نوع الصنف' },
  { key: 'primaryUnit', label: 'الوحدة الأساسية' },
  { key: 'secondaryUnit', label: 'الوحدة الفرعية' },
  { key: 'secondaryUnitQuantity', label: 'كمية الوحدة الفرعية' },
];

const HEADER_SYNONYMS: Record<ImportFieldKey, string[]> = {
  name: ['name', 'item name', 'product name', 'اسم', 'اسم العنصر', 'اسم الصنف', 'الصنف', 'الماده', 'المادة'],
  itemNumber: ['item no', 'item number', 'sku', 'code', 'رقم', 'رقم الصنف', 'كود الصنف', 'كود'],
  itemSymbolName: ['symbol', 'symbol name', 'item symbol', 'اسم رمز الصنف', 'رمز الصنف', 'الرمز'],
  globalReferenceNumber: ['global reference', 'reference', 'global ref', 'رقم مرجع عالمي', 'مرجع عالمي', 'مرجع'],
  barcode: ['barcode', 'bar code', 'الباركود', 'باركود'],
  secondaryBarcode: ['secondary barcode', 'sub barcode', 'باركود الوحدة الفرعية', 'باركود فرعي'],
  additionalDetails: ['details', 'description', 'notes', 'تفاصيل', 'تفاصيل اضافيه', 'تفاصيل إضافية', 'ملاحظات'],
  salePrice: ['sale price', 'selling price', 'price', 'سعر البيع', 'السعر'],
  purchasePrice: ['purchase price', 'cost price', 'cost', 'سعر الشراء', 'التكلفة'],
  groupName: ['group', 'group name', 'category', 'اسم المجموعة', 'المجموعه', 'المجموعة', 'الفئة'],
  itemCategory: ['item type', 'type', 'category type', 'نوع الصنف', 'النوع'],
  primaryUnit: ['primary unit', 'main unit', 'unit', 'الوحدة', 'الوحدة الأساسية'],
  secondaryUnit: ['secondary unit', 'sub unit', 'الوحدة الفرعية'],
  secondaryUnitQuantity: ['secondary qty', 'secondary quantity', 'sub quantity', 'كمية الوحدة الفرعية', 'كمية الفرعية'],
};

function normalizeText(value: string): string {
  return String(value || '')
    .toLowerCase()
    .replace(/[\u064B-\u065F\u0670\u06D6-\u06ED]/g, '')
    .replace(/[إأآٱ]/g, 'ا')
    .replace(/ى/g, 'ي')
    .replace(/ؤ/g, 'و')
    .replace(/ئ/g, 'ي')
    .replace(/ة/g, 'ه')
    .replace(/\s+/g, ' ')
    .trim();
}

function fixArabicMojibake(value: string): string {
  const text = String(value || '').trim();
  if (!text) return '';

  const arabicCount = (text.match(/[\u0600-\u06FF]/g) || []).length;
  const latin1HighCount = (text.match(/[\u00C0-\u00FF]/g) || []).length;

  // Catch common mojibake patterns, including samples like: ÑÞã ÇáÕäÝ
  const looksCorrupted = /[ØÙÐÃÂÑÞÇ]/.test(text) || (arabicCount === 0 && latin1HighCount >= 2);
  if (!looksCorrupted) return text;

  const bytes: number[] = [];
  for (let i = 0; i < text.length; i += 1) {
    const code = text.charCodeAt(i);
    if (code > 255) return text;
    bytes.push(code);
  }

  const scoreArabic = (candidate: string) => (candidate.match(/[\u0600-\u06FF]/g) || []).length;
  const source = new Uint8Array(bytes);
  const originalArabicChars = arabicCount;
  let best = text;
  let bestScore = originalArabicChars;

  const tryDecode = (encoding: string, fatal: boolean) => {
    try {
      const decoded = new TextDecoder(encoding as any, { fatal }).decode(source);
      const score = scoreArabic(decoded);
      if (score > bestScore) {
        best = decoded;
        bestScore = score;
      }
    } catch {
      // Ignore unsupported/invalid decode attempts.
    }
  };

  tryDecode('utf-8', true);
  tryDecode('windows-1256', false);
  tryDecode('iso-8859-6', false);

  return best;
}

function slugText(value: string): string {
  return normalizeText(value).replace(/[^\p{L}\p{N}]+/gu, '');
}

function parseNumber(value: string): number | undefined {
  const normalized = String(value || '').replace(/,/g, '').trim();
  if (!normalized) return undefined;
  const parsed = Number(normalized);
  return Number.isFinite(parsed) ? parsed : undefined;
}

function mapItemCategory(value: string): 'inventory' | 'service' | 'non_stock' | 'bundle' | undefined {
  const normalized = slugText(value);
  if (!normalized) return undefined;
  if (['inventory', 'stock', 'مخزني', 'مخزون', 'بضاعه', 'بضاعة'].includes(normalized)) return 'inventory';
  if (['service', 'خدمه', 'خدمة'].includes(normalized)) return 'service';
  if (['nonstock', 'nonstockitem', 'غيرمخزني', 'غيرمخزون'].includes(normalized)) return 'non_stock';
  if (['bundle', 'kit', 'pack', 'تجميعي', 'حزمه', 'حزمة'].includes(normalized)) return 'bundle';
  return undefined;
}

function autoMapColumns(columns: ColumnOption[]): Partial<Record<ImportFieldKey, string>> {
  const mapped: Partial<Record<ImportFieldKey, string>> = {};
  const usedColumns = new Set<string>();

  IMPORT_FIELDS.forEach((field) => {
    const match = columns.find((column) => {
      if (usedColumns.has(column.id)) return false;
      const normalizedLabel = slugText(column.label);
      return HEADER_SYNONYMS[field.key].some((alias) => slugText(alias) === normalizedLabel);
    });

    if (match) {
      mapped[field.key] = match.id;
      usedColumns.add(match.id);
    }
  });

  return mapped;
}

export default function MaterialImportDialog({ open, onOpenChange, itemGroups, currentItems, onImported }: Props) {
  const { toast } = useToast();
  const [sheets, setSheets] = useState<ParsedSheet[]>([]);
  const [selectedSheetName, setSelectedSheetName] = useState('');
  const [fileName, setFileName] = useState('');
  const [columnMapping, setColumnMapping] = useState<Partial<Record<ImportFieldKey, string>>>({});
  const [report, setReport] = useState<ImportReport | null>(null);
  const [upsertMode, setUpsertMode] = useState(false);
  const [autoFixFileDuplicateBarcode, setAutoFixFileDuplicateBarcode] = useState(false);
  const [importProgress, setImportProgress] = useState<{
    done: number;
    total: number;
    startedAt: number;
  } | null>(null);
  const [isImporting, startImportTransition] = useTransition();
  const [resultRows, setResultRows] = useState<ImportResultRow[]>([]);
  const [resumeFromRowNumber, setResumeFromRowNumber] = useState<number | null>(null);

  const selectedSheet = useMemo(
    () => sheets.find((sheet) => sheet.name === selectedSheetName) || null,
    [selectedSheetName, sheets]
  );

  // Predict item numbers client-side (same algorithm as server addMaterial)
  const maxExistingItemNumber = useMemo(() => {
    let max = 0;
    currentItems.forEach((item) => {
      const n = parseInt(String(item.itemNumber || item.id || '').replace(/\D+/g, ''), 10);
      if (Number.isFinite(n) && n > max) max = n;
    });
    return max;
  }, [currentItems]);

  const groupIdByName = useMemo(() => {
    const map = new Map<string, string>();
    itemGroups.forEach((group) => {
      const groupName = normalizeText(String(group.name || ''));
      if (groupName) {
        map.set(groupName, group.id);
      }
    });
    return map;
  }, [itemGroups]);

  const existingItemNumberMap = useMemo(() => {
    const map = new Map<string, string>();
    currentItems.forEach((item) => {
      const key = normalizeText(String(item.itemNumber || ''));
      if (key) map.set(key, item.id);
    });
    return map;
  }, [currentItems]);

  const existingBarcodeMap = useMemo(() => {
    const map = new Map<string, string>();
    currentItems.forEach((item) => {
      [
        String(item.barcode || ''),
        String(item.secondaryBarcode || ''),
        ...(item.additionalBarcodes || []).map((entry) => String(entry || '')),
        ...((Array.isArray(item.secondaryUnits) ? item.secondaryUnits : []).map((entry) => String(entry?.barcode || ''))),
      ]
        .map(normalizeText)
        .filter(Boolean)
        .forEach((value) => { if (!map.has(value)) map.set(value, item.id); });
    });
    return map;
  }, [currentItems]);

  const analysisRows = useMemo<ImportAnalysisRow[]>(() => {
    if (!selectedSheet) return [];

    const nameColumnId = columnMapping.name;
    const fileItemNumbers = new Set<string>();
    const fileBarcodes = new Set<string>();
    let predictedCounter = maxExistingItemNumber;
    const occupiedBarcodes = new Set<string>(existingBarcodeMap.keys());
    const now = new Date();
    const pad = (num: number) => String(num).padStart(2, '0');
    const barcodeBase = `A${pad(now.getDate())}${pad(now.getMonth() + 1)}${now.getFullYear()}${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
    let generatedCounter = 0;
    const generateAutoBarcodeFromAppPattern = () => {
      while (true) {
        const generated = generatedCounter === 0
          ? barcodeBase
          : `${barcodeBase}${String(generatedCounter).padStart(2, '0')}`;
        generatedCounter += 1;
        const normalizedGenerated = normalizeText(generated);
        if (!occupiedBarcodes.has(normalizedGenerated)) {
          occupiedBarcodes.add(normalizedGenerated);
          return generated;
        }
      }
    };

    return selectedSheet.rows.map((row, index) => {
      const rowNumber = index + 2;
      let autoGeneratedBarcode = false;
      const values = IMPORT_FIELDS.reduce<Partial<Record<ImportFieldKey, string>>>((acc, field) => {
        const columnId = columnMapping[field.key];
        if (!columnId) return acc;
        const column = selectedSheet.columns.find((entry) => entry.id === columnId);
        const rawValue = column ? fixArabicMojibake(String(row[column.index] ?? '').trim()) : '';
        acc[field.key] = rawValue;
        return acc;
      }, {});

      const issues: string[] = [];
      const name = String(values.name || '').trim();
      if (!nameColumnId) {
        issues.push('اربط حقل اسم العنصر بعمود من الملف.');
      } else if (!name) {
        issues.push('اسم العنصر مطلوب.');
      }

      const salePrice = parseNumber(String(values.salePrice || ''));
      if (String(values.salePrice || '').trim() && salePrice === undefined) {
        issues.push('سعر البيع غير صالح.');
      }

      const purchasePrice = parseNumber(String(values.purchasePrice || ''));
      if (String(values.purchasePrice || '').trim() && purchasePrice === undefined) {
        issues.push('سعر الشراء غير صالح.');
      }

      const secondaryUnitQuantity = parseNumber(String(values.secondaryUnitQuantity || ''));
      if (String(values.secondaryUnitQuantity || '').trim() && secondaryUnitQuantity === undefined) {
        issues.push('كمية الوحدة الفرعية غير صالحة.');
      }

      const normalizedItemNumber = normalizeText(String(values.itemNumber || ''));
      let existingItemId: string | undefined;
      if (normalizedItemNumber) {
        const existingId = existingItemNumberMap.get(normalizedItemNumber);
        if (existingId) {
          if (upsertMode) {
            existingItemId = existingId;
          } else {
            issues.push('رقم الصنف موجود مسبقاً في النظام.');
          }
        }
        if (fileItemNumbers.has(normalizedItemNumber)) {
          issues.push('رقم الصنف مكرر داخل الملف.');
        }
        fileItemNumbers.add(normalizedItemNumber);
      }

      const rawBarcode = String(values.barcode || '').trim();
      const normalizedBarcode = normalizeText(rawBarcode);
      if (normalizedBarcode) {
        const existingId = existingBarcodeMap.get(normalizedBarcode);
        if (existingId) {
          if (upsertMode) {
            existingItemId = existingItemId || existingId;
          } else {
            issues.push('الباركود موجود مسبقاً في النظام.');
          }
        }
        if (fileBarcodes.has(normalizedBarcode)) {
          if (autoFixFileDuplicateBarcode) {
            const generatedBarcode = generateAutoBarcodeFromAppPattern();
            values.barcode = generatedBarcode;
            autoGeneratedBarcode = true;
          } else {
            issues.push('الباركود مكرر داخل الملف.');
          }
        } else {
          fileBarcodes.add(normalizedBarcode);
          occupiedBarcodes.add(normalizedBarcode);
        }
      }

      const rawGroupName = String(values.groupName || '').trim();
      const groupId = rawGroupName ? groupIdByName.get(normalizeText(rawGroupName)) : undefined;
      if (rawGroupName && !groupId) {
        issues.push('اسم المجموعة غير موجود في النظام.');
      }

      const rawItemCategory = String(values.itemCategory || '').trim();
      const itemCategory = rawItemCategory ? mapItemCategory(rawItemCategory) : undefined;
      if (rawItemCategory && !itemCategory) {
        issues.push('نوع الصنف غير معروف. استخدم inventory أو service أو non_stock أو bundle.');
      }

      const normalizedPrimaryUnit = String(values.primaryUnit || '').trim();
      const normalizedSecondaryUnit = String(values.secondaryUnit || '').trim();
      const hasValidSecondaryQuantity = Number.isFinite(secondaryUnitQuantity) && Number(secondaryUnitQuantity) > 1;

      const payload: Record<string, unknown> = {
        itemNumber: String(values.itemNumber || '').trim() || undefined,
        name,
        itemSymbolName: String(values.itemSymbolName || '').trim() || undefined,
        globalReferenceNumber: String(values.globalReferenceNumber || '').trim() || undefined,
        barcode: String(values.barcode || '').trim() || undefined,
        secondaryBarcode: String(values.secondaryBarcode || '').trim() || undefined,
        additionalDetails: String(values.additionalDetails || '').trim() || undefined,
        salePrice,
        purchasePrice,
        groupId,
        itemCategory,
        primaryUnit: normalizedPrimaryUnit || undefined,
        secondaryUnit: hasValidSecondaryQuantity ? (normalizedSecondaryUnit || undefined) : undefined,
        secondaryUnitQuantity: hasValidSecondaryQuantity ? secondaryUnitQuantity : undefined,
      };

      // Predict item number: use provided number if unique, else next sequential
      let predictedItemNumber: string | undefined;
      const requestedNum = normalizeText(String(values.itemNumber || ''));
      if (requestedNum && !existingItemNumberMap.has(requestedNum)) {
        predictedItemNumber = String(values.itemNumber || '').trim();
      } else if (!existingItemId) {
        predictedCounter += 1;
        while (existingItemNumberMap.has(String(predictedCounter))) predictedCounter += 1;
        predictedItemNumber = String(predictedCounter);
      }

      return {
        rowNumber,
        values,
        issues,
        payload,
        existingItemId,
        autoGeneratedBarcode,
        predictedItemNumber,
      };
    });
  }, [autoFixFileDuplicateBarcode, columnMapping, existingBarcodeMap, existingItemNumberMap, groupIdByName, maxExistingItemNumber, selectedSheet, upsertMode]);

  const summary = useMemo(() => {
    const total = analysisRows.length;
    const validRows = analysisRows.filter((row) => row.issues.length === 0);
    const valid = validRows.length;
    const invalid = total - valid;
    const toCreate = validRows.filter((row) => !row.existingItemId).length;
    const toUpdate = validRows.filter((row) => !!row.existingItemId).length;
    return { total, valid, invalid, toCreate, toUpdate };
  }, [analysisRows]);

  const previewRows = useMemo(() => analysisRows.slice(0, 8), [analysisRows]);
  const mappedFields = useMemo(() => IMPORT_FIELDS.filter((field) => columnMapping[field.key]), [columnMapping]);

  const handleFileChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (!file) return;

    try {
      const buffer = await file.arrayBuffer();
      const workbook = XLSX.read(buffer, { type: 'array' });
      const parsedSheets = workbook.SheetNames.map((sheetName) => {
        const sheet = workbook.Sheets[sheetName];
        const matrix = (XLSX.utils.sheet_to_json(sheet, { header: 1, defval: '' }) as Array<Array<unknown>>)
          .map((row) => row.map((cell) => String(cell ?? '').trim()))
          .filter((row) => row.some((cell) => String(cell || '').trim().length > 0));

        const headerRow = matrix[0] || [];
        const dataRows = matrix.slice(1);
        const columns = headerRow.map((header, index) => ({
          id: `col_${index}`,
          label: fixArabicMojibake(String(header || `عمود ${index + 1}`)),
          index,
        }));

        return {
          name: sheetName,
          columns,
          rows: dataRows,
        } satisfies ParsedSheet;
      }).filter((sheet) => sheet.columns.length > 0);

      if (parsedSheets.length === 0) {
        toast({ title: 'تعذر قراءة الملف', description: 'الملف لا يحتوي على أعمدة قابلة للقراءة.', variant: 'destructive' });
        return;
      }

      setFileName(file.name);
      setSheets(parsedSheets);
      setSelectedSheetName(parsedSheets[0].name);
      setColumnMapping(autoMapColumns(parsedSheets[0].columns));
      setReport(null);
      setResumeFromRowNumber(null);
    } catch (error) {
      toast({ title: 'فشل تحليل الملف', description: 'تعذر قراءة ملف Excel. تأكد من أن الملف صالح.', variant: 'destructive' });
    } finally {
      event.target.value = '';
    }
  };

  const handleSheetChange = (sheetName: string) => {
    const nextSheet = sheets.find((sheet) => sheet.name === sheetName);
    setSelectedSheetName(sheetName);
    setColumnMapping(nextSheet ? autoMapColumns(nextSheet.columns) : {});
    setReport(null);
    setResumeFromRowNumber(null);
  };

  const handleDownloadTemplate = () => {
    const headers = IMPORT_FIELDS.map((f) => f.label);
    const example = [
      'مثال صنف', 'S001', 'رمز', '', '1234567890', '', 'تفاصيل', '100', '80', 'اسم المجموعة', 'inventory', 'كيلو', 'جرام', '1000',
    ];
    const ws = XLSX.utils.aoa_to_sheet([headers, example]);
    ws['!cols'] = headers.map(() => ({ wch: 20 }));
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, 'الأصناف');
    XLSX.writeFile(wb, 'قالب_استيراد_الأصناف.xlsx');
  };

  const handleDownloadAnnotatedExcel = () => {
    if (!selectedSheet) return;
    // Clone original rows and append predicted item number as last column
    const originalHeaders = selectedSheet.columns.map((c) => c.label);
    const headers = [...originalHeaders, 'رقم الصنف المتوقع (مرجع الاستئناف)'];
    const dataRows = selectedSheet.rows.map((row, idx) => {
      const analysis = analysisRows[idx];
      return [...row, analysis?.predictedItemNumber || analysis?.existingItemId || ''];
    });
    const ws = XLSX.utils.aoa_to_sheet([headers, ...dataRows]);
    ws['!cols'] = headers.map(() => ({ wch: 22 }));
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, selectedSheet.name);
    XLSX.writeFile(wb, `${fileName.replace(/\.[^.]+$/, '')}_مرجع_استيراد.xlsx`);
  };

  const handleDownloadResultsReport = () => {
    if (resultRows.length === 0) return;
    const headers = ['رقم الصف', 'اسم الصنف', 'الباركود', 'رقم الصنف المتوقع', 'رقم الصنف المُعيَّن', 'الحالة', 'الخطأ'];
    const rows = resultRows.map((r) => [r.rowNumber, r.name, r.barcode, r.predictedItemNumber, r.assignedItemNumber, r.status, r.error || '']);
    const ws = XLSX.utils.aoa_to_sheet([headers, ...rows]);
    ws['!cols'] = headers.map(() => ({ wch: 20 }));
    const wb = XLSX.utils.book_new();
    XLSX.utils.book_append_sheet(wb, ws, 'نتائج الاستيراد');
    XLSX.writeFile(wb, `نتائج_الاستيراد_${new Date().toISOString().slice(0, 10)}.xlsx`);
  };

  const handleImport = (startFromRow?: number) => {
    const allReadyRows = analysisRows.filter((row) => row.issues.length === 0);
    const readyRows = typeof startFromRow === 'number'
      ? allReadyRows.filter((row) => row.rowNumber >= startFromRow)
      : allReadyRows;

    if (readyRows.length === 0) {
      toast({ title: 'لا توجد صفوف صالحة', description: 'اربط الحقول وصحح الأخطاء الظاهرة قبل الاستيراد.', variant: 'destructive' });
      return;
    }

    setImportProgress({ done: 0, total: readyRows.length, startedAt: Date.now() });
    setResultRows([]);

    startImportTransition(async () => {
      const CHUNK_SIZE = 25;
      const allInputRows = readyRows.map((row) => ({
        rowNumber: row.rowNumber,
        payload: row.payload,
        existingItemId: row.existingItemId,
      }));
      const readyRowByNumber = new Map(readyRows.map((row) => [row.rowNumber, row]));

      let results: Array<{ rowNumber: number; success: boolean; itemNumber?: string; error?: string }> = [];
      let doneCount = 0;
      let stoppedAtRowNumber: number | null = null;

      for (let i = 0; i < allInputRows.length; i += CHUNK_SIZE) {
        const chunk = allInputRows.slice(i, i + CHUNK_SIZE);
        try {
          const response = await handleBulkImportMaterials(chunk);
          results = results.concat(response.results);
        } catch (e: any) {
          // Mark current chunk as failed, keep remaining rows for resume.
          const failedChunk = chunk.map((r) => ({
            rowNumber: r.rowNumber,
            success: false,
            error: e?.message || 'خطأ في الاتصال',
          }));
          results = results.concat(failedChunk);
          stoppedAtRowNumber = chunk[0]?.rowNumber ?? null;
          break;
        }
        doneCount = Math.min(i + CHUNK_SIZE, allInputRows.length);
        setImportProgress((prev) => prev ? { ...prev, done: doneCount } : prev);
        // Yield to the browser between chunks to keep UI responsive.
        await new Promise((resolve) => setTimeout(resolve, 0));
      }

      setImportProgress((prev) => prev ? { ...prev, done: doneCount } : prev);

      if (stoppedAtRowNumber) {
        setResumeFromRowNumber(stoppedAtRowNumber);
      } else {
        setResumeFromRowNumber(null);
      }

      const resultByRowNumber = new Map(results.map((r) => [r.rowNumber, r]));

      const importedCount = results.filter((r) => r.success && !readyRowByNumber.get(r.rowNumber)?.existingItemId).length;
      const updatedCount = results.filter((r) => r.success && !!readyRowByNumber.get(r.rowNumber)?.existingItemId).length;
      const allFailedRows = results
        .filter((r) => !r.success)
        .map((r) => ({ rowNumber: r.rowNumber, message: r.error || 'فشل.' }));
      const failedRows = allFailedRows.slice(0, 50);

      // Build result rows for download report
      const newResultRows: ImportResultRow[] = readyRows.map((row) => {
        const result = resultByRowNumber.get(row.rowNumber);
        return {
          rowNumber: row.rowNumber,
          name: String(row.values.name || ''),
          barcode: String(row.values.barcode || ''),
          predictedItemNumber: row.predictedItemNumber || '',
          assignedItemNumber: result?.itemNumber || row.predictedItemNumber || '',
          status: !result ? 'فشل' : result.success ? (row.existingItemId ? 'تحديث' : 'نجح') : 'فشل',
          error: result?.error,
        };
      });
      setResultRows(newResultRows);

      // Notify parent to refresh the list after any successful create/update.
      if ((importedCount + updatedCount) > 0) {
        onImported();
      }

      setImportProgress(null);
      setReport({ importedCount, updatedCount, failedRows, failedTotal: allFailedRows.length });

      const totalDone = importedCount + updatedCount;
      if (totalDone > 0) {
        const parts: string[] = [];
        if (importedCount > 0) parts.push(`إنشاء ${importedCount}`);
        if (updatedCount > 0) parts.push(`تحديث ${updatedCount}`);
        toast({
          title: 'اكتمل الاستيراد',
          description:
            allFailedRows.length > 0
              ? `${parts.join('، ')} صنف. تعذر ${allFailedRows.length} صف.`
              : `${parts.join('، ')} صنف بنجاح.`,
        });
        return;
      }

      if (stoppedAtRowNumber) {
        toast({
          title: 'توقف الاستيراد مؤقتاً',
          description: `توقف عند الصف ${stoppedAtRowNumber}. يمكنك الضغط على زر الاستئناف للمتابعة من نفس الموضع.`,
          variant: 'destructive',
        });
        return;
      }

      toast({ title: 'فشل الاستيراد', description: 'لم يتم استيراد أي صف.', variant: 'destructive' });
    });
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="max-h-[90vh] overflow-y-auto sm:max-w-5xl">
        <DialogHeader>
          <DialogTitle className="flex items-center gap-2">
            <FileSpreadsheet className="h-5 w-5" />
            استيراد الأصناف من Excel
          </DialogTitle>
          <DialogDescription>
            ارفع ملف Excel أو CSV، ثم اربط أعمدة الملف بحقول الصنف قبل تنفيذ الاستيراد. هذه النسخة تبدأ بالاستيراد كأصناف جديدة فقط وتمنع التكرارات الواضحة.
          </DialogDescription>
        </DialogHeader>

        <div className="space-y-6">
          <div className="rounded-lg border border-dashed p-4">
            <div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
              <div>
                <p className="font-medium">رفع الملف</p>
                <p className="text-sm text-muted-foreground">الملفات المدعومة: xlsx, xls, csv</p>
                {fileName ? <p className="mt-1 text-sm text-muted-foreground">الملف الحالي: {fileName}</p> : null}
              </div>
              <label className="inline-flex cursor-pointer items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium hover:bg-accent">
                <Upload className="h-4 w-4" />
                اختيار ملف
                <input type="file" accept=".xlsx,.xls,.csv" className="hidden" onChange={handleFileChange} />
              </label>
            </div>
          </div>

          {selectedSheet ? (
            <>
              <div className="grid gap-4 md:grid-cols-2">
                <div className="space-y-2">
                  <Label>ورقة العمل</Label>
                  <Select value={selectedSheetName} onValueChange={handleSheetChange}>
                    <SelectTrigger>
                      <SelectValue placeholder="اختر ورقة العمل" />
                    </SelectTrigger>
                    <SelectContent>
                      {sheets.map((sheet) => (
                        <SelectItem key={sheet.name} value={sheet.name}>
                          {sheet.name}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
                <div className="rounded-md border p-4 text-sm space-y-1">
                  <p>إجمالي الصفوف: <span className="font-semibold">{summary.total}</span></p>
                  <p>صالحة للاستيراد: <span className="font-semibold text-emerald-600">{summary.valid}</span></p>
                  {upsertMode && summary.toUpdate > 0 ? (
                    <p className="text-xs text-muted-foreground">منها {summary.toUpdate} تحديث و{summary.toCreate} جديد</p>
                  ) : null}
                  <p>تحتاج مراجعة: <span className="font-semibold text-amber-600">{summary.invalid}</span></p>
                </div>
              </div>

              <div className="flex items-center gap-3 rounded-md border px-4 py-3">
                <RefreshCw className="h-4 w-4 text-muted-foreground" />
                <div className="flex-1">
                  <p className="text-sm font-medium">وضع التحديث (Upsert)</p>
                  <p className="text-xs text-muted-foreground">عند التفعيل، يتم تحديث الأصناف الموجودة (بحسب رقم الصنف أو الباركود) بدلاً من رفضها.</p>
                </div>
                <button
                  type="button"
                  role="switch"
                  aria-checked={upsertMode}
                  onClick={() => { setUpsertMode((v) => !v); setReport(null); setResumeFromRowNumber(null); }}
                  className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none ${upsertMode ? 'bg-primary' : 'bg-muted-foreground/30'}`}
                >
                  <span className={`inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${upsertMode ? 'translate-x-6' : 'translate-x-1'}`} />
                </button>
              </div>

              <div className="flex items-center gap-3 rounded-md border px-4 py-3">
                <AlertCircle className="h-4 w-4 text-muted-foreground" />
                <div className="flex-1">
                  <p className="text-sm font-medium">معالجة تكرار الباركود داخل الملف</p>
                  <p className="text-xs text-muted-foreground">عند التفعيل، إذا تكرر الباركود في نفس الملف يتم توليد باركود جديد تلقائياً بنفس بنية التطبيق.</p>
                </div>
                <button
                  type="button"
                  role="switch"
                  aria-checked={autoFixFileDuplicateBarcode}
                  onClick={() => { setAutoFixFileDuplicateBarcode((v) => !v); setReport(null); setResumeFromRowNumber(null); }}
                  className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none ${autoFixFileDuplicateBarcode ? 'bg-primary' : 'bg-muted-foreground/30'}`}
                >
                  <span className={`inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${autoFixFileDuplicateBarcode ? 'translate-x-6' : 'translate-x-1'}`} />
                </button>
              </div>

              <div className="space-y-3">
                <div>
                  <h3 className="font-medium">ربط الأعمدة بالحقول</h3>
                  <p className="text-sm text-muted-foreground">تم تطبيق ربط تلقائي مبدئي، ويمكنك تعديله قبل الاستيراد.</p>
                </div>
                <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-3">
                  {IMPORT_FIELDS.map((field) => (
                    <div key={field.key} className="space-y-2 rounded-md border p-3">
                      <Label>{field.label}{field.required ? ' *' : ''}</Label>
                      <Select
                        value={columnMapping[field.key] || '__none__'}
                        onValueChange={(value) => {
                          setColumnMapping((prev) => ({
                            ...prev,
                            [field.key]: value === '__none__' ? undefined : value,
                          }));
                          setReport(null);
                          setResumeFromRowNumber(null);
                        }}
                      >
                        <SelectTrigger>
                          <SelectValue placeholder="اختر العمود" />
                        </SelectTrigger>
                        <SelectContent>
                          <SelectItem value="__none__">بدون ربط</SelectItem>
                          {selectedSheet.columns.map((column) => (
                            <SelectItem key={column.id} value={column.id}>
                              {column.label}
                            </SelectItem>
                          ))}
                        </SelectContent>
                      </Select>
                    </div>
                  ))}
                </div>
              </div>

              <div className="space-y-3">
                <div className="flex items-center justify-between">
                  <div>
                    <h3 className="font-medium">معاينة قبل الاستيراد</h3>
                    <p className="text-sm text-muted-foreground">يتم استيراد الصفوف الصالحة فقط. الصفوف التي فيها مشاكل ستظهر مع سبب الرفض.</p>
                  </div>
                  {selectedSheet && analysisRows.length > 0 ? (
                    <Button type="button" size="sm" variant="outline" onClick={handleDownloadAnnotatedExcel}>
                      <Download className="h-3.5 w-3.5" />
                      تنزيل بأرقام الأصناف المتوقعة
                    </Button>
                  ) : null}
                </div>
                <div className="overflow-x-auto rounded-md border">
                  <Table>
                    <TableHeader>
                      <TableRow>
                        <TableHead>الصف</TableHead>
                        {mappedFields.map((field) => (
                          <TableHead key={field.key}>{field.label}</TableHead>
                        ))}
                        <TableHead>الحالة</TableHead>
                      </TableRow>
                    </TableHeader>
                    <TableBody>
                      {previewRows.length === 0 ? (
                        <TableRow>
                          <TableCell colSpan={mappedFields.length + 2} className="py-6 text-center text-muted-foreground">
                            لا توجد بيانات للمعاينة.
                          </TableCell>
                        </TableRow>
                      ) : (
                        previewRows.map((row) => (
                          <TableRow key={row.rowNumber}>
                            <TableCell className="font-medium">{row.rowNumber}</TableCell>
                            {mappedFields.map((field) => (
                              <TableCell key={field.key}>
                                <div className="flex flex-col gap-1">
                                  <span>{row.values[field.key] || '-'}</span>
                                  {field.key === 'barcode' && row.autoGeneratedBarcode ? (
                                    <span className="text-[11px] text-emerald-700">تم توليد باركود تلقائيا</span>
                                  ) : null}
                                </div>
                              </TableCell>
                            ))}
                            <TableCell>
                              {row.issues.length === 0 ? (
                                <span className="inline-flex items-center gap-1 text-emerald-600">
                                  <CheckCircle2 className="h-4 w-4" />
                                  {row.existingItemId ? 'تحديث' : 'جديد'}
                                </span>
                              ) : (
                                <span className="inline-flex items-start gap-1 text-amber-600">
                                  <AlertCircle className="mt-0.5 h-4 w-4" />
                                  <span>{row.issues.join('، ')}</span>
                                </span>
                              )}
                            </TableCell>
                          </TableRow>
                        ))
                      )}
                    </TableBody>
                  </Table>
                </div>
              </div>

              {importProgress && importProgress.total > 0 ? (() => {
                const pct = Math.round((importProgress.done / importProgress.total) * 100);
                const elapsed = (Date.now() - importProgress.startedAt) / 1000;
                const avgSec = importProgress.done > 0 ? elapsed / importProgress.done : 0;
                const remaining = Math.max(0, Math.round(avgSec * (importProgress.total - importProgress.done)));
                const fmtTime = (s: number) => s < 60 ? `${s} ث` : `${Math.ceil(s / 60)} د`;
                return (
                  <div className="space-y-2 rounded-md border p-4">
                    <div className="flex items-center justify-between text-sm">
                      <span className="font-medium">جارٍ الاستيراد…</span>
                      <span className="text-muted-foreground">{importProgress.done} / {importProgress.total} صف ({pct}%)</span>
                    </div>
                    <div className="h-3 w-full overflow-hidden rounded-full bg-muted">
                      <div
                        className="h-full bg-primary transition-all duration-300"
                        style={{ width: `${pct}%` }}
                      />
                    </div>
                    <div className="flex items-center justify-between text-xs text-muted-foreground">
                      <span>الوقت المنقضي: {fmtTime(Math.round(elapsed))}</span>
                      {importProgress.done > 0 ? (
                        <span>متبقٍّ تقريبًا: {fmtTime(remaining)}</span>
                      ) : null}
                    </div>
                  </div>
                );
              })() : null}

              {report ? (
                <div className="rounded-md border p-4">
                  <h3 className="font-medium">نتيجة الاستيراد</h3>
                  {report.importedCount > 0 ? <p className="mt-2 text-sm">تم إنشاء {report.importedCount} صنف جديد.</p> : null}
                  {report.updatedCount > 0 ? <p className="mt-1 text-sm">تم تحديث {report.updatedCount} صنف موجود.</p> : null}
                  {report.failedRows.length > 0 ? (
                    <div className="mt-3 space-y-2 text-sm text-destructive">
                          {report.failedTotal > report.failedRows.length ? (
                            <p>إجمالي الصفوف الفاشلة: {report.failedTotal} (يتم عرض أول {report.failedRows.length} صف فقط).</p>
                          ) : null}
                      {report.failedRows.map((row) => (
                        <p key={`${row.rowNumber}-${row.message}`}>الصف {row.rowNumber}: {row.message}</p>
                      ))}
                    </div>
                  ) : null}
                </div>
              ) : null}
            </>
          ) : (
            <div className="rounded-md border p-6 text-center text-muted-foreground">
              ارفع ملفًا لبدء تحليل الأعمدة ومعاينة البيانات.
            </div>
          )}
        </div>

        <DialogFooter className="gap-2 sm:justify-between">
          <div className="flex items-center gap-2">
            <Button type="button" variant="outline" onClick={handleDownloadTemplate}>
              <Download className="h-4 w-4" />
              تنزيل قالب Excel
            </Button>
            {resultRows.length > 0 ? (
              <Button type="button" variant="outline" onClick={handleDownloadResultsReport}>
                <Download className="h-4 w-4" />
                تقرير النتائج
              </Button>
            ) : null}
          </div>
          <div className="flex items-center gap-2">
            <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
              إغلاق
            </Button>
            {resumeFromRowNumber ? (
              <Button type="button" variant="outline" onClick={() => handleImport(resumeFromRowNumber)} disabled={!selectedSheet || isImporting}>
                استئناف من الصف {resumeFromRowNumber}
              </Button>
            ) : null}
            <Button type="button" onClick={() => handleImport()} disabled={!selectedSheet || summary.valid === 0 || isImporting}>
              {isImporting ? <Loader2 className="h-4 w-4 animate-spin" /> : null}
              {isImporting ? 'جارٍ الاستيراد...' : 'استيراد الصفوف الصالحة'}
            </Button>
          </div>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
