// @vitest-environment jsdom
/**
 * Expanded tests for tool-registry covering edge cases not in the main test.
 *
 * Focuses on: DisplayMode type completeness, registry size validation,
 * livePreview flag consistency, ResultsPanel / PreviewPanel presence,
 * and verifying the registry aligns with shared TOOLS definitions.
 */
import { describe, expect, it, vi } from "vitest";

// Mock all lazy-loaded tool settings components
vi.mock("@/components/tools/resize-settings", () => ({ ResizeSettings: () => null }));
vi.mock("@/components/tools/crop-settings", () => ({ CropSettings: () => null }));
vi.mock("@/components/tools/rotate-settings", () => ({ RotateSettings: () => null }));
vi.mock("@/components/tools/convert-settings", () => ({ ConvertSettings: () => null }));
vi.mock("@/components/tools/compress-settings", () => ({ CompressSettings: () => null }));
vi.mock("@/components/tools/optimize-for-web-settings", () => ({
  OptimizeForWebSettings: () => null,
}));
vi.mock("@/components/tools/strip-metadata-settings", () => ({
  StripMetadataSettings: () => null,
}));
vi.mock("@/components/tools/edit-metadata-settings", () => ({
  EditMetadataSettings: () => null,
}));
vi.mock("@/components/tools/color-settings", () => ({ ColorSettings: () => null }));
vi.mock("@/components/tools/sharpening-settings", () => ({ SharpeningSettings: () => null }));
vi.mock("@/components/tools/watermark-text-settings", () => ({
  WatermarkTextSettings: () => null,
}));
vi.mock("@/components/tools/watermark-image-settings", () => ({
  WatermarkImageSettings: () => null,
}));
vi.mock("@/components/tools/text-overlay-settings", () => ({
  TextOverlaySettings: () => null,
}));
vi.mock("@/components/tools/compose-settings", () => ({ ComposeSettings: () => null }));
vi.mock("@/components/tools/info-settings", () => ({ InfoSettings: () => null }));
vi.mock("@/components/tools/compare-settings", () => ({ CompareSettings: () => null }));
vi.mock("@/components/tools/find-duplicates-settings", () => ({
  FindDuplicatesSettings: () => null,
}));
vi.mock("@/components/tools/find-duplicates-results", () => ({
  FindDuplicatesResults: () => null,
}));
vi.mock("@/components/tools/color-palette-settings", () => ({
  ColorPaletteSettings: () => null,
}));
vi.mock("@/components/tools/qr-generate-settings", () => ({
  QrGenerateSettings: () => null,
}));
vi.mock("@/components/tools/qr-generate-preview", () => ({
  QrGeneratePreview: () => null,
}));
vi.mock("@/components/tools/barcode-read-settings", () => ({
  BarcodeReadSettings: () => null,
}));
vi.mock("@/components/tools/image-to-base64-settings", () => ({
  ImageToBase64Settings: () => null,
}));
vi.mock("@/components/tools/image-to-base64-results", () => ({
  ImageToBase64Results: () => null,
}));
vi.mock("@/components/tools/collage-settings", () => ({ CollageSettings: () => null }));
vi.mock("@/components/tools/collage-preview", () => ({ CollagePreview: () => null }));
vi.mock("@/components/tools/stitch-settings", () => ({ StitchSettings: () => null }));
vi.mock("@/components/tools/split-settings", () => ({ SplitSettings: () => null }));
vi.mock("@/components/tools/split-canvas", () => ({ SplitCanvas: () => null }));
vi.mock("@/components/tools/border-settings", () => ({ BorderSettings: () => null }));
vi.mock("@/components/tools/svg-to-raster-settings", () => ({
  SvgToRasterSettings: () => null,
}));
vi.mock("@/components/tools/vectorize-settings", () => ({ VectorizeSettings: () => null }));
vi.mock("@/components/tools/gif-tools-settings", () => ({ GifToolsSettings: () => null }));
vi.mock("@/components/tools/bulk-rename-settings", () => ({
  BulkRenameSettings: () => null,
}));
vi.mock("@/components/tools/favicon-settings", () => ({ FaviconSettings: () => null }));
vi.mock("@/components/tools/image-to-pdf-settings", () => ({
  ImageToPdfSettings: () => null,
}));
vi.mock("@/components/tools/pdf-to-image-settings", () => ({
  PdfToImageSettings: () => null,
}));
vi.mock("@/components/tools/pdf-to-image-preview", () => ({
  PdfToImagePreview: () => null,
}));
vi.mock("@/components/tools/replace-color-settings", () => ({
  ReplaceColorSettings: () => null,
}));
vi.mock("@/components/tools/remove-bg-settings", () => ({ RemoveBgSettings: () => null }));
vi.mock("@/components/tools/upscale-settings", () => ({ UpscaleSettings: () => null }));
vi.mock("@/components/tools/ocr-settings", () => ({ OcrSettings: () => null }));
vi.mock("@/components/tools/blur-faces-settings", () => ({
  BlurFacesSettings: () => null,
}));
vi.mock("@/components/tools/enhance-faces-settings", () => ({
  EnhanceFacesSettings: () => null,
}));
vi.mock("@/components/tools/erase-object-settings", () => ({
  EraseObjectSettings: () => null,
}));
vi.mock("@/components/tools/smart-crop-settings", () => ({
  SmartCropSettings: () => null,
}));
vi.mock("@/components/tools/image-enhancement-settings", () => ({
  ImageEnhancementSettings: () => null,
}));
vi.mock("@/components/tools/colorize-settings", () => ({ ColorizeSettings: () => null }));
vi.mock("@/components/tools/noise-removal-settings", () => ({
  NoiseRemovalSettings: () => null,
}));
vi.mock("@/components/tools/passport-photo-settings", () => ({
  PassportPhotoSettings: () => null,
  PassportPhotoPreview: () => null,
}));
vi.mock("@/components/tools/red-eye-removal-settings", () => ({
  RedEyeRemovalSettings: () => null,
}));
vi.mock("@/components/tools/restore-photo-settings", () => ({
  RestorePhotoSettings: () => null,
}));
vi.mock("@/components/tools/transparency-fixer-settings", () => ({
  TransparencyFixerSettings: () => null,
}));
vi.mock("@/components/tools/content-aware-resize-settings", () => ({
  ContentAwareResizeSettings: () => null,
}));
vi.mock("@/components/tools/beautify-settings", () => ({
  BeautifySettings: () => null,
}));
vi.mock("@/components/tools/meme-generator-settings", () => ({
  MemeGeneratorSettings: () => null,
}));
vi.mock("@/components/tools/meme-generator-preview", () => ({
  MemeGeneratorPreview: () => null,
}));
vi.mock("@/components/tools/color-blindness-settings", () => ({
  ColorBlindnessSettings: () => null,
}));
vi.mock("@/components/tools/ai-canvas-expand-settings", () => ({
  AiCanvasExpandSettings: () => null,
}));
vi.mock("@/components/tools/merge-pdf-settings", () => ({
  MergePdfSettings: () => null,
}));
vi.mock("@/components/tools/split-pdf-settings", () => ({
  SplitPdfSettings: () => null,
}));
vi.mock("@/components/tools/compress-pdf-settings", () => ({
  CompressPdfSettings: () => null,
}));
vi.mock("@/components/tools/rotate-pdf-settings", () => ({
  RotatePdfSettings: () => null,
}));
vi.mock("@/components/tools/word-to-pdf-settings", () => ({
  WordToPdfSettings: () => null,
}));
vi.mock("@/components/tools/csv-excel-settings", () => ({
  CsvExcelSettings: () => null,
}));
vi.mock("@/components/tools/csv-json-settings", () => ({
  CsvJsonSettings: () => null,
}));
vi.mock("@/components/tools/json-xml-settings", () => ({
  JsonXmlSettings: () => null,
}));
vi.mock("@/components/tools/split-csv-settings", () => ({
  SplitCsvSettings: () => null,
}));

