import { useState, useEffect, useCallback, useRef, useMemo } from "react";
import { useSearchParams } from "react-router-dom";
import { useTranslation } from "react-i18next";
import {
  AlertCircle,
  ArrowLeft,
  CheckCircle2,
  ExternalLink,
  Eye,
  EyeOff,
  FileText,
  History,
  Image,
  LayoutTemplate,
  List,
  Loader,
  Maximize2,
  Menu,
  PanelLeft,
  PanelLeftClose,
  Palette,
  RefreshCw,
  RotateCcw,
  Save,
  Search,
  Sparkles,
  Type,
  X,
} from "lucide-react";
import type { LucideIcon } from "lucide-react";
import { toast } from "sonner";
import { TemplateService } from "@/user-management/services/api/templateService";
import {
  TemplateResource,
  TemplateSampleSetting,
  TemplateSettingTypeGroup,
  TemplateSampleFileInfo,
} from "@/user-management/services/TemplateConfiguration/types/templateTypes";
import { useHeaderFooterPresigned } from "@/record-management/components/hooks/useHeaderFooterPresigned";
import { SettingHistoryModal } from "./components/SettingHistoryModal";
import { StyleSettingsEditor } from "./components/StyleSettingsEditor";
import { isFontSetting } from "./components/FontSettingsEditor";
import {
  HeaderFooterFileInfo,
  HeaderFooterResponseDto,
} from "@/user-management/services/api/headerFooterService";
import { getDefaultSampleData } from "./utils/styleSettingsConstants";
import { cssStringToObject } from "./utils/cssConversion";
import {
  buildSampleResources,
} from "./utils/templateSamplePayloadUtils";
import {
  buildBulkSavePayload,
  buildSettingBaselines,
  buildSettingsPayloadItems,
  filterChangedSettingOverrides,
  finalizePreviewOverrides,
  type SettingBaseline,
} from "./utils/templateSettingsPayload";
import { useListBulletResources } from "./hooks/useListBulletResources";
import { cn } from "@/shared/lib/utils";
import { useDebounce } from "../components/content/useDebounce";
import { UnsavedChangesModal } from "./components/UnsavedChangesModal";
import { ResetAllDefaultsModal } from "./components/ResetAllDefaultsModal";
import { LetterLabelFieldEditor } from "./components/LetterLabelFieldEditor";
import {
  getLetterLabelKeysForCategory,
  isLetterLabelsSetting,
  LETTER_LABEL_DISPLAY_NAMES,
  normalizeLetterLabelsValue,
  type LetterLabelEntry,
  type LetterLabelKey,
  type LetterLabelsText,
} from "./utils/letterLabelsConstants";
import {
  PageMarginEditor,
  isPageMarginSetting,
  normalizePageMarginValue,
  type PageMarginValue,
} from "./components/PageMarginEditor";
import {
  LayoutConfigEditor,
  isLayoutConfigSetting,
  normalizeLayoutConfigValue,
  type LetterLayoutConfigValue,
} from "./components/LayoutConfigEditor";
import { LETTER_ASSET_PLACEMENT_ELEMENT_ID } from "./components/LetterAssetsPlacementCanvas";
import {
  StyleSettingPanel,
  StyleSettingSelect,
  StyleSettingsSidebar,
  StyleSettingsSidebarItem,
  STYLE_INPUT_CLASS,
} from "./components/styleSettingsUi";

const EMPTY_SELECT_VALUE = "__none__";

const toTemplateSampleFileInfo = (
  fileInfo: HeaderFooterFileInfo,
): TemplateSampleFileInfo => ({
  bucket: "",
  originalname: fileInfo.originalname,
  contentType: fileInfo.contentType,
  fileName: fileInfo.fileName,
  size: fileInfo.size,
});

