// Rôle : affiche les pages toolbox, le panneau latéral et leurs contrôles.
import React, { useEffect, useRef, useState } from "react";
import { Icon } from "../../components/Icon.jsx";
import { ImportButton } from "../../components/ImportButton.jsx";
import { StorageQuota } from "../../components/StorageQuota.jsx";
import { ToastPositionSwitch } from "../../components/ToastPositionSwitch.jsx";
import { usePointerReorder } from "../../hooks/usePointerReorder.js";
import { compressImage } from "../../utils/imageCompression.js";
import { getSetting as dbGetSetting, setSetting as dbSetSetting } from "../../utils/indexedDbStorage.js";
import { getGameCardCover, ToolboxCard, ToolboxGameIcon, ToolboxIconPicker } from "./ToolboxCard.jsx";
import { AddToolControls, ToolboxModules } from "./modules/index.jsx";
import {
  clampQty,
  hostnameFromUrl,
  normalizeCalculatorData,
  normalizeChecklistData,
  normalizeCountersData,
  normalizeImageAnnotationData,
  normalizeLinksData,
  normalizeTaskPlannerData,
  normalizeTimerData,
  normalizeUrl,
  uid
} from "./storage/toolboxStorage.js";

const DRAWER_WIDTH_SETTING = "drawerWidth";

async function copyText(value) {
  try {
    await navigator.clipboard.writeText(value);
    return true;
  } catch {
    return false;
  }
}

export function ToolboxesPage({ siteContent, toolboxes, getToolboxGame, actions, storageUsage, toastPosition, setToastPosition }) {
  const content = siteContent.toolboxes;
  const {
    draggingId: draggingToolboxId,
    dropTarget,
    startDrag: startToolboxDrag
  } = usePointerReorder({
    targetSelector: ".toolbox-card",
    getTargetId: (target) => target.dataset.toolboxId,
    getPlacement: (event, target) => {
      const rect = target.getBoundingClientRect();
      return event.clientY > rect.top + rect.height / 2 || event.clientX > rect.left + rect.width / 2 ? "after" : "before";
    },
    onMove: (draggingId, targetId, placement) => {
      const nextIds = toolboxes.map((toolbox) => toolbox.id).filter((id) => id !== draggingId);
      const targetIndex = nextIds.indexOf(targetId);
      nextIds.splice(placement === "after" ? targetIndex + 1 : targetIndex, 0, draggingId);
      actions.updateToolboxOrder(nextIds);
    }
  });

  return (
    <div className="toolbox-page">
      <section className="page-hero">
        <div>
          <p className="eyebrow">{content.eyebrow}</p>
          <h1>{content.title}</h1>
          <p>{content.summary}</p>
        </div>
      </section>
      <section className="toolbar toolbox-actions-row">
        <div>
          <button className="primary" onClick={() => actions.setCreateModal({})}>{content.newButton}</button>
          <ImportButton className="import-button" label={content.importOne} onFile={actions.importToolbox} />
        </div>
        <div>
          <button className="primary" onClick={actions.exportAllToolboxes}>{content.exportAll}</button>
          <ImportButton className="import-button" label={content.importAll} onFile={actions.importAllToolboxes} />
        </div>
      </section>
      <section className="toolbox-preferences-row" aria-label={content.preferencesLabel}>
        <div>
          <p className="eyebrow">{content.preferencesLabel}</p>
          <strong>{content.toastPositionLabel}</strong>
        </div>
        <ToastPositionSwitch
          position={toastPosition}
          onChange={setToastPosition}
          labels={{
            title: content.toastPositionLabel,
            left: content.toastPositionLeft,
            right: content.toastPositionRight
          }}
        />
      </section>
      <section className="cards">
        <StorageHelpCard help={content.storageHelp} />
        {toolboxes.length ? toolboxes.map((toolbox) => (
          <ToolboxCard
            key={toolbox.id}
            toolbox={toolbox}
            game={getToolboxGame(toolbox)}
            actions={actions}
            draggingToolboxId={draggingToolboxId}
            dropTarget={dropTarget}
            onDragStart={startToolboxDrag}
          />
        )) : (
          <div className="empty"><h2>{content.emptyTitle}</h2><p>{content.emptyText}</p></div>
        )}
      </section>
      <StorageQuota usage={storageUsage} />
    </div>
  );
}