// Wave 5a: Image gap-fill tools
vi.mock("@/components/tools/barcode-generate-settings", () => ({
  BarcodeGenerateSettings: () => null,
}));
vi.mock("@/components/tools/chart-maker-settings", () => ({
  ChartMakerSettings: () => null,
}));
vi.mock("@/components/tools/circle-crop-settings", () => ({
  CircleCropSettings: () => null,
}));
vi.mock("@/components/tools/duotone-settings", () => ({
  DuotoneSettings: () => null,
}));
vi.mock("@/components/tools/gif-webp-settings", () => ({
  GifWebpSettings: () => null,
}));
vi.mock("@/components/tools/histogram-settings", () => ({
  HistogramSettings: () => null,
}));
vi.mock("@/components/tools/image-pad-settings", () => ({
  ImagePadSettings: () => null,
}));
vi.mock("@/components/tools/lqip-placeholder-settings", () => ({
  LqipPlaceholderSettings: () => null,
}));
vi.mock("@/components/tools/pixelate-settings", () => ({
  PixelateSettings: () => null,
}));
vi.mock("@/components/tools/sprite-sheet-settings", () => ({
  SpriteSheetSettings: () => null,
}));
vi.mock("@/components/tools/vignette-settings", () => ({
  VignetteSettings: () => null,
}));

