'use client';

import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useRouter } from 'next/navigation';
import PageLayout from '../../components/PageLayout';
import TranslationWizardModal from './components/TranslationWizardModal';
import AddLanguageModal from './components/AddLanguageModal';
import DeleteLanguageModal from './components/DeleteLanguageModal';
import CategoryManagerModal from './components/CategoryManagerModal';
import ScanResultsModal from './components/ScanResultsModal';
import TranslationCoverageEditor from './components/TranslationCoverageEditor';
import LanguageManagementTopSection from './components/LanguageManagementTopSection';
import { useI18nScanWorkflow } from './hooks/useI18nScanWorkflow';
import { useLanguageManagementTranslations } from './hooks/useLanguageManagementTranslations';
import { useNamespaceCategories } from './hooks/useNamespaceCategories';
import { useModalAnimation } from './hooks/useModalAnimation';
import { useToast } from '../../components/toast/toastComponent';
import { isPageTransitioning } from '../../components/animation/pageTransitionEffect';
import {
  getAllTranslationKeys,
  getEnglishValue,
  useTranslation,
} from '../../i18n/useTranslation';

const CORE_LANGUAGES = new Set(['en', 'de']);
const AUTO_SCROLL_ON_SAVE_STORAGE_KEY = 'language-management-auto-scroll-on-save';

// ── namespace categories
const NAMESPACE_CATEGORIES: { label: string; namespaces: string[] }[] = [
  { label: 'General', namespaces: ['common', 'nav', 'footer', 'home'] },
  { label: 'Auth', namespaces: ['login', 'register', 'passwordReset'] },
  { label: 'Pages', namespaces: ['dashboard', 'profile', 'community', 'shop', 'memberships', 'affiliateLinks', 'aboutUs', 'news'] },
  { label: 'Coffee ABO', namespaces: ['coffeeSelection', 'coffeeSummary'] },
  { label: 'Account', namespaces: ['personalMatrix', 'referralManagement', 'quickactionDashboard', 'suspended'] },
  { label: 'Admin', namespaces: ['adminDashboard', 'userManagement', 'languageManagement', 'contractManagement'] },
  { label: 'Notifications', namespaces: ['toasts'] },
];

function groupKeys(keys: string[]): Record<string, string[]> {
  const groups: Record<string, string[]> = {};
  for (const key of keys) {
    const ns = key.split('.')[0];
    if (!groups[ns]) groups[ns] = [];
    groups[ns].push(key);
  }
  return groups;
}

