// Rôle : fournit l'outil checklist avec quantités, catégories et échange texte.
import { useState } from "react";
import { Icon } from "../../../components/Icon.jsx";
import { useGroupedReorder, moveItem } from "../../../hooks/useGroupedReorder.js";
import { useInlineEdit } from "../../../hooks/useInlineEdit.js";
import { TextExchangeActions } from "./TextExchangeActions.jsx";

export function ChecklistModule({ toolboxId, moduleId, context, editing }) {
  const data = context.normalizeChecklistData(context.getModuleData(toolboxId, moduleId, { items: [] }));
  const textContent = context.moduleText?.checklist || {};
  const [label, setLabel] = useState("");
  const [sectionTitle, setSectionTitle] = useState("");
  const [qty, setQty] = useState(1);
  const namedSections = data.sections.filter((section) => section.title);
  const completedSectionsMode = data.hideCompletedSectionsFully ? "hidden" : data.hideCompletedSections ? "reduced" : "visible";
  const reorderItems = getChecklistReorderItems(data.sections);
  const {
    itemReorder,
    groupReorder,
    getItemProps,
    getGroupProps,
    getGroupBoundaryProps,
    isItemDragging,
    isItemDropTarget,
    isGroupDragging,
    isGroupDropTarget,
    isBoundaryDropTarget,
    getDropPlacement,
    shouldShowGroupBoundaries
  } = useGroupedReorder({
    namespace: `checklist-${moduleId}`,
    items: reorderItems,
    getItemId: (item) => item.id,
    getItemGroup: (item) => item.sectionId,
    getEffectiveGroup: (item) => item.sectionId,
    reorderFeatures: {
      item: { groupChange: true, boundaryDrop: true },
      group: { reorder: true, boundaryDrop: true }
    },
    onItemMove: (operation) => save(moveChecklistItem(data.sections, operation, context)),
    onGroupMove: (operation) => save(moveItem(data.sections, operation.sourceId, operation.targetId, operation.placement))
  });
  const reorder = {
    itemReorder,
    groupReorder,
    getItemProps,
    getGroupProps,
    getGroupBoundaryProps,
    isItemDragging,
    isItemDropTarget,
    isGroupDragging,
    isGroupDropTarget,
    isBoundaryDropTarget,
    getDropPlacement,
    shouldShowGroupBoundaries
  };
  const showBoundaryDropZones = reorder.shouldShowGroupBoundaries();
  const visibleSections = data.sections.filter((section) => !(section.title && data.hideCompletedSectionsFully && isSectionComplete(section, context)));

  function save(sections, settings = {}) {
    context.setModuleData(toolboxId, moduleId, { ...data, ...settings, sections });
  }

  function appendItems(sections, title, items) {
    const cleanTitle = title.trim();
    const existingIndex = sections.findIndex((section) => section.title.toLowerCase() === cleanTitle.toLowerCase());
    if (existingIndex >= 0) {
      return sections.map((section, index) => index === existingIndex ? { ...section, items: [...section.items, ...items] } : section);
    }
    return [...sections, { id: context.uid("section"), title: cleanTitle, items }];
  }

  function addItem(event) {
    event.preventDefault();
    const cleanLabel = label.trim();
    if (!cleanLabel) return;
    const nextItem = { id: context.uid("item"), label: cleanLabel, qtyTarget: Math.max(1, Number(qty) || 1), qtyCurrent: 0 };
    save(appendItems(data.sections, sectionTitle, [nextItem]));
    setLabel("");
    setQty(1);
  }

  function setCompletedSectionsMode(mode) {
    save(data.sections.map((section) => ({ ...section, hideWhenComplete: undefined })), {
      hideCompletedSections: mode === "reduced",
      hideCompletedSectionsFully: mode === "hidden"
    });
  }

  function updateSection(sectionId, updater) {
    save(data.sections.map((section) => section.id === sectionId ? updater(section) : section).filter(keepChecklistSection));
  }

  function renameSection(sectionId, title) {
    save(renameChecklistSection(data.sections, sectionId, title));
  }

  function updateItem(itemId, updater) {
    save(updateChecklistItem(data.sections, itemId, updater));
  }

  function moveItemToCategory(itemId, title) {
    save(moveChecklistItemToCategory(data.sections, itemId, title, context));
  }

  function deleteItem(itemId) {
    save(data.sections.map((section) => ({ ...section, items: section.items.filter((item) => item.id !== itemId) })).filter(keepChecklistSection));
  }

  return (
    <>
      {editing && (
        <div className="module-add-panel">
          <form className="inline-form checklist-add-form" onSubmit={addItem}>
            <input name="section" placeholder={textContent.sectionPlaceholder || "Catégorie"} value={sectionTitle} onChange={(event) => setSectionTitle(event.target.value)} />
            <input name="label" placeholder={textContent.itemPlaceholder || "Nouvel item"} value={label} onChange={(event) => setLabel(event.target.value)} />
            <input className="checklist-qty-input" name="qty" type="number" min="1" value={qty} onChange={(event) => setQty(event.target.value)} aria-label={textContent.quantityLabel || "Quantité cible"} />
            <button className="primary">{textContent.addButton || "Ajouter"}</button>
          </form>
          <TextExchangeActions type="checklist" data={data} context={context} textContent={textContent} onImport={(nextData) => context.setModuleData(toolboxId, moduleId, nextData, "checklist")} />
        </div>
      )}
      {namedSections.length > 0 && (
        <div className="checklist-toolbar" role="radiogroup" aria-label={textContent.completedSectionsModeTitle || "Affichage des catégories terminées"}>
          {[
            { mode: "visible", label: textContent.completedSectionsVisibleLabel || "Visible", icon: "eye-open" },
            { mode: "reduced", label: textContent.completedSectionsReducedLabel || "Réduit", icon: "hide" },
            { mode: "hidden", label: textContent.completedSectionsHiddenLabel || "Caché", icon: "eye-closed" }
          ].map((option) => (
            <button
              className={`checklist-complete-mode-button ${completedSectionsMode === option.mode ? "active" : ""}`}
              type="button"
              role="radio"
              aria-checked={completedSectionsMode === option.mode}
              aria-label={option.label}
              key={option.mode}
              onClick={() => setCompletedSectionsMode(option.mode)}
              title={option.label}
            >
              <Icon name={option.icon} />
            </button>
          ))}
        </div>
      )}
      <ul className="checklist">
        {visibleSections.map((section, index) => {
          const isLastSection = index === visibleSections.length - 1;
          return [
            showBoundaryDropZones ? (
              <li
                className={`checklist-category-boundary-drop-zone ${reorder.isBoundaryDropTarget({ groupId: section.id, placement: "before" }) ? "is-drop-target" : ""}`}
                key={`${section.id}:before-drop`}
                {...reorder.getGroupBoundaryProps({ groupId: section.id, placement: "before" })}
              />
            ) : null,
            <ChecklistSection
              key={section.id}
              section={section}
              data={data}
              context={context}
              reorder={reorder}
              onRenameSection={renameSection}
              onUpdateSection={updateSection}
              onSaveSections={save}
              onUpdateItem={updateItem}
              onMoveItemToCategory={moveItemToCategory}
              onDeleteItem={deleteItem}
            />,
            showBoundaryDropZones && isLastSection ? (
              <li
                className={`checklist-category-boundary-drop-zone ${reorder.isBoundaryDropTarget({ groupId: section.id, placement: "after" }) ? "is-drop-target" : ""}`}
                key={`${section.id}:after-drop`}
                {...reorder.getGroupBoundaryProps({ groupId: section.id, placement: "after" })}
              />
            ) : null
          ];
        })}
      </ul>
    </>
  );
}