function StorageHelpCard({ help }) {
  return (
    <article className="card storage-help-card" aria-labelledby="storage-help-title">
      <div className="card-body">
        <div className="storage-help-heading">
          <span className="storage-help-mark" aria-hidden="true" />
          <div><p className="eyebrow">IndexedDB</p><h2 id="storage-help-title">{help.title}</h2></div>
        </div>
        <p className="storage-help-intro">{help.text}</p>
        <ul className="storage-help-list">
          {help.items.map((item, index) => <li key={item}><span>{index + 1}</span><p>{item}</p></li>)}
        </ul>
      </div>
    </article>
  );
}

export function ToolboxPage(props) {
  const { toolboxId, toolboxes, getToolboxGame } = props;
  const toolbox = toolboxes.find((item) => item.id === toolboxId);
  if (!toolbox) return <div className="empty"><h1>Toolbox introuvable</h1><a className="button" href="#/toolboxes">Retour</a></div>;
  return <ToolboxView {...props} toolbox={toolbox} toolboxGame={getToolboxGame(toolbox)} embedded={false} />;
}

function ToolboxView({ siteContent, toolbox, toolboxGame, embedded, actions, storageUsage, getModuleData, updateToolbox, updateModuleData, addImageFiles }) {
  const moduleColumns = Number(toolbox.moduleColumns) === 1 ? 1 : 2;
  const toolboxGameCover = getGameCardCover(toolboxGame);
  const moduleText = siteContent.toolboxes.modules;
  const moduleContext = {
    getModuleData,
    moduleText,
    normalizeChecklistData,
    normalizeLinksData,
    normalizeCountersData,
    normalizeCalculatorData,
    normalizeImageAnnotationData,
    normalizeTimerData,
    normalizeTaskPlannerData,
    normalizeUrl,
    hostnameFromUrl,
    copyText,
    notify: actions.notify,
    compressImageFile: compressImage,
    clampQty,
    uid,
    setModuleData: updateModuleData,
    addImageFiles,
    createImageAnnotationModule,
    setImage: actions.setImage,
    refresh: () => {}
  };

  function addModule(type) {
    if (!type) return;
    updateToolbox({ ...toolbox, modules: [...toolbox.modules, { id: uid("mod"), type }] });
  }

  function createImageAnnotationModule(dataUrl) {
    if (!dataUrl) return;
    const moduleId = uid("mod");
    updateToolbox({ ...toolbox, modules: [...toolbox.modules, { id: moduleId, type: "imageAnnotation" }] });
    updateModuleData(toolbox.id, moduleId, { image: dataUrl, markers: [] }, "imageAnnotation");
  }

  function moveModule(fromModuleId, toModuleId, placement = "before") {
    if (!fromModuleId || !toModuleId || fromModuleId === toModuleId) return;
    const modules = [...toolbox.modules];
    const fromIndex = modules.findIndex((module) => module.id === fromModuleId);
    const toIndex = modules.findIndex((module) => module.id === toModuleId);
    if (fromIndex < 0 || toIndex < 0) return;
    const [moved] = modules.splice(fromIndex, 1);
    const targetIndex = modules.findIndex((module) => module.id === toModuleId);
    modules.splice(placement === "after" ? targetIndex + 1 : targetIndex, 0, moved);
    updateToolbox({ ...toolbox, modules });
  }

  return (
    <div className={embedded ? "toolbox-embedded" : "toolbox-page"}>
      <section className={embedded ? "toolbox-head page-hero toolbox-head-embedded" : "toolbox-head page-hero"}>
        <div>
          <p className="eyebrow">Toolbox</p>
          <div className="toolbox-title-row">
            {!embedded && !toolboxGame && <ToolboxIconPicker toolbox={toolbox} onChange={(icon) => updateToolbox({ ...toolbox, icon })} />}
            {!embedded && toolboxGameCover && <ToolboxGameIcon game={toolboxGame} />}
            {embedded ? <h1>{toolbox.name}</h1> : (
              <EditableTitle className="toolbox-title" value={toolbox.name} fallback="Nouvelle toolbox" onSave={(name) => name !== toolbox.name && updateToolbox({ ...toolbox, name })} />
            )}
          </div>
          {toolboxGame && (
            <a
              className="button toolbox-hero-link"
              href={embedded ? `#/toolbox/${toolbox.id}` : `#/games/${toolboxGame.id}`}
              onClick={embedded ? () => actions.setDrawerGameId("") : undefined}
            >
              <Icon name="enter" />
              <span>{embedded ? "Vers la toolbox complète" : "Vers la page de jeu"}</span>
            </a>
          )}
        </div>
        <div className="actions">
          <AddToolControls onAdd={addModule} />
        </div>
      </section>
      {!embedded && (
        <section className="modules-toolbar" aria-label="Options d'affichage des outils">
          <div className="layout-switch" role="group" aria-label="Mode d'affichage des outils">
            <button className={moduleColumns === 1 ? "active" : ""} onClick={() => updateToolbox({ ...toolbox, moduleColumns: 1 })} aria-pressed={moduleColumns === 1} aria-label="Afficher en lignes" title="Afficher en lignes"><Icon name="rows" /></button>
            <button className={moduleColumns === 2 ? "active" : ""} onClick={() => updateToolbox({ ...toolbox, moduleColumns: 2 })} aria-pressed={moduleColumns === 2} aria-label="Afficher en colonnes" title="Afficher en colonnes"><Icon name="columns" /></button>
          </div>
        </section>
      )}
      <ToolboxModules
        toolbox={toolbox}
        moduleColumns={moduleColumns}
        context={moduleContext}
        onRename={(moduleId, title) => updateToolbox({ ...toolbox, modules: toolbox.modules.map((module) => module.id === moduleId ? { ...module, title } : module) })}
        onUpdateModule={(moduleId, updater) => updateToolbox({ ...toolbox, modules: toolbox.modules.map((module) => module.id === moduleId ? updater(module) : module) })}
        onDelete={(moduleId) => actions.setConfirmModal({
          title: "Retirer l'outil",
          message: "Retirer cet outil de la toolbox ?",
          confirmLabel: "Retirer",
          danger: true,
          onResolve: (confirmed) => {
            if (!confirmed) return;
            actions.removeModuleData(toolbox.id, moduleId);
            updateToolbox({ ...toolbox, modules: toolbox.modules.filter((module) => module.id !== moduleId) });
          }
        })}
        onMove={moveModule}
      />
      {!embedded && <StorageQuota usage={storageUsage} />}
    </div>
  );
}