import { TOOLS } from "@snapotter/shared";
import type { DisplayMode, ToolRegistryEntry } from "@/lib/tool-registry";
import { getToolRegistryEntry, toolRegistry } from "@/lib/tool-registry";

describe("toolRegistry (expanded)", () => {
  describe("registry size and completeness", () => {
    it("has the same number of entries as TOOLS array", () => {
      expect(toolRegistry.size).toBe(TOOLS.length);
    });

    it("every entry in registry has a matching TOOLS entry", () => {
      const toolIds = new Set(TOOLS.map((t) => t.id));
      for (const registryId of toolRegistry.keys()) {
        expect(toolIds.has(registryId), `registry has ${registryId} not in TOOLS[]`).toBe(true);
      }
    });
  });

  describe("displayMode distribution", () => {
    it("has at least one tool per display mode in use", () => {
      const modesInUse = new Set<DisplayMode>();
      for (const entry of toolRegistry.values()) {
        modesInUse.add(entry.displayMode);
      }

      // These modes should be in use
      expect(modesInUse.has("side-by-side")).toBe(true);
      expect(modesInUse.has("before-after")).toBe(true);
      expect(modesInUse.has("live-preview")).toBe(true);
      expect(modesInUse.has("interactive-crop")).toBe(true);
      expect(modesInUse.has("interactive-eraser")).toBe(true);
      expect(modesInUse.has("no-dropzone")).toBe(true);
      expect(modesInUse.has("custom-results")).toBe(true);
    });
  });

  describe("livePreview flag consistency", () => {
    it("live-preview display mode tools have livePreview flag set", () => {
      for (const [toolId, entry] of toolRegistry) {
        if (entry.displayMode === "live-preview") {
          expect(
            entry.livePreview,
            `${toolId} has live-preview mode but livePreview is falsy`,
          ).toBe(true);
        }
      }
    });

    it("non-live-preview display mode tools do not have livePreview flag", () => {
      const liveModes: DisplayMode[] = ["live-preview"];
      for (const [, entry] of toolRegistry) {
        if (!liveModes.includes(entry.displayMode) && entry.livePreview) {
          // Some tools like rotate use livePreview with before-after mode, which is valid
          // Just verify the flag is a boolean
          expect(typeof entry.livePreview).toBe("boolean");
        }
      }
    });
  });

  describe("ResultsPanel requirements", () => {
    it("all custom-results tools have a ResultsPanel", () => {
      const missing: string[] = [];
      for (const [toolId, entry] of toolRegistry) {
        if (entry.displayMode === "custom-results" && !entry.ResultsPanel) {
          missing.push(toolId);
        }
      }
      expect(
        missing,
        `Tools with custom-results missing ResultsPanel: ${missing.join(", ")}`,
      ).toEqual([]);
    });

    it("tools with no-comparison mode do not require ResultsPanel", () => {
      for (const [, entry] of toolRegistry) {
        if (entry.displayMode === "no-comparison") {
          // ResultsPanel is optional for no-comparison mode
          // Just verify no error occurs
          expect(entry.Settings).toBeDefined();
        }
      }
    });
  });

  describe("PreviewPanel presence", () => {
    it("tools with PreviewPanel have the correct display modes", () => {
      const previewAllowedModes: DisplayMode[] = [
        "no-dropzone",
        "custom-results",
        "interactive-split",
      ];
      for (const [toolId, entry] of toolRegistry) {
        if ((entry as ToolRegistryEntry & { PreviewPanel?: unknown }).PreviewPanel) {
          // PreviewPanel is typically on no-dropzone or custom-results tools
          // Verify the tool has a valid display mode
          expect(
            previewAllowedModes.includes(entry.displayMode) ||
              entry.displayMode === "side-by-side" ||
              entry.displayMode === "before-after" ||
              entry.displayMode === "live-preview",
            `${toolId} has PreviewPanel but unexpected mode ${entry.displayMode}`,
          ).toBe(true);
        }
      }
    });
  });

  describe("specific tool configurations", () => {
    it("watermark-text uses before-after display", () => {
      const entry = getToolRegistryEntry("watermark-text");
      expect(entry?.displayMode).toBe("before-after");
    });

    it("watermark-image uses before-after display", () => {
      const entry = getToolRegistryEntry("watermark-image");
      expect(entry?.displayMode).toBe("before-after");
    });

    it("text-overlay uses before-after display", () => {
      const entry = getToolRegistryEntry("text-overlay");
      expect(entry?.displayMode).toBe("before-after");
    });

    it("replace-color uses before-after display", () => {
      const entry = getToolRegistryEntry("replace-color");
      expect(entry?.displayMode).toBe("before-after");
    });

    it("sharpening uses before-after display", () => {
      const entry = getToolRegistryEntry("sharpening");
      expect(entry?.displayMode).toBe("before-after");
    });

    it("strip-metadata uses no-comparison display", () => {
      const entry = getToolRegistryEntry("strip-metadata");
      expect(entry?.displayMode).toBe("no-comparison");
    });

    it("info uses no-comparison display", () => {
      const entry = getToolRegistryEntry("info");
      expect(entry?.displayMode).toBe("no-comparison");
    });

    it("compare uses before-after display", () => {
      const entry = getToolRegistryEntry("compare");
      expect(entry?.displayMode).toBe("before-after");
    });

    it("color-palette uses no-comparison display", () => {
      const entry = getToolRegistryEntry("color-palette");
      expect(entry?.displayMode).toBe("no-comparison");
    });

    it("barcode-read uses before-after display", () => {
      const entry = getToolRegistryEntry("barcode-read");
      expect(entry?.displayMode).toBe("before-after");
    });

    it("ocr uses before-after display", () => {
      const entry = getToolRegistryEntry("ocr");
      expect(entry?.displayMode).toBe("before-after");
    });

    it("vectorize uses before-after display", () => {
      const entry = getToolRegistryEntry("vectorize");
      expect(entry?.displayMode).toBe("before-after");
    });
  });

  describe("getToolRegistryEntry for all TOOLS", () => {
    it("returns defined entry for every shared TOOLS entry", () => {
      for (const tool of TOOLS) {
        const entry = getToolRegistryEntry(tool.id);
        expect(entry, `getToolRegistryEntry("${tool.id}") returned undefined`).toBeDefined();
      }
    });

    it("each returned entry has Settings as a function or object", () => {
      for (const tool of TOOLS) {
        const entry = getToolRegistryEntry(tool.id);
        if (entry) {
          expect(
            typeof entry.Settings === "function" || typeof entry.Settings === "object",
            `${tool.id} Settings is not function/object`,
          ).toBe(true);
        }
      }
    });
  });
});