function isSectionComplete(section, context) {
  return section.items.length > 0 && section.items.every((item) => context.clampQty(item.qtyCurrent, item.qtyTarget) >= item.qtyTarget);
}

function getSectionHideWhenComplete(section, globalHide) {
  return typeof section.hideWhenComplete === "boolean" ? section.hideWhenComplete : globalHide;
}

function keepChecklistSection(section) {
  return section.items.length;
}

function getChecklistReorderItems(sections) {
  return sections.flatMap((section) => section.items.map((item) => ({ ...item, sectionId: section.id })));
}

function findChecklistSectionByItemId(sections, itemId) {
  return sections.find((section) => section.items.some((item) => item.id === itemId));
}

function renameChecklistSection(sections, sectionId, title) {
  const cleanTitle = title.trim();
  const section = sections.find((entry) => entry.id === sectionId);
  if (!section) return sections;
  const existingSection = sections.find((entry) => entry.id !== sectionId && entry.title.toLowerCase() === cleanTitle.toLowerCase());
  if (!existingSection) {
    return sections.map((entry) => entry.id === sectionId ? { ...entry, title: cleanTitle } : entry).filter(keepChecklistSection);
  }
  return sections.map((entry) => {
    if (entry.id === existingSection.id) return { ...entry, items: [...entry.items, ...section.items] };
    return entry;
  }).filter((entry) => entry.id !== sectionId).filter(keepChecklistSection);
}

