// Page sections — desktop coach/athlete app
const { useState: useStateP, useMemo: useMemoP, useEffect: useEffectP } = React;

// ── DASHBOARD ─────────────────────────────────────────────────────────────
function Dashboard({ t, lang, onStartWorkout, goto }) {
  const recent = HISTORY.slice(0, 5);
  const firstName = (USER.full || USER.name || "GUS").split(" ")[0];
  const weekWorkouts = HISTORY.filter(w => Date.now() - w.dateTs < 7 * 86400000);
  const weekVolume = weekWorkouts.reduce((s, w) => s + w.volume, 0);
  const weekTime = Math.round(weekWorkouts.reduce((s, w) => s + w.duration, 0) / 60);
  return (
    <>
      <div className="page-head">
        <div>
          <h1>{lang === "fr" ? `Bonjour, ${firstName}` : `Welcome back, ${firstName}`}</h1>
          <p className="page-sub">{lang === "fr" ? "Voici ton activité de la semaine." : "Here's how this week is shaping up."}</p>
        </div>
        <button className="btn-primary" onClick={() => goto("workout")}>
          <Icon name="plus" size={14}/> {t.start_workout}
        </button>
      </div>

      <div className="stat-grid">
        <div className="stat-card">
          <div className="stat-label"><Icon name="dumbbell" size={12}/> {t.workouts_this_week}</div>
          <div className="stat-value">{weekWorkouts.length}<span className="stat-unit">/ 4</span></div>
          <div className="stat-trend pos">{lang === "fr" ? "Bien parti 💪" : "On track"}</div>
        </div>
        <div className="stat-card">
          <div className="stat-label"><Icon name="weight" size={12}/> {t.total_volume}</div>
          <div className="stat-value">{(weekVolume/1000).toFixed(1)}<span className="stat-unit">{lang === "fr" ? " t" : " t"}</span></div>
          <div className="stat-trend pos">+ 8.2% {lang === "fr" ? "vs sem. dernière" : "vs last week"}</div>
        </div>
        <div className="stat-card">
          <div className="stat-label"><Icon name="clock" size={12}/> {t.time_trained}</div>
          <div className="stat-value">{weekTime}<span className="stat-unit"> min</span></div>
          <div className="stat-trend muted">{lang === "fr" ? "Moy. 67 min" : "Avg 67 min"}</div>
        </div>
        <div className="stat-card">
          <div className="stat-label"><Icon name="trophy" size={12}/> {t.prs_this_month}</div>
          <div className="stat-value">7</div>
          <div className="stat-trend pos">2 {lang === "fr" ? "cette semaine" : "this week"}</div>
        </div>
      </div>

      <div className="dash-cols">
        <section className="dash-section">
          <div className="section-head">
            <h2>{t.recent_workouts}</h2>
            <button className="link-btn" onClick={() => goto("workouts")}>{t.see_all} →</button>
          </div>
          <div className="workout-list">
            {recent.map(w => <WorkoutRow key={w.id} workout={w} lang={lang}/>)}
          </div>
        </section>

        <section className="dash-section">
          <div className="section-head">
            <h2>{t.quick_start}</h2>
            <button className="link-btn" onClick={() => goto("templates")}>{t.all_templates} →</button>
          </div>
          <div className="quick-grid">
            {TEMPLATES.slice(0, 4).map(tpl => (
              <button key={tpl.id} className="quick-card" onClick={() => onStartWorkout(tpl.id)}
                      style={{"--accent": tpl.color}}>
                <div className="qc-stripe"></div>
                <div className="qc-name">{tpl.name}</div>
                <div className="qc-meta">{tpl.exercises.length} {t.exercises_lower} · ~{tpl.duration} min</div>
              </button>
            ))}
          </div>
        </section>
      </div>
    </>
  );
}

function WorkoutRow({ workout, lang, onClick }) {
  const d = new Date(workout.dateTs);
  const months = lang === "fr"
    ? ["jan","fév","mar","avr","mai","jun","jul","aoû","sep","oct","nov","déc"]
    : ["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"];
  return (
    <div className="workout-row" onClick={onClick}>
      <div className="wr-date">
        <div className="wr-day">{d.getDate()}</div>
        <div className="wr-mon">{months[d.getMonth()]}</div>
      </div>
      <div>
        <div className="wr-name">{workout.name}</div>
        <div className="wr-meta">
          {workout.exercises.length} {lang === "fr" ? "ex." : "exercises"} · {workout.duration}min · {(workout.volume/1000).toFixed(1)}t
          {workout.prs > 0 && <span className="wd-pr" style={{marginLeft: 6}}>+{workout.prs} PR</span>}
        </div>
      </div>
      <div className="wr-tags">
        {[...new Set(workout.exercises.map(e => MUSCLES.find(m=>m.id === EXERCISES.find(ex=>ex.id===e.exerciseId)?.muscle)?.[lang === "fr" ? "fr" : "en"]))]
          .filter(Boolean).slice(0,3).map(m => <span key={m} className="chip-mini">{m}</span>)}
      </div>
    </div>
  );
}

// ── WORKOUTS LIST ────────────────────────────────────────────────────────
function WorkoutsList({ t, lang }) {
  const [openId, setOpenId] = useStateP(HISTORY[0]?.id);
  const monthly = useMemoP(() => {
    const groups = {};
    HISTORY.forEach(w => {
      const d = new Date(w.dateTs);
      const k = `${d.getFullYear()}-${d.getMonth()}`;
      if (!groups[k]) groups[k] = { date: d, workouts: [] };
      groups[k].workouts.push(w);
    });
    return Object.values(groups);
  }, []);
  const monthFmt = (d) => {
    const m = lang === "fr"
      ? ["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"]
      : ["January","February","March","April","May","June","July","August","September","October","November","December"];
    return `${m[d.getMonth()]} ${d.getFullYear()}`;
  };
  return (
    <>
      <div className="page-head">
        <div>
          <h1>{t.history}</h1>
          <p className="page-sub">{lang === "fr" ? "Toutes tes séances passées." : "Every session you've logged."}</p>
        </div>
        <button className="btn-secondary"><Icon name="filter" size={14}/> {lang === "fr" ? "Filtrer" : "Filter"}</button>
      </div>

      {monthly.map((g, gi) => {
        const mVol = g.workouts.reduce((s,w) => s+w.volume, 0);
        const mTime = g.workouts.reduce((s,w) => s+w.duration, 0);
        const mPrs = g.workouts.reduce((s,w) => s+w.prs, 0);
        return (
          <div key={gi} style={{marginBottom: 32}}>
            <div className="month-nav">
              <h2>{monthFmt(g.date)}</h2>
            </div>
            <div className="month-summary">
              <div><div className="ms-label">{t.workouts}</div><div className="ms-val">{g.workouts.length}</div></div>
              <div><div className="ms-label">{t.volume}</div><div className="ms-val">{(mVol/1000).toFixed(1)}<span> t</span></div></div>
              <div><div className="ms-label">{t.time_trained}</div><div className="ms-val">{Math.round(mTime/60)}<span> h</span></div></div>
              <div><div className="ms-label">PRs</div><div className="ms-val">{mPrs}</div></div>
            </div>
            <div style={{display:"flex",flexDirection:"column",gap:8}}>
              {g.workouts.map(w => (
                <WorkoutDetail key={w.id} workout={w} open={openId === w.id} onToggle={() => setOpenId(openId === w.id ? null : w.id)} t={t} lang={lang}/>
              ))}
            </div>
          </div>
        );
      })}
    </>
  );
}

