/**
 * HistoryDashboard
 * Manages annotation history, model inventory, CSV import/export, and bulk model uploads.
 */
import React, { useMemo, useState, useRef } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { Clock, Plus, FileSpreadsheet, Search, X, Loader2, BookOpen, Download, Upload, AlertTriangle, Eye, EyeOff, Filter } from 'lucide-react';
import { exportToCSV } from '../../utils/exportUtils';
import { Button } from '../ui/button';
import { getFormSchema, deleteAnnotation, saveAnnotation } from '../../api/generated';
import AnnotationCard from './AnnotationCard';
import ModelCard from './ModelCard';
import { useLanguage } from '../../context/LanguageContext';
import { parseCSVToAnnotation } from '../../utils/importUtils';
import { calculateHash } from '../../utils/editorUtils';
import { buildModelUploadGroups, extractDroppedModelFiles, validateModelFileBinding } from '../../utils/modelUploadValidation';
import { useMessageDialog } from '../../hooks/useMessageDialog';
import { buildApiUrl } from '../../utils/api';

const normalizeAnnotatorName = (value) => String(value || '').trim().toLowerCase();

export default function HistoryDashboard({ onSelectModel, onAddNew, customData, currentAnnotatorName = '', selectedAtlasId, isLoading, atlases, onAddAnnotation, filterAtlasId, setFilterAtlasId }) {
  const { t, lang } = useLanguage();
  const { alert: showAlert, confirm } = useMessageDialog();
  const queryClient = useQueryClient();

  const [activeTab, setActiveTab] = useState('annotations');
  const [searchTerm, setSearchTerm] = useState("");
  const [selectedIds, setSelectedIds] = useState(new Set());
  const [isExporting, setIsExporting] = useState(false);
  const [isImporting, setIsImporting] = useState(false);
  const [checkFilter, setCheckFilter] = useState('all');

  const [pendingImportsQueue, setPendingImportsQueue] = useState([]);
  const [allDataWaitingForFiles, setAllDataWaitingForFiles] = useState([]);
  const [pendingImportConflicts, setPendingImportConflicts] = useState([]);
  const [importSessionStats, setImportSessionStats] = useState(null);
  const [isBulkDropActive, setIsBulkDropActive] = useState(false);
  const [isMissingFilesDropActive, setIsMissingFilesDropActive] = useState(false);

  const csvInputRef = useRef(null);
  const filesInputRef = useRef(null);
  const modelsInputRef = useRef(null);

  const schemaAtlasId = useMemo(() => {
    if (selectedAtlasId && selectedAtlasId !== 'all') return selectedAtlasId;
    const defaultAtlas = atlases?.find(a => a.je_vychozi || a.id === 'som-facial-somatoscopy-atlas');
    return defaultAtlas ? defaultAtlas.id : null;
  }, [selectedAtlasId, atlases]);

  const selectedAtlasName = useMemo(() => {
    if (!selectedAtlasId || selectedAtlasId === 'all') return t('allAtlases');

    const selectedAtlas = atlases?.find(atlas => String(atlas.id) === String(selectedAtlasId));
    if (selectedAtlas) {
      return lang === 'cs' ? selectedAtlas.nazev_cs : selectedAtlas.nazev_en;
    }

    return String(selectedAtlasId);
  }, [selectedAtlasId, atlases, lang, t]);

  const { data: schemaResponse } = useQuery({
    queryKey: ['formSchema', schemaAtlasId],
    queryFn: () => getFormSchema({ query: { atlasId: schemaAtlasId } }),
    enabled: !!schemaAtlasId,
  });

  const { data: exportSchemaResponse } = useQuery({
    queryKey: ['formSchema', 'all-for-export'],
    queryFn: () => getFormSchema({}),
    enabled: activeTab === 'annotations',
  });

  const { data: modelsData, isLoading: modelsLoading } = useQuery({
    queryKey: ['models', activeTab],
    queryFn: async () => {
      const r = await fetch(buildApiUrl('/api/models'));
      if (!r.ok) throw new Error('Failed to load models');
      return r.json();
    },
    enabled: activeTab === 'models',
  });

  const schema = schemaResponse?.data || [];
  const exportSchema = exportSchemaResponse?.data || schema;
  const exportOrderedTraitIds = useMemo(
    () => exportSchema.flatMap(section => section.znaky?.map(z => z.id) || []),
    [exportSchema]
  );

  const displayAnnotations = useMemo(() => {
    const list = customData || [];
    return list
      .filter(item => {
        // Search filter
        const matchesSearch = item.modelLabel?.toLowerCase().includes(searchTerm.toLowerCase()) ||
                             item.annotator?.toLowerCase().includes(searchTerm.toLowerCase());
        
        // Check status filter
        if (checkFilter === 'unchecked') return matchesSearch && !item.isChecked;
        if (checkFilter === 'checked') return matchesSearch && item.isChecked;
        return matchesSearch;
      })
      .sort((a, b) => new Date(b.lastUpdated) - new Date(a.lastUpdated));
  }, [customData, searchTerm, checkFilter]);

  const hasManualSelection = selectedIds.size > 0;
  const hasFilteredAnnotationScope = activeTab === 'annotations' && (
    searchTerm.trim() !== '' ||
    checkFilter !== 'all' ||
    filterAtlasId !== 'all'
  );

  const exportButtonClass = hasManualSelection
    ? 'bg-blue-600 hover:bg-blue-700 shadow-blue-200'
    : hasFilteredAnnotationScope
      ? 'bg-amber-600 hover:bg-amber-700 shadow-amber-200'
      : 'bg-green-600 hover:bg-green-700 shadow-green-200';

  const exportButtonLabel = hasManualSelection
    ? t('exportSelection').replace('{count}', selectedIds.size)
    : hasFilteredAnnotationScope
      ? t('exportFilter').replace('{count}', displayAnnotations.length)
      : t('exportAll');

  const displayModels = useMemo(() => {
    const list = modelsData || [];
    const annotationsByModel = {};
    (customData || []).forEach(ann => {
      const modelId = ann.modelLabel || ann.modelId;
      if (!annotationsByModel[modelId]) annotationsByModel[modelId] = [];
      annotationsByModel[modelId].push(ann);
    });
    return list.map(model => ({
      ...model,
      annotations: annotationsByModel[model.external_id] || []
    })).filter(item => {
      // Search filter only
      const matchesSearch = item.external_id?.toLowerCase().includes(searchTerm.toLowerCase());
      return matchesSearch;
    });
  }, [modelsData, customData, searchTerm]);

  const processAndSaveRow = async (data, files = {}) => {
    const targetAtlas = atlases.find(a => 
      String(a.id) === String(data.atlasId) || 
      a.nazev_cs === data.atlasName || 
      a.nazev_en === data.atlasName
    );

    if (!targetAtlas) return false;

    const normalizedCurrentAnnotator = normalizeAnnotatorName(currentAnnotatorName);
    const normalizedImportedChecker = normalizeAnnotatorName(data.checkerName);
    const shouldRemainChecked = Boolean(data.isChecked) &&
      Boolean(normalizedCurrentAnnotator) &&
      normalizedImportedChecker === normalizedCurrentAnnotator;

    try {
      const response = await saveAnnotation({
        body: {
          atlasId: targetAtlas.id, 
          modelId: data.modelId,
          annotatorName: data.annotatorName,
          fileHash: data.fileHash,
          values: JSON.stringify(data.values),
          isChecked: shouldRemainChecked,
          checkerName: shouldRemainChecked ? currentAnnotatorName.trim() : '',
          modelFile: files.objFile,
          mtlFile: files.mtlFile,
          textureFile: files.imgFile,
        }
      });

      if (response.error) {
        throw response.error;
      }

      return true;
    } catch (err) {
      console.error('Saving imported row failed:', err);
      return false;
    }
  };

  const formatImportDate = (value) => {
    if (!value) return t('valueNotSpecified');

    const parsedDate = new Date(value);
    if (Number.isNaN(parsedDate.getTime())) return String(value);

    return parsedDate.toLocaleString(lang === 'cs' ? 'cs-CZ' : 'en-US');
  };

  const buildImportSummaryItems = ({ added = 0, replaced = 0, skipped = 0, waiting = 0, failed = 0 }) => ([
    { label: t('importSummaryAddedLabel'), value: added },
    { label: t('importSummaryReplacedLabel'), value: replaced },
    { label: t('importSummarySkippedLabel'), value: skipped },
    { label: t('importSummaryWaitingLabel'), value: waiting },
    { label: t('importSummaryFailedLabel'), value: failed },
  ]);

  const finalizeImportSession = async (stats) => {
    if (!stats) return;

    if (stats.added > 0 || stats.replaced > 0) {
      await queryClient.invalidateQueries({ queryKey: ['annotations'] });
    }

    await showAlert({
      title: t('dialogNoticeTitle'),
      message: t('importSummaryMessage'),
      detailsItems: buildImportSummaryItems(stats),
      tone: stats.failed > 0 ? 'warning' : 'info',
    });
  };

  const handleResolveImportConflict = async (useImported) => {
    const currentConflict = pendingImportConflicts[0];
    if (!currentConflict || !importSessionStats) return;

    setIsImporting(true);
    const nextStats = { ...importSessionStats };

    if (useImported) {
      const saved = await processAndSaveRow(currentConflict.row);
      if (saved) nextStats.replaced++;
      else nextStats.failed++;
    } else {
      nextStats.skipped++;
    }

    const nextConflicts = pendingImportConflicts.slice(1);
    setPendingImportConflicts(nextConflicts);

    if (nextConflicts.length === 0) {
      setImportSessionStats(null);
      await finalizeImportSession(nextStats);
    } else {
      setImportSessionStats(nextStats);
    }

    setIsImporting(false);
  };

  const handleImportCSV = async (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    setIsImporting(true);
    try {
      setPendingImportConflicts([]);
      setImportSessionStats(null);

      const schemaRes = await fetch(buildApiUrl('/api/form-schema'));
      const megaSchema = await schemaRes.json();
      const importedList = await parseCSVToAnnotation(file, megaSchema, lang, atlases);
      const csvRows = Array.isArray(importedList) ? importedList : [importedList];
      
      const currentAnnotations = customData || [];
      const modelsRes = await fetch(buildApiUrl('/api/models'));
      const allModels = modelsRes.ok ? await modelsRes.json() : [];
      
      const queueForFiles = new Map(); 
      const waitingList = [];
      const conflicts = [];
      const importStats = {
        added: 0,
        replaced: 0,
        skipped: 0,
        waiting: 0,
        failed: 0,
      };

      for (const row of csvRows) {
        const matchingAnnotation = currentAnnotations.find((annotation) => {
          const annotationFileHash = annotation.fileHash || annotation.file_hash;
          const annotationAtlasId = String(annotation.atlasId || annotation.atlas_id || '');
          const annotationAnnotator = normalizeAnnotatorName(annotation.annotator || annotation.annotatorName);

          return annotationFileHash === row.fileHash &&
            annotationAtlasId === String(row.atlasId || '') &&
            annotationAnnotator === normalizeAnnotatorName(row.annotatorName);
        });

        if (matchingAnnotation) {
          row.annotationId = matchingAnnotation.annotationId;
          conflicts.push({ row, existing: matchingAnnotation });
          continue;
        }

        const modelInDb = allModels.find(m => m.file_hash === row.fileHash);
        if (modelInDb) {
          const added = await processAndSaveRow(row);
          if (added) importStats.added++;
          else importStats.failed++;
        } else {
          waitingList.push(row);
          if (!queueForFiles.has(row.fileHash)) queueForFiles.set(row.fileHash, row);
        }
      }

      setAllDataWaitingForFiles(waitingList);
      setPendingImportsQueue(Array.from(queueForFiles.values()));
      importStats.waiting = waitingList.length;

      if (conflicts.length > 0) {
        setPendingImportConflicts(conflicts);
        setImportSessionStats(importStats);
      } else {
        await finalizeImportSession(importStats);
      }
    } catch (error) {
      console.error('CSV import failed:', error);
      await showAlert({
        title: t('dialogErrorTitle'),
        message: t('importError'),
        tone: 'error',
      });
    } finally {
      setIsImporting(false);
      e.target.value = "";
    }
  };

  const handleMissingFilesSelection = async (files) => {
    const [group] = await buildModelUploadGroups(files);
    const objFile = group?.obj || null;
    const mtlFile = group?.mtl || null;
    const imgFile = group?.texture || null;

    if (!objFile || pendingImportsQueue.length === 0) return;

    const relationCheck = await validateModelFileBinding({
      objFile,
      mtlFile,
      textureFile: imgFile
    });
    if (!relationCheck.isValid) {
      await showAlert({
        title: t('dialogWarningTitle'),
        message: t('filesNotCorresponding'),
        details: t(relationCheck.messageKey),
        tone: 'warning',
      });
      return;
    }

    const currentModel = pendingImportsQueue[0];
    const uploadedHash = await calculateHash(objFile);

    if (uploadedHash !== currentModel.fileHash) {
      await showAlert({
        title: t('dialogWarningTitle'),
        message: t('importHashMismatch'),
        tone: 'warning',
      });
      return;
    }

    setIsImporting(true);
    const rowsToSave = allDataWaitingForFiles.filter(row => row.fileHash === uploadedHash);
    let savedCount = 0;
    let failedCount = 0;

    for (const row of rowsToSave) {
      const saved = await processAndSaveRow(row, { objFile, mtlFile, imgFile });
      if (saved) savedCount++;
      else failedCount++;
    }

    const nextQueue = pendingImportsQueue.slice(1);
    setPendingImportsQueue(nextQueue);
    setAllDataWaitingForFiles(prev => prev.filter(row => row.fileHash !== uploadedHash));
    if (savedCount > 0) {
      await queryClient.invalidateQueries({ queryKey: ['annotations'] });
    }

    if (failedCount > 0) {
      await showAlert({
        title: t('dialogWarningTitle'),
        message: t('importError'),
        detailsItems: buildImportSummaryItems({
          added: savedCount,
          replaced: 0,
          skipped: 0,
          waiting: allDataWaitingForFiles.length - rowsToSave.length,
          failed: failedCount,
        }),
        tone: 'warning',
      });
    }

    setIsImporting(false);
  };

  const handleMissingFilesUpload = async (e) => {
    try {
      await handleMissingFilesSelection(Array.from(e.target.files || []));
    } finally {
      e.target.value = "";
    }
  };

  const handleExport = async () => {
    const ids = selectedIds.size > 0 ? selectedIds : new Set(displayAnnotations.map(a => a.annotationId));
    if (ids.size === 0) return;
    setIsExporting(true);
    try {
      const res = await fetch(buildApiUrl(`/export/full?lang=${encodeURIComponent(lang)}`));
      const data = await res.json();
      const filtered = data
        .filter(i => ids.has(i.annotationId) || ids.has(i.id))
        .filter(i => selectedAtlasId === 'all' || i.atlasId === selectedAtlasId);
      const exportContext = selectedIds.size > 0
        ? t('exportContextSelection')
        : hasFilteredAnnotationScope
          ? t('exportContextFilter')
          : t('exportContextAll');
      exportToCSV(filtered, t, lang, `${t('exportFileNameBase')}${exportContext}_${new Date().getTime()}.csv`, exportOrderedTraitIds, exportSchema);
    } catch (error) {
      console.error('Export failed:', error);
      await showAlert({
        title: t('dialogErrorTitle'),
        message: t('exportDatabaseError'),
        tone: 'error',
      });
    } finally { setIsExporting(false); }
  };

  const handleSingleExport = async (e, item) => {
    e.stopPropagation();
    const res = await fetch(buildApiUrl(`/annotations/${item.annotationId}?lang=${encodeURIComponent(lang)}`));
    const data = await res.json();
    if (res.ok && data) exportToCSV([data], t, lang, `export_${item.modelLabel}.csv`, exportOrderedTraitIds, exportSchema);
  };

  const handleUploadModelsSelection = async (files) => {
    const fileGroups = await buildModelUploadGroups(files);

    if (files.length > 0 && fileGroups.length === 0) {
      await showAlert({
        title: t('dialogWarningTitle'),
        message: t('missingObjFile'),
        tone: 'warning',
      });
      return;
    }

    let successCount = 0;
    const invalidBindings = [];
    const duplicateNames = [];
    const duplicateModels = [];
    const failedModels = [];

    for (const group of fileGroups) {
      const { modelId } = group;
      if (!group.obj || !group.mtl || !group.texture) {
        invalidBindings.push(`${modelId}: ${t('requireCompleteModelSet')}`);
        continue;
      }

      const relationCheck = await validateModelFileBinding({
        objFile: group.obj,
        mtlFile: group.mtl,
        textureFile: group.texture
      });

      if (!relationCheck.isValid) {
        invalidBindings.push(`${modelId}: ${t(relationCheck.messageKey)}`);
        continue;
      }

      const formData = new FormData();
      formData.append('modelId', modelId);
      formData.append('modelFile', group.obj);
      if (group.mtl) formData.append('mtlFile', group.mtl);
      if (group.texture) formData.append('textureFile', group.texture);

      try {
        const res = await fetch(buildApiUrl('/api/models'), { method: 'POST', body: formData });
        const payload = await res.json().catch(() => ({}));

        if (res.status === 409) {
          if (payload.errorCode === 'modelNameAlreadyExists') {
            const existingName = payload.existingModelName || payload.message || 'unknown';
            duplicateNames.push(`${modelId} -> ${existingName}`);
            continue;
          }

          const existingName = payload.existingModelName || payload.message || payload.existingModelId || 'unknown';
          duplicateModels.push(`${modelId} -> ${existingName}`);
          continue;
        }

        if (!res.ok) {
          failedModels.push(modelId);
          continue;
        }

        successCount++;
      } catch (err) { console.error(err); }
    }

    if (invalidBindings.length > 0) {
      await showAlert({
        title: t('dialogWarningTitle'),
        message: t('filesNotCorresponding'),
        details: invalidBindings.join('\n'),
        tone: 'warning',
      });
    }

    if (duplicateModels.length > 0) {
      await showAlert({
        title: t('modelExistsTitle'),
        message: t('modelsAlreadyUploaded'),
        details: duplicateModels.join('\n'),
        tone: 'warning',
      });
    }

    if (duplicateNames.length > 0) {
      await showAlert({
        title: t('modelExistsTitle'),
        message: t('modelWithSameNameExists'),
        details: duplicateNames.join('\n'),
        tone: 'warning',
      });
    }

    if (failedModels.length > 0) {
      await showAlert({
        title: t('dialogErrorTitle'),
        message: t('uploadError'),
        details: failedModels.join(', '),
        tone: 'error',
      });
    }

    if (successCount > 0) {
      await queryClient.invalidateQueries({ queryKey: ['models'] });
      await showAlert({
        title: t('dialogNoticeTitle'),
        message: t('modelsUploadedCount').replace('{count}', successCount),
        tone: 'info',
      });
    }
  };

  const handleUploadModels = async (e) => {
    try {
      await handleUploadModelsSelection(Array.from(e.target.files || []));
    } finally {
      e.target.value = "";
    }
  };

  const handleBulkDragState = (event, active) => {
    event.preventDefault();
    event.stopPropagation();
    setIsBulkDropActive(active);
  };

  const handleMissingFilesDragState = (event, active) => {
    event.preventDefault();
    event.stopPropagation();
    setIsMissingFilesDropActive(active);
  };

  const handleBulkDrop = async (event) => {
    event.preventDefault();
    event.stopPropagation();
    setIsBulkDropActive(false);
    const files = await extractDroppedModelFiles(event);
    await handleUploadModelsSelection(files);
  };

  const handleMissingFilesDrop = async (event) => {
    event.preventDefault();
    event.stopPropagation();
    setIsMissingFilesDropActive(false);
    const files = await extractDroppedModelFiles(event);
    await handleMissingFilesSelection(files);
  };

  const toggleSelection = (id) => {
    setSelectedIds(prev => {
      const next = new Set(prev);
      if (next.has(id)) next.delete(id); else next.add(id);
      return next;
    });
  };

  const handleDelete = async (e, item) => {
    e.stopPropagation();
    const shouldDelete = await confirm({
      title: t('dialogConfirmTitle'),
      message: t('deleteConfirm').replace('{model}', item.modelLabel).replace('{annotator}', item.annotator),
      tone: 'danger',
      confirmLabel: t('dialogDeleteAction'),
    });
    if (!shouldDelete) return;
    await deleteAnnotation({ path: { annotationId: item.annotationId } });
    queryClient.invalidateQueries({ queryKey: ['annotations'] });
  };

  const handleDeleteModel = async (e, model) => {
    e.stopPropagation();
    const count = model.annotations?.length || 0;
    const message = count > 0
      ? t('deleteModelWithAnnotationsConfirm').replace('{count}', count)
      : t('deleteModelConfirm');
    const shouldDeleteModel = await confirm({
      title: t('dialogConfirmTitle'),
      message,
      tone: 'danger',
      confirmLabel: t('dialogDeleteAction'),
    });
    if (!shouldDeleteModel) return;
    try {
      await fetch(buildApiUrl(`/api/models/${model.id}`), { method: 'DELETE' });
      queryClient.invalidateQueries({ queryKey: ['models'] });
      queryClient.invalidateQueries({ queryKey: ['annotations'] });
    } catch (error) { console.error(error); }
  };

  if (isLoading) return <div className="flex flex-col justify-center items-center h-64 gap-4"><Loader2 className="animate-spin text-blue-600" size={40} /><p className="text-slate-500 font-medium">{t('loadingHistory')}</p></div>;

  return (
    <div className="max-w-7xl mx-auto p-6 lg:p-10">
      <input type="file" ref={csvInputRef} onChange={handleImportCSV} accept=".csv" className="hidden" />
      <input type="file" ref={filesInputRef} onChange={handleMissingFilesUpload} accept=".obj,.mtl,.jpg,.png,.jpeg" multiple directory="" webkitdirectory="" className="hidden" />
      <input type="file" ref={modelsInputRef} onChange={handleUploadModels} accept=".obj,.mtl,.jpg,.png,.jpeg" multiple directory="" webkitdirectory="" className="hidden" />

      {pendingImportConflicts[0] && (
        <div className="mb-10 p-8 bg-sky-50 border-2 border-sky-200 rounded-[40px] flex flex-col gap-6 shadow-xl animate-in fade-in zoom-in duration-300">
          <div className="flex flex-col md:flex-row md:items-start md:justify-between gap-6">
            <div className="flex items-start gap-6">
              <div className="w-16 h-16 bg-white rounded-3xl flex items-center justify-center text-sky-600 border border-sky-100 shadow-sm shrink-0">
                <AlertTriangle size={32} />
              </div>
              <div>
                <div className="flex items-center gap-3 mb-2 flex-wrap">
                  <h4 className="font-black text-sky-900 uppercase text-xs tracking-widest">{t('importConflictTitle')}</h4>
                  <span className="bg-sky-600 text-white text-[10px] px-2.5 py-1 rounded-full font-black uppercase">
                    {pendingImportConflicts.length} {t('remaining')}
                  </span>
                </div>
                <p className="text-sky-900 text-lg font-bold leading-tight">
                  {t('confirmImportOverwrite')
                    .replace('{model}', pendingImportConflicts[0].row.modelId)
                    .replace('{date}', formatImportDate(pendingImportConflicts[0].existing.lastUpdated || pendingImportConflicts[0].existing.savedAt || pendingImportConflicts[0].existing.createdAt))}
                </p>
              </div>
            </div>
          </div>

          <div className="grid gap-4 md:grid-cols-2">
            <div className="rounded-3xl border border-slate-200 bg-white p-5 shadow-sm">
              <div className="text-[10px] font-black uppercase tracking-widest text-slate-500 mb-2">{t('importConflictExistingLabel')}</div>
              <div className="text-base font-bold text-slate-900">{pendingImportConflicts[0].existing.modelLabel || pendingImportConflicts[0].row.modelId}</div>
              <div className="text-sm text-slate-600 mt-1">{t('importConflictExisting').replace('{annotator}', pendingImportConflicts[0].existing.annotator || pendingImportConflicts[0].existing.annotatorName || t('valueNotSpecified'))}</div>
              <div className="text-sm text-slate-500 mt-1">{t('importConflictUpdatedAt').replace('{date}', formatImportDate(pendingImportConflicts[0].existing.lastUpdated || pendingImportConflicts[0].existing.savedAt || pendingImportConflicts[0].existing.createdAt))}</div>
            </div>

            <div className="rounded-3xl border border-sky-200 bg-sky-100/70 p-5 shadow-sm">
              <div className="text-[10px] font-black uppercase tracking-widest text-sky-700 mb-2">{t('importConflictImportedLabel')}</div>
              <div className="text-base font-bold text-slate-900">{pendingImportConflicts[0].row.modelId}</div>
              <div className="text-sm text-slate-700 mt-1">{t('importConflictImported').replace('{annotator}', pendingImportConflicts[0].row.annotatorName || t('valueNotSpecified'))}</div>
              <div className="text-sm text-slate-500 mt-1">{t('importConflictUpdatedAt').replace('{date}', t('importConflictCurrentImport'))}</div>
            </div>
          </div>

          <div className="flex flex-col sm:flex-row gap-3 sm:justify-end">
            <Button
              variant="outline"
              onClick={() => handleResolveImportConflict(false)}
              disabled={isImporting}
              className="h-12 rounded-2xl px-6"
            >
              {t('importConflictKeepExisting')}
            </Button>
            <Button
              onClick={() => handleResolveImportConflict(true)}
              disabled={isImporting}
              className="h-12 rounded-2xl px-6 bg-sky-600 hover:bg-sky-700 text-white"
            >
              {t('importConflictUseImported')}
            </Button>
          </div>
        </div>
      )}

      {pendingImportsQueue[0] && (
        <div
          onDragEnter={(event) => handleMissingFilesDragState(event, true)}
          onDragOver={(event) => handleMissingFilesDragState(event, true)}
          onDragLeave={(event) => handleMissingFilesDragState(event, false)}
          onDrop={handleMissingFilesDrop}
          className={`mb-10 p-8 border-2 rounded-[40px] flex flex-col md:flex-row items-center justify-between gap-8 shadow-xl animate-in fade-in zoom-in duration-300 transition-all ${isMissingFilesDropActive ? 'bg-amber-100 border-amber-400 ring-4 ring-amber-300/50' : 'bg-amber-50 border-amber-200'}`}
        >
          <div className="flex items-center gap-6">
            <div className="w-16 h-16 bg-white rounded-3xl flex items-center justify-center text-amber-600 border border-amber-100 shadow-sm">
              <AlertTriangle size={32} />
            </div>
            <div>
              <div className="flex items-center gap-3 mb-1">
                <h4 className="font-black text-amber-900 uppercase text-xs tracking-widest">{t('importModelMissingTitle')}</h4>
                <span className="bg-amber-600 text-white text-[10px] px-2.5 py-1 rounded-full font-black uppercase">
                  {pendingImportsQueue.length} {t('remaining')}
                </span>
              </div>
              <p className="text-amber-800 text-lg font-bold leading-tight">
                {t('importModelMissingDesc').replace('{model}', pendingImportsQueue[0].modelId)}
              </p>
            </div>
          </div>
          <div className="flex gap-3 shrink-0">
            <Button variant="ghost" onClick={() => { setPendingImportsQueue([]); setAllDataWaitingForFiles([]); }} className="text-amber-700 font-bold px-6 h-14 rounded-2xl">{t('cancelAll')}</Button>
            <Button onClick={() => filesInputRef.current?.click()} className="bg-amber-600 hover:bg-amber-700 text-white font-black px-10 h-14 rounded-2xl shadow-lg flex items-center gap-3">
              <Upload size={20} /> {t('uploadRequiredFiles')}
            </Button>
          </div>
          <div className="w-full md:basis-full text-center text-xs font-bold uppercase tracking-[0.16em] text-amber-700/80">
            {isMissingFilesDropActive ? t('dropModelFolderHere') : t('uploadHint')}
          </div>
        </div>
      )}

      <div className="flex flex-col md:flex-row items-start md:items-center justify-between mb-10 gap-6">
        <div>
          <h2 className="text-4xl font-black text-slate-900 tracking-tighter uppercase mb-1">
            {activeTab === 'annotations' ? t('myAnnotations') : t('models')}
          </h2>
          <div className="flex items-center gap-3">
             <span className="inline-flex items-center px-3 py-1 rounded-full text-[10px] font-black uppercase bg-blue-600 text-white shadow-md">
                <BookOpen size={12} className="mr-2" />
               {selectedAtlasName}
             </span>
          </div>
        </div>

        <div className="flex flex-wrap gap-3 w-full md:w-auto items-center justify-end">
          <div className="relative flex-1 sm:w-80 min-w-[240px]">
            <Search className="absolute left-4 top-1/2 -translate-y-1/2 text-slate-400" size={20} />
            <input
              type="text"
              placeholder={t('searchPlaceholder')}
              value={searchTerm}
              onChange={(e) => setSearchTerm(e.target.value)}
              className="w-full pl-12 pr-4 h-14 bg-white border-2 border-slate-100 rounded-2xl outline-none focus:border-blue-500 transition-all shadow-sm"
            />
          </div>

          {activeTab === 'annotations' && (
            <>
              <Button onClick={() => csvInputRef.current?.click()} variant="outline" className="rounded-2xl px-8 h-14 border-2 border-slate-100 bg-white text-blue-600 font-black hover:bg-blue-50 transition-all shadow-sm flex items-center gap-3">
                {isImporting ? <Loader2 className="animate-spin" size={20} /> : <Upload size={20} />}
                <span className="uppercase tracking-widest text-xs">{t('importCSV')}</span>
              </Button>
                <Button onClick={handleExport} disabled={isExporting || displayAnnotations.length === 0} className={`rounded-2xl px-10 h-14 shadow-xl transition-all text-white font-black flex items-center gap-3 ${exportButtonClass}`}>
                 {isExporting ? <Loader2 className="animate-spin" /> : <FileSpreadsheet size={20} />}
                  <span className="uppercase tracking-widest text-xs">{exportButtonLabel}</span>
              </Button>
            </>
          )}

          {activeTab === 'models' && (
            <div
              onDragEnter={(event) => handleBulkDragState(event, true)}
              onDragOver={(event) => handleBulkDragState(event, true)}
              onDragLeave={(event) => handleBulkDragState(event, false)}
              onDrop={handleBulkDrop}
              className={`flex flex-col items-end gap-1.5 rounded-[24px] border-2 border-dashed p-1.5 transition-all ${isBulkDropActive ? 'border-purple-400 bg-purple-50 shadow-lg' : 'border-transparent'}`}
            >
              <Button onClick={() => modelsInputRef.current?.click()} className="rounded-2xl px-8 h-14 bg-purple-600 hover:bg-purple-700 shadow-xl transition-all text-white font-black flex items-center gap-3">
                <Upload size={20} />
                {t('uploadModels')}
              </Button>
              <p className="px-2 text-right text-[11px] font-semibold tracking-[0.04em] text-slate-500">
                {isBulkDropActive ? t('dropModelFoldersHere') : t('uploadFoldersHint')}
              </p>
            </div>
          )}
        </div>
      </div>

      <div className="mb-8">
        <div className="flex items-center gap-4 mb-4">
          <Filter size={16} className="text-slate-400" />
          <span className="text-sm font-bold text-slate-600 uppercase tracking-wider">{t('filterByAtlas')}</span>
        </div>
        <div className="flex gap-2 flex-wrap">
          <button
            onClick={() => setFilterAtlasId('all')}
            className={`px-4 py-2 rounded-full text-xs font-bold transition-all ${filterAtlasId === 'all' ? 'bg-blue-600 text-white shadow-md' : 'bg-slate-100 text-slate-500 hover:bg-slate-200'}`}
          >
            {t('allAtlases')}
          </button>
          {atlases.map(atlas => (
            <button
              key={atlas.id}
              onClick={() => setFilterAtlasId(atlas.id)}
              className={`px-4 py-2 rounded-full text-xs font-bold transition-all flex items-center gap-2 ${filterAtlasId === atlas.id ? 'bg-blue-600 text-white shadow-md' : 'bg-slate-100 text-slate-500 hover:bg-slate-200'}`}
            >
              {(atlas.je_vychozi || atlas.id === 'ant-anthropological-atlas-of-facial-features') && <BookOpen size={12} />}
              {lang === 'cs' ? atlas.nazev_cs : atlas.nazev_en}
            </button>
          ))}
        </div>
      </div>

      <div className="flex flex-col md:flex-row md:items-center justify-between mb-8 gap-4">
        <div className="flex gap-1 bg-slate-100 p-1.5 rounded-2xl w-fit">
            <button onClick={() => setActiveTab('annotations')} className={`px-6 py-2.5 rounded-xl font-black text-xs uppercase transition-all ${activeTab === 'annotations' ? 'bg-white text-blue-600 shadow-sm' : 'text-slate-500 hover:bg-white/50'}`}>{t('annotations')}</button>
            <button onClick={() => setActiveTab('models')} className={`px-6 py-2.5 rounded-xl font-black text-xs uppercase transition-all ${activeTab === 'models' ? 'bg-white text-blue-600 shadow-sm' : 'text-slate-500 hover:bg-white/50'}`}>{t('models')}</button>
        </div>

        {activeTab === 'annotations' && (
            <div className="flex items-center gap-2 bg-white border-2 border-slate-100 p-1.5 rounded-2xl shadow-sm">
                <Filter size={14} className="ml-2 text-slate-400" />
                <button onClick={() => setCheckFilter('all')} className={`px-4 py-2 rounded-xl text-[10px] font-black uppercase transition-all ${checkFilter === 'all' ? 'bg-slate-900 text-white' : 'text-slate-500 hover:bg-slate-50'}`}>{t('all') || 'Vše'}</button>
                <button onClick={() => setCheckFilter('unchecked')} className={`px-4 py-2 rounded-xl text-[10px] font-black uppercase transition-all ${checkFilter === 'unchecked' ? 'bg-amber-500 text-white' : 'text-slate-500 hover:bg-slate-50'}`}>{t('toCheck') || 'Ke kontrole'}</button>
                <button onClick={() => setCheckFilter('checked')} className={`px-4 py-2 rounded-xl text-[10px] font-black uppercase transition-all ${checkFilter === 'checked' ? 'bg-green-500 text-white' : 'text-slate-500 hover:bg-slate-50'}`}>{t('checkedOnly') || 'Zkontrolované'}</button>
            </div>
        )}

        {activeTab === 'models' && (
            <div className="flex items-center gap-2 bg-white border-2 border-slate-100 p-1.5 rounded-2xl shadow-sm">
                <Filter size={14} className="ml-2 text-slate-400" />
                <button onClick={() => setCheckFilter('all')} className={`px-4 py-2 rounded-xl text-[10px] font-black uppercase transition-all ${checkFilter === 'all' ? 'bg-slate-900 text-white' : 'text-slate-500 hover:bg-slate-50'}`}>{t('all') || 'Vše'}</button>
                <button onClick={() => setCheckFilter('unchecked')} className={`px-4 py-2 rounded-xl text-[10px] font-black uppercase transition-all ${checkFilter === 'unchecked' ? 'bg-amber-500 text-white' : 'text-slate-500 hover:bg-slate-50'}`}>{t('toCheck') || 'Ke kontrole'}</button>
                <button onClick={() => setCheckFilter('checked')} className={`px-4 py-2 rounded-xl text-[10px] font-black uppercase transition-all ${checkFilter === 'checked' ? 'bg-green-500 text-white' : 'text-slate-500 hover:bg-slate-50'}`}>{t('checkedOnly') || 'Zkontrolované'}</button>
            </div>
        )}
      </div>

        {activeTab === 'annotations' && (
          <div className="grid items-start grid-cols-1 gap-4 pb-32 md:grid-cols-2 lg:grid-cols-3 lg:gap-5 xl:grid-cols-4">
            <button onClick={onAddNew} className="bg-white border-[3px] border-dashed border-slate-100 rounded-[28px] p-5 flex flex-col items-center justify-center min-h-[280px] hover:bg-blue-50/50 hover:border-blue-200 transition-all group shadow-sm hover:shadow-xl relative overflow-hidden">
              <div className="w-14 h-14 bg-slate-50 group-hover:bg-blue-100 rounded-2xl flex items-center justify-center mb-4 transition-colors shadow-inner">
                <Plus size={28} className="text-slate-400 group-hover:text-blue-600" />
              </div>
              <span className="font-black text-slate-800 uppercase text-[11px] tracking-[0.18em] text-center">{t('newRecord')}</span>
            </button>

            {displayAnnotations.map((item) => (
              <AnnotationCard
                key={item.annotationId}
                item={item}
                onSelect={() => onSelectModel(item.annotationId)}
                onDelete={handleDelete}
                isSelected={selectedIds.has(item.annotationId)}
                onToggleSelection={(id) => toggleSelection(id)}
                onExport={(e, item) => handleSingleExport(e, item)}
              />
            ))}
          </div>
        )}

        {activeTab === 'models' && (
          <div className="flex flex-col gap-6 pb-32">
            {modelsLoading ? (
              <div className="flex min-h-[320px] items-center justify-center">
                <Loader2 className="animate-spin text-blue-600" size={40} />
              </div>
            ) : (
              displayModels.map((model) => (
                <ModelCard
                  key={model.id}
                  model={model}
                  checkFilter={checkFilter}
                  onAddAnnotation={() => onAddAnnotation(model)}
                  onDelete={handleDeleteModel}
                  onSelectAnnotation={onSelectModel}
                />
              ))
            )}
          </div>
        )}
    </div>
  );
}