function updateChecklistItem(sections, itemId, updater) {
  return sections.map((section) => ({
    ...section,
    items: section.items.map((item) => item.id === itemId ? updater(item) : item).filter((item) => item.label)
  })).filter(keepChecklistSection);
}

function moveChecklistItemToCategory(sections, itemId, title, context) {
  const cleanTitle = title.trim();
  const sourceSection = findChecklistSectionByItemId(sections, itemId);
  const item = sourceSection?.items.find((entry) => entry.id === itemId);
  if (!sourceSection || !item || sourceSection.title.toLowerCase() === cleanTitle.toLowerCase()) return sections;
  const targetSection = sections.find((section) => section.title.toLowerCase() === cleanTitle.toLowerCase());
  const sectionsWithoutItem = sections.map((section) => ({
    ...section,
    items: section.items.filter((entry) => entry.id !== itemId)
  })).filter(keepChecklistSection);
  if (targetSection) {
    return sectionsWithoutItem.map((section) => section.id === targetSection.id ? { ...section, items: [...section.items, item] } : section);
  }
  return [...sectionsWithoutItem, { id: context.uid("section"), title: cleanTitle, items: [item] }];
}

function moveChecklistItem(sections, operation, context) {
  const sourceSection = findChecklistSectionByItemId(sections, operation.sourceId);
  const sourceItem = sourceSection?.items.find((item) => item.id === operation.sourceId);
  if (!sourceSection || !sourceItem) return sections;
  if (operation.targetType === "boundary") return moveChecklistItemToUngroupedBoundary(sections, sourceSection, sourceItem, operation, context);
  const targetSection = operation.targetType === "item"
    ? findChecklistSectionByItemId(sections, operation.targetId)
    : sections.find((section) => section.id === operation.targetGroup);
  if (!targetSection) return sections;
  const sectionsWithoutItem = sections.map((section) => ({
    ...section,
    items: section.items.filter((item) => item.id !== operation.sourceId)
  })).filter(keepChecklistSection);
  return sectionsWithoutItem.map((section) => {
    if (section.id !== targetSection.id) return section;
    if (operation.targetType === "item") {
      const targetIndex = section.items.findIndex((item) => item.id === operation.targetId);
      if (targetIndex < 0) return { ...section, items: [...section.items, sourceItem] };
      const nextItems = [...section.items];
      nextItems.splice(operation.placement === "after" ? targetIndex + 1 : targetIndex, 0, sourceItem);
      return { ...section, items: nextItems };
    }
    return {
      ...section,
      items: operation.placement === "after" ? [...section.items, sourceItem] : [sourceItem, ...section.items]
    };
  });
}

function moveChecklistItemToUngroupedBoundary(sections, sourceSection, sourceItem, operation, context) {
  const targetIndex = sections.findIndex((section) => section.id === operation.targetGroup);
  if (targetIndex < 0) return sections;
  const preferredUngroupedSection = sourceSection.title ? sections.find((section) => !section.title && section.id !== sourceSection.id) : sourceSection;
  const ungroupedSectionId = preferredUngroupedSection?.id || context.uid("section");
  const baseSections = sections
    .map((section) => ({
      ...section,
      items: section.items.filter((item) => item.id !== sourceItem.id)
    }))
    .filter((section) => section.id !== ungroupedSectionId)
    .filter(keepChecklistSection);
  const targetSection = sections[targetIndex];
  const nextTargetIndex = baseSections.findIndex((section) => section.id === targetSection.id);
  const insertIndex = nextTargetIndex < 0
    ? Math.min(targetIndex, baseSections.length)
    : nextTargetIndex + (operation.placement === "after" ? 1 : 0);
  const ungroupedSection = {
    id: ungroupedSectionId,
    title: "",
    items: [...(preferredUngroupedSection?.items || []).filter((item) => item.id !== sourceItem.id), sourceItem]
  };
  const nextSections = [...baseSections];
  nextSections.splice(insertIndex, 0, ungroupedSection);
  return nextSections;
}