const disclosureListStyleImage = (): string => {
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="currentColor"><path d="M4 2v12l10-6z"/></svg>`;
  return `url('data:image/svg+xml;base64,${btoa(svg)}')`;
};

function cssValueToPreviewObject(cssString: string): Record<string, string> {
  const valueObj = cssStringToObject(cssString);
  if (valueObj["list-style"] === "disclosure-closed") {
    valueObj["list-style-image"] = disclosureListStyleImage();
  }
  return valueObj;
}

function resolveGlobalDefaultSettingValue(
  setting: TemplateSampleSetting,
): TemplateSampleSetting["value"] {
  const defaultRow = setting.templateSettingValues?.find(
    (row) => row.unitId == null,
  );
  const defaultValue = defaultRow?.value ?? {};

  if (isLetterLabelsSetting(setting.code)) {
    return normalizeLetterLabelsValue(defaultValue) as TemplateSampleSetting["value"];
  }
  if (isPageMarginSetting(setting.code)) {
    return normalizePageMarginValue(defaultValue) as TemplateSampleSetting["value"];
  }
  if (isLayoutConfigSetting(setting.code)) {
    return normalizeLayoutConfigValue(defaultValue) as TemplateSampleSetting["value"];
  }
  if (typeof defaultValue === "object" && defaultValue !== null) {
    return Object.entries(defaultValue)
      .filter(([, value]) => value !== null && value !== undefined && value !== "null")
      .map(([key, value]) => `${key}: ${value};`)
      .join(" ");
  }
  if (typeof defaultValue === "string") {
    return defaultValue;
  }
  return "";
}

function resolveGlobalDefaultResourceId(
  setting: TemplateSampleSetting,
): string | null {
  const defaultRow = setting.templateSettingValues?.find(
    (row) => row.unitId == null,
  );
  return defaultRow?.resourceId ?? null;
}

// ---------------------------------------------------------------------------
// Unsaved Changes Indicator Component
// ---------------------------------------------------------------------------
const UnsavedChangesIndicator: React.FC<{ visible: boolean }> = ({
  visible,
}) => {
  if (!visible) return null;

  return (
    <div className="flex items-center gap-2 text-amber-600">
      <div className="w-2 h-2 rounded-full bg-amber-600 animate-pulse" />
      <span className="text-sm font-medium">Unsaved changes</span>
    </div>
  );
};

const formatSettingLabel = (code: string) =>
  code
    .replace(/^letter-/, "")
    .replace(/-/g, " ")
    .replace(/\b\w/g, (char) => char.toUpperCase());

const CATEGORY_ICONS: Record<string, LucideIcon> = {
  header: Image,
  footer: Image,
  subject: FileText,
  body: Type,
  receiver: FileText,
  "prefix-suffix": Sparkles,
  cc: List,
  list: List,
  fonts: Type,
  "page-margin": Maximize2,
  layout: LayoutTemplate,
  "reference-number": FileText,
  other: Palette,
};

// ---------------------------------------------------------------------------
// PDF Preview Panel Component
// ---------------------------------------------------------------------------
interface PDFPreviewPanelProps {
  pdfUrl: string | null;
  loading: boolean;
  error: string | null;
  onApply: () => void;
  livePreviewEnabled: boolean;
}

const PDFPreviewPanel: React.FC<PDFPreviewPanelProps> = ({
  pdfUrl,
  loading,
  error,
  onApply,
  livePreviewEnabled,
}) => {
  const { t } = useTranslation();
  const [iframeLoading, setIframeLoading] = useState(true);
  const [iframeError, setIframeError] = useState(false);

  useEffect(() => {
    if (pdfUrl) {
      setIframeLoading(true);
      setIframeError(false);
    }
  }, [pdfUrl]);

  const handleIframeLoad = () => setIframeLoading(false);
  const handleIframeError = () => {
    setIframeLoading(false);
    setIframeError(true);
  };

  return (
    <div className="flex h-full min-h-0 flex-col bg-white dark:bg-gray-900">
      <div className="shrink-0 border-b border-gray-200 p-4 dark:border-gray-700">
        <div className="mb-3 flex items-center justify-between">
          <div>
            <h2 className="text-sm font-semibold text-gray-900 dark:text-white">
              {t("template.pdfPreview", "PDF Preview")}
            </h2>
            <p className="text-xs text-gray-500 dark:text-gray-400">
              {livePreviewEnabled
                ? t("template.autoRefreshEnabled", "Auto refresh is enabled")
                : t("template.manualRefreshEnabled", "Manual refresh")}
            </p>
          </div>
          {pdfUrl && (
            <a
              href={pdfUrl}
              target="_blank"
              rel="noopener noreferrer"
              className="inline-flex h-9 w-9 items-center justify-center rounded-lg border border-gray-200 text-gray-600 transition-colors hover:bg-gray-50 hover:text-purple-700 dark:border-gray-700 dark:text-gray-300 dark:hover:bg-gray-800"
              title={t("template.openInNewTab", "Open in new tab")}
            >
              <ExternalLink className="h-4 w-4" />
            </a>
          )}
        </div>
        <button
          onClick={onApply}
          disabled={loading}
          className="flex w-full items-center justify-center gap-2 rounded-lg bg-purple-600 px-4 py-2 text-white transition-colors hover:bg-purple-700 disabled:cursor-not-allowed disabled:opacity-50 dark:hover:bg-purple-500"
        >
          {loading ? (
            <Loader className="h-4 w-4 animate-spin" />
          ) : (
            <RefreshCw className="h-4 w-4" />
          )}
          {loading
            ? t("template.generatingPreview", "Generating...")
            : t("template.applyChanges", "Apply Changes")}
        </button>
      </div>

      {error && (
        <div className="mx-4 mt-4 shrink-0 rounded-lg border border-red-200 bg-red-50 p-3">
          <p className="text-sm text-red-800">{error}</p>
          <button
            onClick={onApply}
            className="mt-2 text-sm text-red-600 hover:text-red-800 font-medium underline"
          >
            {t("common.retry", "Retry")}
          </button>
        </div>
      )}

      <div className="relative min-h-0 flex-1 overflow-hidden">
        {pdfUrl ? (
          <>
            {iframeLoading && (
              <div className="absolute inset-0 z-10 flex items-center justify-center bg-white/75 dark:bg-gray-900/75">
                <div className="flex flex-col items-center gap-2">
                  <Loader className="h-8 w-8 animate-spin text-purple-600" />
                  <span className="text-sm text-gray-600 dark:text-gray-300">
                    {t("template.loadingPdf", "Loading PDF...")}
                  </span>
                </div>
              </div>
            )}

            {iframeError && (
              <div className="absolute inset-0 flex items-center justify-center bg-gray-50 dark:bg-gray-900">
                <div className="p-6 text-center">
                  <AlertCircle className="mx-auto mb-3 h-8 w-8 text-red-500" />
                  <p className="mb-2 font-medium text-red-600 dark:text-red-400">
                    {t("template.pdfLoadError", "Failed to load PDF preview")}
                  </p>
                  <a
                    href={pdfUrl}
                    target="_blank"
                    rel="noopener noreferrer"
                    className="text-sm text-purple-600 underline hover:text-purple-700"
                  >
                    {t("template.openInNewTab", "Open in new tab")}
                  </a>
                </div>
              </div>
            )}

            <iframe
              src={pdfUrl}
              className="absolute inset-0 h-full w-full border-0 bg-white"
              title="PDF Preview"
              onLoad={handleIframeLoad}
              onError={handleIframeError}
            />
          </>
        ) : (
          <div className="absolute inset-0 flex items-center justify-center bg-gray-50 text-gray-500 dark:bg-gray-900 dark:text-gray-400">
            <div className="max-w-sm px-6 text-center">
              <FileText className="mx-auto mb-4 h-12 w-12 text-gray-300 dark:text-gray-600" />
              <p className="font-medium text-gray-700 dark:text-gray-200">
                {t("template.previewNotGenerated", "Preview not generated yet")}
              </p>
              <p className="mt-1 text-sm">
                {t(
                  "template.clickApplyToPreview",
                  'Click "Apply Changes" to generate preview',
                )}
              </p>
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

// ---------------------------------------------------------------------------
// Main Component Props
// ---------------------------------------------------------------------------
export interface StyleSettingsPageProps {
  templateId: string;
  unitId: string;
  onBack: () => void;
}

// ---------------------------------------------------------------------------
// Main Component
// ---------------------------------------------------------------------------
export const StyleSettingsPage: React.FC<StyleSettingsPageProps> = ({
  templateId,
  unitId,
  onBack,
}) => {
  const { t, i18n } = useTranslation();
  const [searchParams, setSearchParams] = useSearchParams();
  const [showUnsavedModal, setShowUnsavedModal] = useState(false);
  const [showResetModal, setShowResetModal] = useState(false);
  const [resetInProgress, setResetInProgress] = useState(false);
  const pendingNavigation = useRef<(() => void) | null>(null);
  const { data: headerFooterData, isLoading: isHeaderFooterLoading } =
    useHeaderFooterPresigned(unitId);

  // --- State ------------------------------------------------------------
  const [template, setTemplate] = useState<TemplateResource | null>(null);
  const [settings, setSettings] = useState<TemplateSampleSetting[]>([]);
  const [settingGroups, setSettingGroups] = useState<
    TemplateSettingTypeGroup[]
  >([]);
  const [settingsLoading, setSettingsLoading] = useState(false);
  const [pdfUrl, setPdfUrl] = useState<string | null>(null);
  const [previewLoading, setPreviewLoading] = useState(false);
  const [selectedHeaderId, setSelectedHeaderId] = useState<string>("");
  const [selectedFooterId, setSelectedFooterId] = useState<string>("");
  const [headers, setHeaders] = useState<HeaderFooterResponseDto[]>([]);
  const [footers, setFooters] = useState<HeaderFooterResponseDto[]>([]);
  const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
  const [mobileNavOpen, setMobileNavOpen] = useState(false);
  const [layoutPlacementFocusNonce, setLayoutPlacementFocusNonce] = useState(0);
  const [categoryNavCollapsed, setCategoryNavCollapsed] = useState(false);
  const [livePreviewEnabled, setLivePreviewEnabled] = useState(true);
  const [isFirstLoad, setIsFirstLoad] = useState(true);
  const [searchTerm, setSearchTerm] = useState("");
  const lastPreviewedKey = useRef<string | null>(null);
  const [useDefaultSettings, setUseDefaultSettings] = useState<
    Record<string, boolean>
  >({});
  const [previewLanguage, setPreviewLanguage] = useState<"am" | "en">("am");
  const baselineRef = useRef<Record<string, SettingBaseline>>({});
  const settingsLoadedRef = useRef(false);
  const [historySetting, setHistorySetting] =
    useState<TemplateSampleSetting | null>(null);
  const [resourceIds, setResourceIds] = useState<Record<string, string | null>>(
    {},
  );
  const { resources: bulletResources } = useListBulletResources();

  const settingRefs = useRef<Record<string, HTMLDivElement | null>>({});

  const buildSettingsPayload = useCallback(() => {
    return buildSettingsPayloadItems(
      settings,
      resourceIds,
      bulletResources,
      cssValueToPreviewObject,
    );
  }, [settings, resourceIds, bulletResources]);

  const buildPreviewSettingsPayload = useCallback(() => {
    const allItems = buildSettingsPayload();
    const changed = filterChangedSettingOverrides(
      allItems,
      baselineRef.current,
      useDefaultSettings,
    );
    return finalizePreviewOverrides(
      changed,
      useDefaultSettings,
      baselineRef.current,
    );
  }, [buildSettingsPayload, useDefaultSettings]);

  const buildResourcesPayload = useCallback(() => {
    const previewItems = buildPreviewSettingsPayload();
    return buildSampleResources(
      previewItems.map((item) => item.resourceId),
      bulletResources,
    );
  }, [buildPreviewSettingsPayload, bulletResources]);

  // --- Helper: Determine category from setting code --------------------
  const getCategoryForSetting = useCallback((code: string): string => {
    const lower = code.trim().toLowerCase();
    if (isLetterLabelsSetting(lower)) return "";
    if (lower === "letter-layout-config") return "layout";
    if (lower.includes("header")) return "header";
    if (lower.includes("footer")) return "footer";
    if (lower.includes("subject")) return "subject";
    if (lower.includes("body") || lower.includes("content")) return "body";
    if (lower.includes("receiver")) return "receiver";
    if (lower.includes("prefix") || lower.includes("suffix"))
      return "prefix-suffix";
    if (lower.includes("cc")) return "cc";
    if (lower.includes("list")) return "list";
    if (lower === "letter-fonts") return "fonts";
    if (lower === "letter-page-margin") return "page-margin";
    if (lower.includes("reference-number")) return "reference-number";
    return "other";
  }, []);

  // Manual mapping for settings that should appear in additional categories
  const multiCategorySettings: Record<string, string[]> = {
    "letter-list-style": ["receiver"],
    "letter-cc-list-style": ["cc"],
    "letter-for-your-reference-list-style": ["cc"],
    "letter-prefix-style": ["prefix-suffix"],
    "letter-cc-prefix-style": ["cc", "prefix-suffix"],
  };

  // Helper to get all categories a setting belongs to
  const getSettingCategories = useCallback((settingCode: string): string[] => {
    if (isLetterLabelsSetting(settingCode)) return [];
    if (multiCategorySettings[settingCode]) {
      return multiCategorySettings[settingCode];
    }
    const category = getCategoryForSetting(settingCode);
    return category ? [category] : [];
  }, [getCategoryForSetting]);

  // --- Build categories from settings ----------------------------------
  const resolvedPageMargin = useMemo((): PageMarginValue => {
    const marginSetting = settings.find((s) => isPageMarginSetting(s.code));
    if (!marginSetting) {
      return normalizePageMarginValue(null);
    }
    const usesDefault = useDefaultSettings[marginSetting.id] ?? true;
    if (usesDefault) {
      const defaultRow = marginSetting.templateSettingValues?.find(
        (row) => row.unitId == null,
      );
      return normalizePageMarginValue(defaultRow?.value ?? marginSetting.value);
    }
    return normalizePageMarginValue(marginSetting.value);
  }, [settings, useDefaultSettings]);

  const categories = useMemo(() => {
    const locale = i18n.language?.startsWith("am") ? "am" : "en";
    const apiSections = settingGroups.flatMap((group) => group.sections || []);
    if (apiSections.length > 0) {
      const apiCategories = apiSections.map((section) => ({
        code: section.code,
        label: section.name?.[locale] || section.name?.en || section.code,
        settingIds: section.settings.map((setting) => setting.id),
      }));
      const groupedSettingIds = new Set(
        apiCategories.flatMap((category) => category.settingIds),
      );

      // JSON configuration settings may not belong to the backend's CSS
      // sections. Keep them discoverable even when grouped navigation exists.
      settings
        .filter((setting) => !groupedSettingIds.has(setting.id))
        .forEach((setting) => {
          getSettingCategories(setting.code).forEach((code) => {
            const existing = apiCategories.find(
              (category) => category.code === code,
            );
            if (existing) {
              existing.settingIds.push(setting.id);
            } else {
              apiCategories.push({
                code,
                label:
                  code === "layout"
                    ? t("template.letterLayout", "Letter Layout")
                    : formatSettingLabel(code),
                settingIds: [setting.id],
              });
            }
          });
        });

      return apiCategories.filter((category) => category.code !== "labels");
    }

    const categoryMap = new Map<
      string,
      { code: string; label: string; settingIds: string[] }
    >();

    settings.forEach((setting) => {
      const catCodes = getSettingCategories(setting.code);
      catCodes.forEach((catCode) => {
        if (!categoryMap.has(catCode)) {
          const labelMap: Record<string, string> = {
            header: t("template.headerStyle", "Header Style"),
            footer: t("template.footerStyle", "Footer Style"),
            subject: t("template.subjectStyle", "Subject Style"),
            body: t("template.bodyStyle", "Body Style"),
            receiver: t("template.receiverStyle", "Receiver Style"),
            "prefix-suffix": t("template.prefixSuffix", "Prefix / Suffix"),
            cc: t("template.ccStyles", "CC Styles"),
            list: t("template.listStyle", "List Style"),
            fonts: t("template.fonts", "Fonts"),
            "page-margin": t("template.pageMargin", "Page Margins"),
            layout: t("template.letterLayout", "Letter Layout"),
            "reference-number": t(
              "template.referenceNumberStyles",
              "Reference Number Styles",
            ),
            other: t("template.other", "Other"),
          };
          categoryMap.set(catCode, {
            code: catCode,
            label: labelMap[catCode] || catCode,
            settingIds: [],
          });
        }
        categoryMap.get(catCode)!.settingIds.push(setting.id);
      });
    });

    return Array.from(categoryMap.values());
  }, [settings, t, getSettingCategories, settingGroups, i18n.language]);

  const sidebarCategories = useMemo(
    () =>
      categories.filter(
        (category) =>
          category.code !== "fonts" && category.code !== "labels",
      ),
    [categories],
  );

  const letterLabelsSetting = useMemo(
    () => settings.find((setting) => isLetterLabelsSetting(setting.code)),
    [settings],
  );

  const normalizedLetterLabels = useMemo(
    () => normalizeLetterLabelsValue(letterLabelsSetting?.value),
    [letterLabelsSetting?.value],
  );

  const categoryMatchesSearch = useCallback(
    (
      categoryCode: string,
      categoryLabel: string,
      settingIds: string[],
      query: string,
    ): boolean => {
      if (!query) return true;
      if (
        categoryCode.toLowerCase().includes(query) ||
        categoryLabel.toLowerCase().includes(query)
      ) {
        return true;
      }

      const settingCodes = settingIds
        .map((id) => settings.find((setting) => setting.id === id)?.code)
        .filter((code): code is string => Boolean(code));

      for (const id of settingIds) {
        const setting = settings.find((item) => item.id === id);
        if (!setting || isLetterLabelsSetting(setting.code)) continue;
        const value = typeof setting.value === "string" ? setting.value : "";
        if (
          setting.code.toLowerCase().includes(query) ||
          formatSettingLabel(setting.code).toLowerCase().includes(query) ||
          value.toLowerCase().includes(query)
        ) {
          return true;
        }
      }

      for (const labelKey of getLetterLabelKeysForCategory(
        categoryCode,
        settingCodes,
      )) {
        const names = LETTER_LABEL_DISPLAY_NAMES[labelKey];
        const entry = normalizedLetterLabels[labelKey];
        if (
          labelKey.toLowerCase().includes(query) ||
          names.en.toLowerCase().includes(query) ||
          names.am.toLowerCase().includes(query) ||
          entry.en.toLowerCase().includes(query) ||
          entry.am.toLowerCase().includes(query)
        ) {
          return true;
        }
      }

      return false;
    },
    [settings, normalizedLetterLabels],
  );

  const filteredSidebarCategories = useMemo(() => {
    const query = searchTerm.trim().toLowerCase();
    if (!query) return sidebarCategories;
    return sidebarCategories.filter((category) =>
      categoryMatchesSearch(
        category.code,
        category.label,
        category.settingIds,
        query,
      ),
    );
  }, [sidebarCategories, searchTerm, categoryMatchesSearch]);

  const effectiveSelectedCategory = useMemo(() => {
    if (!selectedCategory) return null;
    const query = searchTerm.trim().toLowerCase();
    if (!query || filteredSidebarCategories.length === 0) {
      return selectedCategory;
    }
    if (
      filteredSidebarCategories.some(
        (category) => category.code === selectedCategory,
      )
    ) {
      return selectedCategory;
    }
    return filteredSidebarCategories[0]?.code ?? selectedCategory;
  }, [searchTerm, filteredSidebarCategories, selectedCategory]);

  const showHeaderFooterSection = useMemo(() => {
    const query = searchTerm.trim().toLowerCase();
    if (!query) return true;
    return effectiveSelectedCategory === "layout";
  }, [searchTerm, effectiveSelectedCategory]);

  const editableSettings = useMemo(
    () => settings.filter((setting) => !isFontSetting(setting.code)),
    [settings],
  );

  const totalCustomSettings = useMemo(
    () =>
      Object.values(useDefaultSettings).filter((isDefault) => !isDefault)
        .length,
    [useDefaultSettings],
  );

  const categoryCustomCounts = useMemo(() => {
    const counts = new Map<string, number>();
    const labelsCustomized =
      letterLabelsSetting &&
      useDefaultSettings[letterLabelsSetting.id] === false;

    categories.forEach((category) => {
      let customCount = category.settingIds.filter(
        (id) => useDefaultSettings[id] === false,
      ).length;
      if (
        labelsCustomized &&
        getLetterLabelKeysForCategory(
          category.code,
          category.settingIds
            .map((id) => settings.find((setting) => setting.id === id)?.code)
            .filter((code): code is string => Boolean(code)),
        ).length > 0
      ) {
        customCount += 1;
      }
      counts.set(category.code, customCount);
    });
    return counts;
  }, [categories, useDefaultSettings, letterLabelsSetting, settings]);

  const customizationProgress = useMemo(() => {
    if (editableSettings.length === 0) return 0;
    return Math.round((totalCustomSettings / editableSettings.length) * 100);
  }, [editableSettings.length, totalCustomSettings]);

  const hasSettingsToReset = useMemo(() => {
    if (settings.length === 0) return false;
    if (hasUnsavedChanges) return true;
    return settings.some(
      (setting) =>
        setting.isUnitOverride || useDefaultSettings[setting.id] === false,
    );
  }, [settings, hasUnsavedChanges, useDefaultSettings]);

  const selectedCategorySettingCodes = useMemo(() => {
    if (!effectiveSelectedCategory) return [] as string[];
    const category = sidebarCategories.find(
      (item) => item.code === effectiveSelectedCategory,
    );
    if (!category) return [];
    return category.settingIds
      .map((id) => settings.find((setting) => setting.id === id)?.code)
      .filter((code): code is string => Boolean(code));
  }, [sidebarCategories, effectiveSelectedCategory, settings]);

  const selectedCategoryLabelKeys = useMemo(() => {
    if (!effectiveSelectedCategory) return [] as LetterLabelKey[];
    const keys = getLetterLabelKeysForCategory(
      effectiveSelectedCategory,
      selectedCategorySettingCodes,
    );
    const query = searchTerm.trim().toLowerCase();
    if (!query) return keys;

    return keys.filter((key) => {
      const names = LETTER_LABEL_DISPLAY_NAMES[key];
      const entry = normalizedLetterLabels[key];
      return (
        key.toLowerCase().includes(query) ||
        names.en.toLowerCase().includes(query) ||
        names.am.toLowerCase().includes(query) ||
        entry.en.toLowerCase().includes(query) ||
        entry.am.toLowerCase().includes(query)
      );
    });
  }, [effectiveSelectedCategory, searchTerm, normalizedLetterLabels, selectedCategorySettingCodes]);

  const letterLabelsIsDefault = letterLabelsSetting
    ? (useDefaultSettings[letterLabelsSetting.id] ?? true)
    : true;

  const selectedCategorySettings = useMemo(() => {
    if (!effectiveSelectedCategory || effectiveSelectedCategory === "fonts") return [];
    const query = searchTerm.trim().toLowerCase();
    const categorySettingIds = new Set(
      sidebarCategories.find((category) => category.code === effectiveSelectedCategory)
        ?.settingIds || [],
    );
    return editableSettings.filter((setting) => {
      if (isLetterLabelsSetting(setting.code)) return false;
      const isInCategory = categorySettingIds.has(setting.id);
      if (!isInCategory) return false;
      if (!query) return true;
      const value = typeof setting.value === "string" ? setting.value : "";
      return (
        setting.code.toLowerCase().includes(query) ||
        formatSettingLabel(setting.code).toLowerCase().includes(query) ||
        value.toLowerCase().includes(query)
      );
    });
  }, [editableSettings, sidebarCategories, effectiveSelectedCategory, searchTerm]);

  const selectedCategoryVisibleCount =
    selectedCategorySettings.length + selectedCategoryLabelKeys.length;

  const getCategoryVisibleItemCount = useCallback(
    (categoryCode: string) => {
      const category = categories.find((item) => item.code === categoryCode);
      const settingsCount =
        category?.settingIds.filter((id) => {
          const setting = settings.find((item) => item.id === id);
          return setting && !isLetterLabelsSetting(setting.code);
        }).length ?? 0;
      return settingsCount + getLetterLabelKeysForCategory(
        categoryCode,
        category?.settingIds
          .map((id) => settings.find((setting) => setting.id === id)?.code)
          .filter((code): code is string => Boolean(code)) ?? [],
      ).length;
    },
    [categories, settings],
  );

  // --- Load template metadata -------------------------------------------
  const loadTemplate = useCallback(async () => {
    try {
      const data = await TemplateService.getTemplate(templateId);
      setTemplate(data);
    } catch (err) {
      console.error("Error loading template:", err);
      setError(t("error.loadingTemplate", "Error loading template"));
    }
  }, [templateId, t]);

  // --- Load style settings ----------------------------------------------
  const loadSettings = useCallback(async () => {
    try {
      setSettingsLoading(true);
      setError(null);

      const response =
        await TemplateService.getTemplateSettingsByUnit(templateId, unitId);
      const responseGroups = Array.isArray(response?.groups)
        ? response.groups
        : [];
      setSettingGroups(responseGroups);

      // Non-CSS JSON settings may be returned as unsectioned group settings
      // instead of in the legacy top-level items collection.
      const fetchedSettings = Array.from(
        new Map(
          [
            ...(Array.isArray(response?.items) ? response.items : []),
            ...responseGroups.flatMap((group) => group.settings || []),
            ...responseGroups.flatMap((group) =>
              (group.sections || []).flatMap(
                (section) => section.settings || [],
              ),
            ),
          ].map((setting) => [setting.id, setting]),
        ).values(),
      );

      const processedSettings = fetchedSettings
        .map((setting: any) => {
          if (!setting.id || !setting.code) return null;

          let defaultValue: any = undefined;
          if (setting.value !== null && setting.value !== undefined) {
            defaultValue = setting.value;
          } else if (setting.templateSettingValues?.length > 0) {
            const valueWithUnitId = setting.templateSettingValues.find(
              (tv: any) => tv.unitId !== null && tv.unitId !== undefined,
            );
            if (valueWithUnitId?.value != null) {
              defaultValue = valueWithUnitId.value;
            } else {
              const fallback = setting.templateSettingValues.find(
                (tv: any) => tv.value !== null && tv.value !== undefined,
              );
              defaultValue = fallback?.value;
            }
          }

          // Typed (non-CSS) settings keep their object value intact.
          if (isLetterLabelsSetting(setting.code)) {
            return {
              ...setting,
              value: normalizeLetterLabelsValue(defaultValue),
            };
          }
          if (isPageMarginSetting(setting.code)) {
            return {
              ...setting,
              value: normalizePageMarginValue(defaultValue),
            };
          }
          if (isLayoutConfigSetting(setting.code)) {
            return {
              ...setting,
              value: normalizeLayoutConfigValue(defaultValue),
            };
          }

          let cssString = "";
          if (
            typeof defaultValue === "object" &&
            defaultValue !== null &&
            Object.keys(defaultValue).length > 0
          ) {
            cssString = Object.entries(defaultValue)
              .filter(([, v]) => v !== null && v !== undefined && v !== "null")
              .map(([key, value]) => `${key}: ${value};`)
              .join(" ");
          } else if (typeof defaultValue === "string" && defaultValue.trim()) {
            cssString = defaultValue;
          }

          return { ...setting, value: cssString };
        })
        .filter((s: any) => s !== null);

      setSettings(processedSettings);
      const loadedResourceIds: Record<string, string | null> = {};
      processedSettings.forEach((setting) => {
        if (!setting) return;
        const unitValue = setting.templateSettingValues?.find(
          (value: NonNullable<TemplateSampleSetting["templateSettingValues"]>[number]) =>
            value.unitId != null,
        );
        const defaultValue = setting.templateSettingValues?.find(
          (value: NonNullable<TemplateSampleSetting["templateSettingValues"]>[number]) =>
            value.unitId == null,
        );
        loadedResourceIds[setting.id] =
          setting.resourceId ??
          unitValue?.resourceId ??
          defaultValue?.resourceId ??
          null;
      });
      setResourceIds(loadedResourceIds);
      setHasUnsavedChanges(false);
      setPdfUrl(null);
      lastPreviewedKey.current = null;
      setIsFirstLoad(true);

      const defaultMap: Record<string, boolean> = {};
      processedSettings.forEach((s) => {
        if (s) defaultMap[s.id] = !s.isUnitOverride;
      });
      setUseDefaultSettings(defaultMap);

      const initialPayload = buildSettingsPayloadItems(
        processedSettings,
        loadedResourceIds,
        bulletResources,
        cssValueToPreviewObject,
      );
      baselineRef.current = buildSettingBaselines(
        initialPayload,
        processedSettings,
      );
      settingsLoadedRef.current = false;
    } catch (err) {
      console.error("Error loading settings:", err);
      setError(t("error.loadingSettings", "Error loading style settings"));
    } finally {
      setSettingsLoading(false);
    }
  }, [templateId, unitId, t, bulletResources]);

  // --- Setting change handler --------------------------------------------
  const handleSettingChange = useCallback(
    (index: number, cssString: string) => {
      setSettings((prev) => {
        const newSettings = [...prev];
        newSettings[index] = { ...newSettings[index], value: cssString };
        return newSettings;
      });
      const settingId = settings[index]?.id;
      if (settingId) {
        setUseDefaultSettings((prev) => ({ ...prev, [settingId]: false }));
      }
      setHasUnsavedChanges(true);
    },
    [settings],
  );

  // --- Typed setting change handlers (labels / margins / layout) --------
  const handleTypedSettingChange = useCallback(
    (
      index: number,
      value: LetterLabelsText | PageMarginValue | LetterLayoutConfigValue,
    ) => {
      setSettings((prev) => {
        const newSettings = [...prev];
        newSettings[index] = { ...newSettings[index], value: value as any };
        return newSettings;
      });
      const settingId = settings[index]?.id;
      if (settingId) {
        setUseDefaultSettings((prev) => ({ ...prev, [settingId]: false }));
      }
      setHasUnsavedChanges(true);
    },
    [settings],
  );

  const handleLetterLabelsChange = useCallback(
    (index: number, labels: LetterLabelsText) =>
      handleTypedSettingChange(index, labels),
    [handleTypedSettingChange],
  );

  const handleSingleLetterLabelChange = useCallback(
    (labelKey: LetterLabelKey, entry: LetterLabelEntry) => {
      const index = settings.findIndex((setting) =>
        isLetterLabelsSetting(setting.code),
      );
      if (index < 0) return;
      const labels = normalizeLetterLabelsValue(settings[index].value);
      handleLetterLabelsChange(index, { ...labels, [labelKey]: entry });
    },
    [settings, handleLetterLabelsChange],
  );

  const handlePageMarginChange = useCallback(
    (index: number, margins: PageMarginValue) =>
      handleTypedSettingChange(index, margins),
    [handleTypedSettingChange],
  );

  const handleLayoutConfigChange = useCallback(
    (index: number, layout: LetterLayoutConfigValue) =>
      handleTypedSettingChange(index, layout),
    [handleTypedSettingChange],
  );

  const handleResourceIdChange = useCallback(
    (settingId: string, resourceId: string | null) => {
      setResourceIds((previous) => ({ ...previous, [settingId]: resourceId }));
      setUseDefaultSettings((previous) => ({
        ...previous,
        [settingId]: false,
      }));
      setHasUnsavedChanges(true);
    },
    [],
  );

  // --- Toggle default ---------------------------------------------------
  const handleToggleDefault = useCallback(
    (settingId: string) => {
      const willUseDefault = !(useDefaultSettings[settingId] ?? true);

      setUseDefaultSettings((prev) => {
        const newValue = !prev[settingId];
        if (newValue) {
          const settingIndex = settings.findIndex((s) => s.id === settingId);
          if (settingIndex >= 0) {
            const setting = settings[settingIndex];
            const revertValue = resolveGlobalDefaultSettingValue(setting);
            setSettings((prevSettings) => {
              const newSettings = [...prevSettings];
              newSettings[settingIndex] = {
                ...newSettings[settingIndex],
                value: revertValue as TemplateSampleSetting["value"],
              };
              return newSettings;
            });
          }
        }
        setHasUnsavedChanges(true);
        return { ...prev, [settingId]: newValue };
      });

      if (willUseDefault) {
        setResourceIds((prev) => {
          const next = { ...prev };
          delete next[settingId];
          return next;
        });
      }
    },
    [settings, useDefaultSettings],
  );

  // --- Apply (generate preview) -----------------------------------------
  const handleApply = useCallback(
    async (options?: { dbOnly?: boolean }) => {
      if (!templateId || !unitId) {
        console.error("Missing templateId or unitId");
        return;
      }

      try {
        setPreviewLoading(true);
        setError(null);

        let headerFileInfo: HeaderFooterResponseDto["fileInfo"] | undefined;
        if (selectedHeaderId) {
          const selectedHeader = headers.find((h) => h.id === selectedHeaderId);
          if (selectedHeader?.fileInfo) headerFileInfo = selectedHeader.fileInfo;
        } else if (headers.length > 0) {
          headerFileInfo = headers[0].fileInfo;
        }

        let footerFileInfo: HeaderFooterResponseDto["fileInfo"] | undefined;
        if (selectedFooterId) {
          const selectedFooter = footers.find((f) => f.id === selectedFooterId);
          if (selectedFooter?.fileInfo) footerFileInfo = selectedFooter.fileInfo;
        } else if (footers.length > 0) {
          footerFileInfo = footers[0].fileInfo;
        }

        const dataPayload = {
          ...getDefaultSampleData(previewLanguage),
          unitId,
          ...(headerFileInfo && {
            header: toTemplateSampleFileInfo(headerFileInfo),
          }),
          ...(footerFileInfo && {
            footer: toTemplateSampleFileInfo(footerFileInfo),
          }),
        };

        if (options?.dbOnly) {
          const payload = {
            data: dataPayload,
          };
          const response = await TemplateService.generateSampleTemplate(
            templateId,
            payload,
            unitId,
          );
          if (response.pdf) {
            setPdfUrl(response.pdf);
          } else {
            throw new Error(t("error.noPdfInResponse", "No PDF in response"));
          }
          return;
        }

        const previewItems = buildPreviewSettingsPayload();
        const payload = {
          data: dataPayload,
          ...(previewItems.length > 0
            ? {
                settings: previewItems.map((item) => ({
                  id: item.id,
                  code: item.code,
                  value: item.value,
                  resourceId: item.resourceId,
                })),
              }
            : {}),
          resources: buildResourcesPayload(),
        };

        const response = await TemplateService.generateSampleTemplate(
          templateId,
          payload,
          unitId,
        );

        if (response.pdf) {
          setPdfUrl(response.pdf);
        } else {
          throw new Error(t("error.noPdfInResponse", "No PDF in response"));
        }
      } catch (err: unknown) {
        const errorMessage =
          err instanceof Error
            ? err.message
            : t("error.generatingPreview", "Error generating preview");
        console.error("Error generating preview:", err);
        setError(errorMessage);
        toast.error(errorMessage);
      } finally {
        setPreviewLoading(false);
      }
    },
    [
      templateId,
      unitId,
      selectedHeaderId,
      selectedFooterId,
      headers,
      footers,
      previewLanguage,
      buildPreviewSettingsPayload,
      buildResourcesPayload,
      t,
    ],
  );

  // --- Save (persist to DB) ---------------------------------------------
  const handleSave = useCallback(async () => {
    if (!templateId) {
      console.error("Missing templateId");
      return;
    }

    try {
      setSettingsLoading(true);
      const payloadItems = buildSettingsPayload();
      const valuesToSave = buildBulkSavePayload({
        settings,
        payloadItems,
        useDefaultSettings,
        scope: "unit",
        baselines: baselineRef.current,
      }).filter((item) => {
        if (item.revertToDefault) return true;
        const setting = settings.find((s) => s.id === item.templateSettingId);
        if (!setting || !isFontSetting(setting.code)) return true;
        return Boolean(item.resourceId);
      });

      if (valuesToSave.length === 0) {
        toast.info(
          t("template.noChangesToSave", "No setting changes to save"),
        );
        return;
      }

      await TemplateService.saveBulkTemplateSettingValues(valuesToSave, unitId);
      await loadSettings();
      setHasUnsavedChanges(false);
      void handleApply({ dbOnly: true });
      toast.success(
        t("template.saveSuccess", "Style settings saved successfully"),
      );
    } catch (err: unknown) {
      const errorMessage =
        err instanceof Error
          ? err.message
          : t("error.savingSettings", "Error saving style settings");
      console.error("Error saving settings:", err);
      toast.error(errorMessage);
    } finally {
      setSettingsLoading(false);
    }
  }, [
    templateId,
    buildSettingsPayload,
    settings,
    useDefaultSettings,
    unitId,
    loadSettings,
    handleApply,
    t,
  ]);

  const handleResetAllToDefault = useCallback(async () => {
    if (!templateId || !unitId || settings.length === 0) return;

    const overridesToRevert = settings.filter((setting) => setting.isUnitOverride);

    try {
      setResetInProgress(true);
      setSettingsLoading(true);
      setShowResetModal(false);

      const nextUseDefault: Record<string, boolean> = {};
      const nextResourceIds: Record<string, string | null> = {};
      const nextSettings = settings.map((setting) => {
        nextUseDefault[setting.id] = true;
        const defaultResourceId = resolveGlobalDefaultResourceId(setting);
        if (defaultResourceId) {
          nextResourceIds[setting.id] = defaultResourceId;
        }
        return {
          ...setting,
          value: resolveGlobalDefaultSettingValue(setting),
          isUnitOverride: false,
        };
      });

      setSettings(nextSettings);
      setUseDefaultSettings(nextUseDefault);
      setResourceIds(nextResourceIds);
      setHasUnsavedChanges(false);
      setPdfUrl(null);
      lastPreviewedKey.current = null;
      setIsFirstLoad(false);

      if (overridesToRevert.length > 0) {
        await TemplateService.saveBulkTemplateSettingValues(
          overridesToRevert.map((setting) => ({
            templateSettingId: setting.id,
            revertToDefault: true,
          })),
          unitId,
        );
        await loadSettings();
      }

      void handleApply({ dbOnly: true });
      toast.success(
        t(
          "template.resetAllSuccess",
          "All style settings were reset to global defaults",
        ),
      );
    } catch (err: unknown) {
      const errorMessage =
        err instanceof Error
          ? err.message
          : t("template.resetAllError", "Failed to reset style settings");
      console.error("Error resetting style settings:", err);
      toast.error(errorMessage);
      try {
        await loadSettings();
      } catch {
        // loadSettings already surfaces errors via page state
      }
    } finally {
      setResetInProgress(false);
      setSettingsLoading(false);
    }
  }, [templateId, unitId, settings, loadSettings, handleApply, t]);

  // --- Back navigation with warning -------------------------------------
  const handleBack = useCallback(() => {
    if (hasUnsavedChanges) {
      setShowUnsavedModal(true);
      pendingNavigation.current = onBack;
    } else {
      onBack();
    }
  }, [hasUnsavedChanges, onBack]);

  const handleConfirmLeave = useCallback(() => {
    setShowUnsavedModal(false);
    if (pendingNavigation.current) {
      pendingNavigation.current();
      pendingNavigation.current = null;
    }
  }, []);

  const handleCancelLeave = useCallback(() => {
    setShowUnsavedModal(false);
    pendingNavigation.current = null;
  }, []);
  // --- Header/Footer selection handlers ---------------------------------
  const handleHeaderChange = useCallback((headerId: string) => {
    setSelectedHeaderId(headerId);
    setHasUnsavedChanges(true);
  }, []);

  const handleFooterChange = useCallback((footerId: string) => {
    setSelectedFooterId(footerId);
    setHasUnsavedChanges(true);
  }, []);

  // --- Category selection handler ---------------------------------------
  const scrollToLayoutAssetPlacement = useCallback(() => {
    setLayoutPlacementFocusNonce((nonce) => nonce + 1);
    window.requestAnimationFrame(() => {
      document
        .getElementById(LETTER_ASSET_PLACEMENT_ELEMENT_ID)
        ?.scrollIntoView({ behavior: "smooth", block: "start" });
    });
  }, []);

  const handleSelectCategory = useCallback(
    (categoryCode: string) => {
      setSelectedCategory(categoryCode);
      setMobileNavOpen(false);
      setSearchParams(
        (prev) => {
          const next = new URLSearchParams(prev);
          next.set("category", categoryCode);
          return next;
        },
        { replace: true },
      );
      if (categoryCode === "layout") {
        window.setTimeout(scrollToLayoutAssetPlacement, 150);
        return;
      }
      const category = sidebarCategories.find((item) => item.code === categoryCode);
      const categorySettingIds =
        category?.settingIds.filter((id) => {
          const setting = settings.find((item) => item.id === id);
          return setting && !isLetterLabelsSetting(setting.code);
        }) ?? [];
      const firstSetting = settings.find((setting) =>
        categorySettingIds.includes(setting.id),
      );
      if (firstSetting && settingRefs.current[firstSetting.id]) {
        settingRefs.current[firstSetting.id]?.scrollIntoView({
          behavior: "smooth",
          block: "start",
        });
        return;
      }
      const firstLabelKey = getLetterLabelKeysForCategory(
        categoryCode,
        category?.settingIds
          .map((id) => settings.find((setting) => setting.id === id)?.code)
          .filter((code): code is string => Boolean(code)) ?? [],
      )[0];
      if (
        firstLabelKey &&
        settingRefs.current[`letter-label-${firstLabelKey}`]
      ) {
        settingRefs.current[`letter-label-${firstLabelKey}`]?.scrollIntoView({
          behavior: "smooth",
          block: "start",
        });
        return;
      }
    },
    [settings, sidebarCategories, setSearchParams, scrollToLayoutAssetPlacement],
  );

  useEffect(() => {
    if (effectiveSelectedCategory !== "layout" || settings.length === 0) return;
    const timer = window.setTimeout(scrollToLayoutAssetPlacement, 200);
    return () => window.clearTimeout(timer);
  }, [effectiveSelectedCategory, settings.length, scrollToLayoutAssetPlacement]);

  // --- Effects ---------------------------------------------------------
  // Load headers/footers
  useEffect(() => {
    if (headerFooterData) {
      setHeaders(headerFooterData.headers || []);
      setFooters(headerFooterData.footers || []);
      if (!selectedHeaderId && headerFooterData.headers?.length > 0) {
        setSelectedHeaderId(headerFooterData.headers[0].id);
      }
      if (!selectedFooterId && headerFooterData.footers?.length > 0) {
        setSelectedFooterId(headerFooterData.footers[0].id);
      }
    }
  }, [headerFooterData, selectedHeaderId, selectedFooterId]);

  // Initial load
  useEffect(() => {
    if (templateId && unitId) {
      loadTemplate();
      loadSettings();
    }
  }, [templateId, unitId, loadTemplate, loadSettings]);

  // Set initial category from URL or first available
  useEffect(() => {
    if (sidebarCategories.length === 0) return;

    const categoryFromUrl = searchParams.get("category");
    const matchedCategory = sidebarCategories.find(
      (category) => category.code === categoryFromUrl,
    );

    if (categoryFromUrl === "labels") {
      const fallbackCategory =
        sidebarCategories.find(
          (category) =>
            getLetterLabelKeysForCategory(
              category.code,
              category.settingIds
                .map((id) => settings.find((setting) => setting.id === id)?.code)
                .filter((code): code is string => Boolean(code)),
            ).length > 0,
        ) ?? sidebarCategories[0];
      if (fallbackCategory) {
        setSelectedCategory(fallbackCategory.code);
        setSearchParams(
          (prev) => {
            const next = new URLSearchParams(prev);
            next.set("category", fallbackCategory.code);
            return next;
          },
          { replace: true },
        );
      }
      return;
    }

    if (matchedCategory) {
      if (selectedCategory !== matchedCategory.code) {
        setSelectedCategory(matchedCategory.code);
      }
      return;
    }

    if (!selectedCategory || selectedCategory === "fonts") {
      const firstCategory = sidebarCategories[0].code;
      setSelectedCategory(firstCategory);
      setSearchParams(
        (prev) => {
          const next = new URLSearchParams(prev);
          next.set("category", firstCategory);
          return next;
        },
        { replace: true },
      );
    }
  }, [sidebarCategories, searchParams, selectedCategory, setSearchParams, settings]);

  // Keyboard shortcut: Ctrl/Cmd+S to save
  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if ((event.ctrlKey || event.metaKey) && event.key === "s") {
        event.preventDefault();
        if (hasUnsavedChanges && !settingsLoading) {
          handleSave();
        }
      }
    };
    window.addEventListener("keydown", handleKeyDown);
    return () => window.removeEventListener("keydown", handleKeyDown);
  }, [hasUnsavedChanges, settingsLoading, handleSave]);

  // Warn on page/tab close
  useEffect(() => {
    const handleBeforeUnload = (e: BeforeUnloadEvent) => {
      if (hasUnsavedChanges) {
        e.preventDefault();
        e.returnValue = "";
      }
    };
    window.addEventListener("beforeunload", handleBeforeUnload);
    return () => window.removeEventListener("beforeunload", handleBeforeUnload);
  }, [hasUnsavedChanges]);

  // Live preview debouncing
  const settingsKey = useMemo(
    () =>
      JSON.stringify({
        settings: settings.map((s) => ({ id: s.id, value: s.value })),
        selectedHeaderId,
        selectedFooterId,
        previewLanguage,
        unitId,
      }),
    [settings, selectedHeaderId, selectedFooterId, previewLanguage, unitId],
  );
  const debouncedSettingsKey = useDebounce(settingsKey, 500);

  useEffect(() => {
    if (settings.length > 0 && !settingsLoadedRef.current && unitId) {
      settingsLoadedRef.current = true;
      void handleApply({ dbOnly: true });
    }
  }, [settings.length, unitId, handleApply]);

  useEffect(() => {
    if (!livePreviewEnabled) return;
    if (!templateId || !unitId || settings.length === 0) return;
    if (isFirstLoad) {
      setIsFirstLoad(false);
      return;
    }
    if (debouncedSettingsKey !== lastPreviewedKey.current) {
      lastPreviewedKey.current = debouncedSettingsKey;
      void handleApply();
    }
  }, [debouncedSettingsKey, livePreviewEnabled, handleApply, isFirstLoad, templateId, unitId, settings.length]);

  // --- Loading state check (must be after all hooks) -------------------
  if (settingsLoading && settings.length === 0) {
    return (
      <div className="flex h-96 items-center justify-center">
        <Loader className="h-8 w-8 animate-spin text-purple-600" />
      </div>
    );
  }

  // --- Render -----------------------------------------------------------
  return (
    <div className="flex min-h-[720px] flex-col overflow-hidden rounded-xl bg-gray-50 dark:bg-gray-900">
      {/* Header */}
      <div className="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 px-6 py-4">
        <div className="flex flex-wrap items-center justify-between gap-4">
          <div className="flex items-center gap-4">
            <button
              onClick={handleBack}
              className="flex items-center gap-2 rounded-lg px-2 py-1.5 text-gray-600 transition-colors hover:bg-gray-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white"
            >
              <ArrowLeft className="h-5 w-5" />
              <span className="font-medium">{t("common.back", "Back")}</span>
            </button>
            <div className="h-6 w-px bg-gray-300 dark:bg-gray-600" />
            <h1 className="text-xl font-semibold text-gray-900 dark:text-white">
              {template?.name?.en ||
                t("template.styleSettings", "Style Settings")}
            </h1>
          </div>
          <div className="flex flex-wrap items-center gap-3">
            <div className="hidden items-center gap-3 rounded-lg bg-gray-100 px-3 py-2 text-sm text-gray-600 dark:bg-gray-700 dark:text-gray-300 md:flex">
              <CheckCircle2 className="h-4 w-4 text-emerald-600" />
              <span>
                {settings.length} {t("template.settings", "settings")}
              </span>
              {totalCustomSettings > 0 && (
                <span className="text-purple-600 dark:text-purple-400">
                  · {totalCustomSettings} custom
                </span>
              )}
              <div className="flex items-center gap-2 border-l border-gray-300 pl-3 dark:border-gray-600">
                <div className="h-1.5 w-20 overflow-hidden rounded-full bg-gray-200 dark:bg-gray-600">
                  <div
                    className="h-full rounded-full bg-purple-500 transition-all duration-500"
                    style={{ width: `${customizationProgress}%` }}
                  />
                </div>
                <span className="text-xs text-gray-500">{customizationProgress}%</span>
              </div>
            </div>
            <button
              type="button"
              onClick={() => setShowResetModal(true)}
              disabled={
                settingsLoading ||
                resetInProgress ||
                !hasSettingsToReset ||
                !unitId
              }
              title={
                hasSettingsToReset
                  ? t(
                      "template.resetAllHint",
                      "Restore all unit style settings to global template defaults",
                    )
                  : t(
                      "template.resetAllAlreadyDefault",
                      "All settings already match global defaults",
                    )
              }
              className={cn(
                "inline-flex items-center gap-2 rounded-lg border px-3 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
                hasSettingsToReset
                  ? "border-amber-200 bg-amber-50 text-amber-800 hover:bg-amber-100 dark:border-amber-800 dark:bg-amber-950/40 dark:text-amber-200 dark:hover:bg-amber-950/60"
                  : "border-gray-200 bg-gray-50 text-gray-400 dark:border-gray-700 dark:bg-gray-800/60 dark:text-gray-500",
              )}
            >
              {resetInProgress ? (
                <Loader className="h-4 w-4 animate-spin" />
              ) : (
                <RotateCcw className="h-4 w-4" />
              )}
              {t("template.resetAllToDefault", "Reset to Default")}
            </button>
            <button
              type="button"
              onClick={() => setLivePreviewEnabled((current) => !current)}
              className={cn(
                "inline-flex items-center gap-2 rounded-lg border px-3 py-2 text-sm font-medium transition-colors",
                livePreviewEnabled
                  ? "border-purple-200 bg-purple-50 text-purple-700 dark:border-purple-800 dark:bg-purple-900/30 dark:text-purple-300"
                  : "border-gray-200 bg-white text-gray-600 hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700",
              )}
            >
              {livePreviewEnabled ? (
                <Eye className="h-4 w-4" />
              ) : (
                <EyeOff className="h-4 w-4" />
              )}
              {t("template.livePreview", "Live Preview")}
            </button>
            <div className="flex flex-wrap items-center gap-2 text-sm text-gray-600 dark:text-gray-300">
              <span>{t("template.previewLanguage", "Preview language")}</span>
              <select
                value={previewLanguage}
                onChange={(e) =>
                  setPreviewLanguage(e.target.value as "am" | "en")
                }
                className="rounded-lg border border-gray-300 bg-white px-2 py-1.5 text-sm dark:border-gray-600 dark:bg-gray-800 dark:text-white"
              >
                <option value="am">{t("template.amharic", "Amharic")}</option>
                <option value="en">{t("template.english", "English")}</option>
              </select>
            </div>
            <UnsavedChangesIndicator visible={hasUnsavedChanges} />
          </div>
        </div>
      </div>

      {/* Error Display */}
      {error && (
        <div className="mx-6 mt-4 p-4 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-lg">
          <p className="text-sm text-red-800 dark:text-red-400">{error}</p>
          <button
            onClick={loadSettings}
            className="mt-2 text-sm text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300 font-medium"
          >
            {t("common.retry", "Retry")}
          </button>
        </div>
      )}

      {/* Main Content - 2 Panel Layout */}
      <div className="relative flex min-h-0 flex-1 flex-col overflow-hidden">
        {/* Scoped mobile category drawer — contained within Style Settings */}
        {mobileNavOpen ? (
          <>
            <button
              type="button"
              className="absolute inset-0 z-30 bg-black/40 xl:hidden"
              onClick={() => setMobileNavOpen(false)}
              aria-label={t("common.close", "Close")}
            />
            <aside
              className="absolute left-0 top-0 z-40 flex h-full w-[min(20rem,calc(100%-1rem))] flex-col overflow-hidden border-r border-gray-200 bg-white shadow-2xl xl:hidden dark:border-gray-700 dark:bg-gray-800"
              role="dialog"
              aria-modal="true"
              aria-label={t("template.styleCategories", "Style Categories")}
            >
              <div className="flex items-center justify-between border-b border-gray-200 px-4 py-3 dark:border-gray-700">
                <h2 className="text-sm font-semibold text-gray-900 dark:text-white">
                  {t("template.styleCategories", "Style Categories")}
                </h2>
                <button
                  type="button"
                  onClick={() => setMobileNavOpen(false)}
                  className="rounded-lg p-2 text-gray-500 transition-colors hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700"
                  aria-label={t("common.close", "Close")}
                >
                  <X className="h-4 w-4" />
                </button>
              </div>
              <nav className="flex-1 space-y-1 overflow-y-auto p-4">
                {filteredSidebarCategories.length === 0 ? (
                  <p className="px-2 py-4 text-center text-sm text-gray-500 dark:text-gray-400">
                    {t("common.noResults", "No settings found")}
                  </p>
                ) : (
                  filteredSidebarCategories.map((category) => {
                    const Icon = CATEGORY_ICONS[category.code] ?? Palette;
                    const customCount =
                      categoryCustomCounts.get(category.code) ?? 0;
                    const isActive = effectiveSelectedCategory === category.code;

                    return (
                      <StyleSettingsSidebarItem
                        key={category.code}
                        icon={Icon}
                        label={category.label}
                        isActive={isActive}
                        compact
                        onClick={() => handleSelectCategory(category.code)}
                        meta={
                          <span>
                            {getCategoryVisibleItemCount(category.code)}{" "}
                            {t("template.settings", "settings")}
                          </span>
                        }
                        badge={
                          customCount > 0 ? (
                            <span className="rounded-full bg-amber-100 px-1.5 py-0.5 font-medium text-amber-700 dark:bg-amber-900/40 dark:text-amber-300">
                              {customCount} custom
                            </span>
                          ) : undefined
                        }
                      />
                    );
                  })
                )}
              </nav>
            </aside>
          </>
        ) : null}

        <div className="flex min-h-0 flex-1 flex-col gap-10 overflow-auto p-4 sm:p-6 2xl:flex-row 2xl:gap-0 2xl:overflow-hidden 2xl:p-0">
        {/* Left Panel - split into sidebar + editor area */}
        <div className="flex min-h-0 w-full min-w-0 flex-1 flex-col overflow-hidden rounded-xl border border-gray-200 bg-white dark:border-gray-700 dark:bg-gray-800/50 lg:min-h-[640px] xl:flex-row 2xl:w-1/2 2xl:rounded-none 2xl:border-0 2xl:border-r 2xl:bg-transparent 2xl:dark:bg-transparent">
          {/* Vertical Category Sidebar — xl+ desktop */}
          <StyleSettingsSidebar
            title={t("template.styleCategories", "Style Categories")}
            hint={t("template.categoryHint", "Pick a section to edit")}
            collapsed={categoryNavCollapsed}
            className="hidden xl:flex"
          >
            {filteredSidebarCategories.length === 0 ? (
              <p className="px-2 py-4 text-center text-sm text-gray-500 dark:text-gray-400">
                {t("common.noResults", "No settings found")}
              </p>
            ) : (
              filteredSidebarCategories.map((category) => {
                const Icon = CATEGORY_ICONS[category.code] ?? Palette;
                const customCount =
                  categoryCustomCounts.get(category.code) ?? 0;
                const isActive = effectiveSelectedCategory === category.code;

                return (
                  <StyleSettingsSidebarItem
                    key={category.code}
                    icon={Icon}
                    label={category.label}
                    isActive={isActive}
                    iconOnly={categoryNavCollapsed}
                    onClick={() => handleSelectCategory(category.code)}
                    meta={
                      categoryNavCollapsed ? undefined : (
                        <span>
                          {getCategoryVisibleItemCount(category.code)}{" "}
                          {t("template.settings", "settings")}
                        </span>
                      )
                    }
                    badge={
                      !categoryNavCollapsed && customCount > 0 ? (
                        <span className="rounded-full bg-amber-100 px-1.5 py-0.5 font-medium text-amber-700 dark:bg-amber-900/40 dark:text-amber-300">
                          {customCount} custom
                        </span>
                      ) : undefined
                    }
                  />
                );
              })
            )}
          </StyleSettingsSidebar>

          {/* Editor Area */}
          <div className="min-w-0 flex-1 overflow-y-auto overflow-x-hidden p-4 sm:p-6">
            <div className="space-y-4">
              <div className="flex min-w-0 flex-wrap items-center justify-between gap-3">
                <div className="flex min-w-0 items-start gap-2 sm:gap-3">
                  <button
                    type="button"
                    onClick={() => setMobileNavOpen(true)}
                    className="inline-flex shrink-0 items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm font-medium text-gray-700 shadow-sm transition-colors hover:bg-gray-50 xl:hidden dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
                    aria-label={t("template.styleCategories", "Style Categories")}
                  >
                    <Menu className="h-4 w-4" />
                    <span className="hidden sm:inline">
                      {t("template.styleCategories", "Categories")}
                    </span>
                  </button>
                  <button
                    type="button"
                    onClick={() => setCategoryNavCollapsed((prev) => !prev)}
                    className="hidden shrink-0 items-center gap-2 rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm font-medium text-gray-700 shadow-sm transition-colors hover:bg-gray-50 xl:inline-flex dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
                    aria-label={
                      categoryNavCollapsed
                        ? t("template.expandSidebar", "Expand sidebar")
                        : t("template.collapseSidebar", "Collapse sidebar")
                    }
                    title={
                      categoryNavCollapsed
                        ? t("template.expandSidebar", "Expand sidebar")
                        : t("template.collapseSidebar", "Collapse sidebar")
                    }
                  >
                    {categoryNavCollapsed ? (
                      <PanelLeft className="h-4 w-4" />
                    ) : (
                      <PanelLeftClose className="h-4 w-4" />
                    )}
                  </button>
                  <div className="min-w-0">
                    <h2 className="text-lg font-semibold text-gray-900 dark:text-white">
                      {t("template.styleEditor", "Style Editor")}
                    </h2>
                    <p className="text-sm text-gray-500 dark:text-gray-400">
                      {t(
                        "template.styleEditorHint",
                        "Tune settings, then preview the generated PDF.",
                      )}
                    </p>
                  </div>
                </div>
                <div className="relative w-full sm:w-64">
                  <Search className="pointer-events-none absolute left-3 top-2.5 h-4 w-4 text-gray-400" />
                  <input
                    type="search"
                    value={searchTerm}
                    onChange={(event) => setSearchTerm(event.target.value)}
                    placeholder={t("common.search", "Search settings...")}
                    className={cn(STYLE_INPUT_CLASS, "py-2 pl-9 pr-9")}
                  />
                  {searchTerm ? (
                    <button
                      type="button"
                      onClick={() => setSearchTerm("")}
                      className="absolute right-2.5 top-2.5 rounded p-0.5 text-gray-400 transition-colors hover:text-gray-600 dark:hover:text-gray-200"
                      aria-label={t("common.clear", "Clear")}
                    >
                      <X className="h-4 w-4" />
                    </button>
                  ) : null}
                </div>
              </div>

              {/* Header and Footer Selection */}
              {showHeaderFooterSection ? (
              <StyleSettingPanel
                title={t("template.headerFooterSelection", "Header & Footer")}
                className="space-y-4"
              >
                <div className="flex items-center justify-end">
                  {isHeaderFooterLoading && (
                    <span className="inline-flex items-center gap-2 text-xs text-gray-500">
                      <Loader className="h-3.5 w-3.5 animate-spin" />
                      {t("common.loading", "Loading")}
                    </span>
                  )}
                </div>

                <div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
                  <StyleSettingSelect
                    label={t("addRecord.Header", "Header")}
                    value={selectedHeaderId || EMPTY_SELECT_VALUE}
                    onValueChange={(value) =>
                      handleHeaderChange(
                        value === EMPTY_SELECT_VALUE ? "" : value,
                      )
                    }
                    placeholder={
                      headers?.length
                        ? t("addRecord.Select Header", "Select Header")
                        : t("addRecord.Loading Headers...", "Loading Headers...")
                    }
                    options={[
                      {
                        value: EMPTY_SELECT_VALUE,
                        label: headers?.length
                          ? t("addRecord.Select Header", "Select Header")
                          : t(
                              "addRecord.Loading Headers...",
                              "Loading Headers...",
                            ),
                      },
                      ...headers.map((header) => ({
                        value: header.id,
                        label: header.name?.en || header.name?.am || header.id,
                      })),
                    ]}
                  />

                  <StyleSettingSelect
                    label={t("addRecord.Footer", "Footer")}
                    value={selectedFooterId || EMPTY_SELECT_VALUE}
                    onValueChange={(value) =>
                      handleFooterChange(
                        value === EMPTY_SELECT_VALUE ? "" : value,
                      )
                    }
                    placeholder={
                      footers?.length
                        ? t("addRecord.Select Footer", "Select Footer")
                        : t("addRecord.Loading Footers...", "Loading Footers...")
                    }
                    options={[
                      {
                        value: EMPTY_SELECT_VALUE,
                        label: footers?.length
                          ? t("addRecord.Select Footer", "Select Footer")
                          : t(
                              "addRecord.Loading Footers...",
                              "Loading Footers...",
                            ),
                      },
                      ...footers.map((footer) => ({
                        value: footer.id,
                        label: footer.name?.en || footer.name?.am || footer.id,
                      })),
                    ]}
                  />
                </div>

                {/* Header Preview */}
                {selectedHeaderId &&
                  headers.length > 0 &&
                  (() => {
                    const selectedHeader = headers.find(
                      (h) => h.id === selectedHeaderId,
                    );
                    return selectedHeader?.presigned ? (
                      <div className="rounded-lg border border-dashed border-gray-300 bg-gray-50 p-4 dark:border-gray-600 dark:bg-gray-900/40">
                        <p className="text-sm font-medium text-gray-600 mb-2">
                          {t("addRecord.Header Preview", "Header Preview")}
                        </p>
                        <img
                          src={selectedHeader.presigned}
                          alt={
                            selectedHeader.name?.en ||
                            selectedHeader.name?.am ||
                            "Header"
                          }
                          className="h-auto max-w-full rounded border border-gray-200 bg-white dark:border-gray-700"
                        />
                      </div>
                    ) : null;
                  })()}

                {/* Footer Preview */}
                {selectedFooterId &&
                  footers.length > 0 &&
                  (() => {
                    const selectedFooter = footers.find(
                      (f) => f.id === selectedFooterId,
                    );
                    return selectedFooter?.presigned ? (
                      <div className="rounded-lg border border-dashed border-gray-300 bg-gray-50 p-4 dark:border-gray-600 dark:bg-gray-900/40">
                        <p className="text-sm font-medium text-gray-600 mb-2">
                          {t("addRecord.Footer Preview", "Footer Preview")}
                        </p>
                        <img
                          src={selectedFooter.presigned}
                          alt={
                            selectedFooter.name?.en ||
                            selectedFooter.name?.am ||
                            "Footer"
                          }
                          className="h-auto max-w-full rounded border border-gray-200 bg-white dark:border-gray-700"
                        />
                      </div>
                    ) : null;
                  })()}
              </StyleSettingPanel>
              ) : null}

              {/* Settings for selected category */}
              {settings.length === 0 && !settingsLoading ? (
                <div className="text-center py-8 text-gray-500">
                  {t("template.noSettings", "No style settings available")}
                </div>
              ) : (
                selectedCategory && (
                  <div className="mt-4">
                    <div className="mb-4 flex items-center justify-between">
                      <h3 className="text-lg font-semibold text-gray-900 dark:text-white">
                        {sidebarCategories.find(
                          (c) => c.code === effectiveSelectedCategory,
                        )?.label || effectiveSelectedCategory}
                      </h3>
                      <span className="text-sm text-gray-500 dark:text-gray-400">
                        {selectedCategoryVisibleCount}{" "}
                        {t("template.visible", "visible")}
                      </span>
                    </div>
                    {selectedCategorySettings.map((setting) => {
                      const originalIndex = settings.findIndex(
                        (s) => s.id === setting.id,
                      );
                      return (
                        <div
                          key={setting.id}
                          ref={(el) => {
                            settingRefs.current[setting.id] = el;
                          }}
                        >
                          <div className="mb-2 flex justify-end">
                            <button
                              type="button"
                              onClick={() => setHistorySetting(setting)}
                              className="inline-flex items-center gap-1 rounded-md border border-gray-200 px-2.5 py-1 text-xs font-medium text-gray-600 transition-colors hover:bg-gray-50 dark:border-gray-700 dark:text-gray-300 dark:hover:bg-gray-800"
                            >
                              <History className="h-3.5 w-3.5" />
                              {t("template.viewHistory", "History")}
                            </button>
                          </div>
                          {isPageMarginSetting(setting.code) ? (
                            <PageMarginEditor
                              value={setting.value}
                              isDefault={useDefaultSettings[setting.id] ?? true}
                              onToggleDefault={() =>
                                handleToggleDefault(setting.id)
                              }
                              onChange={(margins) =>
                                handlePageMarginChange(originalIndex, margins)
                              }
                            />
                          ) : isLayoutConfigSetting(setting.code) ? (
                            <LayoutConfigEditor
                              setting={setting}
                              value={normalizeLayoutConfigValue(setting.value)}
                              isDefault={useDefaultSettings[setting.id] ?? true}
                              onToggleDefault={handleToggleDefault}
                              appliesTo={setting.appliesTo}
                              pageMargin={resolvedPageMargin}
                              placementLanguage={previewLanguage}
                              placementFocusNonce={layoutPlacementFocusNonce}
                              onChange={(layout) =>
                                handleLayoutConfigChange(originalIndex, layout)
                              }
                            />
                          ) : (
                            <StyleSettingsEditor
                              setting={setting}
                              index={originalIndex}
                              onChange={handleSettingChange}
                              isDefault={useDefaultSettings[setting.id] ?? true}
                              onToggleDefault={handleToggleDefault}
                              storedResourceId={resourceIds[setting.id] ?? null}
                              previewLanguage={previewLanguage}
                              onListStyleResourceChange={(resourceId) =>
                                handleResourceIdChange(setting.id, resourceId)
                              }
                            />
                          )}
                        </div>
                      );
                    })}
                    {selectedCategoryLabelKeys.length > 0 ? (
                      <div className="mt-6 space-y-3 border-t border-gray-200 pt-5 dark:border-gray-700">
                        <div>
                          <h4 className="text-sm font-semibold text-gray-900 dark:text-white">
                            {t("template.letterLabelFields", "Label text")}
                          </h4>
                          <p className="mt-1 text-xs text-gray-500 dark:text-gray-400">
                            {t(
                              "template.letterLabelsSectionHint",
                              "Customize the printed labels for this section.",
                            )}
                          </p>
                        </div>
                        {selectedCategoryLabelKeys.map((labelKey, labelIndex) => (
                          <div
                            key={labelKey}
                            ref={(el) => {
                              settingRefs.current[`letter-label-${labelKey}`] = el;
                            }}
                          >
                            {labelIndex === 0 && letterLabelsSetting ? (
                              <div className="mb-2 flex justify-end">
                                <button
                                  type="button"
                                  onClick={() =>
                                    setHistorySetting(letterLabelsSetting)
                                  }
                                  className="inline-flex items-center gap-1 rounded-md border border-gray-200 px-2.5 py-1 text-xs font-medium text-gray-600 transition-colors hover:bg-gray-50 dark:border-gray-700 dark:text-gray-300 dark:hover:bg-gray-800"
                                >
                                  <History className="h-3.5 w-3.5" />
                                  {t("template.viewHistory", "History")}
                                </button>
                              </div>
                            ) : null}
                            <LetterLabelFieldEditor
                              labelKey={labelKey}
                              entry={normalizedLetterLabels[labelKey]}
                              isDefault={letterLabelsIsDefault}
                              showDefaultToggle={labelIndex === 0}
                              onToggleDefault={
                                letterLabelsSetting
                                  ? () =>
                                      handleToggleDefault(letterLabelsSetting.id)
                                  : undefined
                              }
                              onChange={(entry) =>
                                handleSingleLetterLabelChange(labelKey, entry)
                              }
                            />
                          </div>
                        ))}
                      </div>
                    ) : null}
                    {selectedCategoryVisibleCount === 0 && (
                      <p className="text-gray-500 text-sm">
                        {t(
                          "template.noSettingsForCategory",
                          "No settings in this category",
                        )}
                      </p>
                    )}
                  </div>
                )
              )}
            </div>
          </div>
        </div>

        {/* Right Panel - PDF Preview */}
        <div className="flex h-[min(78dvh,52rem)] w-full min-w-0 shrink-0 flex-col overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm dark:border-gray-700 sm:h-[min(82dvh,56rem)] 2xl:h-auto 2xl:min-h-[640px] 2xl:w-1/2 2xl:flex-1 2xl:rounded-none 2xl:border-0 2xl:shadow-none">
          <PDFPreviewPanel
            pdfUrl={pdfUrl}
            loading={previewLoading}
            error={error}
            onApply={() => {
              void handleApply();
            }}
            livePreviewEnabled={livePreviewEnabled}
          />
        </div>
        </div>
      </div>

      {/* Footer - Save Button */}
      <div className="bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700 px-6 py-4">
        <div className="flex flex-wrap items-center justify-between gap-4">
          <div className="flex flex-col gap-1">
            <p className="text-sm text-gray-500 dark:text-gray-400">
              {hasUnsavedChanges
                ? t("template.unsavedChanges", "Unsaved changes")
                : t("template.allChangesSaved", "All changes saved")}
              <span className="ml-2 hidden text-xs text-gray-400 sm:inline">
                ({t("template.saveShortcut", "Ctrl+S to save")})
              </span>
            </p>
            <p className="max-w-xl text-xs text-gray-500 dark:text-gray-400">
              {t(
                "template.saveUnitHint",
                "Changes are saved for the selected unit. Use the default toggle on a setting to remove your unit override.",
              )}
            </p>
          </div>
          <button
            onClick={handleSave}
            disabled={settingsLoading || !hasUnsavedChanges || !unitId}
            className="inline-flex items-center gap-2 rounded-lg bg-purple-600 px-6 py-2 font-medium text-white transition-colors hover:bg-purple-700 disabled:cursor-not-allowed disabled:opacity-50 dark:hover:bg-purple-500"
          >
            {settingsLoading ? (
              <Loader className="h-4 w-4 animate-spin" />
            ) : (
              <Save className="h-4 w-4" />
            )}
            {settingsLoading
              ? t("template.saving", "Saving...")
              : t("common.save", "Save")}
          </button>
        </div>
      </div>
      <SettingHistoryModal
        open={historySetting !== null}
        onOpenChange={(open) => {
          if (!open) setHistorySetting(null);
        }}
        setting={historySetting}
        unitId={unitId}
        onRestored={async () => {
          await loadSettings();
          void handleApply({ dbOnly: true });
        }}
      />
      <UnsavedChangesModal
        isOpen={showUnsavedModal}
        onConfirm={handleConfirmLeave}
        onCancel={handleCancelLeave}
      />
      <ResetAllDefaultsModal
        isOpen={showResetModal}
        busy={resetInProgress}
        onConfirm={() => {
          void handleResetAllToDefault();
        }}
        onCancel={() => {
          if (!resetInProgress) setShowResetModal(false);
        }}
      />
    </div>
  );
};
