const { useState, useEffect, useRef, useContext, createContext } = React;

/* ------------------------------------------------------------------ */
/* API                                                                  */
/* ------------------------------------------------------------------ */
const BASE = '/api';

async function request(path, options = {}) {
  const res = await fetch(`${BASE}${path}`, {
    credentials: 'include',
    headers: options.body instanceof FormData ? undefined : { 'Content-Type': 'application/json' },
    ...options,
  });
  if (res.status === 401) {
    const err = new Error('unauthorized');
    err.unauthorized = true;
    throw err;
  }
  if (!res.ok) throw new Error(`API error ${res.status} on ${path}`);
  if (res.status === 204) return null;
  return res.json();
}

const api = {
  // Auth
  me: () => request('/auth/me'),
  login: (username, password) => request('/auth/login', { method: 'POST', body: JSON.stringify({ username, password }) }),
  logout: () => request('/auth/logout', { method: 'POST' }),

  // Projects
  getProjects: () => request('/projects'),
  getProject: (id) => request(`/projects/${id}`),
  createProject: (data) => request('/projects', { method: 'POST', body: JSON.stringify(data) }),
  updateProject: (id, data) => request(`/projects/${id}`, { method: 'PUT', body: JSON.stringify(data) }),
  deleteProject: (id) => request(`/projects/${id}`, { method: 'DELETE' }),
  getProjectSkills: (id) => request(`/projects/${id}/skills`),
  addProjectSkill: (id, skill_id) => request(`/projects/${id}/skills`, { method: 'POST', body: JSON.stringify({ skill_id }) }),
  removeProjectSkill: (id, linkId) => request(`/projects/${id}/skills/${linkId}`, { method: 'DELETE' }),

  // Trainings
  getTrainings: () => request('/trainings'),
  getTraining: (id) => request(`/trainings/${id}`),
  createTraining: (data) => request('/trainings', { method: 'POST', body: JSON.stringify(data) }),
  updateTraining: (id, data) => request(`/trainings/${id}`, { method: 'PUT', body: JSON.stringify(data) }),
  deleteTraining: (id) => request(`/trainings/${id}`, { method: 'DELETE' }),
  getTrainingSkills: (id) => request(`/trainings/${id}/skills`),
  addTrainingSkill: (id, skill_id) => request(`/trainings/${id}/skills`, { method: 'POST', body: JSON.stringify({ skill_id }) }),
  removeTrainingSkill: (id, linkId) => request(`/trainings/${id}/skills/${linkId}`, { method: 'DELETE' }),

  // Skills
  getSkills: () => request('/skills'),
  getSkill: (id) => request(`/skills/${id}`),
  createSkill: (data) => request('/skills', { method: 'POST', body: JSON.stringify(data) }),
  updateSkill: (id, data) => request(`/skills/${id}`, { method: 'PUT', body: JSON.stringify(data) }),
  deleteSkill: (id) => request(`/skills/${id}`, { method: 'DELETE' }),
  uploadSkillVideo: (id, file) => {
    const fd = new FormData();
    fd.append('video', file);
    return request(`/skills/${id}/video`, { method: 'POST', body: fd });
  },
  uploadSkillFrames: (id, blobs) => {
    const fd = new FormData();
    blobs.forEach((b, i) => fd.append('frames', b, `frame-${i}.jpg`));
    return request(`/skills/${id}/frames`, { method: 'POST', body: fd });
  },
  deleteSkillFrame: (id, frameId) => request(`/skills/${id}/frames/${frameId}`, { method: 'DELETE' }),
};

/* ------------------------------------------------------------------ */
/* Tiny hash router                                                    */
/* ------------------------------------------------------------------ */
function navigate(path) { window.location.hash = path; }