function ChecklistSection({ section, context, data, reorder, onRenameSection, onUpdateSection, onSaveSections, onUpdateItem, onMoveItemToCategory, onDeleteItem }) {
  const showTitle = Boolean(section.title);
  const sectionComplete = showTitle && isSectionComplete(section, context);
  const hideWhenComplete = getSectionHideWhenComplete(section, data.hideCompletedSections);
  const isAutoCollapsed = sectionComplete && hideWhenComplete;
  const isCollapsed = Boolean(section.collapsed) || isAutoCollapsed;
  const textContent = context.moduleText?.checklist || {};
  const className = [
    "checklist-section",
    showTitle ? "is-grouped" : "",
    sectionComplete ? "is-complete" : "",
    isCollapsed ? "is-collapsed" : "",
    reorder.isGroupDragging(section.id) ? "is-dragging" : "",
    reorder.isGroupDropTarget(section.id) ? "is-drop-target" : "",
    reorder.getDropPlacement("group", section.id) === "after" ? "drop-after" : ""
  ].filter(Boolean).join(" ");
  const titleEdit = useInlineEdit({
    value: section.title,
    onCommit: (title) => onRenameSection(section.id, title)
  });
  const [editingItemId, setEditingItemId] = useState("");

  if (sectionComplete && data.hideCompletedSectionsFully) return null;

  function saveItems(items) {
    onUpdateSection(section.id, (entry) => ({ ...entry, items }));
  }

  function toggleSectionCollapsed() {
    const nextCollapsed = !isCollapsed;
    const nextSections = data.sections.map((entry) => {
      if (entry.id === section.id) {
        const nextSection = { ...entry };
        if (nextCollapsed) {
          if (sectionComplete) {
            nextSection.hideWhenComplete = true;
            delete nextSection.collapsed;
          } else {
            nextSection.collapsed = true;
          }
        } else {
          delete nextSection.collapsed;
          if (sectionComplete) nextSection.hideWhenComplete = false;
        }
        return nextSection;
      }
      if (data.hideCompletedSections && !nextCollapsed && entry.title && isSectionComplete(entry, context)) return { ...entry, hideWhenComplete: true };
      return entry;
    });
    const nextCompletedSections = nextSections.filter((entry) => entry.title && isSectionComplete(entry, context));
    const allHidden = nextCompletedSections.length > 0 && nextCompletedSections.every((entry) => getSectionHideWhenComplete(entry, false));
    onSaveSections(nextSections, { hideCompletedSections: allHidden });
  }

  return (
    <li className={className} {...reorder.getGroupProps({ groupId: section.id })}>
      {showTitle && (
        <div className="checklist-section-header">
          <button
            className="checklist-drag-handle"
            type="button"
            onPointerDown={(event) => reorder.groupReorder.startDrag(event, { groupId: section.id })}
            aria-label={`${textContent.reorderSectionTitle || "Déplacer la catégorie"} ${section.title}`}
            title={textContent.reorderTitle || "Déplacer"}
          >
            <Icon name="drag" />
          </button>
          <h3>
            <input
              {...titleEdit.getInputProps({
                className: "checklist-section-title-input",
                title: textContent.sectionEditTitle || "Renommer la catégorie",
                "aria-label": textContent.sectionEditTitle || "Renommer la catégorie"
              })}
            />
          </h3>
          <div className="checklist-section-actions">
            <span>{section.items.filter((item) => context.clampQty(item.qtyCurrent, item.qtyTarget) >= item.qtyTarget).length} / {section.items.length}</span>
            <button
              className="checklist-section-collapse-button"
              type="button"
              onClick={toggleSectionCollapsed}
              aria-expanded={!isCollapsed}
              title={isCollapsed ? textContent.showCompletedSectionTitle || "Afficher cette catégorie" : textContent.hideCompletedSectionTitle || "Réduire cette catégorie"}
              aria-label={isCollapsed ? textContent.showCompletedSectionTitle || "Afficher cette catégorie" : textContent.hideCompletedSectionTitle || "Réduire cette catégorie"}
            >
              <Icon name={isCollapsed ? "chevron-down" : "chevron-up"} />
            </button>
          </div>
        </div>
      )}
      {!isCollapsed && (
        <ul className="checklist-section-items">
          {section.items.map((item) => (
            <ChecklistItem
              key={item.id}
              item={item}
              section={section}
              context={context}
              reorder={reorder}
              items={section.items}
              save={saveItems}
              onUpdateItem={onUpdateItem}
              onMoveItemToCategory={onMoveItemToCategory}
              onDeleteItem={onDeleteItem}
              editing={editingItemId === item.id}
              onToggleEditing={() => setEditingItemId(editingItemId === item.id ? "" : item.id)}
            />
          ))}
        </ul>
      )}
    </li>
  );
}

