"use client";

import { useState, useCallback, useRef, useEffect } from "react";
import { useRouter } from "next/navigation";
import { Exercise } from "@prisma/client";
import { ChevronDown, ChevronUp, Loader, Trash2, Plus, Save, Pencil, Check, ArrowUp, ArrowDown, Clock, X } from "lucide-react";
import ExercisePicker from "./ExercisePicker";
import SetRow, { InputField } from "./SetRow";
import { formatSetsSummary } from "@/lib/formatSets";

// --------------- Exercise History Popup ---------------
type HistoryEntry = {
  workout: { id: string; date: string; name?: string };
  sets: Array<{ weight?: number; reps?: number; weightUnit?: string }>;
};

const HISTORY_PAGE_SIZE = 25;

function ExerciseHistoryPopup({
  exerciseId,
  onClose,
}: {
  exerciseId: string;
  onClose: () => void;
}) {
  const [history, setHistory] = useState<HistoryEntry[]>([]);
  const [loading, setLoading] = useState(true);
  const [loadingMore, setLoadingMore] = useState(false);
  const [hasMore, setHasMore] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const popupRef = useRef<HTMLDivElement>(null);
  const sentinelRef = useRef<HTMLDivElement>(null);

  // Initial fetch (page 1)
  useEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const res = await fetch(
          `/api/exercises/${exerciseId}?offset=0&limit=${HISTORY_PAGE_SIZE}`,
        );
        if (res.ok) {
          const data = await res.json();
          if (!cancelled) {
            setHistory(data.history || []);
            setHasMore(!!data.hasMore);
          }
        } else if (!cancelled) {
          setError(`Failed to load history (${res.status})`);
        }
      } catch (e) {
        if (!cancelled) setError("Failed to load history");
      }
      if (!cancelled) setLoading(false);
    })();
    return () => {
      cancelled = true;
    };
  }, [exerciseId]);

  // Infinite scroll — observe a sentinel below the rendered list. The
  // root is the popup's scroll container (the popup itself), not the
  // viewport, since the user scrolls inside the popup.
  useEffect(() => {
    if (loading || !hasMore || !sentinelRef.current || !popupRef.current) {
      return;
    }
    const sentinel = sentinelRef.current;
    const root = popupRef.current;
    const observer = new IntersectionObserver(
      (entries) => {
        if (!entries[0]?.isIntersecting) return;
        if (loadingMore || !hasMore) return;
        setLoadingMore(true);
        (async () => {
          try {
            const res = await fetch(
              `/api/exercises/${exerciseId}?offset=${history.length}&limit=${HISTORY_PAGE_SIZE}`,
            );
            if (res.ok) {
              const data = await res.json();
              setHistory((prev) => [...prev, ...(data.history || [])]);
              setHasMore(!!data.hasMore);
            } else {
              setError(`Failed to load more (${res.status})`);
              setHasMore(false);
            }
          } catch {
            setError("Failed to load more");
            setHasMore(false);
          }
          setLoadingMore(false);
        })();
      },
      { root, rootMargin: "60px" },
    );
    observer.observe(sentinel);
    return () => observer.disconnect();
  }, [loading, hasMore, loadingMore, history.length, exerciseId]);

  // Close on outside click
  useEffect(() => {
    const handler = (e: MouseEvent) => {
      if (popupRef.current && !popupRef.current.contains(e.target as Node)) {
        onClose();
      }
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, [onClose]);

  return (
    <div
      ref={popupRef}
      className="absolute left-0 right-0 top-full mt-1 z-50 bg-zinc-900 border border-zinc-700 rounded-lg shadow-xl max-h-80 overflow-y-auto"
    >
      <div className="flex items-center justify-between px-3 py-2 border-b border-zinc-800 sticky top-0 bg-zinc-900 z-10">
        <span className="text-xs font-semibold text-zinc-400 uppercase tracking-wider">
          Exercise History
        </span>
        <button
          type="button"
          onClick={onClose}
          className="p-0.5 text-zinc-500 hover:text-white"
        >
          <X className="w-3.5 h-3.5" />
        </button>
      </div>
      {loading ? (
        <div className="flex items-center justify-center py-6">
          <Loader className="w-4 h-4 animate-spin text-zinc-500" />
        </div>
      ) : history.length === 0 ? (
        <p className="text-xs text-zinc-500 text-center py-4">No history yet</p>
      ) : (
        <>
          <div className="divide-y divide-zinc-800/50">
            {history.map((entry) => {
              const d = new Date(entry.workout.date);
              const dateStr = d.toLocaleDateString("en-US", {
                month: "short",
                day: "numeric",
                year: "numeric",
              });
              const summary = formatSetsSummary(entry.sets);
              return (
                <div key={entry.workout.id} className="px-3 py-2">
                  <div className="flex items-baseline gap-2">
                    <span className="text-[11px] text-zinc-500 flex-shrink-0">
                      {dateStr}
                    </span>
                    <span className="text-[11px] text-zinc-600">·</span>
                    <span className="text-[11px] text-zinc-500">
                      {entry.sets.length} set
                      {entry.sets.length !== 1 ? "s" : ""}
                    </span>
                  </div>
                  {summary && (
                    <p className="text-xs text-zinc-300 mt-0.5">{summary}</p>
                  )}
                </div>
              );
            })}
          </div>
          {/* Sentinel + status row at the bottom of the list */}
          <div ref={sentinelRef} className="flex justify-center py-2">
            {loadingMore && (
              <Loader className="w-3.5 h-3.5 animate-spin text-zinc-500" />
            )}
            {!loadingMore && !hasMore && history.length >= HISTORY_PAGE_SIZE && (
              <span className="text-[10px] text-zinc-600 uppercase tracking-wider">
                End of history
              </span>
            )}
            {error && (
              <span className="text-[10px] text-red-400">{error}</span>
            )}
          </div>
        </>
      )}
    </div>
  );
}

function parseInputFields(exercise: Exercise): InputField[] {
  try {
    const raw = (exercise as any).inputFields;
    if (raw && typeof raw === "string") {
      return JSON.parse(raw);
    }
  } catch {}
  return ["sets", "reps", "weight"];
}

interface ExerciseWithSets {
  exercise: Exercise;
  sets: Array<{
    setNumber: number;
    reps?: number;
    weight?: number;
    rpe?: number;
    durationSeconds?: number;
    distance?: number;
    calories?: number;
    customMetrics?: Record<string, string>;
    notes?: string;
    forceEdit?: boolean; // When true, start in edit mode even if data is pre-filled
  }>;
}

export interface EditWorkoutData {
  id: string;
  name: string;
  date: string; // ISO string
  durationMinutes?: number | null;
  difficulty?: number | null;
  caloriesBurned?: number | null;
  notes?: string | null;
  exercises: Array<{
    exercise: Exercise;
    sets: Array<{
      setNumber: number;
      reps?: number;
      weight?: number;
      rpe?: number;
      durationSeconds?: number;
      distance?: number;
      calories?: number;
      customMetrics?: Record<string, string>;
      notes?: string;
    }>;
  }>;
}

interface WorkoutFormProps {
  exercises: Exercise[];
  recentlyUsedExercises?: string[];
  editWorkout?: EditWorkoutData;
}

export default function WorkoutForm({
  exercises: initialExercises,
  recentlyUsedExercises = [],
  editWorkout,
}: WorkoutFormProps) {
  const router = useRouter();
  const [loading, setLoading] = useState(false);
  const [exercises, setExercises] = useState<Exercise[]>(initialExercises);

  const [workoutName, setWorkoutName] = useState(editWorkout?.name || "");
  const [workoutDate, setWorkoutDate] = useState(() => {
    if (editWorkout?.date) {
      return new Date(editWorkout.date).toISOString().split("T")[0];
    }
    return new Date().toISOString().split("T")[0];
  });
  const [duration, setDuration] = useState(editWorkout?.durationMinutes?.toString() || "");
  const [difficulty, setDifficulty] = useState(editWorkout?.difficulty?.toString() || "");
  const [workoutCalories, setWorkoutCalories] = useState(editWorkout?.caloriesBurned?.toString() || "");
  const [notes, setNotes] = useState(editWorkout?.notes || "");
  const [notesLocked, setNotesLocked] = useState(!!editWorkout?.notes);
  const [addedExercises, setAddedExercises] = useState<ExerciseWithSets[]>(
    editWorkout?.exercises || []
  );
  const [expandedExercise, setExpandedExercise] = useState<string | null>(null);
  const [historyPopupExercise, setHistoryPopupExercise] = useState<string | null>(null);

  // Header lock state (name + date lock after first save, or immediately for edits)
  const [headerLocked, setHeaderLocked] = useState(!!editWorkout);

  // Auto-save state — if editing, start with existing workout ID
  const [savedWorkoutId, setSavedWorkoutId] = useState<string | null>(editWorkout?.id || null);
  const [autoSaving, setAutoSaving] = useState(false);
  const [showSavedFlash, setShowSavedFlash] = useState(false);
  const savingRef = useRef(false);
  const pendingAutoSaveRef = useRef(false);
  const savedFlashTimer = useRef<NodeJS.Timeout | null>(null);

  // Flash "Saved ✓" briefly after each successful save
  const triggerSavedFlash = useCallback(() => {
    setShowSavedFlash(true);
    if (savedFlashTimer.current) clearTimeout(savedFlashTimer.current);
    savedFlashTimer.current = setTimeout(() => setShowSavedFlash(false), 2000);
  }, []);

  // Cleanup timer on unmount
  useEffect(() => {
    return () => {
      if (savedFlashTimer.current) clearTimeout(savedFlashTimer.current);
    };
  }, []);

  // ---------- Build payload from current state ----------
  const buildPayload = useCallback(
    (currentExercises?: ExerciseWithSets[]) => {
      const exs = currentExercises ?? addedExercises;
      return {
        name: workoutName,
        durationMinutes: duration ? parseInt(duration) : undefined,
        difficulty: difficulty ? parseInt(difficulty) : undefined,
        caloriesBurned: workoutCalories ? parseInt(workoutCalories) : undefined,
        notes: notes || undefined,
        date: new Date(workoutDate + "T12:00:00").toISOString(),
        sets: exs.flatMap((e) =>
          e.sets.map((s) => ({
            exerciseId: e.exercise.id,
            setNumber: s.setNumber,
            reps: s.reps,
            weight: s.weight,
            weightUnit: (e.exercise as any).defaultWeightUnit || "lbs",
            rpe: s.rpe,
            durationSeconds: s.durationSeconds,
            distance: s.distance,
            distanceUnit: s.distance !== undefined ? "mi" : undefined,
            calories: s.calories,
            customMetrics: s.customMetrics,
            notes: s.notes,
          }))
        ),
      };
    },
    [workoutName, workoutDate, duration, difficulty, workoutCalories, notes, addedExercises]
  );

  // ---------- Auto-save: create or update ----------
  const autoSave = useCallback(
    async (overrideExercises?: ExerciseWithSets[]) => {
      if (savingRef.current) {
        // Don't drop updates while a save is in-flight; queue one follow-up save.
        pendingAutoSaveRef.current = true;
        return;
      }
      savingRef.current = true;
      setAutoSaving(true);

      try {
        const payload = buildPayload(overrideExercises);

        if (!savedWorkoutId) {
          // First save — POST to create
          const response = await fetch("/api/workouts", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(payload),
          });

          if (response.ok) {
            const created = await response.json();
            setSavedWorkoutId(created.id);
            triggerSavedFlash();
            setHeaderLocked(true);
          }
        } else {
          // Subsequent save — PATCH to update
          const response = await fetch(`/api/workouts/${savedWorkoutId}`, {
            method: "PATCH",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify({
              ...payload,
              durationMinutes: payload.durationMinutes ?? null,
              difficulty: payload.difficulty ?? null,
              caloriesBurned: payload.caloriesBurned ?? null,
              notes: payload.notes ?? null,
            }),
          });

          if (response.ok) {
            triggerSavedFlash();
            setHeaderLocked(true);
          }
        }
      } catch (error) {
        console.error("Auto-save failed:", error);
      } finally {
        savingRef.current = false;
        setAutoSaving(false);
        if (pendingAutoSaveRef.current) {
          pendingAutoSaveRef.current = false;
          setTimeout(() => {
            void autoSave();
          }, 0);
        }
      }
    },
    [buildPayload, savedWorkoutId, triggerSavedFlash]
  );

  // ---------- Exercise handlers ----------
  const handleAddExercise = (exercise: Exercise) => {
    if (addedExercises.some((e) => e.exercise.id === exercise.id)) {
      setExpandedExercise(exercise.id);
      return;
    }

    setAddedExercises((prev) => [
      ...prev,
      {
        exercise,
        sets: [{ setNumber: 1, reps: undefined, weight: undefined }],
      },
    ]);
    setExpandedExercise(exercise.id);
  };

  const handleExerciseCreated = (exercise: Exercise) => {
    setExercises((prev) => [...prev, exercise]);
  };

  const handleMoveExercise = (exerciseId: string, direction: "up" | "down") => {
    setAddedExercises((prev) => {
      const idx = prev.findIndex((e) => e.exercise.id === exerciseId);
      if (idx < 0) return prev;
      const swapIdx = direction === "up" ? idx - 1 : idx + 1;
      if (swapIdx < 0 || swapIdx >= prev.length) return prev;
      const updated = [...prev];
      [updated[idx], updated[swapIdx]] = [updated[swapIdx], updated[idx]];
      return updated;
    });
  };

  const handleRemoveExercise = (exerciseId: string) => {
    setAddedExercises((prev) => {
      const updated = prev.filter((e) => e.exercise.id !== exerciseId);
      // Auto-save after removing exercise
      setTimeout(() => autoSave(updated), 0);
      return updated;
    });
    if (expandedExercise === exerciseId) setExpandedExercise(null);
  };

  const handleAddSet = (exerciseId: string) => {
    setAddedExercises((prev) =>
      prev.map((e) => {
        if (e.exercise.id === exerciseId) {
          const nextSetNumber =
            Math.max(...e.sets.map((s) => s.setNumber), 0) + 1;
          return {
            ...e,
            sets: [
              ...e.sets,
              { setNumber: nextSetNumber, reps: undefined, weight: undefined },
            ],
          };
        }
        return e;
      })
    );
  };

  const handleRemoveSet = (exerciseId: string, setNumber: number) => {
    setAddedExercises((prev) => {
      const updated = prev.map((e) => {
        if (e.exercise.id === exerciseId) {
          return {
            ...e,
            sets: e.sets.filter((s) => s.setNumber !== setNumber),
          };
        }
        return e;
      });
      // Auto-save after removing set
      setTimeout(() => autoSave(updated), 0);
      return updated;
    });
  };

  const handleUpdateSet = (
    exerciseId: string,
    setNumber: number,
    data: {
      reps?: number;
      weight?: number;
      rpe?: number;
      notes?: string;
      durationSeconds?: number;
      distance?: number;
      calories?: number;
      customMetrics?: Record<string, string>;
    }
  ) => {
    setAddedExercises((prev) =>
      prev.map((e) => {
        if (e.exercise.id === exerciseId) {
          return {
            ...e,
            sets: e.sets.map((s) =>
              s.setNumber === setNumber ? { ...s, ...data } : s
            ),
          };
        }
        return e;
      })
    );
  };

  // Called when user confirms a set (check icon) — triggers auto-save
  // Also clears forceEdit so the set stays locked when the exercise is collapsed/re-expanded
  const handleSetConfirmed = (exerciseId?: string, setNumber?: number) => {
    if (exerciseId && setNumber !== undefined) {
      setAddedExercises((prev) =>
        prev.map((e) => {
          if (e.exercise.id === exerciseId) {
            return {
              ...e,
              sets: e.sets.map((s) =>
                s.setNumber === setNumber ? { ...s, forceEdit: false } : s
              ),
            };
          }
          return e;
        })
      );
    }
    // Small delay to let state settle after the SetRow's emitUpdate
    setTimeout(() => autoSave(), 50);
  };

  // Called when user taps "next set" arrow — confirm current set + add new pre-filled set
  const handleNextSet = (
    exerciseId: string,
    currentValues: {
      weight?: string;
      reps?: string;
      rpe?: string;
      notes?: string;
      duration?: string;
      distance?: string;
      calories?: string;
    }
  ) => {
    setAddedExercises((prev) =>
      prev.map((e) => {
        if (e.exercise.id === exerciseId) {
          const nextSetNumber =
            Math.max(...e.sets.map((s) => s.setNumber), 0) + 1;
          return {
            ...e,
            // Clear forceEdit on all existing sets (they're confirmed now)
            sets: [
              ...e.sets.map((s) => (s.forceEdit ? { ...s, forceEdit: false } : s)),
              {
                setNumber: nextSetNumber,
                weight: currentValues.weight ? parseFloat(currentValues.weight) : undefined,
                reps: undefined, // User typically changes reps per set
                rpe: currentValues.rpe ? parseInt(currentValues.rpe) : undefined,
                notes: currentValues.notes || undefined,
                forceEdit: true, // Start in edit mode even though weight is pre-filled
              },
            ],
          };
        }
        return e;
      })
    );
    // Auto-save after confirming the current set
    setTimeout(() => autoSave(), 50);
  };

  // Called when user saves notes — triggers auto-save
  const handleNotesSave = () => {
    setNotesLocked(true);
    setTimeout(() => autoSave(), 50);
  };

  // ---------- Save and Close ----------
  const handleSaveAndClose = async (e: React.FormEvent) => {
    e.preventDefault();

    if (addedExercises.length === 0) {
      alert("Please add at least one exercise");
      return;
    }

    setLoading(true);

    try {
      // Wait for any in-flight auto-save to finish to avoid race conditions
      // (both would delete-all-sets + recreate simultaneously)
      while (savingRef.current) {
        await new Promise((r) => setTimeout(r, 100));
      }
      // Prevent auto-saves from starting while we do the final save
      savingRef.current = true;
      pendingAutoSaveRef.current = false;

      const payload = buildPayload();

      if (!savedWorkoutId) {
        // Never saved before — create
        const response = await fetch("/api/workouts", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(payload),
        });

        if (!response.ok) throw new Error("Failed to save workout");
      } else {
        // Already saved — final update
        const response = await fetch(`/api/workouts/${savedWorkoutId}`, {
          method: "PATCH",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            ...payload,
            durationMinutes: payload.durationMinutes ?? null,
            difficulty: payload.difficulty ?? null,
            caloriesBurned: payload.caloriesBurned ?? null,
            notes: payload.notes ?? null,
          }),
        });

        if (!response.ok) throw new Error("Failed to save workout");
      }

      // Navigate back: to detail page if editing, otherwise to list
      if (editWorkout) {
        router.push(`/main/workouts/${savedWorkoutId || editWorkout.id}`);
      } else {
        router.push("/main/workouts");
      }
    } catch (error) {
      console.error("Error saving workout:", error);
      alert("Failed to save workout. Please try again.");
    } finally {
      savingRef.current = false;
      setLoading(false);
    }
  };

  return (
    <form
      onSubmit={handleSaveAndClose}
      onKeyDown={(e) => {
        // Prevent Enter from submitting form when editing inputs
        if (e.key === "Enter") {
          const target = e.target as HTMLElement;
          const tag = target.tagName.toLowerCase();
          // Allow submit only from the submit button itself
          if (tag === "input" || tag === "textarea" || tag === "select") {
            e.preventDefault();
          }
        }
      }}
      className="space-y-6"
    >
      {/* Auto-save indicator — fixed height to prevent layout shift */}
      <div className="h-4 flex items-center justify-center">
        <div className={`flex items-center gap-1.5 text-[10px] transition-opacity duration-300 ${autoSaving || showSavedFlash ? "opacity-100" : "opacity-0"} ${autoSaving ? "text-zinc-500" : "text-green-500"}`}>
          {autoSaving ? (
            <>
              <Loader className="w-3 h-3 animate-spin" />
              <span>Saving...</span>
            </>
          ) : (
            <>
              <Check className="w-3 h-3" />
              <span>Saved</span>
            </>
          )}
        </div>
      </div>

      {/* Workout name & date */}
      {headerLocked ? (
        <div className="flex items-center gap-3">
          <div className="flex-1 min-w-0">
            <h2 className="text-lg font-bold text-white truncate">{workoutName || "Unnamed Workout"}</h2>
            <p className="text-sm text-zinc-400">
              {new Date(workoutDate + "T12:00:00").toLocaleDateString("en-US", {
                weekday: "short",
                month: "short",
                day: "numeric",
                year: "numeric",
              })}
            </p>
          </div>
          <button
            type="button"
            onClick={() => setHeaderLocked(false)}
            className="p-2 rounded-lg text-zinc-400 hover:text-white hover:bg-zinc-800 transition-colors flex-shrink-0"
            aria-label="Edit name and date"
          >
            <Pencil className="w-4 h-4" />
          </button>
        </div>
      ) : (
        <>
          <div>
            <label className="block text-sm font-medium text-zinc-400 mb-1">
              Workout Name
            </label>
            <input
              type="text"
              value={workoutName}
              onChange={(e) => setWorkoutName(e.target.value)}
              placeholder="- -"
              className="w-full px-4 py-3 border border-zinc-700 rounded-lg bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 placeholder:text-zinc-600"
            />
          </div>

          <div>
            <label className="block text-sm font-medium text-zinc-400 mb-1">
              Date
            </label>
            <input
              type="date"
              value={workoutDate}
              onChange={(e) => setWorkoutDate(e.target.value)}
              className="w-full px-4 py-3 border border-zinc-700 rounded-lg bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 [color-scheme:dark]"
            />
          </div>
        </>
      )}

      {/* Exercises */}
      <div>
        <h3 className="text-sm font-semibold text-zinc-400 uppercase tracking-wider mb-3">
          Exercises
        </h3>

        {/* Added exercises */}
        {addedExercises.length > 0 && (
          <div className="space-y-2 mb-4">
            {addedExercises.map((item, exIdx) => (
              <div
                key={item.exercise.id}
                className="border border-zinc-800 rounded-lg bg-zinc-900 relative"
              >
                {/* Exercise header — compact with reorder */}
                <div className="flex items-center">
                  {/* Reorder buttons */}
                  {addedExercises.length > 1 && (
                    <div className="flex flex-col pl-1.5 -mr-1 flex-shrink-0">
                      <button
                        type="button"
                        onClick={() => handleMoveExercise(item.exercise.id, "up")}
                        disabled={exIdx === 0}
                        className="p-0.5 text-zinc-600 hover:text-zinc-300 disabled:opacity-20 disabled:hover:text-zinc-600 transition-colors"
                        aria-label="Move exercise up"
                      >
                        <ArrowUp className="w-3 h-3" />
                      </button>
                      <button
                        type="button"
                        onClick={() => handleMoveExercise(item.exercise.id, "down")}
                        disabled={exIdx === addedExercises.length - 1}
                        className="p-0.5 text-zinc-600 hover:text-zinc-300 disabled:opacity-20 disabled:hover:text-zinc-600 transition-colors"
                        aria-label="Move exercise down"
                      >
                        <ArrowDown className="w-3 h-3" />
                      </button>
                    </div>
                  )}

                  <button
                    type="button"
                    onClick={() =>
                      setExpandedExercise(
                        expandedExercise === item.exercise.id
                          ? null
                          : item.exercise.id
                      )
                    }
                    className="flex-1 flex items-center justify-between px-3 py-2.5 hover:bg-zinc-800/50 transition-colors rounded-lg min-w-0"
                  >
                    <div className="text-left flex-1 min-w-0">
                      <div className="flex items-baseline gap-2">
                        <h4 className="font-semibold text-white text-sm truncate">
                          {item.exercise.name}
                        </h4>
                        <span className="text-xs text-zinc-500 flex-shrink-0">
                          {item.sets.length} set{item.sets.length !== 1 ? "s" : ""}
                        </span>
                      </div>
                      {item.sets.some((s) => s.reps || s.weight) && (
                        <p className="text-xs text-zinc-400 mt-0.5 truncate">
                          {formatSetsSummary(item.sets)}
                        </p>
                      )}
                    </div>
                    {expandedExercise === item.exercise.id ? (
                      <ChevronUp className="w-4 h-4 text-zinc-500 flex-shrink-0 ml-2" />
                    ) : (
                      <ChevronDown className="w-4 h-4 text-zinc-500 flex-shrink-0 ml-2" />
                    )}
                  </button>

                  {/* History popup toggle */}
                  <button
                    type="button"
                    onClick={(e) => {
                      e.stopPropagation();
                      setHistoryPopupExercise(
                        historyPopupExercise === item.exercise.id ? null : item.exercise.id
                      );
                    }}
                    className="p-2 mr-1 rounded-md flex-shrink-0 transition-colors text-zinc-500 hover:text-zinc-200 hover:bg-zinc-800"
                    aria-label="View exercise history"
                    title="View history"
                  >
                    <Clock className="w-4 h-4" />
                  </button>
                </div>

                {/* Exercise history popup */}
                {historyPopupExercise === item.exercise.id && (
                  <ExerciseHistoryPopup
                    exerciseId={item.exercise.id}
                    onClose={() => setHistoryPopupExercise(null)}
                  />
                )}

                {/* Exercise body (expanded) */}
                {expandedExercise === item.exercise.id && (
                  <div className="border-t border-zinc-800 p-3 space-y-3">
                    <div className="space-y-2">
                      {item.sets.map((set, idx) => (
                        <SetRow
                          key={`${item.exercise.id}-${set.setNumber}`}
                          setNumber={set.setNumber}
                          inputFields={parseInputFields(item.exercise)}
                          weightUnit={(item.exercise as any).defaultWeightUnit || "lbs"}
                          initialReps={set.reps}
                          initialWeight={set.weight}
                          initialRpe={set.rpe}
                          initialDuration={set.durationSeconds}
                          initialDistance={set.distance}
                          initialCalories={set.calories}
                          initialCustomMetrics={set.customMetrics}
                          initialNotes={set.notes}
                          initialLocked={
                            set.forceEdit
                              ? false
                              : !!(
                                  set.reps ||
                                  set.weight ||
                                  set.durationSeconds ||
                                  set.distance ||
                                  set.calories ||
                                  (set.customMetrics &&
                                    Object.values(set.customMetrics).some((v) => v))
                                )
                          }
                          autoFocus={
                            set.forceEdit ||
                            (idx === item.sets.length - 1 &&
                              !set.reps &&
                              !set.weight &&
                              !set.durationSeconds &&
                              !set.distance &&
                              !set.calories)
                          }
                          onUpdate={(data) =>
                            handleUpdateSet(
                              item.exercise.id,
                              set.setNumber,
                              data
                            )
                          }
                          onConfirm={() => handleSetConfirmed(item.exercise.id, set.setNumber)}
                          onNextSet={(vals) => handleNextSet(item.exercise.id, vals)}
                          onDelete={() =>
                            handleRemoveSet(item.exercise.id, set.setNumber)
                          }
                        />
                      ))}
                    </div>

                    <div className="flex gap-2">
                      <button
                        type="button"
                        onClick={() => handleAddSet(item.exercise.id)}
                        className="flex-1 py-1.5 border border-dashed border-zinc-700 rounded-lg text-zinc-400 text-sm font-medium hover:text-white hover:border-zinc-600 transition-colors flex items-center justify-center gap-1.5"
                      >
                        <Plus className="w-3.5 h-3.5" />
                        Add Set
                      </button>

                      <button
                        type="button"
                        onClick={() => handleRemoveExercise(item.exercise.id)}
                        className="py-1.5 px-3 text-red-500 text-sm font-medium hover:bg-red-950/30 rounded-lg transition-colors flex items-center gap-1.5"
                      >
                        <Trash2 className="w-3.5 h-3.5" />
                        Remove
                      </button>
                    </div>
                  </div>
                )}
              </div>
            ))}
          </div>
        )}

        {/* Inline exercise search */}
        <ExercisePicker
          exercises={exercises}
          recentlyUsed={recentlyUsedExercises}
          onSelect={handleAddExercise}
          onExerciseCreated={handleExerciseCreated}
        />
      </div>

      {/* Post-workout: Notes, Duration, Calories, Difficulty */}
      <div className="space-y-3">
        <h3 className="text-sm font-semibold text-zinc-400 uppercase tracking-wider">
          Post-Workout
        </h3>

        {/* Notes — lockable */}
        <div>
          <div className="flex items-center justify-between mb-1">
            <label className="text-[10px] font-medium text-zinc-500">Notes</label>
            {notes && (
              <button
                type="button"
                onClick={notesLocked ? () => setNotesLocked(false) : handleNotesSave}
                className="text-[10px] text-zinc-500 hover:text-zinc-300 transition-colors"
              >
                {notesLocked ? "Edit" : "Save"}
              </button>
            )}
          </div>
          {notesLocked ? (
            <button
              type="button"
              onClick={() => setNotesLocked(false)}
              className="w-full text-left px-3 py-2 border border-zinc-700 rounded-md bg-zinc-900 text-sm text-zinc-300 hover:bg-zinc-800 transition-colors"
            >
              <p className="line-clamp-2">{notes}</p>
            </button>
          ) : (
            <textarea
              value={notes}
              onChange={(e) => setNotes(e.target.value)}
              placeholder="Type notes as you go..."
              className="w-full px-3 py-2 border border-zinc-700 rounded-md bg-zinc-800 text-sm text-white focus:outline-none focus:ring-2 focus:ring-white/20 placeholder:text-zinc-600 resize-none"
              rows={2}
            />
          )}
        </div>

        <div className="grid grid-cols-3 gap-3">
          {/* Duration */}
          <div>
            <div className="flex items-center gap-2 mb-1">
              <label className="text-[10px] font-medium text-zinc-500 whitespace-nowrap">Duration</label>
              {duration && (
                <button type="button" onClick={() => setDuration("")} className="text-[9px] text-zinc-600 hover:text-zinc-400">✕</button>
              )}
            </div>
            {duration ? (
              <input
                type="number"
                value={duration}
                onChange={(e) => setDuration(e.target.value)}
                placeholder="min"
                className="w-full px-2 py-1.5 border border-zinc-700 rounded-md text-sm bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 placeholder:text-zinc-600"
              />
            ) : (
              <button
                type="button"
                onClick={() => setDuration("45")}
                className="w-full py-1.5 border border-dashed border-zinc-700 rounded-md text-zinc-500 text-xs hover:text-white hover:border-zinc-600 transition-colors"
              >
                N/A
              </button>
            )}
          </div>

          {/* Calories */}
          <div>
            <div className="flex items-center gap-2 mb-1">
              <label className="text-[10px] font-medium text-zinc-500 whitespace-nowrap">Calories</label>
              {workoutCalories && (
                <button type="button" onClick={() => setWorkoutCalories("")} className="text-[9px] text-zinc-600 hover:text-zinc-400">✕</button>
              )}
            </div>
            {workoutCalories ? (
              <input
                type="number"
                value={workoutCalories}
                onChange={(e) => setWorkoutCalories(e.target.value)}
                placeholder="kcal"
                className="w-full px-2 py-1.5 border border-zinc-700 rounded-md text-sm bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20 placeholder:text-zinc-600"
              />
            ) : (
              <button
                type="button"
                onClick={() => setWorkoutCalories("300")}
                className="w-full py-1.5 border border-dashed border-zinc-700 rounded-md text-zinc-500 text-xs hover:text-white hover:border-zinc-600 transition-colors"
              >
                N/A
              </button>
            )}
          </div>

          {/* Difficulty */}
          <div>
            <div className="flex items-center gap-2 mb-1">
              <label className="text-[10px] font-medium text-zinc-500 whitespace-nowrap">Difficulty</label>
              {difficulty && (
                <button type="button" onClick={() => setDifficulty("")} className="text-[9px] text-zinc-600 hover:text-zinc-400">✕</button>
              )}
            </div>
            {difficulty ? (
              <select
                value={difficulty}
                onChange={(e) => setDifficulty(e.target.value)}
                className="w-full px-2 py-1.5 border border-zinc-700 rounded-md text-sm bg-zinc-800 text-white focus:outline-none focus:ring-2 focus:ring-white/20"
              >
                {Array.from({ length: 10 }, (_, i) => (
                  <option key={i + 1} value={String(i + 1)}>{i + 1}/10</option>
                ))}
              </select>
            ) : (
              <button
                type="button"
                onClick={() => setDifficulty("5")}
                className="w-full py-1.5 border border-dashed border-zinc-700 rounded-md text-zinc-500 text-xs hover:text-white hover:border-zinc-600 transition-colors"
              >
                N/A
              </button>
            )}
          </div>
        </div>
      </div>

      {/* Save and Close button */}
      <button
        type="submit"
        disabled={loading}
        className="w-full py-3 bg-white text-black font-semibold rounded-lg hover:bg-zinc-200 disabled:bg-zinc-700 disabled:text-zinc-500 disabled:cursor-not-allowed flex items-center justify-center gap-2 transition"
      >
        {loading ? (
          <>
            <Loader className="w-5 h-5 animate-spin" />
            Saving...
          </>
        ) : (
          <>
            <Save className="w-4 h-4" />
            Save and Close
          </>
        )}
      </button>
    </form>
  );
}
