// SCREEN — GALLERY · THE VISUAL RECORD
// An inspection & documentation tool, not a photo showcase. Capture-first,
// organized by Event, with Area coverage tracking and per-photo metadata.

// ── Photo-record routing helpers ──────────────────────────────────────
// Each photo is addressable via a URL hash: #p=<vehicleId>~<photoId>
function vrParsePhotoHash() {
  const m = /[#&]p=([^&]+)/.exec((typeof window !== 'undefined' && window.location.hash) || '');
  if (!m) return null;
  const parts = decodeURIComponent(m[1]).split('~');
  return { vid: parts[0], pid: parts[1] };
}
function vrPhotoHashFrag(vid, pid) { return '#p=' + encodeURIComponent(vid + '~' + pid); }
function vrPhotoHref(vid, pid) { return window.location.origin + window.location.pathname + vrPhotoHashFrag(vid, pid); }

// Build related photos: same event first, then same area across events.
function vrBuildRelated(events, photo) {
  const out = [];
  const seen = new Set([photo.id]);
  events.forEach(e => {
    if (e.photos.some(p => p.id === photo.id)) {
      e.photos.forEach(p => { if (!seen.has(p.id)) { seen.add(p.id); out.push(p); } });
    }
  });
  events.forEach(e => e.photos.forEach(p => {
    if (p.area === photo.area && !seen.has(p.id)) { seen.add(p.id); out.push(p); }
  }));
  return out.slice(0, 12);
}

function ScreenGallery({ vehicle = VEHICLE }) {
  const v = vehicle;
  const [events, setEvents] = React.useState(() => seedVisualRecord(v));
  const [view, setView] = React.useState('event');     // 'event' | 'area'
  const [expanded, setExpanded] = React.useState(null); // event id
  const [selectedArea, setSelectedArea] = React.useState(null);
  const [record, setRecord] = React.useState(null);     // { list, idx } — routed full-page record
  const [shareState, setShareState] = React.useState(null);
  const [capture, setCapture] = React.useState(false);
  const [captureTarget, setCaptureTarget] = React.useState(null); // existing event to append to
  const [toast, setToast] = React.useState(null);

  // Re-seed when switching vehicles.
  React.useEffect(() => {
    setEvents(seedVisualRecord(v));
    setExpanded(null); setSelectedArea(null); setRecord(null);
  }, [v.id]);

  // ── Record routing ──
  const openRecord = (list, idx, push = true) => {
    if (idx == null || idx < 0 || !list || !list[idx]) return;
    setRecord({ list, idx });
    if (push) window.history.pushState({ vrPhoto: list[idx].id }, '', vrPhotoHashFrag(v.id, list[idx].id));
  };
  const closeRecord = () => { window.history.back(); };
  const goNext = () => setRecord(r => {
    if (!r || r.idx >= r.list.length - 1) return r;
    const idx = r.idx + 1;
    window.history.replaceState({ vrPhoto: r.list[idx].id }, '', vrPhotoHashFrag(v.id, r.list[idx].id));
    return { ...r, idx };
  });
  const goPrev = () => setRecord(r => {
    if (!r || r.idx <= 0) return r;
    const idx = r.idx - 1;
    window.history.replaceState({ vrPhoto: r.list[idx].id }, '', vrPhotoHashFrag(v.id, r.list[idx].id));
    return { ...r, idx };
  });
  const jumpTo = (photo) => setRecord(r => {
    let list = r && r.list;
    let idx = list ? list.findIndex(p => p.id === photo.id) : -1;
    if (idx < 0) {
      const ev = events.find(e => e.photos.some(p => p.id === photo.id));
      if (!ev) return r;
      list = ev.photos; idx = ev.photos.findIndex(p => p.id === photo.id);
    }
    window.history.replaceState({ vrPhoto: list[idx].id }, '', vrPhotoHashFrag(v.id, list[idx].id));
    return { list, idx };
  });
  const shareRecord = async () => {
    if (!record) return;
    const href = vrPhotoHref(v.id, record.list[record.idx].id);
    try {
      if (navigator.share) { await navigator.share({ title: 'Photo record · ' + v.model, url: href }); }
      else if (navigator.clipboard) { await navigator.clipboard.writeText(href); }
    } catch (e) { /* user cancelled or blocked */ }
    setShareState('copied');
    setToast('Link copied');
    setTimeout(() => { setShareState(null); setToast(null); }, 2200);
  };

  // Cold-load deep link → open the record once events are seeded.
  React.useEffect(() => {
    const pending = window.__vrPendingPhoto;
    if (!pending) return;
    window.__vrPendingPhoto = null;
    const ev = events.find(e => e.photos.some(p => p.id === pending));
    if (ev) {
      const idx = ev.photos.findIndex(p => p.id === pending);
      window.history.replaceState({}, '', window.location.pathname); // clean base to return to
      openRecord(ev.photos, idx, true);
    }
  }, []); // eslint-disable-line

  // Browser back/forward syncs the open record to the URL.
  React.useEffect(() => {
    const onPop = () => {
      const r = vrParsePhotoHash();
      if (r && r.vid === v.id) {
        const ev = events.find(e => e.photos.some(p => p.id === r.pid));
        if (ev) { setRecord({ list: ev.photos, idx: ev.photos.findIndex(p => p.id === r.pid) }); return; }
      }
      setRecord(null);
    };
    window.addEventListener('popstate', onPop);
    return () => window.removeEventListener('popstate', onPop);
  }, [events, v.id]);

  const totalPhotos = events.reduce((s, e) => s + e.count, 0);
  const flagged = events.reduce((s, e) => s + (e.damageCount || 0), 0);
  const coverage = vrAreaCoverage(events);
  const documentedAreas = coverage.filter(a => a.count > 0).length;

  const openCapture = (targetEvent) => {
    setCaptureTarget(targetEvent || null);
    setCapture(true);
  };
  const closeCapture = () => { setCapture(false); setCaptureTarget(null); };

  const deletePhoto = (photo) => {
    setEvents(prev => prev.map(e => {
      if (!e.photos.some(p => p.id === photo.id)) return e;
      const photos = e.photos.filter(p => p.id !== photo.id);
      return { ...e, photos, count: Math.max(photos.length, e.count - 1) };
    }));
    setRecord(r => (r && r.list[r.idx] && r.list[r.idx].id === photo.id) ? null : r);
    setToast('Photo removed');
    setTimeout(() => setToast(null), 2200);
  };

  // Open a photo's full-page record from a given browsing list.
  const openPhoto = (photo, list) => {
    const arr = list || [photo];
    openRecord(arr, arr.findIndex(p => p.id === photo.id));
  };

  const onCapture = (files, eventType, area, targetId) => {
    const now = new Date();
    const dateStr = now.toLocaleDateString('en-US', { month: 'short', day: '2-digit', year: 'numeric' });
    const timeStr = now.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
    const newPhotos = files.map((f, i) => ({
      id: 'cap-' + Date.now() + '-' + i,
      area,
      src: URL.createObjectURL(f),
      time: `${dateStr} · ${timeStr}`,
      condition: 'Good',
      damage: area === 'Damage' ? 'Flagged on site — review required' : null,
      restoration: (eventType === 'Restoration' || eventType === 'Paint Work' || eventType === 'Mechanical Work' || eventType === 'Interior Restoration') ? eventType : null,
      photographer: 'You',
      odometer: v.mileage || 0,
      tags: [area, eventType],
      note: 'Captured on site',
      docs: 0,
      _new: true,
    }));

    let targetId2 = null;
    setEvents(prev => {
      // Append directly to a specific existing event.
      if (targetId) {
        targetId2 = targetId;
        return prev.map(e => e.id === targetId ? {
          ...e,
          photos: [...newPhotos, ...e.photos],
          count: e.count + newPhotos.length,
          areas: Array.from(new Set([area, ...e.areas])),
        } : e);
      }
      // Otherwise group into today's session of this event type, or start one.
      const idx = prev.findIndex(e => e.type === eventType && e.date === dateStr);
      if (idx >= 0) {
        const cp = [...prev];
        const ev = { ...cp[idx] };
        ev.photos = [...newPhotos, ...ev.photos];
        ev.count += newPhotos.length;
        ev.areas = Array.from(new Set([area, ...ev.areas]));
        cp[idx] = ev;
        targetId2 = ev.id;
        // float the active session to the top
        cp.splice(idx, 1);
        return [ev, ...cp];
      }
      const ev = {
        id: 'ev-' + Date.now(), type: eventType, date: dateStr, time: timeStr,
        photographer: 'You', note: 'On-site capture session — ' + area + '.',
        condition: 'Good', areas: [area], photos: newPhotos,
        count: newPhotos.length, damageCount: area === 'Damage' ? newPhotos.length : 0,
      };
      targetId2 = ev.id;
      return [ev, ...prev];
    });

    closeCapture();
    setView('event');
    setExpanded(targetId2);
    setToast(`${files.length} photo${files.length > 1 ? 's' : ''} added to ${eventType}`);
    setTimeout(() => setToast(null), 2600);
  };

  const Seg = ({ id, label }) => {
    const on = view === id;
    return (
      <button onClick={() => { setView(id); setSelectedArea(null); }} style={{
        flex: 1, padding: '10px 0', cursor: 'pointer', border: 'none',
        borderLeft: id === 'area' ? `1px solid ${P.slate}` : 'none',
        background: on ? P.paper : 'transparent', color: on ? P.ink : P.paper,
        fontFamily: T.mono, fontSize: 9.5, fontWeight: 600, letterSpacing: '0.16em',
        textTransform: 'uppercase',
      }}>{label}</button>
    );
  };

  const stage = (typeof document !== 'undefined') ? document.getElementById('proto-stage') : null;

  return (
    <div className="proto-screen" style={{ background: P.ink, color: P.paper }}>

      <ScreenIntro
        eyebrow="GALLERY · VISUAL RECORD"
        title="THE VISUAL RECORD"
        sub={`${totalPhotos} photos across ${events.length} documentation events. Capture, tag and retrieve condition photography on site.`}
      />

      {/* Summary */}
      <SpecStrip items={[
        { label: 'PHOTOS', value: totalPhotos },
        { label: 'EVENTS', value: events.length },
        { label: 'FLAGGED', value: flagged },
        { label: 'COVERAGE', value: `${documentedAreas}/${VR_AREAS.length}` },
      ]} />

      {/* Primary capture CTA */}
      <div style={{ padding: '18px 22px 14px' }}>
        <button onClick={() => openCapture(null)} style={{
          width: '100%', background: P.gold, border: 'none', cursor: 'pointer',
          padding: '16px 18px', display: 'flex', alignItems: 'center', gap: 14,
        }}>
          <div style={{
            width: 42, height: 42, borderRadius: 999, background: P.ink,
            display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
          }}>
            <Icon name="camera" size={22} color={P.gold} strokeWidth={1.7} />
          </div>
          <div style={{ textAlign: 'left' }}>
            <div style={{
              fontFamily: T.display, fontSize: 19, fontWeight: 700, color: P.ink,
              letterSpacing: '-0.01em', lineHeight: 1,
            }}>ADD PHOTOS</div>
            <div style={{
              fontFamily: T.mono, fontSize: 8.5, letterSpacing: '0.14em', textTransform: 'uppercase',
              color: 'rgba(10,10,11,0.62)', marginTop: 5,
            }}>CAMERA · LIBRARY · ON-SITE CAPTURE</div>
          </div>
        </button>
      </div>

      {/* View toggle */}
      <div style={{ padding: '0 22px 16px' }}>
        <div style={{ display: 'flex', border: `1px solid ${P.slate}` }}>
          <Seg id="event" label="By Event" />
          <Seg id="area" label="By Area" />
        </div>
      </div>

      {/* BY EVENT */}
      {view === 'event' && (
        <>
          <RowRule>DOCUMENTATION EVENTS · {events.length}</RowRule>
          <div style={{ padding: '14px 22px 8px' }}>
            {events.map(ev => (
              <VREventCard
                key={ev.id}
                event={ev}
                expanded={expanded === ev.id}
                onToggle={() => setExpanded(expanded === ev.id ? null : ev.id)}
                onOpenPhoto={openPhoto}
                onAddToEvent={openCapture}
                onDeletePhoto={deletePhoto}
              />
            ))}
          </div>
        </>
      )}

      {/* BY AREA */}
      {view === 'area' && !selectedArea && (
        <>
          <RowRule>AREA COVERAGE · {documentedAreas}/{VR_AREAS.length}</RowRule>
          <div style={{ padding: '14px 22px 8px', display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 8 }}>
            {coverage.map(a => {
              const has = a.count > 0;
              return (
                <button key={a.name} onClick={() => has && setSelectedArea(a.name)} style={{
                  textAlign: 'left', cursor: has ? 'pointer' : 'default',
                  background: P.graphite, border: 'none',
                  borderLeft: `2px solid ${has ? P.gold : P.slate}`,
                  padding: '14px 14px 13px', opacity: has ? 1 : 0.55,
                  display: 'flex', flexDirection: 'column', gap: 10, minHeight: 96,
                  justifyContent: 'space-between',
                }}>
                  <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
                    <Icon name={a.icon} size={20} color={has ? P.gold : P.mute} strokeWidth={1.5} />
                    <span style={{
                      fontFamily: T.mono, fontSize: 7.5, fontWeight: 700, letterSpacing: '0.1em',
                      textTransform: 'uppercase', padding: '3px 6px',
                      color: has ? P.ink : P.mute, background: has ? P.gold : 'transparent',
                      border: has ? 'none' : `1px solid ${P.slate}`,
                    }}>{has ? 'DOCUMENTED' : 'GAP'}</span>
                  </div>
                  <div>
                    <div style={{
                      fontFamily: T.display, fontSize: 14, fontWeight: 600, color: P.paper,
                      letterSpacing: '-0.005em', lineHeight: 1.1,
                    }}>{a.name}</div>
                    <div style={{
                      fontFamily: T.mono, fontSize: 8.5, letterSpacing: '0.12em', textTransform: 'uppercase',
                      color: P.mute, marginTop: 4,
                    }}>{has ? `${a.count} PHOTOS` : 'NOT CAPTURED'}</div>
                  </div>
                </button>
              );
            })}
          </div>
        </>
      )}

      {/* BY AREA — drill-in */}
      {view === 'area' && selectedArea && (() => {
        const a = coverage.find(x => x.name === selectedArea);
        return (
          <>
            <div style={{ padding: '0 22px 2px' }}>
              <button onClick={() => setSelectedArea(null)} style={{
                background: 'transparent', border: 'none', cursor: 'pointer', padding: '0 0 12px',
                display: 'flex', alignItems: 'center', gap: 7, color: P.gold,
                fontFamily: T.mono, fontSize: 9, fontWeight: 600, letterSpacing: '0.16em', textTransform: 'uppercase',
              }}>
                <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M19 12H5M5 12l6-6M5 12l6 6"/></svg>
                ALL AREAS
              </button>
            </div>
            <RowRule>{selectedArea.toUpperCase()} · {a.count}</RowRule>
            <div style={{ padding: '14px 22px 8px', display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 4 }}>
              {a.photos.map(p => (
                <VRPhotoTile key={p.id} photo={p} onOpen={(ph) => openPhoto(ph, a.photos)} showArea={false} />
              ))}
            </div>
          </>
        );
      })()}

      <div style={{ height: 24 }} />

      {/* Portaled overlays — anchored to the phone screen */}
      {stage && capture && ReactDOM.createPortal(
        <VRCaptureSheet vehicle={v} targetEvent={captureTarget} onClose={closeCapture} onCapture={onCapture} />, stage
      )}
      {stage && record && ReactDOM.createPortal(
        <VRPhotoRecord
          vehicle={v}
          photo={record.list[record.idx]}
          index={record.idx}
          total={record.list.length}
          related={vrBuildRelated(events, record.list[record.idx])}
          onPrev={goPrev}
          onNext={goNext}
          onClose={closeRecord}
          onShare={shareRecord}
          onJumpTo={jumpTo}
          onDelete={(ph) => { deletePhoto(ph); if (window.location.hash) window.history.back(); }}
          shareState={shareState}
        />, stage
      )}
      {stage && toast && ReactDOM.createPortal(
        <div style={{
          position: 'absolute', left: 22, right: 22, bottom: 44, zIndex: 100,
          background: P.paper, color: P.ink, padding: '12px 16px',
          display: 'flex', alignItems: 'center', gap: 10,
          animation: 'sheetIn .25s cubic-bezier(.2,.7,.3,1)',
          boxShadow: '0 18px 40px -12px rgba(0,0,0,0.6)',
        }}>
          <Icon name="camera" size={16} color={P.ink} strokeWidth={1.8} />
          <span style={{ fontFamily: T.mono, fontSize: 9.5, fontWeight: 600, letterSpacing: '0.1em', textTransform: 'uppercase' }}>{toast}</span>
        </div>, stage
      )}
    </div>
  );
}

Object.assign(window, { ScreenGallery });