export function ToolboxDrawer({ gameId, game, siteContent, toolboxes, links, actions, storageUsage, getModuleData, updateToolbox, updateModuleData, addImageFiles }) {
  const selectedId = links[gameId] || "";
  const toolbox = toolboxes.find((item) => item.id === selectedId);
  const [width, setWidth] = useState("");
  const panelRef = useRef(null);

  useEffect(() => {
    let cancelled = false;
    dbGetSetting(DRAWER_WIDTH_SETTING, "")
      .then((storedWidth) => {
        if (cancelled) return;
        const value = Number(storedWidth);
        if (Number.isFinite(value) && value > 0) setWidth(Math.min(Math.max(value, 360), Math.floor(window.innerWidth * 0.94)));
      })
      .catch(() => {});
    return () => { cancelled = true; };
  }, []);

  function startResize(event) {
    const panel = panelRef.current;
    if (!panel) return;
    event.preventDefault();
    const startX = event.clientX;
    const startWidth = panel.getBoundingClientRect().width;
    const minWidth = 360;
    const maxWidth = Math.floor(window.innerWidth * 0.94);
    document.body.classList.add("is-resizing-drawer");
    const onMove = (moveEvent) => {
      const nextWidth = Math.min(Math.max(startWidth + startX - moveEvent.clientX, minWidth), maxWidth);
      setWidth(nextWidth);
      dbSetSetting(DRAWER_WIDTH_SETTING, Math.round(nextWidth)).catch(() => {});
    };
    const stop = () => {
      document.body.classList.remove("is-resizing-drawer");
      window.removeEventListener("pointermove", onMove);
      window.removeEventListener("pointerup", stop);
      window.removeEventListener("pointercancel", stop);
    };
    window.addEventListener("pointermove", onMove);
    window.addEventListener("pointerup", stop);
    window.addEventListener("pointercancel", stop);
  }

  return (
    <aside className="drawer" id="toolbox-drawer" aria-hidden="false" style={width ? { "--drawer-panel-width": `${width}px` } : undefined}>
      <div className="drawer-backdrop" onClick={() => actions.setDrawerGameId("")} />
      <span className="drawer-resize-handle" aria-hidden="true" onPointerDown={startResize} />
      <section className="drawer-panel legacy-scrollbar" ref={panelRef} style={width ? { width } : undefined}>
        <div className="drawer-content">
          <header>
            <div>
              <p className="eyebrow">Toolbox liée</p>
              <div className="drawer-toolbox-actions" aria-label="Actions toolbox liée">
                <button className="drawer-action-button" onClick={() => actions.setLinkModalGameId(gameId)} aria-label="Lier une toolbox" title="Lier"><Icon name="link" /></button>
                <ImportButton className="drawer-action-button import-icon-button" ariaLabel="Importer une toolbox" title="Importer" icon="import" onFile={(file) => actions.importToolbox(file, gameId)} />
                <button className="drawer-action-button" onClick={() => actions.exportToolbox(selectedId)} disabled={!selectedId} aria-label="Exporter la toolbox liée" title="Exporter"><Icon name="export" /></button>
              </div>
            </div>
            <button className="drawer-close-button" onClick={() => actions.setDrawerGameId("")} aria-label="Fermer" title="Fermer"><Icon name="close" /></button>
          </header>
          {toolbox ? <ToolboxView siteContent={siteContent} toolbox={toolbox} toolboxGame={game} embedded actions={actions} storageUsage={storageUsage} getModuleData={getModuleData} updateToolbox={updateToolbox} updateModuleData={updateModuleData} addImageFiles={addImageFiles} /> : (
            <div className="empty"><p>Aucune toolbox associée à cette page jeu.</p><button className="primary" onClick={() => actions.setCreateModal({ gameId })}>Créer et associer</button></div>
          )}
          <StorageQuota usage={storageUsage} />
        </div>
      </section>
    </aside>
  );
}

function EditableTitle({ value, fallback, onSave, className = "module-title" }) {
  const ref = useRef(null);
  useEffect(() => {
    if (ref.current && document.activeElement !== ref.current) ref.current.textContent = value;
  }, [value]);
  return (
    <h1
      ref={ref}
      className={className}
      contentEditable
      suppressContentEditableWarning
      spellCheck="false"
      title="Cliquer pour renommer"
      onFocus={(event) => { event.currentTarget.dataset.previousTitle = event.currentTarget.textContent.trim(); }}
      onBlur={(event) => onSave(event.currentTarget.textContent.trim() || fallback)}
      onKeyDown={(event) => {
        if (event.key === "Enter") {
          event.preventDefault();
          event.currentTarget.blur();
        }
        if (event.key === "Escape") {
          event.preventDefault();
          event.currentTarget.textContent = event.currentTarget.dataset.previousTitle || value;
          event.currentTarget.blur();
        }
      }}
    >{value}</h1>
  );
}