function ChecklistItem({ item, section, context, reorder, items, save, onUpdateItem, onMoveItemToCategory, onDeleteItem, editing, onToggleEditing }) {
  const done = context.clampQty(item.qtyCurrent, item.qtyTarget) >= item.qtyTarget;
  const textContent = context.moduleText?.checklist || {};
  const className = [
    "checklist-item",
    done ? "is-complete" : "",
    reorder.isItemDragging(item.id) ? "is-dragging" : "",
    reorder.isItemDropTarget(item.id) ? "is-drop-target" : "",
    reorder.getDropPlacement("item", item.id) === "after" ? "drop-after" : ""
  ].filter(Boolean).join(" ");
  const labelEdit = useInlineEdit({
    value: item.label,
    transform: (draft) => String(draft || "").trim() || item.label,
    onCommit: (label) => onUpdateItem(item.id, (entry) => ({ ...entry, label })),
    autoFocus: editing,
    focusKey: item.id
  });
  const categoryEdit = useInlineEdit({
    value: section.title,
    onCommit: (title) => onMoveItemToCategory(item.id, title)
  });

  function updateItem(updater) {
    save(items.map((entry) => entry.id === item.id ? updater(entry) : entry));
  }

  function toggleChecked() {
    updateItem((entry) => ({
      ...entry,
      qtyCurrent: done ? 0 : entry.qtyTarget
    }));
  }

  return (
    <li className={className} {...reorder.getItemProps({ itemId: item.id, groupId: section.id })}>
      <div className={`checklist-item-main ${editing ? "is-editing" : ""}`}>
        <button
          className="checklist-drag-handle"
          type="button"
          onPointerDown={(event) => reorder.itemReorder.startDrag(event, item.id)}
          aria-label={`${textContent.reorderTitle || "Déplacer"} ${item.label}`}
          title={textContent.reorderTitle || "Déplacer"}
        >
          <Icon name="drag" />
        </button>
        {item.qtyTarget === 1 ? (
          <input
            type="checkbox"
            checked={done}
            onChange={(event) => updateItem((entry) => ({ ...entry, qtyTarget: 1, qtyCurrent: event.target.checked ? 1 : 0 }))}
            aria-label={`Terminer ${item.label}`}
          />
        ) : (
          <div className="checklist-qty-controls" aria-label={`Quantité ${item.label}`}>
            <button type="button" onClick={() => updateItem((entry) => ({ ...entry, qtyCurrent: context.clampQty(entry.qtyCurrent - 1, entry.qtyTarget) }))} aria-label={context.moduleText?.checklist?.decrementLabel || "Retirer une quantité"}>-</button>
            <label className="checklist-qty-current">
              <input
                type="number"
                max={item.qtyTarget}
                value={context.clampQty(item.qtyCurrent, item.qtyTarget)}
                style={{ "--qty-current-digits": String(context.clampQty(item.qtyCurrent, item.qtyTarget)).length }}
                onChange={(event) => updateItem((entry) => ({ ...entry, qtyCurrent: context.clampQty(event.target.value, entry.qtyTarget) }))}
                aria-label={`${context.moduleText?.checklist?.currentQuantityLabel || "Quantité actuelle"} ${item.label}`}
              />
              <span>/ {item.qtyTarget}</span>
            </label>
            <button type="button" onClick={() => updateItem((entry) => ({ ...entry, qtyCurrent: context.clampQty(entry.qtyCurrent + 1, entry.qtyTarget) }))} aria-label={context.moduleText?.checklist?.incrementLabel || "Ajouter une quantité"}>+</button>
          </div>
        )}
        {editing ? (
          <>
            <input
              {...labelEdit.getInputProps({
                className: "checklist-label-input",
                "aria-label": textContent.itemEditLabel || "Libellé"
              })}
            />
            <input
              {...categoryEdit.getInputProps({
                className: "checklist-category-input",
                placeholder: textContent.sectionPlaceholder || "Catégorie",
                "aria-label": textContent.categoryEditLabel || "Catégorie"
              })}
            />
          </>
        ) : (
          <button className="checklist-item-summary" type="button" onClick={toggleChecked} title={item.label}>
            <span>{item.label}</span>
          </button>
        )}
      </div>
      <button type="button" className="checklist-edit-button" onClick={onToggleEditing} aria-label={`${textContent.editTitle || "Modifier"} ${item.label}`} title={textContent.editTitle || "Modifier"}>
        <Icon name="edit" />
      </button>
      <button className="checklist-delete-button danger" onClick={() => onDeleteItem(item.id)} aria-label={`${context.moduleText?.checklist?.deleteTitle || "Supprimer"} ${item.label}`} title={context.moduleText?.checklist?.deleteTitle || "Supprimer"}>
        <Icon name="trash" />
      </button>
    </li>
  );
}
