// Rôle : fournit l'outil timer avec chronomètre, comptes à rebours et échange texte.
import { useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
import { Icon } from "../../../components/Icon.jsx";
import { Tabs } from "../../../components/Tabs.jsx";
import { useDraftForm } from "../../../hooks/useDraftForm.js";
import { useInlineEdit } from "../../../hooks/useInlineEdit.js";
import { moveItem, useGroupedReorder } from "../../../hooks/useGroupedReorder.js";
import {
  formatDuration,
  formatDurationWithCentiseconds,
  formatTargetTime,
  getCentiseconds,
  getCountdownTargetMs,
  getDailyTargetMs,
  getIntervalAnchorMs,
  getNowMs,
  getTimePatternTargetMs,
  getTimePatternRecurrenceMs,
  timePartsToDurationMs,
  timePartsToString
} from "./timerUtils.js";
import { TextExchangeActions } from "./TextExchangeActions.jsx";

const TIMER_TABS = [
  { id: "stopwatch", label: "Chronomètre", icon: "stopwatch" },
  { id: "countdown", label: "Compte à rebours", icon: "hourglass" }
];

const COUNTDOWN_TYPES = ["duration", "daily_time", "time_pattern", "interval"];
const EMPTY_TIME_PARTS = { hours: "", minutes: "", seconds: "" };
const DEFAULT_COUNTDOWN_FORM = {
  label: "",
  type: "duration",
  duration: EMPTY_TIME_PARTS,
  time: EMPTY_TIME_PARTS,
  pattern: EMPTY_TIME_PARTS,
  interval: EMPTY_TIME_PARTS,
  intervalStartTime: EMPTY_TIME_PARTS
};
const ALERT_MODES = [
  { mode: "off", icon: "sound-mute" },
  { mode: "visible", icon: "sound-min" },
  { mode: "site", icon: "sound-max" }
];
const ALERT_MIN_DELAY_MS = 5 * 60 * 1000;
const AUTO_REFRESH_COUNTDOWN_TYPES = new Set(["time_pattern", "interval"]);
const TOGGLE_REFRESH_COUNTDOWN_TYPES = new Set(["daily_time", "interval"]);

function isAlertGuarded(countdown) {
  if (countdown?.type === "interval") return Number(countdown.intervalMs) < ALERT_MIN_DELAY_MS;
  if (countdown?.type === "time_pattern") return getTimePatternRecurrenceMs(countdown.pattern) < ALERT_MIN_DELAY_MS;
  return false;
}

function getAlertGuardMessage(textContent) {
  return textContent.alertTooSoonTitle || "Alerte indisponible pour une répétition inférieure à 5 minutes";
}

function canToggleAutoRefresh(countdown) {
  return TOGGLE_REFRESH_COUNTDOWN_TYPES.has(countdown?.type) && !isAlertGuarded(countdown);
}

function TimerValue({ ms, compact = false, showCentiseconds = true }) {
  if (!showCentiseconds) return <span className="timer-value">{formatDuration(ms)}</span>;
  if (!compact) return <span className="timer-value">{formatDurationWithCentiseconds(ms)}</span>;

  return (
    <span className="timer-value is-compact">
      <span>{formatDuration(ms)}</span>
      <small>{getCentiseconds(ms)}</small>
    </span>
  );
}

function getCountdownMetaParts(countdown, textContent) {
  if (countdown.type === "duration") return [`${textContent.durationType || "Durée"} ${formatDuration(countdown.durationMs || 0)}`];
  if (countdown.type === "daily_time") return [`${textContent.dailyTimeType || "Heure précise"} ${countdown.time}`];
  if (countdown.type === "time_pattern") return [`${textContent.timePatternType || "Heure / minute / seconde"} ${countdown.pattern}`];
  if (countdown.type === "interval") {
    const startLabel = countdown.startMode === "time" && countdown.startTime
      ? `${textContent.intervalStartTimeLabel || "Départ"} ${countdown.startTime}`
      : `${textContent.intervalStartTimeLabel || "Départ"} ${formatTargetTime(countdown.anchorAt)}`;
    return [`${textContent.intervalType || "Intervalle"} ${formatDuration(countdown.intervalMs || 0)}`, startLabel];
  }
  return [];
}

function handleEditableKeyDown(event, callback) {
  if (event.key !== "Enter" && event.key !== " ") return;
  event.preventDefault();
  callback();
}

function hasTimePartValue(parts) {
  return Boolean(String(parts?.hours || "").trim() || String(parts?.minutes || "").trim() || String(parts?.seconds || "").trim());
}

function getCountdownValidationError(type, draft, textContent) {
  const requiredError = textContent.requiredError || "Valeur requise.";
  const invalidError = textContent.invalidError || "Valeur invalide.";
  if (type === "duration" && timePartsToDurationMs(draft.duration) <= 0) {
    return requiredError;
  }
  if (type === "daily_time" && !timePartsToString(draft.time)) {
    return invalidError;
  }
  if (type === "time_pattern") {
    if (!hasTimePartValue(draft.pattern)) return requiredError;
    if (!timePartsToString(draft.pattern, { allowWildcard: true })) return invalidError;
  }
  if (type === "interval") {
    const startTimeHasValue = hasTimePartValue(draft.intervalStartTime);
    if (timePartsToDurationMs(draft.interval) <= 0) return requiredError;
    if (startTimeHasValue && !timePartsToString(draft.intervalStartTime)) return invalidError;
  }
  return "";
}

export function TimerModule({ toolboxId, moduleId, context, editing }) {
  const data = context.normalizeTimerData(context.getModuleData(toolboxId, moduleId, { activeTab: "stopwatch" }));
  const textContent = context.moduleText?.timer || {};
  const activeTab = data.activeTab;
  const [nowMs, setNowMs] = useState(getNowMs);
  const countdownDraft = useDraftForm(DEFAULT_COUNTDOWN_FORM);

  useEffect(() => {
    const intervalId = window.setInterval(() => setNowMs(getNowMs()), 50);
    return () => window.clearInterval(intervalId);
  }, []);

  const stopwatchElapsedMs = data.stopwatch.startedAt
    ? data.stopwatch.elapsedMs + Math.max(0, nowMs - data.stopwatch.startedAt)
    : data.stopwatch.elapsedMs;
  const visibleCountdowns = useMemo(() => {
    const countdowns = data.countdowns.map((countdown) => ({ ...countdown, targetMs: getCountdownTargetMs(countdown, nowMs) }));
    if (!data.sortResults) return countdowns;
    return [...countdowns].sort((a, b) => (a.targetMs || Number.POSITIVE_INFINITY) - (b.targetMs || Number.POSITIVE_INFINITY));
  }, [data.countdowns, data.sortResults, nowMs]);
  const countdownReorder = useGroupedReorder({
    namespace: "timer-countdowns",
    items: data.countdowns,
    getItemId: (countdown) => countdown.id,
    getParentId: () => moduleId,
    canMoveItem: () => !data.sortResults,
    onItemMove: (operation) => {
      if (data.sortResults) return;
      save({ ...data, countdowns: moveItem(data.countdowns, operation.sourceId, operation.targetId, operation.placement) });
    },
    hierarchy: { enabled: true, stickyParents: true }
  });

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

  function setActiveTab(nextActiveTab) {
    save({ ...data, activeTab: nextActiveTab });
  }

  function setScrollResults(scrollResults) {
    save({ ...data, scrollResults });
  }

  function setSortResults(sortResults) {
    save({ ...data, sortResults });
  }

  function updateStopwatch(stopwatch) {
    save({ ...data, stopwatch });
  }

  function startStopwatch() {
    if (data.stopwatch.startedAt) return;
    updateStopwatch({ ...data.stopwatch, startedAt: getNowMs() });
  }

  function pauseStopwatch() {
    if (!data.stopwatch.startedAt) return;
    updateStopwatch({
      ...data.stopwatch,
      startedAt: 0,
      elapsedMs: stopwatchElapsedMs
    });
  }

  function resetStopwatch() {
    updateStopwatch({ ...data.stopwatch, elapsedMs: 0, startedAt: 0 });
  }

  function addLap() {
    if (!stopwatchElapsedMs) return;
    updateStopwatch({
      ...data.stopwatch,
      laps: [
        {
          id: context.uid("timer"),
          label: "",
          elapsedMs: stopwatchElapsedMs
        },
        ...data.stopwatch.laps
      ]
    });
  }

  function deleteLap(lapId) {
    updateStopwatch({ ...data.stopwatch, laps: data.stopwatch.laps.filter((lap) => lap.id !== lapId) });
  }

  function renameLap(lapId, label) {
    updateStopwatch({
      ...data.stopwatch,
      laps: data.stopwatch.laps.map((lap) => lap.id === lapId ? { ...lap, label: label.trim() } : lap)
    });
  }

  function createCountdown(event) {
    countdownDraft.handleSubmit(event, (draft, { updateValues }) => {
      const type = COUNTDOWN_TYPES.includes(draft.type) ? draft.type : "duration";
      const validationError = getCountdownValidationError(type, draft, textContent);
      if (validationError) return validationError;
      const label = draft.label.trim() || textContent.defaultCountdownLabel || "Timer";
      const now = getNowMs();
      let countdown = null;

      if (type === "duration") {
        const durationMs = timePartsToDurationMs(draft.duration);
        if (durationMs > 0) countdown = { id: context.uid("timer"), label, type, durationMs, targetAt: now + durationMs };
      }
      if (type === "daily_time") {
        const time = timePartsToString(draft.time);
        const targetAt = getDailyTargetMs(time, now);
        if (time && targetAt) countdown = { id: context.uid("timer"), label, type, time, targetAt };
      }
      if (type === "time_pattern") {
        const pattern = hasTimePartValue(draft.pattern) ? timePartsToString(draft.pattern, { allowWildcard: true }) : "";
        if (pattern && getTimePatternTargetMs(pattern, now)) countdown = { id: context.uid("timer"), label, type, pattern };
      }
      if (type === "interval") {
        const intervalMs = timePartsToDurationMs(draft.interval);
        const startTime = hasTimePartValue(draft.intervalStartTime) ? timePartsToString(draft.intervalStartTime) : "";
        const startMode = startTime ? "time" : "now";
        const anchorAt = getIntervalAnchorMs(startMode, startTime, now);
        const targetAt = getCountdownTargetMs({ type, intervalMs, anchorAt, autoRefresh: true }, now);
        if (intervalMs > 0) {
          countdown = {
            id: context.uid("timer"),
            label,
            type,
            intervalMs,
            anchorAt,
            targetAt,
            startMode,
            ...(startTime ? { startTime } : {}),
            autoRefresh: intervalMs >= ALERT_MIN_DELAY_MS
          };
        }
      }

      if (!countdown) return;
      save({ ...data, countdowns: [...data.countdowns, countdown] });
      updateValues({ label: "" });
    });
  }

  function deleteCountdown(countdownId) {
    save({ ...data, countdowns: data.countdowns.filter((countdown) => countdown.id !== countdownId) });
  }

  function resetCountdown(countdown) {
    if (countdown.type !== "duration" && countdown.type !== "daily_time" && countdown.type !== "interval") return;
    const now = getNowMs();
    let nextCountdown = null;
    if (countdown.type === "duration") nextCountdown = { ...countdown, targetAt: now + countdown.durationMs };
    if (countdown.type === "daily_time") nextCountdown = { ...countdown, targetAt: getDailyTargetMs(countdown.time, now) };
    if (countdown.type === "interval") {
      const anchorAt = getIntervalAnchorMs(countdown.startMode, countdown.startTime, now);
      const targetAt = getCountdownTargetMs({ ...countdown, anchorAt, autoRefresh: true }, now);
      nextCountdown = { ...countdown, anchorAt, targetAt };
    }
    if (!nextCountdown) return;
    save({ ...data, countdowns: data.countdowns.map((item) => item.id === countdown.id ? nextCountdown : item) });
  }

  function toggleCountdownAutoRefresh(countdownId) {
    const countdown = data.countdowns.find((item) => item.id === countdownId);
    if (!TOGGLE_REFRESH_COUNTDOWN_TYPES.has(countdown?.type)) return;
    if (!countdown.autoRefresh && !canToggleAutoRefresh(countdown)) {
      context.notify?.(getAlertGuardMessage(textContent));
      return;
    }
    const now = getNowMs();
    save({
      ...data,
      countdowns: data.countdowns.map((item) => {
        if (item.id !== countdownId) return item;
        const autoRefresh = !item.autoRefresh;
        if (item.type === "daily_time") return { ...item, autoRefresh, targetAt: getDailyTargetMs(item.time, now) };
        if (item.type === "interval") {
          const anchorAt = getIntervalAnchorMs(item.startMode, item.startTime, now);
          const targetAt = getCountdownTargetMs({ ...item, anchorAt, autoRefresh: true }, now);
          return { ...item, autoRefresh, anchorAt, targetAt };
        }
        return item;
      })
    });
  }

  function renameCountdown(countdownId, label) {
    save({
      ...data,
      countdowns: data.countdowns.map((countdown) => countdown.id === countdownId ? { ...countdown, label: label.trim() } : countdown)
    });
  }

  function setCountdownAlertMode(countdownId, alertMode) {
    const countdown = data.countdowns.find((item) => item.id === countdownId);
    if (alertMode !== "off" && AUTO_REFRESH_COUNTDOWN_TYPES.has(countdown?.type) && isAlertGuarded(countdown)) {
      context.notify?.(getAlertGuardMessage(textContent));
      return;
    }
    save({
      ...data,
      countdowns: data.countdowns.map((countdown) => countdown.id === countdownId ? { ...countdown, alertMode } : countdown)
    });
  }

  function resetActiveResults() {
    if (activeTab === "stopwatch") {
      resetStopwatch();
      return;
    }
    save({ ...data, countdowns: [] });
  }

  return (
    <div className="timer-module">
      {editing && (
        <div className="module-add-panel timer-exchange-panel">
          <TextExchangeActions type="timer" data={data} context={context} textContent={textContent} onImport={(nextData) => save(nextData)} />
        </div>
      )}
      <section className="timer-control-card">
        <Tabs
          className="timer-tabs"
          tabs={[
            { ...TIMER_TABS[0], label: textContent.stopwatchTab || TIMER_TABS[0].label },
            { ...TIMER_TABS[1], label: textContent.countdownTab || TIMER_TABS[1].label }
          ]}
          activeTab={activeTab}
          onChange={setActiveTab}
          iconOnly
        />
        {activeTab === "stopwatch" ? (
          <StopwatchControls
            textContent={textContent}
            elapsedMs={stopwatchElapsedMs}
            running={Boolean(data.stopwatch.startedAt)}
            onStart={startStopwatch}
            onPause={pauseStopwatch}
            onReset={resetStopwatch}
            onLap={addLap}
          />
        ) : (
          <CountdownControls
            textContent={textContent}
            form={countdownDraft.values}
            error={countdownDraft.error}
            onChange={countdownDraft.updateValues}
            onSubmit={createCountdown}
          />
        )}
      </section>
      <section className={`tool-split-results timer-results-card ${data.scrollResults ? "is-scrollable" : ""}`}>
        <div className="tool-split-actions">
          <button className="tool-split-action-button danger" type="button" onClick={resetActiveResults} aria-label={textContent.resetTitle || "Réinitialiser"} title={textContent.resetTitle || "Réinitialiser"}>
            <Icon name="rubber" />
          </button>
          {activeTab === "countdown" && (
            <button
              className={`tool-split-scroll-toggle timer-sort-toggle ${data.sortResults ? "active" : ""}`}
              type="button"
              onClick={() => setSortResults(!data.sortResults)}
              aria-pressed={data.sortResults}
              title={textContent.sortTitle || "Trier par temps restant"}
              aria-label={textContent.sortTitle || "Trier par temps restant"}
            >
              <Icon name="sort-time" />
              <i aria-hidden="true" />
            </button>
          )}
          <button
            className={`tool-split-scroll-toggle timer-scroll-toggle ${data.scrollResults ? "active" : ""}`}
            type="button"
            onClick={() => setScrollResults(!data.scrollResults)}
            aria-pressed={data.scrollResults}
            title={textContent.scrollableTitle || "Liste scrollable"}
            aria-label={textContent.scrollableTitle || "Liste scrollable"}
          >
            <Icon name="scrollable" />
            <i aria-hidden="true" />
          </button>
        </div>
        <div className={`tool-split-tree timer-tree ${data.scrollResults ? "is-scrollable legacy-scrollbar" : ""}`}>
          {activeTab === "stopwatch" ? (
            <StopwatchLapList laps={data.stopwatch.laps} textContent={textContent} onRename={renameLap} onDelete={deleteLap} />
          ) : (
            <CountdownList countdowns={visibleCountdowns} nowMs={nowMs} textContent={textContent} reorder={countdownReorder} reorderEnabled={!data.sortResults} parentId={moduleId} onRename={renameCountdown} onAlertModeChange={setCountdownAlertMode} onReset={resetCountdown} onAutoRefreshToggle={toggleCountdownAutoRefresh} onDelete={deleteCountdown} />
          )}
        </div>
      </section>
    </div>
  );
}

function TimerAlertModeSwitch({ mode, blocked, textContent, onChange }) {
  const labels = {
    off: textContent.alertOffTitle || "Pas d'alerte",
    visible: textContent.alertVisibleTitle || "Alerte quand la toolbox est affichée",
    site: textContent.alertSiteTitle || "Alerte sur tout le site"
  };
  const blockedTitle = getAlertGuardMessage(textContent);

  return (
    <div
      className={`timer-alert-mode-switch ${blocked ? "is-blocked" : ""}`}
      role="group"
      aria-label={textContent.alertModeTitle || "Mode d'alerte"}
      title={blocked ? blockedTitle : undefined}
      onClick={(event) => event.stopPropagation()}
      onKeyDown={(event) => event.stopPropagation()}
    >
      {ALERT_MODES.map((option) => {
        const label = labels[option.mode];
        const disabled = Boolean(blocked);
        return (
        <button
          key={option.mode}
          className={`timer-alert-mode-button ${!blocked && mode === option.mode ? "active" : ""}`}
          type="button"
          onClick={() => onChange(option.mode)}
          disabled={disabled}
          aria-pressed={mode === option.mode}
          aria-label={disabled ? blockedTitle : label}
          title={disabled ? blockedTitle : label}
        >
          <Icon name={option.icon} />
        </button>
        );
      })}
    </div>
  );
}

function StopwatchControls({ textContent, elapsedMs, running, onStart, onPause, onReset, onLap }) {
  return (
    <div className="timer-control-panel" role="tabpanel">
      <span>{textContent.stopwatchTitle || "Chronomètre à étapes"}</span>
      <strong><TimerValue ms={elapsedMs} compact /></strong>
      <div className="timer-actions">
        <button className="primary timer-action-button" type="button" onClick={running ? onPause : onStart} aria-label={running ? textContent.pauseButton || "Pause" : textContent.startButton || "Lancer"} title={running ? textContent.pauseButton || "Pause" : textContent.startButton || "Lancer"}>
          <Icon name={running ? "pause-circle" : "play-circle"} />
        </button>
        <button className="timer-action-button" type="button" onClick={onLap} disabled={!elapsedMs} aria-label={textContent.lapButton || "Étape"} title={textContent.lapButton || "Étape"}>
          <Icon name="record-circle" />
        </button>
        <button className="danger timer-action-button" type="button" onClick={onReset} aria-label={textContent.resetTitle || "Réinitialiser"} title={textContent.resetTitle || "Réinitialiser"}>
          <Icon name="stop-circle" />
        </button>
      </div>
    </div>
  );
}

function CountdownControls({ textContent, form, error, onChange, onSubmit }) {
  return (
    <form className="timer-control-panel timer-countdown-form" role="tabpanel" onSubmit={onSubmit} aria-describedby={error ? "timer-countdown-error" : undefined}>
      <label>
        <span>{textContent.countdownLabel || "Libellé"}</span>
        <input value={form.label} onChange={(event) => onChange({ label: event.target.value })} placeholder={textContent.countdownLabelPlaceholder || "Boss, event, craft..."} />
      </label>
      <label>
        <span>{textContent.countdownTypeLabel || "Type"}</span>
        <select value={form.type} onChange={(event) => onChange({ type: event.target.value })}>
          <option value="duration">{textContent.durationType || "Durée"}</option>
          <option value="daily_time">{textContent.dailyTimeType || "Heure précise"}</option>
          <option value="time_pattern">{textContent.timePatternType || "Pattern horaire"}</option>
          <option value="interval">{textContent.intervalType || "Intervalle"}</option>
        </select>
      </label>
      {form.type === "duration" && (
        <label>
          <span className="timer-field-spacer" aria-hidden="true" />
          <span className="sr-only">{textContent.durationLabel || "Durée"}</span>
          <TimePartsInput value={form.duration} onChange={(duration) => onChange({ duration })} />
        </label>
      )}
      {form.type === "daily_time" && (
        <label>
          <span className="timer-field-spacer" aria-hidden="true" />
          <span className="sr-only">{textContent.dailyTimeLabel || "Heure"}</span>
          <TimePartsInput value={form.time} onChange={(time) => onChange({ time })} />
        </label>
      )}
      {form.type === "time_pattern" && (
        <label>
          <span className="timer-field-spacer" aria-hidden="true" />
          <span className="sr-only">{textContent.timePatternLabel || "Heure / minute / seconde"}</span>
          <TimePartsInput value={form.pattern} onChange={(pattern) => onChange({ pattern })} allowWildcard />
        </label>
      )}
      {form.type === "interval" && (
        <div className="timer-interval-fields">
          <label>
            <span>{textContent.intervalLabel || "Toutes les"}</span>
            <TimePartsInput value={form.interval} onChange={(interval) => onChange({ interval })} />
          </label>
          <label>
            <span>{textContent.intervalStartTimeLabel || "Départ"}</span>
            <TimePartsInput value={form.intervalStartTime} onChange={(intervalStartTime) => onChange({ intervalStartTime })} />
          </label>
        </div>
      )}
      {error && (
        <p id="timer-countdown-error" className="timer-form-error" role="alert">
          <Icon name="close" />
          <span>{error}</span>
        </p>
      )}
      <button className="primary" type="submit">{textContent.addCountdownButton || "Ajouter"}</button>
    </form>
  );
}

function TimePartsInput({ value, onChange, allowWildcard = false }) {
  function updatePart(part, nextValue) {
    const cleanValue = allowWildcard && /^x+$/i.test(nextValue.trim()) ? "X" : nextValue.replace(/[^\d]/g, "").slice(0, 2);
    onChange({ ...value, [part]: cleanValue });
  }

  return (
    <div className="time-parts-input" role="group" aria-label="Format heure minute seconde">
      <input value={value.hours} onChange={(event) => updatePart("hours", event.target.value)} placeholder="hh" inputMode={allowWildcard ? "text" : "numeric"} />
      <span>:</span>
      <input value={value.minutes} onChange={(event) => updatePart("minutes", event.target.value)} placeholder="mm" inputMode={allowWildcard ? "text" : "numeric"} />
      <span>:</span>
      <input value={value.seconds} onChange={(event) => updatePart("seconds", event.target.value)} placeholder="ss" inputMode={allowWildcard ? "text" : "numeric"} />
    </div>
  );
}

function StopwatchLapList({ laps, textContent, onRename, onDelete }) {
  const [editingId, setEditingId] = useState("");
  if (!laps.length) return <p className="muted">{textContent.emptySteps || "Aucune étape enregistrée."}</p>;
  return (
    <ul className="tool-split-entry-list timer-list">
      {laps.map((lap, index) => (
        <li key={lap.id} className={`timer-list-item ${editingId === lap.id ? "is-editing" : ""}`}>
          <div className="tool-split-entry timer-entry has-single-action">
            {editingId === lap.id ? (
              <EditableTimerLabel
                value={lap.label}
                placeholder={`${textContent.stepLabel || "Étape"} ${laps.length - index}`}
                ariaLabel={textContent.lapLabelAriaLabel || "Libellé de l'étape"}
                onRename={(label) => onRename(lap.id, label)}
                onDone={() => setEditingId("")}
              >
                <TimerValue ms={lap.elapsedMs} />
              </EditableTimerLabel>
            ) : (
              <span
                className="tool-split-entry-summary timer-entry-summary"
                role="button"
                tabIndex={0}
                onClick={() => setEditingId(lap.id)}
                onKeyDown={(event) => handleEditableKeyDown(event, () => setEditingId(lap.id))}
              >
                <span className="timer-entry-line">
                  <TimerValue ms={lap.elapsedMs} />
                  <span>{lap.label || `${textContent.stepLabel || "Étape"} ${laps.length - index}`}</span>
                </span>
              </span>
            )}
            <button className="danger" type="button" onClick={() => onDelete(lap.id)} aria-label={textContent.deleteTitle || "Supprimer"} title={textContent.deleteTitle || "Supprimer"}>
              <Icon name="trash" />
            </button>
          </div>
        </li>
      ))}
    </ul>
  );
}

function CountdownList({ countdowns, nowMs, textContent, reorder, reorderEnabled, parentId, onRename, onAlertModeChange, onReset, onAutoRefreshToggle, onDelete }) {
  const [editingId, setEditingId] = useState("");
  if (!countdowns.length) return <p className="muted">{textContent.emptyCountdowns || "Aucun compte à rebours configuré."}</p>;
  return (
    <ul className="tool-split-entry-list timer-list">
      {countdowns.map((countdown) => {
        const remainingMs = countdown.targetMs - nowMs;
        const expired = remainingMs <= 0;
        const canReset = countdown.type === "duration";
        const canToggleRefresh = TOGGLE_REFRESH_COUNTDOWN_TYPES.has(countdown.type);
        const refreshBlocked = canToggleRefresh && !canToggleAutoRefresh(countdown);
        const refreshTitle = refreshBlocked
          ? getAlertGuardMessage(textContent)
          : textContent.autoRefreshTitle || "Répéter automatiquement";
        const className = [
          "timer-list-item",
          expired ? "is-expired" : "",
          editingId === countdown.id ? "is-editing" : "",
          reorderEnabled && reorder.isItemDragging(countdown.id) ? "is-dragging" : "",
          reorderEnabled && reorder.isItemDropTarget(countdown.id) ? "is-drop-target" : "",
          reorderEnabled && reorder.getDropPlacement("item", countdown.id) === "after" ? "drop-after" : ""
        ].filter(Boolean).join(" ");
        const reorderProps = reorderEnabled ? reorder.getItemProps({ itemId: countdown.id, parentId }) : {};

        return (
          <li key={countdown.id} className={className} {...reorderProps}>
            <div className={`tool-split-entry timer-entry has-single-action ${reorderEnabled ? "has-drag-handle" : ""} ${editingId !== countdown.id ? "has-inline-controls" : ""} ${(canReset || canToggleRefresh) && editingId !== countdown.id ? "has-inline-reset" : ""}`}>
              {reorderEnabled && (
                <button
                  className="timer-drag-handle"
                  type="button"
                  onPointerDown={(event) => reorder.itemReorder.startDrag(event, countdown.id)}
                  aria-label={`${textContent.reorderTitle || "Déplacer"} ${countdown.label}`}
                  title={textContent.reorderTitle || "Déplacer"}
                >
                  <Icon name="drag" />
                </button>
              )}
              {editingId === countdown.id ? (
                <EditableTimerLabel
                  value={countdown.label}
                  placeholder={textContent.defaultCountdownLabel || "Timer"}
                  ariaLabel={textContent.countdownLabel || "Libellé"}
                  onRename={(label) => onRename(countdown.id, label)}
                  onDone={() => setEditingId("")}
                >
                  <TimerValue ms={remainingMs} showCentiseconds={false} />
                </EditableTimerLabel>
              ) : (
                <span
                  className="tool-split-entry-summary timer-entry-summary"
                  role="button"
                  tabIndex={0}
                  onClick={() => setEditingId(countdown.id)}
                  onKeyDown={(event) => handleEditableKeyDown(event, () => setEditingId(countdown.id))}
                >
                  <span className="timer-entry-line">
                    <TimerValue ms={remainingMs} showCentiseconds={false} />
                    <span>{countdown.label}</span>
                    <span className="timer-inline-controls">
                      {canReset && (
                        <button
                          className="timer-inline-reset"
                          type="button"
                          onClick={(event) => {
                            event.stopPropagation();
                            onReset(countdown);
                          }}
                          aria-label={textContent.resetTitle || "Réinitialiser"}
                          title={textContent.resetTitle || "Réinitialiser"}
                        >
                          <Icon name="refresh" />
                        </button>
                      )}
                      {canToggleRefresh && (
                        <button
                          className={`timer-inline-refresh-toggle ${countdown.autoRefresh ? "active" : ""} ${refreshBlocked ? "is-blocked" : ""}`}
                          type="button"
                          onClick={(event) => {
                            event.stopPropagation();
                            onAutoRefreshToggle(countdown.id);
                          }}
                          disabled={refreshBlocked}
                          aria-pressed={Boolean(countdown.autoRefresh)}
                          aria-label={refreshTitle}
                          title={refreshTitle}
                        >
                          <Icon name="refresh" />
                          <i aria-hidden="true" />
                        </button>
                      )}
                    <TimerAlertModeSwitch
                      mode={countdown.alertMode}
                      blocked={AUTO_REFRESH_COUNTDOWN_TYPES.has(countdown.type) && isAlertGuarded(countdown)}
                      textContent={textContent}
                        onChange={(alertMode) => onAlertModeChange(countdown.id, alertMode)}
                      />
                    </span>
                  </span>
                </span>
              )}
              <button className="danger" type="button" onClick={() => onDelete(countdown.id)} aria-label={textContent.deleteTitle || "Supprimer"} title={textContent.deleteTitle || "Supprimer"}>
                <Icon name="trash" />
              </button>
            </div>
            <p className="timer-entry-meta">
              <span>
                {getCountdownMetaParts(countdown, textContent).map((part, index) => (
                  <b key={`${part}-${index}`}>{part}</b>
                ))}
              </span>
              <em>
                <b>{expired ? textContent.finishedLabel || "Terminé" : `${textContent.targetLabel || "Prochaine occurrence"} ${formatTargetTime(countdown.targetMs)}`}</b>
              </em>
            </p>
          </li>
        );
      })}
    </ul>
  );
}

function EditableTimerLabel({ value, placeholder, ariaLabel, children, onRename, onDone }) {
  const inlineEdit = useInlineEdit({
    value,
    onCommit: onRename,
    onDone,
    autoFocus: true,
    commitUnchanged: true
  });

  return (
    <>
      <span className="tool-split-entry-value timer-entry-value is-readonly">{children}</span>
      <input
        {...inlineEdit.getInputProps({
          className: "tool-split-entry-label timer-lap-label",
          placeholder,
          "aria-label": ariaLabel
        })}
      />
    </>
  );
}