export default function LanguageManagementPage() {
  const { t } = useTranslation();
  const router = useRouter();
  const { showToast } = useToast();

  const notifyAction = useCallback((notice: { variant: 'success' | 'error' | 'info' | 'warning'; message: string }) => {
    showToast({
      variant: notice.variant,
      message: notice.message,
      duration: notice.variant === 'error' ? 6000 : 3500,
    });
  }, [showToast]);

  const handleUnauthorized = useCallback(() => {
    router.push('/login');
  }, [router]);

  const {
    showScanModal,
    setShowScanModal,
    lastScanTime,
    isScanning,
    isAutoFixing,
    isAddingMissingKeys,
    scanError,
    workspaceScan,
    selectedFiles,
    fixableFiles,
    forceConvertToClient,
    setForceConvertToClient,
    scan,
    runFixSelected,
    addMissingKeys,
    toggleFileSelection,
    selectAllFiles,
    clearSelectedFiles,
  } = useI18nScanWorkflow({ onUnauthorized: handleUnauthorized });

  // ── all flat keys from the English source-of-truth
  const allKeys = useMemo(() => getAllTranslationKeys(), []);
  const keyGroups = useMemo(() => groupKeys(allKeys), [allKeys]);
  const namespaces = useMemo(() => Object.keys(keyGroups).sort(), [keyGroups]);

  const {
    data,
    isLoading: isTranslationsLoading,
    loadingPhase: translationsLoadingPhase,
    loadingProgress: translationsLoadingProgress,
    loadingLogs: translationsLoadingLogs,
    allLanguages,
    activeLang,
    setActiveLang,
    getDisplayValue,
    isDirty,
    saved,
    saveError,
    handleChange,
    handleSave,
    showAddModal,
    setShowAddModal,
    newCode,
    setNewCode,
    newName,
    setNewName,
    addError,
    setAddError,
    handleAddLanguage,
    deleteTarget,
    setDeleteTarget,
    handleDeleteLanguage,
    isBuiltin,
  } = useLanguageManagementTranslations({
    coreLanguages: CORE_LANGUAGES,
    onAction: notifyAction,
    onUnauthorized: handleUnauthorized,
  });

  const [showTranslationWizard, setShowTranslationWizard] = useState(false);
  const [wizardIndex, setWizardIndex] = useState(0);
  const [wizardInput, setWizardInput] = useState('');
  const [wizardMarkGlobal, setWizardMarkGlobal] = useState(false);
  const [wizardUseEnglishReference, setWizardUseEnglishReference] = useState(false);
  const [isWizardSavingStep, setIsWizardSavingStep] = useState(false);

  const [newGlobalKeySelection, setNewGlobalKeySelection] = useState('');
  const [reloadAfterScanClose, setReloadAfterScanClose] = useState(false);
  const [pendingAutoFixResult, setPendingAutoFixResult] = useState(false);

  const {
    activeCategory,
    setActiveCategory,
    showCategoryManagerModal,
    setShowCategoryManagerModal,
    isPreferencesDirty,
    preferencesHydrated,
    preferencesLoadingPhase,
    preferencesLoadingProgress,
    preferencesLoadingLogs,
    isSavingPreferences,
    savePreferences,
    categoriesWithKnownNamespaces,
    uncategorizedNamespaces,
    addNamespaceToCategory,
    removeNamespaceFromCategory,
    newCategoryLabel,
    setNewCategoryLabel,
    assignNamespaceByCategory,
    setAssignNamespaceByCategory,
    expandedCategoryId,
    setExpandedCategoryId,
    dragNamespace,
    setDragNamespace,
    handleCreateCategory,
    deleteCategory,
    globalKnownKeys,
    globalKeySet,
    addGlobalKey,
    removeGlobalKey,
    englishReferenceKeysByLanguage,
    englishReferenceKeySetByLanguage,
    setEnglishReferenceKey,
  } = useNamespaceCategories({
    namespaces,
    allKeys,
    defaultCategories: NAMESPACE_CATEGORIES,
    onAction: notifyAction,
    onUnauthorized: handleUnauthorized,
  });

  const hasUnsavedChanges = isDirty || isPreferencesDirty;
  const isInitialDataLoading = isTranslationsLoading || !preferencesHydrated;
  const initialLoadingProgress = Math.round((translationsLoadingProgress + preferencesLoadingProgress) / 2);
  const [isPageTransitionDone, setIsPageTransitionDone] = useState(() => !isPageTransitioning);
  const [showDelayedFetchingScreen, setShowDelayedFetchingScreen] = useState(false);
  const [showDelayedFetchLogs, setShowDelayedFetchLogs] = useState(false);
  const combinedLoadingLogs = useMemo(() => {
    const preferenceLines = preferencesLoadingLogs.map((line) => `[PREF] ${line}`);
    const translationLines = translationsLoadingLogs.map((line) => `[I18N] ${line}`);
    return [...preferenceLines, ...translationLines].slice(-18);
  }, [preferencesLoadingLogs, translationsLoadingLogs]);
  const { isRendered: isSaveBarRendered, isVisible: isSaveBarVisible } = useModalAnimation(hasUnsavedChanges);

  useEffect(() => {
    if (isPageTransitionDone) return;
    let rafId: number | null = null;

    const pollTransition = () => {
      if (!isPageTransitioning) {
        setIsPageTransitionDone(true);
        return;
      }
      rafId = window.requestAnimationFrame(pollTransition);
    };

    rafId = window.requestAnimationFrame(pollTransition);
    return () => {
      if (rafId) window.cancelAnimationFrame(rafId);
    };
  }, [isPageTransitionDone]);

  useEffect(() => {
    if (!isInitialDataLoading || !isPageTransitionDone) {
      setShowDelayedFetchingScreen(false);
      return;
    }

    const timeoutId = window.setTimeout(() => setShowDelayedFetchingScreen(true), 350);
    return () => window.clearTimeout(timeoutId);
  }, [isInitialDataLoading, isPageTransitionDone]);

  useEffect(() => {
    if (!showDelayedFetchingScreen) {
      setShowDelayedFetchLogs(false);
      return;
    }

    const timeoutId = window.setTimeout(() => setShowDelayedFetchLogs(true), 1400);
    return () => window.clearTimeout(timeoutId);
  }, [showDelayedFetchingScreen]);

  const showFetchingScreen = isInitialDataLoading && isPageTransitionDone && showDelayedFetchingScreen;
  const showWarmGap = isInitialDataLoading && isPageTransitionDone && !showDelayedFetchingScreen;

  // ── search / filter
  const [search, setSearch] = useState('');
  const [autoScrollOnPanelOpen, setAutoScrollOnPanelOpen] = useState(true);
  const [autoScrollOnSave, setAutoScrollOnSave] = useState(() => {
    if (typeof window === 'undefined') return false;
    return window.localStorage.getItem(AUTO_SCROLL_ON_SAVE_STORAGE_KEY) === '1';
  });
  const [activeNamespacePanel, setActiveNamespacePanel] = useState<string | null>(null);

  const languageManagementHeaderRef = useRef<HTMLDivElement | null>(null);
  const openedNamespacePanelRef = useRef<HTMLDivElement | null>(null);
  const openFromPanelClickRef = useRef(false);
  const saveBarRef = useRef<HTMLDivElement | null>(null);

  const [showScrollHint, setShowScrollHint] = useState(false);
  const scrollHintTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const { isRendered: isHintRendered, isVisible: isHintVisible } = useModalAnimation(showScrollHint);

  useEffect(() => {
    if (typeof window === 'undefined') return;
    window.localStorage.setItem(AUTO_SCROLL_ON_SAVE_STORAGE_KEY, autoScrollOnSave ? '1' : '0');
  }, [autoScrollOnSave]);

  const filteredGroups = useMemo(() => {
    const q = search.toLowerCase();
    if (!q) return keyGroups;
    const result: Record<string, string[]> = {};
    for (const [ns, keys] of Object.entries(keyGroups)) {
      const filtered = keys.filter(
        (k) =>
          k.toLowerCase().includes(q) ||
          getEnglishValue(k).toLowerCase().includes(q)
      );
      if (filtered.length > 0) result[ns] = filtered;
    }
    return result;
  }, [keyGroups, search]);

  // ── scan results: coverage per namespace
  const scanResults = useMemo(() => {
    return namespaces.map((ns) => {
      const keys = keyGroups[ns] ?? [];
      let translated = 0;
      if (activeLang === 'en') {
        translated = keys.length; // English is the source
      } else {
        translated = keys.filter((k) => getDisplayValue(k) !== '').length;
      }
      return { ns, total: keys.length, translated, missing: keys.length - translated };
    });
  }, [namespaces, keyGroups, activeLang, getDisplayValue]);


  const categoryNamespaces = useMemo(() => {
    if (activeCategory === 'all') return null; // null = no filter
    if (activeCategory === 'global') return [];
    return categoriesWithKnownNamespaces.find((c) => c.id === activeCategory)?.namespaces ?? [];
  }, [activeCategory, categoriesWithKnownNamespaces]);

  const filteredNs = useMemo(() => {
    if (activeCategory === 'global') return [];
    const base = Object.keys(filteredGroups).sort();
    if (!categoryNamespaces) return base;
    return base.filter((ns) => categoryNamespaces.includes(ns));
  }, [activeCategory, filteredGroups, categoryNamespaces]);

  // Keep active panel in sync with currently visible namespaces
  useEffect(() => {
    if (activeCategory === 'global') {
      setActiveNamespacePanel(null);
      return;
    }

    if (filteredNs.length === 0) {
      setActiveNamespacePanel(null);
      return;
    }

    if (!activeNamespacePanel || !filteredNs.includes(activeNamespacePanel)) {
      setActiveNamespacePanel(filteredNs[0]);
    }
  }, [activeCategory, filteredNs, activeNamespacePanel]);

  const totalKeys = allKeys.length;

  const isMissingForLanguage = (key: string, languageCode: string) => {
    if (languageCode === 'en') return false;
    if (globalKeySet.has(key)) return false;
    if (englishReferenceKeySetByLanguage[languageCode]?.has(key)) return false;

    const value = (data.translations[languageCode]?.[key] ?? '').trim();
    const englishValue = getEnglishValue(key).trim();
    return value === '' || value === englishValue;
  };

  const namespaceTranslationStats = useMemo(() => {
    const stats: Record<string, { total: number; translated: number; missing: number }> = {};

    for (const ns of namespaces) {
      const keys = keyGroups[ns] ?? [];
      const total = keys.length;
      let translated = 0;

      if (activeLang === 'en') {
        translated = total;
      } else {
        translated = keys.filter((k) => !isMissingForLanguage(k, activeLang)).length;
      }

      stats[ns] = { total, translated, missing: Math.max(total - translated, 0) };
    }

    return stats;
  }, [namespaces, keyGroups, activeLang, data.translations, globalKeySet]);

  const allTabStats = useMemo(() => {
    return Object.values(namespaceTranslationStats).reduce(
      (acc, cur) => ({
        total: acc.total + cur.total,
        translated: acc.translated + cur.translated,
        missing: acc.missing + cur.missing,
      }),
      { total: 0, translated: 0, missing: 0 }
    );
  }, [namespaceTranslationStats]);

  const categoryTabStats = useMemo(() => {
    const result: Record<string, { total: number; translated: number; missing: number }> = {};
    for (const cat of categoriesWithKnownNamespaces) {
      result[cat.id] = cat.namespaces.reduce(
        (acc, ns) => {
          const st = namespaceTranslationStats[ns] ?? { total: 0, translated: 0, missing: 0 };
          return {
            total: acc.total + st.total,
            translated: acc.translated + st.translated,
            missing: acc.missing + st.missing,
          };
        },
        { total: 0, translated: 0, missing: 0 }
      );
    }
    return result;
  }, [categoriesWithKnownNamespaces, namespaceTranslationStats]);

  const translationProgressPercent = useMemo(() => {
    if (allTabStats.total === 0) return 100;
    return Math.round((allTabStats.translated / allTabStats.total) * 100);
  }, [allTabStats]);

  const wizardMissingKeys = useMemo(() => {
    if (activeLang === 'en') return [] as string[];
    return allKeys.filter((k) => isMissingForLanguage(k, activeLang));
  }, [activeLang, allKeys, data.translations, globalKeySet]);

  const currentWizardKey = showTranslationWizard ? wizardMissingKeys[wizardIndex] ?? null : null;

  const globalFilteredKeys = useMemo(() => {
    const q = search.toLowerCase().trim();
    if (!q) return [...globalKnownKeys].sort();
    return globalKnownKeys
      .filter((key) => key.toLowerCase().includes(q) || getEnglishValue(key).toLowerCase().includes(q))
      .sort();
  }, [globalKnownKeys, search]);

  const availableGlobalKeyOptions = useMemo(() => {
    const globalSet = new Set(globalKnownKeys);
    return allKeys.filter((key) => !globalSet.has(key)).sort();
  }, [allKeys, globalKnownKeys]);

  const globalTabStats = useMemo(() => {
    const total = globalKnownKeys.length;
    // Global keys are intentionally the same across languages — never count as missing
    return { total, translated: total, missing: 0 };
  }, [globalKnownKeys]);

  useEffect(() => {
    if (!showTranslationWizard) return;
    if (wizardMissingKeys.length === 0) {
      setShowTranslationWizard(false);
      return;
    }
    if (wizardIndex > wizardMissingKeys.length - 1) {
      setWizardIndex(0);
      return;
    }

    const key = wizardMissingKeys[wizardIndex];
    setWizardInput(data.translations[activeLang]?.[key] ?? '');
    setWizardMarkGlobal(globalKnownKeys.includes(key));
    setWizardUseEnglishReference(Boolean(englishReferenceKeySetByLanguage[activeLang]?.has(key)));
  }, [showTranslationWizard, wizardIndex, wizardMissingKeys, data.translations, activeLang, globalKnownKeys, englishReferenceKeySetByLanguage]);

  const saveCurrentWizardValue = () => {
    if (!currentWizardKey) return;

    const trimmedWizardInput = wizardInput.trim();
    const englishValue = getEnglishValue(currentWizardKey).trim();
    const nextTranslations: Record<string, Record<string, string>> = {
      ...data.translations,
      [activeLang]: {
        ...(data.translations[activeLang] ?? {}),
      },
    };

    const nextGlobalKeysSet = new Set(globalKnownKeys);
    const nextEnglishReferenceKeysByLanguage = {
      ...englishReferenceKeysByLanguage,
      [activeLang]: [...(englishReferenceKeysByLanguage[activeLang] ?? [])],
    };
    const nextEnglishReferenceSet = new Set(nextEnglishReferenceKeysByLanguage[activeLang] ?? []);

    if (wizardUseEnglishReference) {
      nextTranslations[activeLang][currentWizardKey] = englishValue;
      handleChange(currentWizardKey, englishValue);

      setEnglishReferenceKey(activeLang, currentWizardKey, true);
      nextEnglishReferenceSet.add(currentWizardKey);

      if (wizardMarkGlobal) {
        addGlobalKey(currentWizardKey);
        nextGlobalKeysSet.add(currentWizardKey);
      } else {
        removeGlobalKey(currentWizardKey);
        nextGlobalKeysSet.delete(currentWizardKey);
      }

      nextEnglishReferenceKeysByLanguage[activeLang] = [...nextEnglishReferenceSet].sort((a, b) => a.localeCompare(b));
      return {
        nextTranslations,
        preferencesSnapshot: {
          globalKeys: [...nextGlobalKeysSet].sort((a, b) => a.localeCompare(b)),
          englishReferenceKeysByLanguage: nextEnglishReferenceKeysByLanguage,
        },
      };
    }

    // Global keys intentionally reuse the source term and don't require a local override.
    const nextValue = wizardMarkGlobal && trimmedWizardInput === englishValue
      ? ''
      : trimmedWizardInput;

    nextTranslations[activeLang][currentWizardKey] = nextValue;
    handleChange(currentWizardKey, nextValue);

    setEnglishReferenceKey(activeLang, currentWizardKey, false);
    nextEnglishReferenceSet.delete(currentWizardKey);

    if (wizardMarkGlobal) {
      addGlobalKey(currentWizardKey);
      nextGlobalKeysSet.add(currentWizardKey);
    } else {
      removeGlobalKey(currentWizardKey);
      nextGlobalKeysSet.delete(currentWizardKey);
    }

    const normalizedEnglishReferenceKeysByLanguage = { ...nextEnglishReferenceKeysByLanguage };
    const normalizedKeys = [...nextEnglishReferenceSet].sort((a, b) => a.localeCompare(b));
    if (normalizedKeys.length === 0) {
      delete normalizedEnglishReferenceKeysByLanguage[activeLang];
    } else {
      normalizedEnglishReferenceKeysByLanguage[activeLang] = normalizedKeys;
    }

    return {
      nextTranslations,
      preferencesSnapshot: {
        globalKeys: [...nextGlobalKeysSet].sort((a, b) => a.localeCompare(b)),
        englishReferenceKeysByLanguage: normalizedEnglishReferenceKeysByLanguage,
      },
    };
  };

  const openTranslationWizard = () => {
    if (wizardMissingKeys.length === 0) return;
    setWizardIndex(0);
    setShowTranslationWizard(true);
  };

  const goToNextWizardStep = async () => {
    if (isWizardSavingStep) return;

    setIsWizardSavingStep(true);
    const saveSnapshot = saveCurrentWizardValue();
    try {
      if (saveSnapshot) {
        // Persist both translation content and preferences on every wizard step.
        await handleSave(saveSnapshot.nextTranslations);
        await savePreferences(saveSnapshot.preferencesSnapshot);
      }
      if (wizardIndex >= wizardMissingKeys.length - 1) {
        setShowTranslationWizard(false);
        return;
      }
      setWizardIndex((prev) => prev + 1);
    } finally {
      setIsWizardSavingStep(false);
    }
  };

  const skipWizardStep = () => {
    if (wizardIndex >= wizardMissingKeys.length - 1) {
      setShowTranslationWizard(false);
      return;
    }
    setWizardIndex((prev) => prev + 1);
  };

  const goToPreviousWizardStep = () => {
    if (wizardIndex <= 0) return;
    setWizardIndex((prev) => prev - 1);
  };

  useEffect(() => {
    if (!activeNamespacePanel) return;
    if (!openFromPanelClickRef.current) return;
    if (!autoScrollOnPanelOpen || !openedNamespacePanelRef.current) {
      openFromPanelClickRef.current = false;
      return;
    }

    openedNamespacePanelRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
    openFromPanelClickRef.current = false;
  }, [activeNamespacePanel, autoScrollOnPanelOpen]);

  const scrollToLanguageManagementHeader = () => {
    if (!languageManagementHeaderRef.current) return;
    languageManagementHeaderRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
  };

  // Show scroll-to-save hint whenever a namespace panel is opened and there are unsaved changes
  // It stays visible until explicitly dismissed (button click) or save bar disappears
  useEffect(() => {
    if (!activeNamespacePanel || !isSaveBarRendered) {
      setShowScrollHint(false);
      return;
    }
    if (scrollHintTimerRef.current) clearTimeout(scrollHintTimerRef.current);
    setShowScrollHint(true);
  }, [activeNamespacePanel, isSaveBarRendered]);

  // Hide scroll hint when the save bar scrolls into view
  useEffect(() => {
    const el = saveBarRef.current;
    if (!el) return;
    const observer = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) setShowScrollHint(false); },
      { threshold: 0.5 }
    );
    observer.observe(el);
    return () => observer.disconnect();
  }, [isSaveBarRendered]);

  useEffect(() => {
    if (!pendingAutoFixResult || !workspaceScan) return;

    const changedFiles = workspaceScan.changedFileCount ?? 0;
    const createdKeys = workspaceScan.createdKeyCount ?? 0;
    if (changedFiles > 0 || createdKeys > 0) {
      setReloadAfterScanClose(true);
      showToast({
        variant: 'success',
        message: `Auto-fix finished: ${changedFiles} files updated, ${createdKeys} keys created.`,
        duration: 4200,
      });
    }

    setPendingAutoFixResult(false);
  }, [pendingAutoFixResult, workspaceScan, showToast]);

  const handleRunFixSelected = async () => {
    setPendingAutoFixResult(true);
    await runFixSelected();
  };

  const closeScanModal = () => {
    setShowScanModal(false);
    if (!reloadAfterScanClose) return;

    showToast({
      variant: 'info',
      message: t('autofix.k3871d88e'),
      duration: 1800,
    });

    setTimeout(() => {
      if (typeof window !== 'undefined') {
        window.location.reload();
      }
    }, 260);

    setReloadAfterScanClose(false);
  };

  const handleSaveAll = async () => {
    const hadChangesToSave = isDirty || isPreferencesDirty;
    console.debug('[LanguageManagement][SaveAll] start', {
      isDirty,
      isPreferencesDirty,
      hasUnsavedChanges,
      autoScrollOnSave,
    });

    if (isDirty) {
      console.debug('[LanguageManagement][SaveAll] saving:translations');
      await handleSave();
      console.debug('[LanguageManagement][SaveAll] saved:translations');
    }

    if (isPreferencesDirty) {
      console.debug('[LanguageManagement][SaveAll] saving:preferences');
      const savedPreferences = await savePreferences();
      console.debug('[LanguageManagement][SaveAll] saved:preferences', { savedPreferences });
    }

    if (autoScrollOnSave && hadChangesToSave) {
      scrollToLanguageManagementHeader();
    }

    console.debug('[LanguageManagement][SaveAll] done');
  };

  return (
    <PageLayout contentClassName="flex-1 relative w-full">
      <div className="min-h-screen bg-[radial-gradient(circle_at_top_left,rgba(251,191,36,0.10),transparent_22%),radial-gradient(circle_at_top_right,rgba(56,189,248,0.10),transparent_24%),linear-gradient(180deg,#f8fafc_0%,#f8fafc_50%,#eef2ff_100%)]">
        <div className="max-w-[1820px] mx-auto px-4 sm:px-6 xl:px-10 py-8 space-y-5">
        {showFetchingScreen ? (
          <div className="rounded-[28px] border border-white/80 bg-white/90 p-8 shadow-[0_24px_70px_-40px_rgba(15,23,42,0.3)] backdrop-blur">
            <div className="flex items-center gap-4">
              <div className="relative h-10 w-10">
                <span className="absolute inset-0 rounded-full border-2 border-slate-200" />
                <span className="absolute inset-0 animate-spin rounded-full border-2 border-transparent border-t-slate-700" />
              </div>
              <div className="space-y-1">
                <p className="text-sm font-semibold text-slate-900">{t('autofix.k78e1bf35')}</p>
                <p className="text-xs text-slate-500">
                  I18N: {translationsLoadingPhase} | PREF: {preferencesLoadingPhase}
                </p>
              </div>
              <div className="ml-auto text-sm font-semibold text-slate-700">{initialLoadingProgress}%</div>
            </div>
            <div className="mt-5 h-2 w-full overflow-hidden rounded-full bg-slate-100">
              <div
                className="h-full rounded-full bg-slate-600 transition-[width] duration-300"
                style={{ width: `${Math.max(6, initialLoadingProgress)}%` }}
              />
            </div>

            {showDelayedFetchLogs && (
              <div className="mt-5 rounded-2xl border border-slate-200 bg-slate-950/95 p-3 text-slate-100 shadow-inner">
                <div className="flex items-center justify-between">
                  <p className="text-xs font-semibold tracking-wide text-slate-200">{t('autofix.k1c7ec4f2')}</p>
                  <p className="text-[11px] text-slate-400">{t('autofix.k057b3dbd')}</p>
                </div>
                <div className="mt-2 h-40 overflow-y-auto rounded-lg bg-black/30 p-2 font-mono text-[11px] leading-5">
                  {combinedLoadingLogs.length === 0 ? (
                    <p className="text-slate-400">{t('autofix.k835d3cbf')}</p>
                  ) : (
                    combinedLoadingLogs.map((line, idx) => (
                      <p key={`${line}-${idx}`} className="text-slate-200">{line}</p>
                    ))
                  )}
                </div>
              </div>
            )}
          </div>
        ) : showWarmGap ? (
          <div className="h-24" />
        ) : (
          <>
        <LanguageManagementTopSection
          headerRef={languageManagementHeaderRef}
          totalKeys={totalKeys}
          onScan={scan}
          isScanning={isScanning}
          isAutoFixing={isAutoFixing}
          onBackToAdmin={() => router.push('/admin')}
          isDirty={hasUnsavedChanges}
          onSave={handleSaveAll}
          saved={saved}
          saveError={saveError}
          allLanguages={allLanguages}
          activeLang={activeLang}
          setActiveLang={setActiveLang}
          isBuiltin={isBuiltin}
          onDeleteLanguageRequest={setDeleteTarget}
          onOpenAddLanguage={() => setShowAddModal(true)}
          allTabStats={allTabStats}
          translationProgressPercent={translationProgressPercent}
          wizardMissingKeysCount={wizardMissingKeys.length}
          onOpenTranslationWizard={openTranslationWizard}
        />

        <TranslationCoverageEditor
          activeCategory={activeCategory}
          setActiveCategory={setActiveCategory}
          categoriesWithKnownNamespaces={categoriesWithKnownNamespaces}
          allTabStats={allTabStats}
          categoryTabStats={categoryTabStats}
          globalTabStats={globalTabStats}
          activeLang={activeLang}
          allLanguages={allLanguages}
          search={search}
          setSearch={setSearch}
          autoScrollOnPanelOpen={autoScrollOnPanelOpen}
          setAutoScrollOnPanelOpen={setAutoScrollOnPanelOpen}
          autoScrollOnSave={autoScrollOnSave}
          setAutoScrollOnSave={setAutoScrollOnSave}
          newGlobalKeySelection={newGlobalKeySelection}
          setNewGlobalKeySelection={setNewGlobalKeySelection}
          availableGlobalKeyOptions={availableGlobalKeyOptions}
          addGlobalKey={addGlobalKey}
          globalFilteredKeys={globalFilteredKeys}
          removeGlobalKey={removeGlobalKey}
          getDisplayValue={getDisplayValue}
          translations={data.translations}
          handleChange={handleChange}
          globalKeySet={globalKeySet}
          englishReferenceKeySet={englishReferenceKeySetByLanguage[activeLang] ?? new Set<string>()}
          setEnglishReferenceForKey={(key, enabled) => {
            setEnglishReferenceKey(activeLang, key, enabled);
            if (enabled) {
              handleChange(key, getEnglishValue(key));
            }
          }}
          filteredNs={filteredNs}
          filteredGroups={filteredGroups}
          activeNamespacePanel={activeNamespacePanel}
          setActiveNamespacePanel={setActiveNamespacePanel}
          namespaceTranslationStats={namespaceTranslationStats}
          openedNamespacePanelRef={openedNamespacePanelRef}
          openFromPanelClickRef={openFromPanelClickRef}
          onBackToPanels={scrollToLanguageManagementHeader}
          onOpenCategoryManager={() => setShowCategoryManagerModal(true)}
        />
          </>
        )}

        </div>
      </div>

      {/* Scroll-to-top floating button */}
      <button
        type="button"
        aria-label={t('autofix.kb494ddd8')}
        onClick={scrollToLanguageManagementHeader}
        className="group fixed bottom-36 right-5 z-50 flex h-10 w-10 items-center justify-center rounded-full border border-white/70 bg-white/80 shadow-[0_8px_24px_-8px_rgba(15,23,42,0.28)] backdrop-blur-md transition-all duration-300 ease-out hover:-translate-y-0.5 hover:scale-105 hover:bg-white hover:shadow-[0_12px_32px_-10px_rgba(15,23,42,0.36)]"
      >
        <svg className="h-4 w-4 text-slate-700 transition-transform duration-300 ease-out group-hover:-translate-y-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M5 15l7-7 7 7" />
        </svg>
      </button>

      {/* Scroll-to-save floating button */}
      <button
        type="button"
        aria-label={t('autofix.k889cc3e3')}
        onClick={() => {
          if (saveBarRef.current) {
            saveBarRef.current.scrollIntoView({ behavior: 'smooth', block: 'end' });
          } else {
            const roots = [
              document.scrollingElement,
              document.documentElement,
              document.body,
            ].filter(Boolean) as HTMLElement[];

            const maxScrollTop = Math.max(
              0,
              ...roots.map((root) => root.scrollHeight - window.innerHeight)
            );

            // Trigger scroll on all possible roots so it works regardless of which element owns scrolling.
            roots.forEach((root) => {
              root.scrollTo({ top: maxScrollTop, behavior: 'smooth' });
            });
            window.scrollTo({ top: maxScrollTop, behavior: 'smooth' });
          }
          setShowScrollHint(false);
        }}
        className="group fixed bottom-24 right-5 z-50 flex h-10 w-10 items-center justify-center rounded-full border border-white/70 bg-white/80 shadow-[0_8px_24px_-8px_rgba(15,23,42,0.28)] backdrop-blur-md transition-all duration-300 ease-out hover:translate-y-0.5 hover:scale-105 hover:bg-white hover:shadow-[0_12px_32px_-10px_rgba(15,23,42,0.36)]"
      >
        <svg className="h-4 w-4 text-slate-700 transition-transform duration-300 ease-out group-hover:translate-y-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M19 9l-7 7-7-7" />
        </svg>
      </button>

      {/* Scroll-to-save hint tooltip */}
      {isHintRendered && (
        <button
          type="button"
          aria-label={t('autofix.k0b27fdf8')}
          onClick={() => {
            saveBarRef.current?.scrollIntoView({ behavior: 'smooth', block: 'end' });
            setShowScrollHint(false);
          }}
          className={`fixed bottom-[5.25rem] right-[4rem] z-50 transition-all duration-500 ${
            isHintVisible ? 'opacity-100 translate-x-0' : 'opacity-0 translate-x-3 pointer-events-none'
          }`}
        >
          {/* outer pulsing ring */}
          <span className="absolute inset-0 rounded-2xl animate-pulse bg-gradient-to-br from-sky-400/20 via-blue-300/15 to-indigo-400/20" />
          <div className="relative flex items-center gap-2.5 rounded-2xl border border-blue-300/80 bg-gradient-to-br from-sky-50 via-blue-50 to-indigo-50 px-3.5 py-2.5 shadow-[0_8px_28px_-8px_rgba(37,99,235,0.35)] backdrop-blur-md">
            {/* logo */}
            <img
              src="/images/logos/PP_Logo_BW_round.png"
              alt={t('autofix.k788633d1')}
              className="h-7 w-7 rounded-full border border-blue-200/70 shadow-sm shrink-0 object-cover"
            />
            <div className="flex flex-col leading-tight">
              <span className="text-[11px] font-bold text-blue-950 whitespace-nowrap">{t('autofix.k5188f06f')}</span>
              <span className="text-[10px] font-medium text-blue-700 whitespace-nowrap">Click to scroll &amp; save ↓</span>
            </div>
            {/* pulsing dot */}
            <span className="relative flex h-2 w-2 shrink-0">
              <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-500 opacity-75" />
              <span className="relative inline-flex h-2 w-2 rounded-full bg-blue-500" />
            </span>
            {/* caret pointing right toward the chevron button */}
            <span className="absolute -right-[5px] top-1/2 -translate-y-1/2 h-2.5 w-2.5 rotate-45 border-r border-t border-blue-300/80 bg-indigo-50" />
          </div>
        </button>
      )}

      {/* Glassy save bar */}
      {isSaveBarRendered && (
        <div
          ref={saveBarRef}
          className={`w-full border-t border-white/60 bg-white/70 backdrop-blur-md px-4 py-4 transition-opacity duration-300 ${
            isSaveBarVisible ? 'opacity-100' : 'opacity-0'
          }`}
        >
          <div className="max-w-[1820px] mx-auto flex items-center justify-between gap-4">
            <span className="text-sm font-medium text-slate-700">{t('autofix.kd63c8219')}</span>
            <button
              onClick={handleSaveAll}
              disabled={isSavingPreferences}
              className="rounded-2xl bg-slate-900 text-white px-5 py-2 text-sm font-semibold shadow-[0_18px_40px_-24px_rgba(15,23,42,0.85)] hover:bg-slate-800 transition disabled:opacity-50"
            >{isSavingPreferences ? t('autofix.kac6cedc7') : 'Save'}</button>
          </div>
        </div>
      )}

      <TranslationWizardModal
        isOpen={showTranslationWizard}
        currentWizardKey={currentWizardKey}
        wizardIndex={wizardIndex}
        wizardMissingCount={wizardMissingKeys.length}
        activeLang={activeLang}
        allLanguages={allLanguages}
        wizardInput={wizardInput}
        setWizardInput={setWizardInput}
        wizardMarkGlobal={wizardMarkGlobal}
        setWizardMarkGlobal={setWizardMarkGlobal}
        wizardUseEnglishReference={wizardUseEnglishReference}
        setWizardUseEnglishReference={setWizardUseEnglishReference}
        englishValue={currentWizardKey ? getEnglishValue(currentWizardKey) : ''}
        addGlobalKey={addGlobalKey}
        removeGlobalKey={removeGlobalKey}
        onClose={() => setShowTranslationWizard(false)}
        onPrevious={goToPreviousWizardStep}
        onSkip={skipWizardStep}
        onNext={goToNextWizardStep}
        isSavingStep={isWizardSavingStep}
      />

      <AddLanguageModal
        isOpen={showAddModal}
        newCode={newCode}
        setNewCode={setNewCode}
        newName={newName}
        setNewName={setNewName}
        addError={addError}
        setAddError={setAddError}
        onClose={() => setShowAddModal(false)}
        onAdd={handleAddLanguage}
      />

      <DeleteLanguageModal
        deleteTarget={deleteTarget}
        allLanguages={allLanguages}
        onClose={() => setDeleteTarget(null)}
        onDelete={handleDeleteLanguage}
      />

      <CategoryManagerModal
        isOpen={showCategoryManagerModal}
        onClose={() => {
          setShowCategoryManagerModal(false);
          if (isPreferencesDirty) void savePreferences();
        }}
        newCategoryLabel={newCategoryLabel}
        setNewCategoryLabel={setNewCategoryLabel}
        onCreateCategory={handleCreateCategory}
        uncategorizedNamespaces={uncategorizedNamespaces}
        categoriesWithKnownNamespaces={categoriesWithKnownNamespaces}
        namespaces={namespaces}
        assignNamespaceByCategory={assignNamespaceByCategory}
        setAssignNamespaceByCategory={setAssignNamespaceByCategory}
        expandedCategoryId={expandedCategoryId}
        setExpandedCategoryId={setExpandedCategoryId}
        dragNamespace={dragNamespace}
        setDragNamespace={setDragNamespace}
        addNamespaceToCategory={addNamespaceToCategory}
        removeNamespaceFromCategory={removeNamespaceFromCategory}
        deleteCategory={deleteCategory}
      />

      <ScanResultsModal
        isOpen={showScanModal}
        onClose={closeScanModal}
        lastScanTime={lastScanTime}
        workspaceScan={workspaceScan}
        totalKeys={totalKeys}
        namespacesCount={namespaces.length}
        allLanguages={allLanguages}
        activeLang={activeLang}
        scanResults={scanResults}
        scanError={scanError}
        isScanning={isScanning}
        isAutoFixing={isAutoFixing}
        isAddingMissingKeys={isAddingMissingKeys}
        fixableFiles={fixableFiles}
        selectedFiles={selectedFiles}
        forceConvertToClient={forceConvertToClient}
        onToggleFile={toggleFileSelection}
        onSelectAll={selectAllFiles}
        onClear={clearSelectedFiles}
        onToggleForceConvertToClient={() => setForceConvertToClient((prev) => !prev)}
        onRunFixSelected={handleRunFixSelected}
        onAddMissingKeys={addMissingKeys}
      />
    </PageLayout>
  );
}