function useRoute() {
  const [hash, setHash] = useState(window.location.hash || '#/projects');
  useEffect(() => {
    const onChange = () => setHash(window.location.hash || '#/projects');
    window.addEventListener('hashchange', onChange);
    return () => window.removeEventListener('hashchange', onChange);
  }, []);
  const path = (hash.replace(/^#/, '') || '/projects');
  const parts = path.split('/').filter(Boolean);

  if (parts[0] === 'projects' && parts.length === 1) return { page: 'projectsList' };
  if (parts[0] === 'projects' && parts.length === 2) return { page: 'projectDetail', id: parts[1] };
  if (parts[0] === 'training' && parts.length === 1) return { page: 'trainingList' };
  if (parts[0] === 'training' && parts.length === 2) return { page: 'trainingDetail', id: parts[1] };
  if (parts[0] === 'skills' && parts.length === 1) return { page: 'skillsList' };
  if (parts[0] === 'skills' && parts[1] === 'new') return { page: 'skillForm' };
  if (parts[0] === 'skills' && parts.length === 3 && parts[2] === 'edit') return { page: 'skillForm', id: parts[1] };
  return { page: 'projectsList' };
}

/* ------------------------------------------------------------------ */
/* Auth context                                                        */
/* ------------------------------------------------------------------ */
const AuthContext = createContext({ authenticated: false, loading: true });

function AuthProvider({ children }) {
  const [authenticated, setAuthenticated] = useState(false);
  const [loading, setLoading] = useState(true);
  const [loginOpen, setLoginOpen] = useState(false);

  useEffect(() => {
    api.me().then((r) => setAuthenticated(r.authenticated)).finally(() => setLoading(false));
  }, []);

  const login = async (username, password) => {
    const r = await api.login(username, password);
    setAuthenticated(true);
    setLoginOpen(false);
    return r;
  };
  const logout = async () => {
    await api.logout();
    setAuthenticated(false);
  };

  return (
    <AuthContext.Provider value={{ authenticated, loading, login, logout, loginOpen, setLoginOpen }}>
      {children}
      {loginOpen && <LoginModal />}
    </AuthContext.Provider>
  );
}

function useAuth() { return useContext(AuthContext); }

function LoginModal() {
  const { login, setLoginOpen } = useAuth();
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const [busy, setBusy] = useState(false);

  const submit = async (e) => {
    e.preventDefault();
    setError('');
    setBusy(true);
    try {
      await login(username, password);
    } catch (err) {
      setError('Wrong username or password.');
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="modal-overlay" onClick={() => setLoginOpen(false)}>
      <div className="modal-sheet" onClick={(e) => e.stopPropagation()}>
        <button className="modal-close" onClick={() => setLoginOpen(false)}>✕</button>
        <h3>Log in to edit</h3>
        <form onSubmit={submit}>
          <div className="field">
            <label>Username</label>
            <input type="text" value={username} onChange={(e) => setUsername(e.target.value)} autoFocus />
          </div>
          <div className="field">
            <label>Password</label>
            <input type="password" value={password} onChange={(e) => setPassword(e.target.value)} />
          </div>
          {error && <div className="login-error">{error}</div>}
          <button className="login-submit" type="submit" disabled={busy}>
            {busy ? 'Logging in…' : 'Log in'}
          </button>
        </form>
        <div className="login-note">Anyone can view — logging in is only needed to add, edit, or delete.</div>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/* Shared components                                                   */
/* ------------------------------------------------------------------ */
function TabBar({ active }) {
  const { authenticated, loading, logout, setLoginOpen } = useAuth();
  const tabs = [
    { key: 'projects', label: 'Projects', path: '#/projects' },
    { key: 'training', label: 'Training', path: '#/training' },
    { key: 'skills', label: 'Skills', path: '#/skills' },
  ];
  return (
    <div className="tab-bar">
      <div className="tabs">
        {tabs.map((t) => (
          <button
            key={t.key}
            className={`tab ${active === t.key ? `active ${t.key}` : ''}`}
            onClick={() => navigate(t.path)}
          >
            {t.label}
          </button>
        ))}
      </div>
      {!loading && (
        <button
          className={`auth-btn ${authenticated ? 'logged-in' : ''}`}
          title={authenticated ? 'Log out' : 'Log in to edit'}
          onClick={() => (authenticated ? logout() : setLoginOpen(true))}
        >
          {authenticated ? '🔓' : '🔒'}
        </button>
      )}
    </div>
  );
}

function FloatingButton({ onClick, label = '+' }) {
  const { authenticated } = useAuth();
  if (!authenticated) return null;
  return (
    <button className="fab" onClick={onClick} aria-label="Add">{label}</button>
  );
}

const REVEAL = 112;

function SwipeListItem({ colorClass, onTap, onEdit, onDelete, children }) {
  const { authenticated } = useAuth();
  const [dragX, setDragX] = useState(0);
  const startX = useRef(null);
  const dragging = useRef(false);

  const onPointerDown = (e) => {
    if (!authenticated) return;
    startX.current = (e.touches ? e.touches[0].clientX : e.clientX);
    dragging.current = true;
  };
  const onPointerMove = (e) => {
    if (!dragging.current) return;
    const x = (e.touches ? e.touches[0].clientX : e.clientX);
    const delta = x - startX.current;
    const next = Math.min(0, Math.max(-REVEAL, dragX + delta));
    setDragX(next);
    startX.current = x;
  };
  const endDrag = () => {
    dragging.current = false;
    setDragX((x) => (x < -REVEAL / 2 ? -REVEAL : 0));
  };

  const handleTap = () => {
    if (dragX !== 0) { setDragX(0); return; }
    onTap && onTap();
  };

  return (
    <div className="swipe-row">
      {authenticated && (
        <div className="swipe-actions">
          {onEdit && <button className="edit" onClick={() => { setDragX(0); onEdit(); }}>✎</button>}
          {onDelete && <button className="delete" onClick={() => { setDragX(0); onDelete(); }}>🗑</button>}
        </div>
      )}
      <div
        className={`swipe-fg ${colorClass}`}
        style={{ transform: `translateX(${dragX}px)`, transition: dragging.current ? 'none' : 'transform 0.2s ease' }}
        onMouseDown={onPointerDown}
        onMouseMove={onPointerMove}
        onMouseUp={endDrag}
        onMouseLeave={() => dragging.current && endDrag()}
        onTouchStart={onPointerDown}
        onTouchMove={onPointerMove}
        onTouchEnd={endDrag}
        onClick={handleTap}
      >
        {children}
      </div>
    </div>
  );
}

function PhotoCycler({ frames = [] }) {
  const [index, setIndex] = useState(0);
  const startY = useRef(null);
  const accum = useRef(0);
  const STEP = 24;

  const onDown = (e) => { e.stopPropagation(); startY.current = e.touches ? e.touches[0].clientY : e.clientY; accum.current = 0; };
  const onMove = (e) => {
    if (startY.current === null || !frames.length) return;
    e.stopPropagation();
    const y = e.touches ? e.touches[0].clientY : e.clientY;
    const delta = y - startY.current;
    startY.current = y;
    accum.current += delta;
    if (Math.abs(accum.current) >= STEP) {
      const steps = Math.trunc(accum.current / STEP);
      setIndex((i) => (i - steps + frames.length * 100) % frames.length);
      accum.current = 0;
    }
  };
  const onUp = (e) => { e.stopPropagation(); startY.current = null; };

  return (
    <div className="skill-icon" onMouseDown={onDown} onMouseMove={onMove} onMouseUp={onUp} onMouseLeave={onUp}
      onTouchStart={onDown} onTouchMove={onMove} onTouchEnd={onUp}>
      {frames.length ? <img src={frames[index].image_path} alt="" draggable={false} /> : '🎤'}
    </div>
  );
}

function VideoModal({ skill, onClose }) {
  if (!skill) return null;
  return (
    <div className="video-overlay">
      <button className="video-close" onClick={onClose}>✕</button>
      {skill.video_path ? (
        <video src={skill.video_path} controls autoPlay playsInline />
      ) : (
        <div style={{ color: 'white', margin: 'auto', padding: 20, textAlign: 'center' }}>
          No video saved for "{skill.name}" yet.
        </div>
      )}
    </div>
  );
}

function SkillPickerModal({ existingIds = [], onPick, onClose }) {
  const [skills, setSkills] = useState([]);
  useEffect(() => { api.getSkills().then(setSkills); }, []);
  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal-sheet" onClick={(e) => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose}>✕</button>
        <h3>Add a skill</h3>
        {skills.length === 0 && <div className="empty-state">No skills yet — create one from the Skills tab first.</div>}
        {skills.map((s) => {
          const already = existingIds.includes(s.id);
          return (
            <div className="picker-row" key={s.id}>
              <div style={{ flex: 1 }}>
                <div className="name">{s.name}</div>
                <div className="meta">{[s.level, s.tags].filter(Boolean).join(' | ')}</div>
              </div>
              <button className="capture-btn" style={{ width: 'auto', padding: '8px 14px' }} disabled={already} onClick={() => onPick(s.id)}>
                {already ? 'Added' : 'Add'}
              </button>
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/* Pages                                                                */
/* ------------------------------------------------------------------ */
function ProjectsList() {
  const [projects, setProjects] = useState([]);
  const load = () => api.getProjects().then(setProjects);
  useEffect(() => { load(); }, []);

  const createNew = async () => {
    const p = await api.createProject({ name: 'New Project', song_name: '' });
    navigate(`#/projects/${p.id}`);
  };

  return (
    <div className="screen">
      <TabBar active="projects" />
      <div className="list">
        {projects.length === 0 && <div className="empty-state">No projects yet.</div>}
        {projects.map((p) => (
          <SwipeListItem key={p.id} colorClass="purple" onTap={() => navigate(`#/projects/${p.id}`)}
            onEdit={() => navigate(`#/projects/${p.id}`)}
            onDelete={async () => { await api.deleteProject(p.id); load(); }}>
            <div>
              <div className="title">{p.name || 'Project name'}</div>
              <div className="subtitle">{p.song_name || 'Song name'}</div>
            </div>
          </SwipeListItem>
        ))}
      </div>
      <FloatingButton onClick={createNew} />
    </div>
  );
}

function fmtDate(d) {
  if (!d) return 'Date';
  return new Date(d).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' });
}

function TrainingList() {
  const [trainings, setTrainings] = useState([]);
  const load = () => api.getTrainings().then(setTrainings);
  useEffect(() => { load(); }, []);

  const createNew = async () => {
    const t = await api.createTraining({ name: 'New Training', training_date: null });
    navigate(`#/training/${t.id}`);
  };

  return (
    <div className="screen">
      <TabBar active="training" />
      <div className="list">
        {trainings.length === 0 && <div className="empty-state">No training sessions yet.</div>}
        {trainings.map((t) => (
          <SwipeListItem key={t.id} colorClass="pink" onTap={() => navigate(`#/training/${t.id}`)}
            onEdit={() => navigate(`#/training/${t.id}`)}
            onDelete={async () => { await api.deleteTraining(t.id); load(); }}>
            <div>
              <div className="title">{t.name || 'Training name'}</div>
              <div className="subtitle">{fmtDate(t.training_date)}</div>
            </div>
          </SwipeListItem>
        ))}
      </div>
      <FloatingButton onClick={createNew} />
    </div>
  );
}

function SkillsList() {
  const [skills, setSkills] = useState([]);
  const [playing, setPlaying] = useState(null);
  const load = () => api.getSkills().then(setSkills);
  useEffect(() => { load(); }, []);

  return (
    <div className="screen">
      <TabBar active="skills" />
      <div className="list">
        {skills.length === 0 && <div className="empty-state">No skills yet.</div>}
        {skills.map((s) => (
          <SwipeListItem key={s.id} colorClass="purple skill-row-fg" onTap={() => setPlaying(s)}
            onEdit={() => navigate(`#/skills/${s.id}/edit`)}
            onDelete={async () => { await api.deleteSkill(s.id); load(); }}>
            <PhotoCycler frames={s.frames} />
            <div>
              <div className="title">{s.name || 'Name of skill'}</div>
              <div className="subtitle">{[s.level, s.tags].filter(Boolean).join(' | ') || 'Level | Tags'}</div>
            </div>
            <div className="skill-trailing">🎤</div>
          </SwipeListItem>
        ))}
      </div>
      <FloatingButton onClick={() => navigate('#/skills/new')} />
      <VideoModal skill={playing} onClose={() => setPlaying(null)} />
    </div>
  );
}

function ProjectDetail({ id }) {
  const { authenticated } = useAuth();
  const [project, setProject] = useState(null);
  const [links, setLinks] = useState([]);
  const [playing, setPlaying] = useState(null);
  const [picking, setPicking] = useState(false);

  const load = async () => {
    setProject(await api.getProject(id));
    setLinks(await api.getProjectSkills(id));
  };
  useEffect(() => { load(); }, [id]);

  const saveField = async (field, value) => {
    setProject((p) => ({ ...p, [field]: value }));
    await api.updateProject(id, { [field]: value });
  };
  const addSkill = async (skillId) => { await api.addProjectSkill(id, skillId); setPicking(false); load(); };
  const removeSkill = async (linkId) => { await api.removeProjectSkill(id, linkId); load(); };
  const deleteProject = async () => { await api.deleteProject(id); navigate('#/projects'); };

  if (!project) return null;

  return (
    <div className="screen">
      <div className="detail-header purple">
        <button className="back-btn" onClick={() => navigate('#/projects')}>←</button>
        <input className="header-input" value={project.name} placeholder="Project Name" readOnly={!authenticated}
          onChange={(e) => saveField('name', e.target.value)} />
        <input className="header-subinput" value={project.song_name || ''} placeholder="Song name" readOnly={!authenticated}
          onChange={(e) => saveField('song_name', e.target.value)} />
      </div>

      <div className="list">
        {links.length === 0 && <div className="empty-state">No skills added yet.</div>}
        {links.map((s) => (
          <SwipeListItem key={s.link_id} colorClass="purple skill-row-fg" onTap={() => setPlaying(s)}
            onDelete={() => removeSkill(s.link_id)}>
            <div className="skill-icon">🎤</div>
            <div>
              <div className="title">{s.name}</div>
              <div className="subtitle">{[s.level, s.tags].filter(Boolean).join(' | ')}</div>
            </div>
          </SwipeListItem>
        ))}
      </div>

      <FloatingButton onClick={() => setPicking(true)} />
      {authenticated && <button className="circle-delete" onClick={deleteProject}>✕</button>}

      <VideoModal skill={playing} onClose={() => setPlaying(null)} />
      {picking && <SkillPickerModal existingIds={links.map((l) => l.id)} onPick={addSkill} onClose={() => setPicking(false)} />}
    </div>
  );
}

function toInputDate(d) {
  if (!d) return '';
  return new Date(d).toISOString().slice(0, 10);
}

function TrainingDetail({ id }) {
  const { authenticated } = useAuth();
  const [training, setTraining] = useState(null);
  const [links, setLinks] = useState([]);
  const [playing, setPlaying] = useState(null);
  const [picking, setPicking] = useState(false);

  const load = async () => {
    setTraining(await api.getTraining(id));
    setLinks(await api.getTrainingSkills(id));
  };
  useEffect(() => { load(); }, [id]);

  const saveField = async (field, value) => {
    setTraining((t) => ({ ...t, [field]: value }));
    await api.updateTraining(id, { [field]: value });
  };
  const addSkill = async (skillId) => { await api.addTrainingSkill(id, skillId); setPicking(false); load(); };
  const removeSkill = async (linkId) => { await api.removeTrainingSkill(id, linkId); load(); };
  const deleteTraining = async () => { await api.deleteTraining(id); navigate('#/training'); };

  if (!training) return null;

  return (
    <div className="screen">
      <div className="detail-header pink">
        <button className="back-btn" onClick={() => navigate('#/training')}>←</button>
        <input className="header-input" value={training.name} placeholder="Training" readOnly={!authenticated}
          onChange={(e) => saveField('name', e.target.value)} />
        <input className="header-subinput" type="date" value={toInputDate(training.training_date)} readOnly={!authenticated}
          onChange={(e) => saveField('training_date', e.target.value)} />
      </div>

      <div className="list">
        {links.length === 0 && <div className="empty-state">No skills added yet.</div>}
        {links.map((s) => (
          <SwipeListItem key={s.link_id} colorClass="purple skill-row-fg" onTap={() => setPlaying(s)}
            onDelete={() => removeSkill(s.link_id)}>
            <div className="skill-icon">🎤</div>
            <div>
              <div className="title">{s.name}</div>
              <div className="subtitle">{[s.level, s.tags].filter(Boolean).join(' | ')}</div>
            </div>
          </SwipeListItem>
        ))}
      </div>

      <FloatingButton onClick={() => setPicking(true)} />
      {authenticated && <button className="circle-delete pink" onClick={deleteTraining}>✕</button>}

      <VideoModal skill={playing} onClose={() => setPlaying(null)} />
      {picking && <SkillPickerModal existingIds={links.map((l) => l.id)} onPick={addSkill} onClose={() => setPicking(false)} />}
    </div>
  );
}

function SkillForm({ id }) {
  const { authenticated, setLoginOpen } = useAuth();
  const [skillId, setSkillId] = useState(id || null);
  const [name, setName] = useState('');
  const [type, setType] = useState('');
  const [level, setLevel] = useState('Beginner');
  const [tags, setTags] = useState('');
  const [videoPath, setVideoPath] = useState(null);
  const [frames, setFrames] = useState([]);
  const [scrub, setScrub] = useState(0);
  const [duration, setDuration] = useState(0);
  const [uploading, setUploading] = useState(false);

  const videoRef = useRef(null);
  const canvasRef = useRef(null);

  useEffect(() => {
    if (!id) return;
    api.getSkill(id).then((s) => {
      setName(s.name || '');
      setType(s.type || '');
      setLevel(s.level || 'Beginner');
      setTags(s.tags || '');
      setVideoPath(s.video_path);
      setFrames(s.frames || []);
    });
  }, [id]);

  if (!authenticated) {
    return (
      <div className="screen">
        <div className="detail-header purple">
          <button className="back-btn" onClick={() => navigate('#/skills')}>←</button>
          <div style={{ marginTop: 30, fontSize: 20, fontWeight: 700 }}>Skill</div>
        </div>
        <div className="empty-state">
          Log in to add or edit skills.
          <div style={{ marginTop: 14 }}>
            <button className="login-submit" onClick={() => setLoginOpen(true)}>Log in</button>
          </div>
        </div>
      </div>
    );
  }

  const ensureSkillId = async () => {
    if (skillId) return skillId;
    const created = await api.createSkill({ name: name || 'New Skill', type, level, tags });
    setSkillId(created.id);
    return created.id;
  };

  const onVideoChosen = async (e) => {
    const file = e.target.files[0];
    if (!file) return;
    setUploading(true);
    const sid = await ensureSkillId();
    const updated = await api.uploadSkillVideo(sid, file);
    setVideoPath(updated.video_path);
    setUploading(false);
  };

  const onLoadedMeta = () => setDuration((videoRef.current && videoRef.current.duration) || 0);

  const onScrubChange = (e) => {
    const t = Number(e.target.value);
    setScrub(t);
    if (videoRef.current) videoRef.current.currentTime = t;
  };

  const captureFrame = async () => {
    const video = videoRef.current;
    const canvas = canvasRef.current;
    if (!video || !canvas) return;
    canvas.width = video.videoWidth || 300;
    canvas.height = video.videoHeight || 300;
    const ctx = canvas.getContext('2d');
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
    canvas.toBlob(async (blob) => {
      const sid = await ensureSkillId();
      const updated = await api.uploadSkillFrames(sid, [blob]);
      setFrames(updated.frames);
    }, 'image/jpeg', 0.85);
  };

  const removeFrame = async (frameId) => {
    const sid = await ensureSkillId();
    await api.deleteSkillFrame(sid, frameId);
    setFrames((f) => f.filter((fr) => fr.id !== frameId));
  };

  const save = async () => {
    const sid = await ensureSkillId();
    await api.updateSkill(sid, { name, type, level, tags });
    navigate('#/skills');
  };

  return (
    <div className="screen">
      <div className="detail-header purple">
        <button className="back-btn" onClick={() => navigate('#/skills')}>←</button>
        <button className="check-btn" onClick={save}>✓</button>
        <div style={{ marginTop: 30, fontSize: 20, fontWeight: 700 }}>Skill</div>
      </div>

      <div className="form-body">
        {!videoPath ? (
          <label className="upload-video-btn">
            <input type="file" accept="video/*" hidden onChange={onVideoChosen} />
            <span style={{ fontSize: 24 }}>＋</span>
            <span>{uploading ? 'Uploading…' : 'Upload video'}</span>
          </label>
        ) : (
          <React.Fragment>
            <video ref={videoRef} src={videoPath} onLoadedMetadata={onLoadedMeta}
              style={{ width: '100%', borderRadius: 12, marginBottom: 10, background: '#000' }} playsInline muted />
            <div className="scrubber-wrap">
              <input type="range" min={0} max={duration || 0} step={0.05} value={scrub} onChange={onScrubChange} />
            </div>
            <button className="capture-btn" onClick={captureFrame} style={{ marginBottom: 16 }}>
              Capture frame from this moment
            </button>
            <canvas ref={canvasRef} style={{ display: 'none' }} />
          </React.Fragment>
        )}

        <div className="photo-strip">
          {frames.map((f) => (
            <div className="photo-thumb" key={f.id}>
              <img src={f.image_path} alt="" />
              <button className="rm" onClick={() => removeFrame(f.id)}>✕</button>
            </div>
          ))}
        </div>

        <div className="field">
          <label>Name</label>
          <input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="Skill name" />
        </div>
        <div className="field">
          <label>Type</label>
          <input type="text" value={type} onChange={(e) => setType(e.target.value)} placeholder="e.g. Choreography, Vocal, Formation" />
        </div>
        <div className="field">
          <label>Level</label>
          <select value={level} onChange={(e) => setLevel(e.target.value)}>
            <option>Beginner</option>
            <option>Intermediate</option>
            <option>Advanced</option>
          </select>
        </div>
        <div className="field">
          <label>Tags</label>
          <input type="text" value={tags} onChange={(e) => setTags(e.target.value)} placeholder="comma, separated, tags" />
        </div>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/* App root                                                             */
/* ------------------------------------------------------------------ */
function App() {
  const route = useRoute();
  let page;
  if (route.page === 'projectsList') page = <ProjectsList />;
  else if (route.page === 'projectDetail') page = <ProjectDetail id={route.id} />;
  else if (route.page === 'trainingList') page = <TrainingList />;
  else if (route.page === 'trainingDetail') page = <TrainingDetail id={route.id} />;
  else if (route.page === 'skillsList') page = <SkillsList />;
  else if (route.page === 'skillForm') page = <SkillForm id={route.id} />;
  else page = <ProjectsList />;

  return (
    <AuthProvider>
      <div className="app-shell">{page}</div>
    </AuthProvider>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