function WorkoutDetail({ workout, open, onToggle, t, lang }) {
  const d = new Date(workout.dateTs);
  const months = lang === "fr" ? ["jan","fév","mar","avr","mai","jun","jul","aoû","sep","oct","nov","déc"]
                                : ["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"];
  return (
    <div className="workout-detail">
      <button className="wd-head" onClick={onToggle}>
        <div className="wr-date">
          <div className="wr-day">{d.getDate()}</div>
          <div className="wr-mon">{months[d.getMonth()]}</div>
        </div>
        <div>
          <div className="wr-name">{workout.name}</div>
          <div className="wr-meta">
            {workout.exercises.length} {lang === "fr" ? "ex." : "exercises"} · {workout.duration}min · {(workout.volume/1000).toFixed(1)}t
            {workout.prs > 0 && <span className="wd-pr" style={{marginLeft: 6}}>+{workout.prs} PR</span>}
          </div>
        </div>
        <Icon name={open ? "chevron-up" : "chevron-down"} size={16}/>
      </button>
      {open && (
        <div className="wd-body">
          {workout.exercises.map((e, i) => {
            const ex = EXERCISES.find(x => String(x.id) === String(e.exerciseId));
            return (
              <div key={i}>
                <div className="wd-ex-name">{ex?.name || e.name || e.exerciseId || "Exercise"}</div>
                <div className="wd-sets">
                  {e.sets.map((s, j) => (
                    <div key={j} className={"wd-set" + (s.isPR ? " pr" : "")}>
                      <span className="wd-set-n">{j+1}</span>
                      <span className="wd-set-w">{s.weight}{lang === "fr" ? "kg" : "kg"}</span>
                      <span className="wd-set-x">×</span>
                      <span>{s.reps}</span>
                      {s.isPR && <span className="wd-pr">PR</span>}
                    </div>
                  ))}
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ── CALENDAR ─────────────────────────────────────────────────────────────
function CalendarPage({ t, lang }) {
  const today = new Date();
  const [month, setMonth] = useStateP(today.getMonth());
  const [year, setYear] = useStateP(today.getFullYear());
  const [selected, setSelected] = useStateP(null);
  const [editWorkout, setEditWorkout] = useStateP(null);
  const [, setVersion] = useStateP(0);
  const historyKey = HISTORY.map(w => `${w.id}:${w.date}:${w.exercises?.length || 0}`).join("|");

  const firstDay = new Date(year, month, 1).getDay();
  const startOffset = (firstDay + 6) % 7; // Mon-first
  const daysInMonth = new Date(year, month + 1, 0).getDate();

  const workoutByDate = useMemoP(() => {
    const m = {};
    HISTORY.forEach(w => {
      const d = new Date(w.dateTs);
      const k = `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
      m[k] = w;
    });
    return m;
  }, [historyKey]);

  const monthNames = lang === "fr"
    ? ["Janvier","Février","Mars","Avril","Mai","Juin","Juillet","Août","Septembre","Octobre","Novembre","Décembre"]
    : ["January","February","March","April","May","June","July","August","September","October","November","December"];
  const dayNames = lang === "fr" ? ["L","M","M","J","V","S","D"] : ["M","T","W","T","F","S","S"];

  const cells = [];
  for (let i = 0; i < startOffset; i++) cells.push(null);
  for (let d = 1; d <= daysInMonth; d++) cells.push(d);

  const sel = selected ? workoutByDate[`${year}-${month}-${selected}`] : null;

  return (
    <>
      <div className="page-head">
        <div>
          <h1>{t.calendar}</h1>
          <p className="page-sub">{lang === "fr" ? "Visualise ta régularité." : "Visualize your consistency."}</p>
        </div>
        <button className="btn-primary"><Icon name="plus" size={14}/> {lang === "fr" ? "Programmer" : "Schedule"}</button>
      </div>

      <div className="cal-layout">
        <div className="cal-main">
          <div className="cal-head">
            <button className="icon-btn" onClick={() => { if(month===0){setMonth(11);setYear(year-1);}else setMonth(month-1); }}>
              <Icon name="chevron-left" size={16}/>
            </button>
            <div className="cal-title">{monthNames[month]} {year}</div>
            <button className="icon-btn" onClick={() => { if(month===11){setMonth(0);setYear(year+1);}else setMonth(month+1); }}>
              <Icon name="chevron-right" size={16}/>
            </button>
          </div>
          <div className="cal-grid">
            {dayNames.map((d, i) => <div key={i} className="cal-dow">{d}</div>)}
            {cells.map((d, i) => {
              if (d === null) return <div key={i} className="cal-day empty"></div>;
              const k = `${year}-${month}-${d}`;
              const w = workoutByDate[k];
              const isToday = d === today.getDate() && month === today.getMonth() && year === today.getFullYear();
              const isSel = d === selected;
              return (
                <button key={i}
                        className={"cal-day" + (w ? " has-workout" : "") + (isToday ? " today" : "") + (isSel ? " selected" : "")}
                        onClick={() => setSelected(d)}>
                  <span className="cd-num">{d}</span>
                  {w && <span className="cd-marker" style={{background: TEMPLATES.find(t => t.name === w.name)?.color || "var(--primary)"}}></span>}
                </button>
              );
            })}
          </div>
        </div>

        <div className="cal-side">
          {sel ? (
            <>
              <WorkoutSummaryCard workout={sel} selected={selected} monthName={monthNames[month]} lang={lang} onEdit={() => setEditWorkout(sel)}/>
            </>
          ) : (
            <div className="cs-empty">
              <Icon name="calendar" size={32} color="var(--text-dim)"/>
              <p style={{marginTop: 12}}>{lang === "fr" ? "Sélectionne un jour pour voir les détails." : "Pick a day to see details."}</p>
            </div>
          )}
        </div>
      </div>
      {editWorkout && <WorkoutEditModal workout={editWorkout} lang={lang} onClose={() => setEditWorkout(null)} onSaved={async () => { await window.loadGusBackendData(); setEditWorkout(null); setVersion(v => v + 1); }}/>}
    </>
  );
}

function WorkoutSummaryCard({ workout, selected, monthName, lang, onEdit }) {
  return (
    <>
      <div className="cs-day">{selected} {monthName}</div>
      <div className="cs-name">{workout.name}</div>
      <div className="cs-meta">{workout.exercises.length} {lang === "fr" ? "exercices" : "exercises"} · {workout.duration}min · {(workout.volume/1000).toFixed(1)}t</div>
      <button className="btn-secondary" style={{width:"100%",justifyContent:"center",margin:"10px 0"}} onClick={onEdit}>
        <Icon name="edit" size={12}/> {lang === "fr" ? "Modifier la séance" : "Edit workout"}
      </button>
      <div className="cs-list">
        {workout.exercises.map((e, i) => {
          const ex = EXERCISES.find(x => String(x.id) === String(e.exerciseId));
          return (
            <div key={i} className="cs-ex">
              <span>{ex?.name || e.name || e.exerciseId || "Exercise"}</span>
              <span className="cs-sets">{e.sets.length} × {e.sets[0]?.reps || "-"}</span>
            </div>
          );
        })}
      </div>
    </>
  );
}

function WorkoutEditModal({ workout, lang, onClose, onSaved }) {
  const [name, setName] = useStateP(workout.name || "Workout");
  const [duration, setDuration] = useStateP(workout.duration || 45);
  const [exercises, setExercises] = useStateP((workout.exercises || []).map(ex => ({
    exerciseId:ex.exerciseId,
    sets:(ex.sets || []).map(s => ({ weight:Number(s.weight || 0), reps:Number(s.reps || 0), completed:s.done !== false, isPR:!!s.isPR }))
  })));
  const [busy, setBusy] = useStateP(false);
  const updateSet = (ei, si, field, value) => {
    setExercises(cur => cur.map((ex, i) => i === ei ? {
      ...ex,
      sets:ex.sets.map((s, j) => j === si ? { ...s, [field]:field === "completed" || field === "isPR" ? value : Number(value) || 0 } : s)
    } : ex));
  };
  async function save() {
    setBusy(true);
    try {
      await window.GusApi.api(`/workouts/${workout.id}`, {
        method:"PUT",
        body:JSON.stringify({
          name,
          durationMinutes:Number(duration) || 1,
          exercises:exercises.map(ex => ({
            exerciseId:ex.exerciseId,
            sets:ex.sets.map((s, i) => ({ setNumber:i+1, weight:s.weight, reps:s.reps, completed:s.completed, isPR:s.isPR }))
          }))
        })
      });
      await onSaved();
    } finally {
      setBusy(false);
    }
  }
  return (
    <div className="modal-overlay">
      <div className="modal-card week-builder">
        <div className="modal-head">
          <h2>{lang === "fr" ? "Résumé de séance" : "Workout summary"}</h2>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={14}/></button>
        </div>
        <div className="modal-body">
          <div className="form-row two">
            <div><label>{lang === "fr" ? "Nom" : "Name"}</label><input value={name} onChange={e => setName(e.target.value)}/></div>
            <div><label>{lang === "fr" ? "Durée" : "Duration"}</label><input type="number" min="1" value={duration} onChange={e => setDuration(e.target.value)}/></div>
          </div>
          <div className="workout-edit-list">
            {exercises.map((ex, ei) => {
              const meta = EXERCISES.find(e => String(e.id) === String(ex.exerciseId));
              return (
                <div className="workout-edit-ex" key={ei}>
                  <div className="wd-ex-name">{meta?.name || ex.exerciseId}</div>
                  {ex.sets.map((s, si) => (
                    <div className="workout-edit-set" key={si}>
                      <span>{si + 1}</span>
                      <input type="number" value={s.weight} onChange={e => updateSet(ei, si, "weight", e.target.value)}/>
                      <input type="number" value={s.reps} onChange={e => updateSet(ei, si, "reps", e.target.value)}/>
                      <label><input type="checkbox" checked={s.completed} onChange={e => updateSet(ei, si, "completed", e.target.checked)}/> {lang === "fr" ? "fait" : "done"}</label>
                    </div>
                  ))}
                </div>
              );
            })}
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn-secondary" onClick={onClose}>{lang === "fr" ? "Annuler" : "Cancel"}</button>
          <button className="btn-primary" onClick={save} disabled={busy}>{busy ? "..." : (lang === "fr" ? "Sauver" : "Save")}</button>
        </div>
      </div>
    </div>
  );
}

// ── WORKOUT START ────────────────────────────────────────────────────────
function WorkoutPage({ t, lang, onStartWorkout }) {
  const [mode, setMode] = useStateP("blank");
  const [templateId, setTemplateId] = useStateP(TEMPLATES[0]?.id || "");
  const [templateDay, setTemplateDay] = useStateP("");
  const [query, setQuery] = useStateP("");
  const [draftName, setDraftName] = useStateP(lang === "fr" ? "Entraînement libre" : "Blank workout");
  const [selected, setSelected] = useStateP([]);
  const [photoBusy, setPhotoBusy] = useStateP(false);
  const [photoResult, setPhotoResult] = useStateP(null);
  const [photoError, setPhotoError] = useStateP("");
  const [photoImage, setPhotoImage] = useStateP("");
  const [photoName, setPhotoName] = useStateP("");
  const [photoMuscle, setPhotoMuscle] = useStateP("");
  const [photoContext, setPhotoContext] = useStateP("");
  const muscleOptions = [
    { value:"", fr:"Non précisé", en:"Not specified" },
    { value:"chest", fr:"Pectoraux", en:"Chest" },
    { value:"back", fr:"Dos", en:"Back" },
    { value:"shoulders", fr:"Épaules", en:"Shoulders" },
    { value:"biceps", fr:"Biceps", en:"Biceps" },
    { value:"triceps", fr:"Triceps", en:"Triceps" },
    { value:"quadriceps", fr:"Quadriceps", en:"Quadriceps" },
    { value:"hamstrings", fr:"Ischio-jambiers", en:"Hamstrings" },
    { value:"glutes", fr:"Fessiers", en:"Glutes" },
    { value:"calves", fr:"Mollets", en:"Calves" },
    { value:"abs", fr:"Abdos", en:"Abs" },
    { value:"forearms", fr:"Avant-bras", en:"Forearms" },
    { value:"adductors", fr:"Adducteurs", en:"Adductors" },
    { value:"abductors", fr:"Abducteurs", en:"Abductors" }
  ];
  const exerciseResults = useMemoP(() => {
    const q = query.trim().toLowerCase();
    const list = q ? EXERCISES.filter(e => [e.name, e.fr, e.muscle, e.equipment].join(" ").toLowerCase().includes(q)) : EXERCISES;
    return list.slice(0, 24);
  }, [query]);
  const muscleChoiceLabels = Object.fromEntries(muscleOptions.map(m => [m.value, lang === "fr" ? m.fr : m.en]));
  const resultMatchOk = !photoResult?.matchedExercise || !photoMuscle ||
    String(photoResult.matchedExercise.muscleGroup || "").toLowerCase().includes(String(muscleChoiceLabels[photoMuscle] || photoMuscle).toLowerCase()) ||
    (photoMuscle === "shoulders" && /shoulder|épaule|epaule|delt/i.test(String(photoResult.matchedExercise.muscleGroup || "") + " " + String(photoResult.matchedExercise.name || "")));
  const selectedTemplate = TEMPLATES.find(tpl => String(tpl.id) === String(templateId));
  const templateDays = Array.isArray(selectedTemplate?.raw?.days) ? selectedTemplate.raw.days : [];
  const addExercise = ex => {
    if (!ex?.id) return;
    setSelected(cur => [...cur, { id:ex.id, exerciseId:ex.id, name:ex.name, sets:3, reps:10, restSeconds:90 }]);
  };
  const removeExercise = idx => setSelected(cur => cur.filter((_, i) => i !== idx));
  const startBlank = () => {
    const session = window.blankWorkoutSession(draftName, selected);
    onStartWorkout(session);
  };
  const readPhoto = file => new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(String(reader.result || ""));
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
  const selectPhoto = async file => {
    if (!file) return;
    setPhotoError("");
    setPhotoResult(null);
    try {
      setPhotoImage(await readPhoto(file));
      setPhotoName(file.name || (lang === "fr" ? "Photo sélectionnée" : "Selected photo"));
    } catch (e) {
      setPhotoError(e.message || (lang === "fr" ? "Lecture de la photo impossible" : "Unable to read photo"));
    }
  };
  const analyzeSelectedPhoto = async () => {
    if (!photoImage) {
      setPhotoError(lang === "fr" ? "Ajoute une photo avant de lancer l'analyse." : "Add a photo before analyzing.");
      return;
    }
    setPhotoBusy(true); setPhotoError(""); setPhotoResult(null);
    try {
      const result = await window.GusApi.api("/ai/recognize-machine", {
        method:"POST",
        body:JSON.stringify({
          image:photoImage,
          muscleHint:photoMuscle,
          context:photoContext
        })
      });
      setPhotoResult(result);
    } catch (e) {
      setPhotoError(e.message || (lang === "fr" ? "Analyse impossible" : "Unable to analyze photo"));
    } finally {
      setPhotoBusy(false);
    }
  };
  const requestCreation = async proposalOverride => {
    if (!photoResult?.proposal) return;
    await window.GusApi.api("/exercise-requests", {
      method:"POST",
      body:JSON.stringify({ ...photoResult, proposal:proposalOverride || photoResult.proposal })
    });
    setPhotoResult({ ...photoResult, requested:true });
  };
  return (
    <>
      <div className="page-head">
        <div>
          <h1>{lang === "fr" ? "Workout" : "Workout"}</h1>
          <p className="page-sub">{lang === "fr" ? "Démarre vite depuis un modèle ou construis ta séance au fur et à mesure." : "Start from a template or build a workout as you go."}</p>
        </div>
      </div>

      <div className="workout-start-layout">
        <section className="workout-start-panel">
          <div className="seg workout-mode">
            <button className={mode === "blank" ? "active" : ""} onClick={() => setMode("blank")}>{lang === "fr" ? "Blank" : "Blank"}</button>
            <button className={mode === "template" ? "active" : ""} onClick={() => setMode("template")}>{lang === "fr" ? "Template" : "Template"}</button>
          </div>

          {mode === "template" ? (
            <div className="workout-template-start">
              <label className="form-label">{lang === "fr" ? "Choisir un template" : "Choose template"}</label>
              <select className="input" value={templateId} onChange={e => { setTemplateId(e.target.value); setTemplateDay(""); }}>
                {TEMPLATES.map(tpl => <option key={tpl.id} value={tpl.id}>{tpl.name}</option>)}
              </select>
              {templateDays.length > 1 && (
                <>
                  <label className="form-label">{lang === "fr" ? "Jour à lancer" : "Day to start"}</label>
                  <select className="input" value={templateDay} onChange={e => setTemplateDay(e.target.value)}>
                    <option value="">{lang === "fr" ? "Tout le template" : "Full template"}</option>
                    {templateDays.map((d, i) => <option key={d.dayNumber || i} value={i}>{d.name || `${lang === "fr" ? "Jour" : "Day"} ${i + 1}`}</option>)}
                  </select>
                </>
              )}
              <button className="btn-primary full" onClick={() => onStartWorkout(templateId, templateDay === "" ? null : Number(templateDay))} disabled={!templateId}>
                <Icon name="play" size={14}/> {lang === "fr" ? "Démarrer" : "Start"}
              </button>
            </div>
          ) : (
            <div className="workout-builder">
              <label className="form-label">{lang === "fr" ? "Nom de la séance" : "Workout name"}</label>
              <input className="input" value={draftName} onChange={e => setDraftName(e.target.value)}/>
              <div className="search-wrap">
                <Icon name="search" size={14} color="var(--text-muted)"/>
                <input placeholder={lang === "fr" ? "Chercher un exercice..." : "Search exercise..."} value={query} onChange={e => setQuery(e.target.value)}/>
              </div>
              <div className="workout-ex-results">
                {exerciseResults.map(ex => (
                  <button key={ex.id} className="workout-ex-pick" onClick={() => addExercise(ex)}>
                    <ExerciseThumb exercise={ex} size={34}/>
                    <span>{lang === "fr" && ex.fr ? ex.fr : ex.name}</span>
                    <small>{ex.equipment} · {ex.muscle}</small>
                    <Icon name="plus" size={13}/>
                  </button>
                ))}
              </div>
            </div>
          )}
        </section>

        <section className="workout-start-panel">
          <div className="section-head">
            <h2>{lang === "fr" ? "Séance en préparation" : "Workout draft"}</h2>
            <span className="muted">{selected.length} {lang === "fr" ? "exercices" : "exercises"}</span>
          </div>
          <div className="workout-draft-list">
            {selected.map((item, idx) => {
              const ex = EXERCISES.find(e => String(e.id) === String(item.exerciseId));
              return (
                <div className="workout-draft-row" key={idx}>
                  <ExerciseThumb exercise={ex} size={34}/>
                  <div>
                    <strong>{ex?.name || item.name}</strong>
                    <span>{item.sets} x {item.reps} · {item.restSeconds}s</span>
                  </div>
                  <button className="icon-btn" onClick={() => removeExercise(idx)}><Icon name="x" size={12}/></button>
                </div>
              );
            })}
            {!selected.length && <p className="muted">{lang === "fr" ? "Ajoute des exercices manuellement ou avec une photo." : "Add exercises manually or with a photo."}</p>}
          </div>
          <button className="btn-primary full" onClick={startBlank} disabled={!selected.length}>
            <Icon name="play" size={14}/> {lang === "fr" ? "Démarrer la séance blank" : "Start blank workout"}
          </button>
        </section>

        <section className="workout-start-panel photo-panel">
          <h2>{lang === "fr" ? "Ajouter par photo" : "Add from photo"}</h2>
          <p className="muted">{lang === "fr" ? "Prends une photo de la machine. Ajoute le muscle cible et un peu de contexte pour aider l'analyse." : "Take a machine photo. Add the target muscle and context to improve detection."}</p>
          <div className="photo-context-grid">
            <div>
              <label className="form-label">{lang === "fr" ? "Muscle ciblé" : "Target muscle"}</label>
              <select className="input" value={photoMuscle} onChange={e => setPhotoMuscle(e.target.value)}>
                {muscleOptions.map(m => <option key={m.value} value={m.value}>{lang === "fr" ? m.fr : m.en}</option>)}
              </select>
            </div>
            <div>
              <label className="form-label">{lang === "fr" ? "Contexte" : "Context"}</label>
              <input className="input" value={photoContext} onChange={e => setPhotoContext(e.target.value)} placeholder={lang === "fr" ? "Ex: machine épaule, mouvement assis..." : "Ex: shoulder machine, seated movement..."}/>
            </div>
          </div>
          <label className="photo-upload-btn">
            <Icon name="image" size={16}/> {photoImage ? (lang === "fr" ? "Changer la photo" : "Change photo") : (lang === "fr" ? "Photo / caméra" : "Photo / camera")}
            <input type="file" accept="image/*" capture="environment" onChange={e => selectPhoto(e.target.files?.[0])}/>
          </label>
          {photoImage && (
            <div className="photo-ready">
              <img src={photoImage} alt=""/>
              <div>
                <strong>{photoName}</strong>
                <span>{lang === "fr" ? "Prêt à analyser avec les champs ci-dessus." : "Ready to analyze with the fields above."}</span>
              </div>
            </div>
          )}
          <button className="btn-primary" onClick={analyzeSelectedPhoto} disabled={photoBusy || !photoImage}>
            <Icon name="search" size={14}/> {photoBusy ? (lang === "fr" ? "Analyse..." : "Analyzing...") : (lang === "fr" ? "Lancer l'analyse" : "Analyze photo")}
          </button>
          {photoError && <div className="form-error">{photoError}</div>}
          {photoResult && (
            <div className="photo-result">
              <strong>{photoResult.machineName || (lang === "fr" ? "Machine détectée" : "Detected machine")}</strong>
              <span>{Math.round((photoResult.confidence || 0) * 100)}% · {photoResult.reason}</span>
              {photoResult.matchedExercise && resultMatchOk ? (
                <div className="photo-local-match">
                  {(photoResult.matchedExercise.image || photoResult.photo) && <img src={photoResult.matchedExercise.image || photoResult.photo} alt=""/>}
                  <div>
                    <strong>{photoResult.matchedExercise.name}</strong>
                    <span>{photoResult.matchedExercise.muscleGroup} · {photoResult.matchedExercise.equipment}</span>
                  </div>
                  <button className="btn-primary" onClick={() => addExercise({ id:photoResult.matchedExercise.id, name:photoResult.matchedExercise.name })}>
                    <Icon name="plus" size={12}/> {lang === "fr" ? "Ajouter" : "Add"}
                  </button>
                </div>
              ) : photoResult.requested ? (
                <div className="form-success">{lang === "fr" ? "Demande envoyée à l'admin." : "Request sent to admin."}</div>
              ) : (
                <>
                  <p>{lang === "fr" ? "Aucun exercice équivalent dans la BD. Choisis l'option la plus proche ou envoie une demande générale à l'admin." : "No matching exercise in the DB. Choose the closest option or send a general admin request."}</p>
                  {!!photoResult.choices?.length && (
                    <div className="photo-choice-list">
                      {photoResult.choices.map((choice, idx) => (
                        <button className="photo-choice" key={idx} onClick={() => requestCreation(choice)}>
                          {(choice.image || photoResult.photo) && <img src={choice.image || photoResult.photo} alt=""/>}
                          <strong>{choice.name}</strong>
                          <span>{choice.muscleGroup} · {choice.equipment}</span>
                          <small>{choice.description || choice.reason || ""}</small>
                        </button>
                      ))}
                    </div>
                  )}
                  <button className="btn-secondary" onClick={() => requestCreation()}>
                    <Icon name="check" size={12}/> {lang === "fr" ? "Aucun des choix / demander à l'admin" : "None of these / ask admin"}
                  </button>
                </>
              )}
            </div>
          )}
        </section>
      </div>
    </>
  );
}

// ── TEMPLATES ────────────────────────────────────────────────────────────
function TemplatesPage({ t, lang, onStartWorkout }) {
  const templates = Array.isArray(TEMPLATES) ? TEMPLATES : [];
  const [builderOpen, setBuilderOpen] = useStateP(false);
  const [menuId, setMenuId] = useStateP(null);
  const [editTpl, setEditTpl] = useStateP(null);
  const [shareTpl, setShareTpl] = useStateP(null);
  const [addToWeekTpl, setAddToWeekTpl] = useStateP(null);
  const [startTpl, setStartTpl] = useStateP(null);
  const [, setVersion] = useStateP(0);
  const refreshTemplates = async () => {
    if (window.loadGusBackendData) await window.loadGusBackendData();
    setVersion(v => v + 1);
  };
  const deleteTemplate = async tpl => {
    const ok = confirm(lang === "fr" ? `Supprimer "${tpl.name}" ?` : `Delete "${tpl.name}"?`);
    if (!ok) return;
    try {
      await window.GusApi.api(`/templates/${tpl.id}`, { method:"DELETE" });
      await refreshTemplates();
    } catch (e) {
      alert(e.message || (lang === "fr" ? "Impossible de supprimer ce template" : "Unable to delete this template"));
    }
  };
  return (
    <>
      <div className="page-head">
        <div>
          <h1>{t.templates}</h1>
          <p className="page-sub">{lang === "fr" ? "Tes routines, prêtes à lancer." : "Your routines, ready to launch."}</p>
        </div>
        <button className="btn-secondary" onClick={() => setBuilderOpen(true)}><Icon name="plus" size={14}/> {lang === "fr" ? "Nouveau modèle" : "New template"}</button>
      </div>

      <div className="tpl-grid">
        {templates.map(tpl => (
          <div key={tpl.id} className="tpl-card" style={{"--accent": tpl.color}}>
            <div className="tpl-stripe"></div>
            <div className="tpl-head">
              <div>
                <div className="tpl-cat">{tpl.category}</div>
                <div className="tpl-name">{tpl.name}</div>
              </div>
              <button className="icon-btn" onClick={e => { e.stopPropagation(); setMenuId(String(menuId) === String(tpl.id) ? null : tpl.id); }}>
                <Icon name="more" size={14}/>
              </button>
              {String(menuId) === String(tpl.id) && (
                <div className="tpl-menu">
                  <button onClick={() => { setEditTpl(tpl); setMenuId(null); }}>{lang === "fr" ? "Modifier" : "Edit"}</button>
                  <button onClick={() => { setShareTpl(tpl); setMenuId(null); }}>{lang === "fr" ? "Partager" : "Share"}</button>
                  <button onClick={() => { setAddToWeekTpl(tpl); setMenuId(null); }}>{lang === "fr" ? "Ajouter à une semaine" : "Add to week"}</button>
                  <button className="danger" onClick={() => { setMenuId(null); deleteTemplate(tpl); }}>{lang === "fr" ? "Supprimer" : "Delete"}</button>
                </div>
              )}
            </div>
            <div className="tpl-stats">
              <span>{(tpl.exercises || []).length} {t.exercises_lower}</span>
              <span>·</span>
              <span>~{tpl.duration} min</span>
              <span>·</span>
              <span>{lang === "fr" ? "Lancée" : "Run"} {tpl.runs || 0}×</span>
            </div>
            <div className="tpl-ex">
              {(tpl.exercises || []).slice(0, 5).map((e, i) => {
                const ex = EXERCISES.find(x => String(x.id) === String(e.exerciseId));
                return (
                  <div key={i} className="tpl-ex-row" style={{display:"flex",alignItems:"center",gap:8}}>
                    <ExerciseThumb exercise={ex} size={24} showPlay={false}/>
                    <span className="tpl-ex-name" style={{flex:1}}>{ex?.name || e.exerciseId}</span>
                    <span className="tpl-ex-sets">{e.sets} × {e.repsRange}</span>
                  </div>
                );
              })}
              {(tpl.exercises || []).length > 5 && (
                <div className="tpl-ex-row">
                  <span className="muted" style={{fontSize: 11}}>+ {(tpl.exercises || []).length - 5} {lang === "fr" ? "autres" : "more"}</span>
                </div>
              )}
            </div>
            <button className="tpl-start" onClick={() => {
              const days = tpl.raw?.days || [];
              if (days.length > 1) setStartTpl(tpl);
              else onStartWorkout(tpl.id);
            }}>
              <Icon name="play" size={12}/> {t.start_workout}
            </button>
          </div>
        ))}
      </div>
      {builderOpen && <WeeklyTemplateBuilder lang={lang} onClose={() => setBuilderOpen(false)} onSaved={refreshTemplates}/>}
      {editTpl && <TemplateEditModal tpl={editTpl} lang={lang} onClose={() => setEditTpl(null)} onSaved={async () => { setEditTpl(null); await refreshTemplates(); }}/>}
      {shareTpl && <TemplateShareModal tpl={shareTpl} lang={lang} onClose={() => setShareTpl(null)} onSaved={async () => { setShareTpl(null); await refreshTemplates(); }}/>}
      {addToWeekTpl && <AddTemplateToWeekModal tpl={addToWeekTpl} lang={lang} onClose={() => setAddToWeekTpl(null)} onSaved={async () => { setAddToWeekTpl(null); await refreshTemplates(); }}/>}
      {startTpl && <StartTemplateDayModal tpl={startTpl} lang={lang} onClose={() => setStartTpl(null)} onStart={(dayIndex) => { setStartTpl(null); onStartWorkout(startTpl.id, dayIndex); }}/>}
    </>
  );
}

function StartTemplateDayModal({ tpl, lang, onClose, onStart }) {
  const days = tpl.raw?.days || [];
  return (
    <div className="modal-overlay">
      <div className="modal-card compact-modal">
        <div className="modal-head">
          <h2>{lang === "fr" ? "Choisir le jour" : "Choose day"}</h2>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={14}/></button>
        </div>
        <div className="modal-body">
          <div className="template-day-start-list">
            {days.map((day, i) => (
              <button key={day.dayNumber || i} className="template-day-start" onClick={() => onStart(i)}>
                <div>
                  <strong>{day.name || `${lang === "fr" ? "Jour" : "Day"} ${i + 1}`}</strong>
                  <span>{(day.exercises || []).length} {lang === "fr" ? "exercices" : "exercises"}</span>
                </div>
                <Icon name="play" size={14}/>
              </button>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function normalizeTemplateDays(tpl, dayNames) {
  const raw = tpl?.raw || tpl || {};
  if (Array.isArray(raw.days) && raw.days.length) {
    return raw.days.map((d, i) => ({
      dayNumber: d.dayNumber || i + 1,
      name: d.name || dayNames[i] || `Day ${i + 1}`,
      exercises: Array.isArray(d.exercises) ? d.exercises : []
    }));
  }
  return [{
    dayNumber: 1,
    name: dayNames[0] || "Day 1",
    exercises: Array.isArray(tpl?.exercises) ? tpl.exercises : []
  }];
}

function sourceTemplateExercises(tpl) {
  const days = normalizeTemplateDays(tpl, ["Day 1"]);
  return days.flatMap(d => d.exercises || []);
}

function normalizeTemplateExercise(ex) {
  return {
    exerciseId:ex.exerciseId,
    sets:Number(ex.sets || ex.targetSets || 3),
    reps:Number(ex.reps || ex.targetReps || parseInt(ex.repsRange) || 10),
    weight:Number(ex.weight || 0),
    restSeconds:Number(ex.restSeconds ?? ex.rest ?? 90)
  };
}

function templateExercisesForBackend(tpl) {
  return sourceTemplateExercises(tpl).map(normalizeTemplateExercise);
}

function templateDaysForBackend(days, dayNames) {
  return days.map((d, i) => ({
    dayNumber:i + 1,
    name:d.name || dayNames[i] || `Day ${i + 1}`,
    exercises:(d.exercises || []).map(normalizeTemplateExercise)
  }));
}

function ExerciseTemplateLibrary({ lang, days, selectedDay, setSelectedDay, matches, addExercise }) {
  return (
    <div className="template-ex-library">
      <div className="template-ex-library-head">
        <div>
          <strong>{lang === "fr" ? "Bibliothèque d'exercices" : "Exercise library"}</strong>
          <span>{matches.length} {lang === "fr" ? "résultats" : "results"}</span>
        </div>
        <select value={selectedDay} onChange={e => setSelectedDay(Number(e.target.value))}>
          {days.map((day, i) => <option key={day.dayNumber || i} value={i}>{day.name || `${lang === "fr" ? "Jour" : "Day"} ${i + 1}`}</option>)}
        </select>
      </div>
      <div className="template-ex-library-list">
        {matches.map(ex => (
          <button key={ex.id} className="template-ex-pick" onClick={() => addExercise(selectedDay, ex.id)}>
            <ExerciseThumb exercise={ex} size={34} showPlay={false}/>
            <span>{lang === "fr" && ex.fr ? ex.fr : ex.name}</span>
            <small>{ex.equipment}</small>
            <Icon name="plus" size={13}/>
          </button>
        ))}
      </div>
    </div>
  );
}

function WeeklyTemplateBuilder({ lang, onClose, onSaved }) {
  const dayNames = lang === "fr"
    ? ["Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche"]
    : ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
  const [name, setName] = useStateP(lang === "fr" ? "Nouvelle semaine" : "New training week");
  const [description, setDescription] = useStateP("");
  const [days, setDays] = useStateP(dayNames.map((d, i) => ({ dayNumber:i+1, name:d, exercises:[] })));
  const [query, setQuery] = useStateP("");
  const [libraryDay, setLibraryDay] = useStateP(0);
  const [defaultRest, setDefaultRest] = useStateP(90);
  const [busy, setBusy] = useStateP(false);
  const [error, setError] = useStateP("");
  const matches = EXERCISES.filter(e => {
    const q = query.toLowerCase();
    return !q || e.name.toLowerCase().includes(q) || (e.fr || "").toLowerCase().includes(q);
  });
  const addExercise = (di, exerciseId) => {
    setDays(cur => cur.map((d, i) => i === di
      ? { ...d, exercises:[...d.exercises, { exerciseId, sets:3, reps:10, weight:0, restSeconds:Number(defaultRest) || 0 }] }
      : d
    ));
  };
  const removeExercise = (di, xi) => {
    setDays(cur => cur.map((d, i) => i === di
      ? { ...d, exercises:d.exercises.filter((_, x) => x !== xi) }
      : d
    ));
  };
  const updateDayName = (di, v) => setDays(cur => cur.map((d, i) => i === di ? { ...d, name:v } : d));
  const updateEx = (di, xi, field, v) => {
    setDays(cur => cur.map((d, i) => i === di ? {
      ...d,
      exercises:d.exercises.map((ex, x) => x === xi ? { ...ex, [field]:Number(v) || 0 } : ex)
    } : d));
  };
  const applyRestToAll = () => {
    setDays(cur => cur.map(d => ({
      ...d,
      exercises:d.exercises.map(ex => ({ ...ex, restSeconds:Number(defaultRest) || 0 }))
    })));
  };
  async function saveTemplate() {
    setBusy(true); setError("");
    try {
      const cleanDays = days.map((d, i) => ({
        dayNumber:i+1,
        name:d.name || dayNames[i],
        exercises:d.exercises
      }));
      if (!name.trim()) throw new Error(lang === "fr" ? "Nom requis" : "Name required");
      if (!cleanDays.some(d => d.exercises.length)) throw new Error(lang === "fr" ? "Ajoute au moins un exercice" : "Add at least one exercise");
      await window.GusApi.api("/templates", {
        method:"POST",
        body:JSON.stringify({
          name:name.trim(),
          description,
          numDays:7,
          tags:JSON.stringify(["week"]),
          days:cleanDays
        })
      });
      await window.loadGusBackendData();
      if (onSaved) await onSaved();
      onClose();
    } catch (e) {
      setError(e.message || "Erreur");
    } finally {
      setBusy(false);
    }
  }
  return (
    <div className="modal-overlay">
      <div className="modal-card week-builder">
        <div className="modal-head">
          <h2>{lang === "fr" ? "Créer un template semaine" : "Create weekly template"}</h2>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={14}/></button>
        </div>
        <div className="modal-body">
          <div className="form-row three">
            <div>
              <label>{lang === "fr" ? "Nom" : "Name"}</label>
              <input value={name} onChange={e => setName(e.target.value)}/>
            </div>
            <div>
              <label>{lang === "fr" ? "Recherche exercice" : "Exercise search"}</label>
              <input value={query} onChange={e => setQuery(e.target.value)} placeholder={lang === "fr" ? "Bench, curl, squat..." : "Bench, curl, squat..."}/>
            </div>
            <div>
              <label>{lang === "fr" ? "Pause entre séries" : "Rest between sets"}</label>
              <div className="inline-rest-control">
                <input type="number" min="0" step="5" value={defaultRest} onChange={e => setDefaultRest(e.target.value)}/>
                <button className="btn-ghost" onClick={applyRestToAll}>{lang === "fr" ? "Appliquer" : "Apply"}</button>
              </div>
            </div>
          </div>
          <div className="form-row">
            <label>Description</label>
            <input value={description} onChange={e => setDescription(e.target.value)}/>
          </div>
          <ExerciseTemplateLibrary
            lang={lang}
            days={days}
            selectedDay={libraryDay}
            setSelectedDay={setLibraryDay}
            matches={matches}
            addExercise={addExercise}
          />
          <div className="week-grid">
            {days.map((day, di) => (
              <div className="week-day" key={day.dayNumber}>
                <input className="week-day-name" value={day.name} onChange={e => updateDayName(di, e.target.value)}/>
                <div className="week-ex-list">
                  {day.exercises.map((ex, xi) => {
                    const meta = EXERCISES.find(e => String(e.id) === String(ex.exerciseId));
                    return (
                      <div className="week-ex-row" key={xi}>
                        <ExerciseThumb exercise={meta} size={28} showPlay={false}/>
                        <span>{meta?.name || ex.exerciseId}</span>
                        <input type="number" min="1" value={ex.sets} onChange={e => updateEx(di, xi, "sets", e.target.value)}/>
                        <input type="number" min="1" value={ex.reps} onChange={e => updateEx(di, xi, "reps", e.target.value)}/>
                        <div className="rest-cell">
                          <input type="number" min="0" step="5" value={ex.restSeconds || 0} onChange={e => updateEx(di, xi, "restSeconds", e.target.value)} aria-label={lang === "fr" ? "Repos en secondes" : "Rest seconds"}/>
                          <span>s</span>
                        </div>
                        <button className="icon-btn" onClick={() => removeExercise(di, xi)}><Icon name="x" size={12}/></button>
                      </div>
                    );
                  })}
                </div>
                <select onChange={e => { if(e.target.value) { addExercise(di, e.target.value); e.target.value = ""; } }}>
                  <option value="">{lang === "fr" ? "+ Exercice" : "+ Exercise"}</option>
                  {matches.map(ex => <option key={ex.id} value={ex.id}>{ex.name}</option>)}
                </select>
              </div>
            ))}
          </div>
          {error && <div style={{color:"var(--danger)",fontSize:13,marginTop:12}}>{error}</div>}
        </div>
        <div className="modal-foot">
          <button className="btn-secondary" onClick={onClose}>{lang === "fr" ? "Annuler" : "Cancel"}</button>
          <button className="btn-primary" onClick={saveTemplate} disabled={busy}>{busy ? "..." : (lang === "fr" ? "Créer la semaine" : "Create week")}</button>
        </div>
      </div>
    </div>
  );
}

function TemplateEditModal({ tpl, lang, onClose, onSaved }) {
  const raw = tpl.raw || tpl;
  const dayNames = lang === "fr"
    ? ["Jour 1","Jour 2","Jour 3","Jour 4","Jour 5","Jour 6","Jour 7"]
    : ["Day 1","Day 2","Day 3","Day 4","Day 5","Day 6","Day 7"];
  const [name, setName] = useStateP(raw.name || tpl.name || "");
  const [description, setDescription] = useStateP(raw.description || "");
  const [days, setDays] = useStateP(normalizeTemplateDays(tpl, dayNames).map((d, i) => ({
    ...d,
    dayNumber:i + 1,
    name:d.name || dayNames[i] || `Day ${i + 1}`,
    exercises:(d.exercises || []).map(normalizeTemplateExercise)
  })));
  const [query, setQuery] = useStateP("");
  const [libraryDay, setLibraryDay] = useStateP(0);
  const [defaultRest, setDefaultRest] = useStateP(days.flatMap(d => d.exercises || [])[0]?.restSeconds ?? 90);
  const [busy, setBusy] = useStateP(false);
  const [error, setError] = useStateP("");
  const matches = EXERCISES.filter(e => {
    const q = query.toLowerCase();
    return !q || e.name.toLowerCase().includes(q) || (e.fr || "").toLowerCase().includes(q);
  });
  const addExercise = (di, exerciseId) => {
    setDays(cur => cur.map((d, i) => i === di
      ? { ...d, exercises:[...(d.exercises || []), { exerciseId, sets:3, reps:10, weight:0, restSeconds:Number(defaultRest) || 0 }] }
      : d
    ));
  };
  const removeExercise = (di, xi) => {
    setDays(cur => cur.map((d, i) => i === di
      ? { ...d, exercises:(d.exercises || []).filter((_, x) => x !== xi) }
      : d
    ));
  };
  const updateDayName = (di, v) => setDays(cur => cur.map((d, i) => i === di ? { ...d, name:v } : d));
  const updateEx = (di, xi, field, v) => {
    setDays(cur => cur.map((d, i) => i === di ? {
      ...d,
      exercises:(d.exercises || []).map((ex, x) => x === xi ? { ...ex, [field]:field === "exerciseId" ? v : Number(v) || 0 } : ex)
    } : d));
  };
  const applyRestToAll = () => {
    setDays(cur => cur.map(d => ({
      ...d,
      exercises:(d.exercises || []).map(ex => ({ ...ex, restSeconds:Number(defaultRest) || 0 }))
    })));
  };
  async function save() {
    setBusy(true); setError("");
    try {
      if (!name.trim()) throw new Error(lang === "fr" ? "Nom requis" : "Name required");
      const cleanDays = templateDaysForBackend(days, dayNames);
      if (!cleanDays.some(d => d.exercises.length)) throw new Error(lang === "fr" ? "Ajoute au moins un exercice" : "Add at least one exercise");
      await window.GusApi.api(`/templates/${tpl.id}`, {
        method:"PUT",
        body:JSON.stringify({
          name:name.trim(),
          description,
          numDays:Math.max(raw.numDays || cleanDays.length || 1, cleanDays.length),
          tags:raw.tags || "[]",
          days:cleanDays
        })
      });
      await onSaved();
    } catch (e) {
      setError(e.message || "Erreur");
    } finally {
      setBusy(false);
    }
  }
  return (
    <div className="modal-overlay">
      <div className="modal-card week-builder">
        <div className="modal-head">
          <h2>{lang === "fr" ? "Modifier le template" : "Edit template"}</h2>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={14}/></button>
        </div>
        <div className="modal-body">
          <div className="form-row three">
            <div>
              <label>{lang === "fr" ? "Nom" : "Name"}</label>
              <input value={name} onChange={e => setName(e.target.value)}/>
            </div>
            <div>
              <label>{lang === "fr" ? "Recherche exercice" : "Exercise search"}</label>
              <input value={query} onChange={e => setQuery(e.target.value)} placeholder={lang === "fr" ? "Bench, curl, squat..." : "Bench, curl, squat..."}/>
            </div>
            <div>
              <label>{lang === "fr" ? "Pause entre séries" : "Rest between sets"}</label>
              <div className="inline-rest-control">
                <input type="number" min="0" step="5" value={defaultRest} onChange={e => setDefaultRest(e.target.value)}/>
                <button className="btn-ghost" onClick={applyRestToAll}>{lang === "fr" ? "Appliquer" : "Apply"}</button>
              </div>
            </div>
          </div>
          <div className="form-row">
            <label>Description</label>
            <input value={description} onChange={e => setDescription(e.target.value)}/>
          </div>
          <ExerciseTemplateLibrary
            lang={lang}
            days={days}
            selectedDay={libraryDay}
            setSelectedDay={setLibraryDay}
            matches={matches}
            addExercise={addExercise}
          />
          <div className="template-edit-hint">
            <span>{lang === "fr" ? "Séries" : "Sets"}</span>
            <span>{lang === "fr" ? "Rép." : "Reps"}</span>
            <span>{lang === "fr" ? "Repos" : "Rest"}</span>
          </div>
          <div className={"week-grid" + (days.length <= 2 ? " edit-grid" : "")}>
            {days.map((day, di) => (
              <div className="week-day" key={day.dayNumber || di}>
                <input className="week-day-name" value={day.name} onChange={e => updateDayName(di, e.target.value)}/>
                <div className="week-ex-list">
                  {(day.exercises || []).map((ex, xi) => {
                    const meta = EXERCISES.find(e => String(e.id) === String(ex.exerciseId));
                    return (
                      <div className="week-ex-row" key={xi}>
                        <ExerciseThumb exercise={meta} size={28} showPlay={false}/>
                        <span>{meta?.name || ex.exerciseId}</span>
                        <input type="number" min="1" value={ex.sets} onChange={e => updateEx(di, xi, "sets", e.target.value)} title={lang === "fr" ? "Séries" : "Sets"}/>
                        <input type="number" min="1" value={ex.reps} onChange={e => updateEx(di, xi, "reps", e.target.value)} title={lang === "fr" ? "Répétitions" : "Reps"}/>
                        <div className="rest-cell">
                          <input type="number" min="0" step="5" value={ex.restSeconds} onChange={e => updateEx(di, xi, "restSeconds", e.target.value)} aria-label={lang === "fr" ? "Repos en secondes" : "Rest seconds"}/>
                          <span>s</span>
                        </div>
                        <button className="icon-btn" onClick={() => removeExercise(di, xi)}><Icon name="x" size={12}/></button>
                      </div>
                    );
                  })}
                </div>
                <select onChange={e => { if(e.target.value) { addExercise(di, e.target.value); e.target.value = ""; } }}>
                  <option value="">{lang === "fr" ? "+ Exercice" : "+ Exercise"}</option>
                  {matches.map(ex => <option key={ex.id} value={ex.id}>{ex.name}</option>)}
                </select>
              </div>
            ))}
          </div>
          {error && <div className="form-error">{error}</div>}
        </div>
        <div className="modal-foot">
          <button className="btn-secondary" onClick={onClose}>{lang === "fr" ? "Annuler" : "Cancel"}</button>
          <button className="btn-primary" onClick={save} disabled={busy}>{busy ? "..." : (lang === "fr" ? "Sauver" : "Save")}</button>
        </div>
      </div>
    </div>
  );
}

function TemplateShareModal({ tpl, lang, onClose, onSaved }) {
  const raw = tpl.raw || tpl;
  const [users, setUsers] = useStateP([]);
  const [selected, setSelected] = useStateP(new Set(raw.sharedWith || []));
  const [busy, setBusy] = useStateP(false);
  const [error, setError] = useStateP("");
  useEffectP(() => {
    let live = true;
    window.GusApi.api("/users").then(list => { if (live) setUsers(Array.isArray(list) ? list : []); }).catch(e => setError(e.message || "Erreur"));
    return () => { live = false; };
  }, []);
  const toggle = id => {
    setSelected(cur => {
      const next = new Set(cur);
      next.has(id) ? next.delete(id) : next.add(id);
      return next;
    });
  };
  async function save() {
    setBusy(true); setError("");
    try {
      await window.GusApi.api(`/templates/${tpl.id}/share`, {
        method:"PATCH",
        body:JSON.stringify({ sharedWith:Array.from(selected) })
      });
      await onSaved();
    } catch (e) {
      setError(e.message || (lang === "fr" ? "Partage réservé à l'admin" : "Admin only"));
    } finally {
      setBusy(false);
    }
  }
  return (
    <div className="modal-overlay">
      <div className="modal-card compact-modal">
        <div className="modal-head">
          <h2>{lang === "fr" ? "Partager le template" : "Share template"}</h2>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={14}/></button>
        </div>
        <div className="modal-body">
          <div className="share-list">
            {users.map(u => (
              <label className="share-user" key={u.id}>
                <input type="checkbox" checked={selected.has(u.id)} onChange={() => toggle(u.id)}/>
                <span>{u.name || u.email}</span>
                <small>{u.email}</small>
              </label>
            ))}
            {!users.length && !error && <div className="muted">{lang === "fr" ? "Chargement..." : "Loading..."}</div>}
          </div>
          {error && <div className="form-error">{error}</div>}
        </div>
        <div className="modal-foot">
          <button className="btn-secondary" onClick={onClose}>{lang === "fr" ? "Annuler" : "Cancel"}</button>
          <button className="btn-primary" onClick={save} disabled={busy}>{busy ? "..." : (lang === "fr" ? "Partager" : "Share")}</button>
        </div>
      </div>
    </div>
  );
}

function AddTemplateToWeekModal({ tpl, lang, onClose, onSaved }) {
  const weeks = (Array.isArray(TEMPLATES) ? TEMPLATES : []).filter(t => String(t.id) !== String(tpl.id) && ((t.raw?.numDays || 0) >= 7 || (t.raw?.days || []).length >= 7));
  const dayNames = lang === "fr"
    ? ["Lundi","Mardi","Mercredi","Jeudi","Vendredi","Samedi","Dimanche"]
    : ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"];
  const [weekId, setWeekId] = useStateP(weeks[0]?.id || "");
  const [dayIndex, setDayIndex] = useStateP(0);
  const [busy, setBusy] = useStateP(false);
  const [error, setError] = useStateP("");
  async function save() {
    setBusy(true); setError("");
    try {
      const week = weeks.find(w => String(w.id) === String(weekId));
      if (!week) throw new Error(lang === "fr" ? "Choisis un template semaine" : "Choose a weekly template");
      const raw = week.raw || week;
      const days = normalizeTemplateDays(week, dayNames);
      while (days.length < 7) days.push({ dayNumber:days.length + 1, name:dayNames[days.length], exercises:[] });
      const source = templateExercisesForBackend(tpl);
      if (!source.length) throw new Error(lang === "fr" ? "Ce template n'a pas d'exercices" : "This template has no exercises");
      days[dayIndex] = { ...days[dayIndex], exercises:[...(days[dayIndex].exercises || []), ...source] };
      await window.GusApi.api(`/templates/${week.id}`, {
        method:"PUT",
        body:JSON.stringify({
          name:raw.name || week.name,
          description:raw.description || "",
          numDays:7,
          tags:raw.tags || JSON.stringify(["week"]),
          days
        })
      });
      await onSaved();
    } catch (e) {
      setError(e.message || "Erreur");
    } finally {
      setBusy(false);
    }
  }
  return (
    <div className="modal-overlay">
      <div className="modal-card compact-modal">
        <div className="modal-head">
          <h2>{lang === "fr" ? "Ajouter à une semaine" : "Add to week"}</h2>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={14}/></button>
        </div>
        <div className="modal-body">
          <div className="form-row">
            <label>{lang === "fr" ? "Template semaine" : "Weekly template"}</label>
            <select value={weekId} onChange={e => setWeekId(e.target.value)}>
              {weeks.map(w => <option key={w.id} value={w.id}>{w.name}</option>)}
            </select>
          </div>
          <div className="form-row">
            <label>{lang === "fr" ? "Jour" : "Day"}</label>
            <select value={dayIndex} onChange={e => setDayIndex(Number(e.target.value))}>
              {dayNames.map((d, i) => <option key={d} value={i}>{d}</option>)}
            </select>
          </div>
          {!weeks.length && <div className="form-error">{lang === "fr" ? "Crée d'abord un template semaine." : "Create a weekly template first."}</div>}
          {error && <div className="form-error">{error}</div>}
        </div>
        <div className="modal-foot">
          <button className="btn-secondary" onClick={onClose}>{lang === "fr" ? "Annuler" : "Cancel"}</button>
          <button className="btn-primary" onClick={save} disabled={busy || !weeks.length}>{busy ? "..." : (lang === "fr" ? "Ajouter" : "Add")}</button>
        </div>
      </div>
    </div>
  );
}

// ── EXERCISES BROWSER ────────────────────────────────────────────────────
function ExercisesPage({ t, lang }) {
  const [search, setSearch] = useStateP("");
  const [muscle, setMuscle] = useStateP(null);
  const [level, setLevel] = useStateP(null);
  const [equip, setEquip] = useStateP(null);
  const [selectedId, setSelectedId] = useStateP(EXERCISES[0]?.id || null);
  const [, setMediaVersion] = useStateP(0);

  const filtered = EXERCISES.filter(e => {
    if (search && !e.name.toLowerCase().includes(search.toLowerCase()) && !(e.fr || "").toLowerCase().includes(search.toLowerCase())) return false;
    if (muscle && e.muscle !== muscle) return false;
    if (level && e.level !== level) return false;
    if (equip && e.equipment !== equip) return false;
    return true;
  });

  const sel = EXERCISES.find(e => e.id === selectedId) || filtered[0];
  const stats = HISTORY_STATS_BY_EXERCISE[sel?.id] || { sessions: 0, bestWeight: "—", bestE1RM: "—" };
  const videoSrc = sel?.videoUrl || sel?.youtube || "";
  const imageSrc = sel?.thumb || sel?.imgStart || sel?.localImg || "";
  useEffectP(() => {
    if (!sel?.pageUrl || (sel.videoUrl && imageSrc)) return;
    let live = true;
    window.GusApi.api(`/exercise-img?url=${encodeURIComponent(sel.pageUrl)}`).then(r => {
      if (!live) return;
      if (r.imgUrl) { sel.thumb = r.imgUrl; sel.localImg = r.imgUrl; }
      if (r.videoUrl) sel.videoUrl = r.videoUrl;
      setMediaVersion(v => v + 1);
    }).catch(() => {});
    return () => { live = false; };
  }, [selectedId]);

  const equips = ["barbell","dumbbell","machine","cable","bodyweight","kettlebell"];
  const levels = ["beginner","intermediate","advanced"];

  return (
    <>
      <div className="page-head">
        <div>
          <h1>{t.exercises}</h1>
          <p className="page-sub">{lang === "fr" ? "240+ mouvements avec notes de forme." : "240+ movements with form notes."}</p>
        </div>
        <button className="btn-secondary"><Icon name="plus" size={14}/> {lang === "fr" ? "Exercice perso" : "Custom exercise"}</button>
      </div>

      <div className="ex-layout">
        <aside className="ex-filters">
          <div className="search-wrap">
            <Icon name="search" size={14} color="var(--text-muted)"/>
            <input type="text" placeholder={lang === "fr" ? "Rechercher…" : "Search…"} value={search} onChange={e => setSearch(e.target.value)}/>
          </div>

          <div className="filter-section">
            <div className="filter-label">{t.muscle}</div>
            <MuscleSilhouette selected={muscle} onSelect={setMuscle} gender={USER.gender} view="front"/>
          </div>

          <div className="filter-section">
            <div className="filter-label">{lang === "fr" ? "Niveau" : "Level"}</div>
            <div className="muscle-chips">
              {levels.map(lv => (
                <button key={lv} className={"chip" + (level === lv ? " active" : "")} onClick={() => setLevel(level === lv ? null : lv)}>
                  {lang === "fr" ? ({beginner:"Débutant",intermediate:"Intermédiaire",advanced:"Avancé"})[lv] : lv.charAt(0).toUpperCase()+lv.slice(1)}
                </button>
              ))}
            </div>
          </div>

          <div className="filter-section">
            <div className="filter-label">{lang === "fr" ? "Équipement" : "Equipment"}</div>
            <div className="muscle-chips">
              {equips.map(eq => (
                <button key={eq} className={"chip" + (equip === eq ? " active" : "")} onClick={() => setEquip(equip === eq ? null : eq)}>
                  {lang === "fr" ? ({barbell:"Barre",dumbbell:"Haltères",machine:"Machine",cable:"Câble",bodyweight:"Poids du corps",kettlebell:"Kettlebell"})[eq] : eq.charAt(0).toUpperCase()+eq.slice(1)}
                </button>
              ))}
            </div>
          </div>
        </aside>

        <div className="ex-list">
          <div className="ex-list-head">{filtered.length} {lang === "fr" ? "exercices" : "exercises"}</div>
          {filtered.map(e => (
            <button key={e.id} className={"ex-row" + (e.id === selectedId ? " active" : "")} onClick={() => setSelectedId(e.id)}>
              <ExerciseThumb exercise={e} size={44} showPlay={false}/>
              <div>
                <div className="ex-name">{lang === "fr" && e.fr ? e.fr : e.name}</div>
                <div className="ex-tags">
                  <span className="ex-tag muscle">{MUSCLES.find(m => m.id === e.muscle)?.[lang === "fr" ? "fr" : "en"]}</span>
                  <span className="ex-tag-sm">{e.equipment}</span>
                </div>
              </div>
              <div className={"ex-level lv-" + e.level}>{e.level.charAt(0).toUpperCase()}</div>
            </button>
          ))}
        </div>

        <div className="ex-detail">
          {sel && (
            <>
              <div className="ex-media">
                <div className="ex-video-placeholder real-media">
                  {videoSrc ? (
                    /\.(mp4|webm)(\?|$)/i.test(videoSrc)
                      ? <video src={videoSrc} controls playsInline/>
                      : <iframe src={videoSrc} title={sel.name} allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowFullScreen></iframe>
                  ) : (
                    <>
                      <Icon name="play-circle" size={32} color="var(--text-dim)"/>
                      <div className="ex-media-label">VIDEO</div>
                      <div className="ex-media-sub">{sel.name.toLowerCase().replace(/\s+/g,"_")}.mp4</div>
                    </>
                  )}
                </div>
                <div className="ex-img-placeholder real-media">
                  {imageSrc ? (
                    <img src={imageSrc} alt={sel.name}/>
                  ) : (
                    <>
                      <Icon name="image" size={32} color="var(--text-dim)"/>
                      <div className="ex-media-label">{lang === "fr" ? "IMAGE" : "IMAGE"}</div>
                      <div className="ex-media-sub">{sel.muscle}_photo.jpg</div>
                    </>
                  )}
                </div>
              </div>
              <div className="ex-detail-body">
                <div>
                  <h2>{lang === "fr" && sel.fr ? sel.fr : sel.name}</h2>
                  <div className="ex-secondary muted">
                    <span className={"ex-tag lv-"+sel.level}>{sel.level}</span>
                    <span>·</span>
                    <span>{sel.equipment}</span>
                    <span>·</span>
                    <span>{lang === "fr" ? "Cible" : "Target"}: {MUSCLES.find(m => m.id === sel.muscle)?.[lang === "fr" ? "fr" : "en"]}</span>
                  </div>
                </div>

                <div>
                  <div className="filter-label" style={{marginBottom: 6}}>{lang === "fr" ? "Muscles secondaires" : "Secondary muscles"}</div>
                  <div className="ex-detail-tags">
                    {(sel.secondary || []).map(s => <span key={s} className="ex-tag">{MUSCLES.find(m => m.id === s)?.[lang === "fr" ? "fr" : "en"] || s}</span>)}
                  </div>
                </div>

                <div>
                  <div className="filter-label" style={{marginBottom: 6}}>{lang === "fr" ? "Notes de forme" : "Form cues"}</div>
                  <ul style={{margin: 0, paddingLeft: 16, fontSize: 12.5, color: "var(--text-muted)", lineHeight: 1.6}}>
                    {(sel.cues?.[lang] || sel.cues?.en || []).map((c, i) => <li key={i}>{c}</li>)}
                  </ul>
                </div>

                <div>
                  <div className="filter-label" style={{marginBottom: 6}}>{lang === "fr" ? "Tes statistiques" : "Your stats"}</div>
                  <div className="ex-stats-mini">
                    <div>
                      <div className="esm-label">{lang === "fr" ? "Séances" : "Sessions"}</div>
                      <div className="esm-val">{stats.sessions}</div>
                    </div>
                    <div>
                      <div className="esm-label">{lang === "fr" ? "Meilleur" : "Best"}</div>
                      <div className="esm-val">{stats.bestWeight}</div>
                    </div>
                    <div>
                      <div className="esm-label">e1RM</div>
                      <div className="esm-val">{stats.bestE1RM}</div>
                    </div>
                  </div>
                </div>
              </div>
            </>
          )}
        </div>
      </div>
    </>
  );
}

// (the old MuscleSilhouette here was removed — primitives.jsx now provides a
// gendered anatomical version with front/back views)

Object.assign(window, { Dashboard, WorkoutsList, CalendarPage, WorkoutPage, TemplatesPage, ExercisesPage, WorkoutRow });
