// Rôle : vérifie les invariants statiques des toolboxes et de leurs outils.
import { readFile } from "node:fs/promises";
import { test } from "node:test";
import assert from "node:assert/strict";

test("toolbox storage, cards and pages are wired", async () => {
  const source = await readFile("website/src/main.jsx", "utf8");
  const toolboxCard = await readFile("website/src/features/toolboxes/ToolboxCard.jsx", "utf8");
  const toolboxPages = await readFile("website/src/features/toolboxes/ToolboxPages.jsx", "utf8");
  const toolboxActions = await readFile("website/src/features/toolboxes/useToolboxActions.js", "utf8");
  const toolboxStorage = await readFile("website/src/features/toolboxes/storage/toolboxStorage.js", "utf8");
  const indexedToolboxesHook = await readFile("website/src/features/toolboxes/storage/useIndexedToolboxes.js", "utf8");
  const storageQuota = await readFile("website/src/components/StorageQuota.jsx", "utf8");
  const importButton = await readFile("website/src/components/ImportButton.jsx", "utf8");
  const reorderHook = await readFile("website/src/hooks/usePointerReorder.js", "utf8");
  const groupedReorderHook = await readFile("website/src/hooks/useGroupedReorder.js", "utf8");
  const inlineEditHook = await readFile("website/src/hooks/useInlineEdit.js", "utf8");
  const draftFormHook = await readFile("website/src/hooks/useDraftForm.js", "utf8");

  assert.match(`${indexedToolboxesHook}\n${toolboxPages}`, /indexedDbStorage\.js/);
  assert.match(source, /features\/toolboxes\/storage\/useIndexedToolboxes\.js/);
  assert.match(source, /features\/toolboxes\/useToolboxActions\.js/);
  assert.match(indexedToolboxesHook, /export function useIndexedToolboxes/);
  assert.match(indexedToolboxesHook, /getStorageEstimate/);
  assert.match(toolboxActions, /export function useToolboxActions/);
  assert.match(toolboxActions, /importAllToolboxesPayload/);
  assert.match(toolboxActions, /async function addImageFiles/);
  assert.match(`${source}\n${toolboxActions}`, /features\/toolboxes\/storage\/toolboxStorage\.js/);
  assert.match(toolboxStorage, /TOOLBOX_ICON_FILES/);
  assert.match(toolboxStorage, /export function normalizeToolboxIcon/);
  assert.match(toolboxStorage, /export function createGlobalExportPayload/);
  assert.match(toolboxStorage, /qtyTarget/);
  assert.match(toolboxStorage, /qtyCurrent/);
  assert.match(toolboxStorage, /hideCompletedSections/);
  assert.match(toolboxStorage, /hideCompletedSectionsFully/);
  assert.match(toolboxStorage, /hideWhenComplete/);
  assert.match(toolboxStorage, /collapsed/);
  assert.match(toolboxStorage, /module\.scrollable/);
  assert.match(toolboxStorage, /export function normalizeLinksData/);
  assert.match(toolboxStorage, /export function normalizeCountersData/);
  assert.match(toolboxStorage, /export function normalizeCombosData/);
  assert.match(toolboxStorage, /export function normalizeCalculatorData/);
  assert.match(toolboxStorage, /export function normalizeTableData/);
  assert.match(toolboxStorage, /export function normalizeTimerData/);
  assert.match(toolboxStorage, /export function normalizeTaskPlannerData/);
  assert.match(toolboxStorage, /export function normalizeImageAnnotationData/);
  assert.match(toolboxStorage, /export function compactModuleDataForStorage\(type, value\)/);
  assert.match(toolboxStorage, /scrollResults/);
  assert.match(toolboxCard, /DEFAULT_TOOLBOX_ICON/);
  assert.match(toolboxCard, /export function ToolboxCard/);
  assert.match(toolboxCard, /export function ToolboxIconPicker/);
  assert.match(toolboxCard, /export function ToolboxGameIcon/);
  assert.match(toolboxCard, /toolbox-card-drag-handle/);
  assert.match(toolboxCard, /reorder\.getItemProps/);
  assert.match(toolboxCard, /toolbox-card-cover-link/);
  assert.match(toolboxCard, /toolbox-icon-cover/);
  assert.match(toolboxPages, /\.\/ToolboxCard\.jsx/);
  assert.match(toolboxPages, /updateToolboxOrder/);
  assert.match(toolboxPages, /useGroupedReorder/);
  assert.match(toolboxPages, /useInlineEdit/);
  assert.match(toolboxPages, /getContentEditableProps/);
  assert.match(toolboxPages, /orientation: "horizontal"/);
  assert.match(toolboxPages, /components\/StorageQuota\.jsx/);
  assert.match(toolboxPages, /components\/ImportButton\.jsx/);
  assert.match(toolboxPages, /import-icon-button/);
  assert.match(toolboxPages, /getToolboxGame\(toolbox\)/);
  assert.match(toolboxPages, /Vers la page de jeu/);
  assert.match(toolboxPages, /Vers la toolbox complète/);
  assert.match(toolboxPages, /#\/games\/\$\{toolboxGame\.id\}/);
  assert.match(toolboxPages, /#\/toolbox\/\$\{toolbox\.id\}/);
  assert.match(toolboxPages, /setDrawerGameId\(""\)/);
  assert.match(toolboxPages, /moduleColumns/);
  assert.match(toolboxPages, /normalizeCombosData/);
  assert.match(toolboxPages, /function ToolboxView/);
  assert.doesNotMatch(toolboxPages, /usePointerReorder/);
  assert.match(storageQuota, /export function StorageQuota/);
  assert.match(storageQuota, /role="progressbar"/);
  assert.match(importButton, /export function ImportButton/);
  assert.match(importButton, /accept="application\/json"/);
  assert.match(reorderHook, /export function usePointerReorder/);
  assert.match(reorderHook, /setPointerCapture/);
  assert.match(reorderHook, /elementsFromPoint/);
  assert.match(reorderHook, /elementFromPoint/);
  assert.match(groupedReorderHook, /export function useGroupedReorder/);
  assert.match(groupedReorderHook, /usePointerReorder/);
  assert.match(groupedReorderHook, /export function getGroupedEntries/);
  assert.match(groupedReorderHook, /export function applyGroupedReorderOperation/);
  assert.match(groupedReorderHook, /data-reorder-orientation/);
  assert.match(groupedReorderHook, /operation\.sourceParentId === operation\.targetParentId/);
  assert.match(inlineEditHook, /export function useInlineEdit/);
  assert.match(inlineEditHook, /skipCommitRef/);
  assert.match(inlineEditHook, /blurOnEscape/);
  assert.match(inlineEditHook, /commitOnEnter/);
  assert.match(inlineEditHook, /getContentEditableProps/);
  assert.match(draftFormHook, /export function useDraftForm/);
  assert.match(draftFormHook, /getFieldProps/);
  assert.match(draftFormHook, /handleSubmit/);
  assert.match(draftFormHook, /preventDefault/);
});

test("toolbox module registry and modules expose expected behavior", async () => {
  const source = await readFile("website/src/main.jsx", "utf8");
  const moduleRegistry = await readFile("website/src/features/toolboxes/modules/index.jsx", "utf8");
  const notepadModule = await readFile("website/src/features/toolboxes/modules/NotepadModule.jsx", "utf8");
  const combosModule = await readFile("website/src/features/toolboxes/modules/CombosModule.jsx", "utf8");
  const calculatorModule = await readFile("website/src/features/toolboxes/modules/CalculatorModule.jsx", "utf8");
  const tableModule = await readFile("website/src/features/toolboxes/modules/TableModule.jsx", "utf8");
  const tableFormulaEngine = await readFile("website/src/features/toolboxes/modules/tableFormulaEngine.js", "utf8");
  const timerModule = await readFile("website/src/features/toolboxes/modules/TimerModule.jsx", "utf8");
  const taskPlannerModule = await readFile("website/src/features/toolboxes/modules/TaskPlannerModule.jsx", "utf8");
  const checklistModule = await readFile("website/src/features/toolboxes/modules/ChecklistModule.jsx", "utf8");
  const imagesModule = await readFile("website/src/features/toolboxes/modules/ImagesModule.jsx", "utf8");
  const imageAnnotationModule = await readFile("website/src/features/toolboxes/modules/ImageAnnotationModule.jsx", "utf8");
  const linksModule = await readFile("website/src/features/toolboxes/modules/LinksModule.jsx", "utf8");
  const textImportModal = await readFile("website/src/features/toolboxes/modules/TextImportModal.jsx", "utf8");
  const countersModule = await readFile("website/src/features/toolboxes/modules/CountersModule.jsx", "utf8");
  const textImport = await readFile("website/src/features/toolboxes/modules/textImport.js", "utf8");
  const imageViewer = await readFile("website/src/components/ImageViewer.jsx", "utf8");

  assert.match(moduleRegistry, /export const TOOLBOX_MODULES/);
  assert.match(moduleRegistry, /export function AddToolControls/);
  assert.match(moduleRegistry, /export function ToolboxModules/);
  assert.match(moduleRegistry, /MODULE_COMPONENTS/);
  assert.match(moduleRegistry, /notepad:/);
  assert.match(moduleRegistry, /checklist:/);
  assert.match(moduleRegistry, /images:/);
  assert.match(moduleRegistry, /links:/);
  assert.match(moduleRegistry, /counters:/);
  assert.match(moduleRegistry, /combos:/);
  assert.match(moduleRegistry, /CombosModule/);
  assert.match(moduleRegistry, /calculator:/);
  assert.match(moduleRegistry, /table:/);
  assert.match(moduleRegistry, /table: \{ label: "Tableau", icon: "table", Component: TableModule, editable: false, scrollable: true \}/);
  assert.match(moduleRegistry, /timer:/);
  assert.match(moduleRegistry, /taskPlanner:/);
  assert.match(moduleRegistry, /imageAnnotation:/);
  assert.match(moduleRegistry, /Annotation d'images/);
  assert.match(moduleRegistry, /editable: false/);
  assert.match(moduleRegistry, /module-edit-button/);
  assert.match(moduleRegistry, /itemReorder\.startDrag/);
  assert.match(moduleRegistry, /onPointerDown/);
  assert.match(moduleRegistry, /useGroupedReorder/);
  assert.match(moduleRegistry, /useInlineEdit/);
  assert.match(moduleRegistry, /getContentEditableProps/);
  assert.match(moduleRegistry, /tool-add-card/);
  assert.match(moduleRegistry, /tool-quick-add-button/);
  assert.match(moduleRegistry, /tool-add-quick-toggle/);
  assert.match(moduleRegistry, /scrollable: true/);
  assert.match(moduleRegistry, /module-content/);
  assert.match(moduleRegistry, /module-scroll-button/);
  assert.match(moduleRegistry, /Icon name="dropdown"/);
  assert.match(moduleRegistry, /CompactDropdown/);
  assert.doesNotMatch(source, /<select value="" onChange=\{\(event\) => addModule/);
  assert.match(notepadModule, /export function NotepadModule/);
  assert.match(combosModule, /export function CombosModule/);
  assert.match(combosModule, /keyboardMouse/);
  assert.match(combosModule, /Nintendo 64/);
  assert.match(combosModule, /ComboInputToken/);
  assert.match(combosModule, /ComboSequence/);
  assert.match(combosModule, /keyboardLayout/);
  assert.match(combosModule, /simultaneousMode/);
  assert.match(combosModule, /SPECIAL_INPUT_GROUP/);
  assert.match(combosModule, /grab/);
  assert.match(combosModule, /protect/);
  assert.match(combosModule, /shoot/);
  assert.match(combosModule, /holdMs/);
  assert.match(combosModule, /toggleSelectedInputHold/);
  assert.match(combosModule, /combo-hold-field/);
  assert.match(combosModule, /useInlineEdit/);
  assert.match(combosModule, /useGroupedReorder/);
  assert.match(combosModule, /reorderFeatures/);
  assert.match(combosModule, /namespace: `combos-\$\{moduleId\}`/);
  assert.match(combosModule, /getGroupBoundaryProps/);
  assert.match(combosModule, /combos-category-boundary-drop-zone/);
  assert.match(combosModule, /function setComboItemCategory/);
  assert.match(combosModule, /setItemGroup: setComboItemCategory/);
  assert.doesNotMatch(combosModule, /canMoveItem:/);
  assert.doesNotMatch(combosModule, /canMoveGroup:/);
  assert.match(calculatorModule, /export function CalculatorModule/);
  assert.match(calculatorModule, /calculateExpression/);
  assert.match(calculatorModule, /activeParentId/);
  assert.match(calculatorModule, /parentId/);
  assert.match(calculatorModule, /useInlineEdit/);
  assert.match(calculatorModule, /useGroupedReorder/);
  assert.match(calculatorModule, /calculator-drag-handle/);
  assert.match(calculatorModule, /scrollResults/);
  assert.match(calculatorModule, /tool-split-scroll-toggle/);
  assert.match(calculatorModule, /EditableCalculatorLabel/);
  assert.match(calculatorModule, /tool-split-entry-label/);
  assert.match(calculatorModule, /copyChecklistImport/);
  assert.match(calculatorModule, /resetCalculator/);
  assert.match(calculatorModule, /returnToRoot/);
  assert.match(calculatorModule, /setExpression\(activeParent \? formatResult\(activeParent\.value\) : ""\)/);
  assert.match(calculatorModule, /Quantité non modifiable/);
  assert.match(calculatorModule, /entry\.label \|\| formatResult\(entry\.value\)/);
  assert.match(calculatorModule, /ResizeObserver/);
  assert.match(calculatorModule, /--calculator-scroll-height/);
  assert.match(calculatorModule, /CalculatorEntries/);
  assert.match(tableModule, /export function TableModule/);
  assert.match(tableModule, /Icon name="add-row"/);
  assert.match(tableModule, /Icon name="add-column"/);
  assert.match(tableModule, /Icon name="remove-row"/);
  assert.match(tableModule, /Icon name="remove-column"/);
  assert.match(tableModule, /insertFormulaReferenceSelection/);
  assert.match(tableModule, /startFormulaSelection/);
  assert.match(tableModule, /copyTsv/);
  assert.match(tableModule, /notepad-toolbar table-toolbar/);
  assert.match(tableModule, /notepad-toolbar-group/);
  assert.match(tableModule, /notepad-toolbar-button/);
  assert.match(tableModule, /selection/);
  assert.match(tableModule, /draggingSelectionRef/);
  assert.match(tableModule, /isMultiCellSelection/);
  assert.match(tableModule, /handleCellKeyDown/);
  assert.match(tableModule, /clearSelection/);
  assert.match(tableModule, /event\.key === "Delete"/);
  assert.match(tableModule, /ArrowUp/);
  assert.match(tableModule, /ArrowDown/);
  assert.match(tableModule, /ArrowLeft/);
  assert.match(tableModule, /ArrowRight/);
  assert.match(tableModule, /function HeaderLabelInput/);
  assert.match(tableModule, /useInlineEdit/);
  assert.match(tableModule, /event\.target\.select/);
  assert.match(tableFormulaEngine, /export function evaluateTableCell/);
  assert.doesNotMatch(tableFormulaEngine, /Function\(/);
  assert.doesNotMatch(tableFormulaEngine, /\beval\(/);
  assert.match(timerModule, /export function TimerModule/);
  assert.match(timerModule, /Tabs/);
  assert.match(timerModule, /stopwatch/);
  assert.match(timerModule, /countdown/);
  assert.match(timerModule, /useInlineEdit/);
  assert.match(timerModule, /useDraftForm/);
  assert.match(timerModule, /normalizeTimerData/);
  assert.match(taskPlannerModule, /export function TaskPlannerModule/);
  assert.match(taskPlannerModule, /normalizeTaskPlannerData/);
  assert.match(taskPlannerModule, /applyDueResets/);
  assert.match(taskPlannerModule, /relations/);
  assert.match(taskPlannerModule, /prerequisite/);
  assert.match(taskPlannerModule, /categoryOrder/);
  assert.match(taskPlannerModule, /categoryLabel/);
  assert.match(taskPlannerModule, /task-planner-warning/);
  assert.match(taskPlannerModule, /useGroupedReorder/);
  assert.match(taskPlannerModule, /useInlineEdit/);
  assert.match(taskPlannerModule, /useDraftForm/);
  assert.match(taskPlannerModule, /commitOnEnter: false/);
  assert.match(taskPlannerModule, /reorderFeatures/);
  assert.doesNotMatch(taskPlannerModule, /canMoveItem:/);
  assert.doesNotMatch(taskPlannerModule, /canMoveGroup:/);
  assert.match(checklistModule, /export function ChecklistModule/);
  assert.match(checklistModule, /TextImportModal/);
  assert.match(checklistModule, /Icon name="import"/);
  assert.match(checklistModule, /editing &&/);
  assert.match(checklistModule, /ChecklistItem/);
  assert.match(checklistModule, /ChecklistSection/);
  assert.match(checklistModule, /parseChecklistImport/);
  assert.match(checklistModule, /parseColonImportLines/);
  assert.match(checklistModule, /startsWith\("#"\)/);
  assert.match(checklistModule, /chevron-down/);
  assert.match(checklistModule, /chevron-up/);
  assert.match(checklistModule, /Number\.parseInt/);
  assert.match(checklistModule, /checklist-qty-current/);
  assert.match(checklistModule, /checklist-delete-button danger/);
  assert.match(checklistModule, /useGroupedReorder/);
  assert.match(checklistModule, /getItemProps/);
  assert.match(checklistModule, /getGroupProps/);
  assert.match(checklistModule, /getGroupBoundaryProps/);
  assert.match(checklistModule, /checklist-category-boundary-drop-zone/);
  assert.match(checklistModule, /itemReorder\.startDrag/);
  assert.match(checklistModule, /groupReorder\.startDrag/);
  assert.match(checklistModule, /useInlineEdit/);
  assert.match(checklistModule, /moveChecklistItemToCategory/);
  assert.match(textImportModal, /createPortal/);
  assert.match(textImportModal, /lockBodyScroll/);
  assert.match(imagesModule, /export function ImagesModule/);
  assert.match(imagesModule, /useGroupedReorder/);
  assert.match(imagesModule, /orientation: "horizontal"/);
  assert.match(imagesModule, /editing &&/);
  assert.match(imagesModule, /clipboardData/);
  assert.match(imagesModule, /createImageAnnotationModule/);
  assert.match(imagesModule, /image-annotate-button/);
  assert.match(imagesModule, /dataTransfer\.files/);
  assert.match(imageAnnotationModule, /export function ImageAnnotationModule/);
  assert.match(imageAnnotationModule, /annotation-marker/);
  assert.match(imageAnnotationModule, /setImageFromFiles/);
  assert.match(imageAnnotationModule, /context\.compressImageFile/);
  assert.match(imageAnnotationModule, /context\.setImage/);
  assert.match(imageAnnotationModule, /createMarkerId/);
  assert.match(imageAnnotationModule, /<Icon name="zoom"/);
  assert.match(linksModule, /export function LinksModule/);
  assert.match(linksModule, /TextImportModal/);
  assert.match(linksModule, /Icon name="import"/);
  assert.match(linksModule, /editing &&/);
  assert.match(linksModule, /normalizeUrl/);
  assert.match(linksModule, /copyText/);
  assert.match(linksModule, /parseColonImportLines/);
  assert.match(linksModule, /context\.normalizeUrl/);
  assert.match(linksModule, /useGroupedReorder/);
  assert.match(linksModule, /useDraftForm/);
  assert.match(linksModule, /linkDraft\.getFieldProps/);
  assert.match(linksModule, /link-drag-handle/);
  assert.match(countersModule, /export function CountersModule/);
  assert.match(countersModule, /editing &&/);
  assert.match(countersModule, /counter-actions/);
  assert.match(countersModule, /useGroupedReorder/);
  assert.match(countersModule, /useDraftForm/);
  assert.match(countersModule, /counterDraft\.getFieldProps/);
  assert.match(countersModule, /orientation: "horizontal"/);
  assert.match(countersModule, /counter-drag-handle/);
  assert.match(timerModule, /useGroupedReorder/);
  assert.match(timerModule, /reorderEnabled=\{!data\.sortResults\}/);
  assert.match(timerModule, /parentId=\{moduleId\}/);
  assert.match(timerModule, /timer-drag-handle/);
  assert.match(textImport, /export function parseColonImportLines/);
  assert.match(textImport, /line\.indexOf\(":\"\)/);
  assert.match(imageViewer, /image-viewer-media/);
  assert.match(imageViewer, /image-viewer-image-frame/);
  assert.match(imageViewer, /image-viewer-marker/);
  assert.match(imageViewer, /function openImageInNewTab/);
  assert.match(imageViewer, /!hasMarkers &&/);
  assert.match(imageViewer, /<Icon name="zoom"/);
  assert.match(imageViewer, /annotation-marker-list themed-scrollbar/);
});
