// Rôle : fournit l'outil annotation d'images avec marqueurs éditables et échange texte.
import { useCallback, useEffect, useRef, useState } from "react";
import { Icon } from "../../../components/Icon.jsx";
import { Tooltip } from "../../../components/Tooltip.jsx";
import { DrawingOverlay } from "./DrawingOverlay.jsx";
import { TextExchangeActions } from "./TextExchangeActions.jsx";

function markerLabel(index, marker, textContent) {
  return marker.label || `${textContent.markerPrefix || "Marqueur"} ${index + 1}`;
}

export function ImageAnnotationModule({ toolboxId, moduleId, context, editing }) {
  const data = context.normalizeImageAnnotationData(context.getModuleData(toolboxId, moduleId, { image: "", markers: [] }));
  const textContent = context.moduleText?.imageAnnotation || {};
  const previewMediaRef = useRef(null);
  const sessionKey = `sokkog:image-annotation-drawings:${toolboxId}:${moduleId}`;
  const [dragOver, setDragOver] = useState(false);
  const [drawingMode, setDrawingMode] = useState("permanent");
  const [temporaryDrawings, setTemporaryDrawings] = useState({ strokes: [] });
  const markers = data.markers;
  const drawings = drawingMode === "permanent" ? data.drawings || { strokes: [] } : temporaryDrawings;
  const pastePlaceholder = textContent.pastePlaceholder || "Coller une image ici";
  const getPreviewSurfaceSize = useCallback((element) => ({
    width: element?.clientWidth || 0,
    height: element?.clientHeight || 0
  }), []);

  useEffect(() => {
    try {
      const stored = JSON.parse(sessionStorage.getItem(sessionKey) || "{\"strokes\":[]}");
      setTemporaryDrawings(stored?.strokes ? stored : { strokes: [] });
    } catch {
      setTemporaryDrawings({ strokes: [] });
    }
  }, [sessionKey]);

  useEffect(() => {
    if (drawingMode !== "temporary") return;
    try {
      sessionStorage.setItem(sessionKey, JSON.stringify(temporaryDrawings));
    } catch {
      context.notify?.(textContent.sessionStorageError || "Les annotations temporaires n'ont pas pu être sauvegardées.");
    }
  }, [context, drawingMode, sessionKey, temporaryDrawings, textContent.sessionStorageError]);

  function save(nextData) {
    context.setModuleData(toolboxId, moduleId, nextData);
  }

  async function setImageFromFiles(files) {
    const file = [...files].find((item) => item?.type?.startsWith("image/"));
    if (!file) return;
    save({ image: await context.compressImageFile(file), markers: [], drawings: { strokes: [] } });
    setTemporaryDrawings({ strokes: [] });
    setDragOver(false);
  }

  function removeImage() {
    save({ image: "", markers: [], drawings: { strokes: [] } });
    setTemporaryDrawings({ strokes: [] });
  }

  return (
    <div className="image-annotation-module">
      {editing && (
        <div className="module-add-panel">
          <label
            className={`dropzone annotation-dropzone ${dragOver ? "is-drag-over" : ""}`}
            onDragOver={(event) => {
              event.preventDefault();
              event.dataTransfer.dropEffect = "copy";
              setDragOver(true);
            }}
            onDragLeave={() => setDragOver(false)}
            onDrop={(event) => {
              event.preventDefault();
              setImageFromFiles(event.dataTransfer.files);
            }}
          >
            <input type="file" accept="image/*" hidden onChange={(event) => setImageFromFiles(event.target.files)} />
            {data.image ? textContent.replaceImage || "Remplacer l'image" : textContent.addImage || "Ajouter une image"}
          </label>
          <div
            className="paste-target"
            contentEditable
            suppressContentEditableWarning
            role="textbox"
            aria-label={textContent.pasteAriaLabel || "Coller une image à annoter depuis le presse-papiers"}
            onFocus={(event) => {
              if (event.currentTarget.textContent.trim() === pastePlaceholder) event.currentTarget.textContent = "";
            }}
            onBlur={(event) => {
              if (!event.currentTarget.textContent.trim()) event.currentTarget.textContent = pastePlaceholder;
            }}
            onPaste={(event) => {
              const files = [...(event.clipboardData?.items || [])]
                .filter((item) => item.type.startsWith("image/"))
                .map((item) => item.getAsFile())
                .filter(Boolean);
              if (!files.length) return;
              event.preventDefault();
              event.currentTarget.textContent = pastePlaceholder;
              setImageFromFiles(files);
            }}
          >
            {pastePlaceholder}
          </div>
          <TextExchangeActions type="imageAnnotation" data={data} context={context} textContent={textContent} onImport={(nextData) => {
            save(nextData);
            setTemporaryDrawings({ strokes: [] });
          }} />
        </div>
      )}

      {data.image ? (
        <div className="annotation-workspace">
          <div className="annotation-stage annotation-stage-preview" aria-label={textContent.stageAriaLabel || "Image annotée"}>
            <div className="annotation-media" ref={previewMediaRef}>
              <img src={data.image} alt={textContent.imageAlt || "Image annotée"} draggable="false" />
              <div className="annotation-preview-actions">
                <button
                  className="tool-split-action-button"
                  type="button"
                  onClick={() => context.setImage({
                    dataUrl: data.image,
                    markers,
                    drawings,
                    alt: textContent.imageAlt || "Image annotée",
                    canAnnotate: true,
                    createMarkerId: () => context.uid("marker"),
                    createStrokeId: () => context.uid("stroke"),
                    drawingMode,
                    markerPrefix: textContent.markerPrefix || "Marqueur",
                    addMarkerAriaLabel: textContent.addMarkerAriaLabel || "Ajouter un marqueur sur l'image",
                    markerPlaceholder: textContent.markerPlaceholder || "Libellé du marqueur",
                    deleteMarkerTitle: textContent.deleteMarkerTitle || "Supprimer",
                    drawingLabel: textContent.drawingLabel || "Dessin",
                    drawTitle: textContent.drawTitle || "Dessiner",
                    eraseTitle: textContent.eraseTitle || "Gommer",
                    undoDrawingTitle: textContent.undoDrawingTitle || "Annuler le dernier trait",
                    clearDrawingTitle: textContent.clearDrawingTitle || "Effacer les dessins",
                    drawingColorLabel: textContent.drawingColorLabel || "Couleur du dessin",
                    drawingWidthLabel: textContent.drawingWidthLabel || "Épaisseur du trait",
                    temporaryTitle: textContent.temporaryTitle || "Annotations temporaires",
                    permanentTitle: textContent.permanentTitle || "Annotations permanentes",
                    onChangeMarkers: (nextMarkers) => save({ ...data, markers: nextMarkers }),
                    onChangeDrawings: (nextDrawings, nextMode = drawingMode) => {
                      if (nextMode === "permanent") save({ ...data, drawings: nextDrawings });
                      else setTemporaryDrawings(nextDrawings);
                    },
                    onChangeDrawingMode: (nextMode, currentDrawings) => {
                      setDrawingMode(nextMode);
                      if (nextMode === "permanent") save({ ...data, drawings: currentDrawings });
                      else setTemporaryDrawings(currentDrawings);
                    }
                  })}
                  aria-label={textContent.previewAriaLabel || "Agrandir l'image annotée"}
                  title={textContent.previewTitle || "Agrandir"}
                >
                  <Icon name="zoom" />
                </button>
                {editing && (
                  <button className="tool-split-action-button danger" type="button" onClick={removeImage} aria-label={textContent.deleteImageTitle || "Supprimer l'image"} title={textContent.deleteImageTitle || "Supprimer l'image"}>
                    <Icon name="trash" />
                  </button>
                )}
              </div>
              {markers.map((marker, index) => (
                <Tooltip
                  as="span"
                  key={marker.id}
                  className="annotation-marker"
                  content={markerLabel(index, marker, textContent)}
                  position="top"
                  style={{ "--marker-x": `${marker.x}%`, "--marker-y": `${marker.y}%` }}
                >
                  {index + 1}
                </Tooltip>
              ))}
              <DrawingOverlay
                active={false}
                erase={false}
                strokes={drawings.strokes}
                color="#f6c453"
                width={4}
                onChange={() => {}}
                coordinateMode="percent"
                getSurfaceSize={() => getPreviewSurfaceSize(previewMediaRef.current)}
              />
            </div>
          </div>
        </div>
      ) : (
        <p className="annotation-empty muted">{textContent.emptyImage || "Ajoutez une image pour commencer l'annotation."}</p>
      )}
    </div>
  );
}
