/* Dailies — Feedback Thread.
   The IC reviews feedback that's landed, as a DIRECT, multi-reviewer
   conversation: reviewers and the IC in a raw back-and-forth.
   Handles image (single) and video (sectioned) feedback.
   ============================================================ */

const { useState, useEffect, useRef, useCallback } = React;

const HOME_HREF = 'IC Home.html';

/* ---------- People ---------- */
const PEOPLE = {
  BR: { initials: 'BR', name: 'Brian Robbins', role: 'Co-Founder · CEO' },
  EP: { initials: 'EP', name: 'Eve Park', role: 'Creative Director' },
  MC: { initials: 'MC', name: 'Maya Chen', role: 'Lead Character Artist' }
};

/* ---------- Icons ---------- */
const BackChevron = ({ size = 16 }) =>
<svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M15 18l-6-6 6-6" /></svg>;

const Chevron = ({ size = 16 }) =>
<svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M6 9l6 6 6-6" /></svg>;

const PlayIcon = ({ size = 16 }) =>
<svg viewBox="0 0 24 24" width={size} height={size} fill="currentColor" stroke="none"><path d="M7 5l13 7-13 7V5z" /></svg>;

const MicIcon = ({ size = 18 }) =>
<svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="9" y="3" width="6" height="11" rx="3" /><path d="M5 11a7 7 0 0014 0M12 18v3" /></svg>;

const StopIcon = ({ size = 12 }) =>
<svg viewBox="0 0 24 24" width={size} height={size} fill="currentColor"><rect x="6" y="6" width="12" height="12" /></svg>;

const SendArrow = ({ size = 16 }) =>
<svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6" /></svg>;

const UploadIcon = ({ size = 13 }) =>
<svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M12 19V6M6 12l6-6 6 6" /></svg>;


/* ---------- Asset definitions (image + video) ---------- */
const ASSETS = {
  image: {
    name: 'Eloise · Pose v2',
    phase: 'Refinement',
    type: 'image',
    img: 'assets/eloise.jpg',
    landedAgo: 'Feedback landed · 12m ago',
    nextLabel: 'Pose v3',
    nextNote: 'Spun the silhouette, slid the pug back. Take a look.',
    versions: [
    { id: 'v1', name: 'Pose v1', when: 'Yesterday', img: null },
    { id: 'v2', name: 'Pose v2', when: 'This morning', img: 'assets/eloise.jpg', current: true, tag: 'Reviewed' }],

    feedback: {
      from: 'BR', time: '12m',
      headline: 'So close, Maya. Two small things.',
      prose: 'This is the closest we\u2019ve been to the book \u2014 the warmth is exactly right and I love where her face landed.',
      actions: [
      'Push the silhouette one more notch \u2014 I want her hair wilder, more attitude.',
      'The pug is pulling focus. Drop his eyeline so he\u2019s looking up at her, or slide him back six inches.',
      'Send me the radiator-angle version too whenever you get to it.']

    },
    note: { from: 'EP', time: '9m', text: 'Agreed on the pug. And don\u2019t touch that cream wash on the back wall \u2014 it\u2019s perfect.' },
    transcript: 'When you say wilder \u2014 do you mean more volume in the hair, or more movement?',
    clarify: [
    'Movement, not volume. Like she just spun around to look at you \u2014 the volume\u2019s already there.',
    'Keep the eyeline soft. She\u2019s curious, not startled.',
    'Honestly? Trust your gut on that one. You know Eloise better than any of us.'],

    onReact: { from: 'BR', text: 'Perfect. Ping me the second it\u2019s up and I\u2019ll turn it around fast.' },
    approve: [
    { from: 'BR', text: 'That\u2019s it. The spin reads, and the pug finally knows his place. This is the one.' },
    { from: 'EP', text: 'Gorgeous, Maya. Lock the pose and take it to ink.' }],

    approveSys: 'Brian approved · Eve approved'
  },
  video: {
    name: 'Bucket List · Ep 4 cold open',
    phase: 'Final review',
    type: 'video',
    mono: 'BLF', dur: '2:34',
    landedAgo: 'Feedback landed · 26m ago',
    nextLabel: 'Cut C',
    nextNote: 'Trimmed the dad\u2019s reaction a beat, warmed the bed. New cut attached.',
    versions: [
    { id: 'a', name: 'Cut A', when: 'Tuesday', dark: true },
    { id: 'b', name: 'Cut B', when: 'This morning', dark: true, current: true, tag: 'Reviewed' }],

    feedback: {
      from: 'BR', time: '26m',
      headline: 'The open works \u2014 it\u2019s all about timing now.',
      sections: [
      { tag: 'Early', prose: 'Strong open. Color pass is great \u2014 don\u2019t touch the grade.', actions: ['Hold the wide one extra frame before the cut in.'] },
      { tag: 'Mid', prose: 'This is where it drags. The dad\u2019s reaction shot runs a full count too long.', actions: ['Trim the dad reaction by a beat.', 'Tighten the bridge underneath it.'] },
      { tag: 'Late', prose: 'Landing\u2019s good but the bed feels generic in the last few seconds.', actions: ['Try a bed with more bottom end.'] }]

    },
    note: { from: 'EP', time: '20m', text: 'Same note on the mid. Everything else is locked for me.' },
    transcript: 'Which beat is dragging for you \u2014 the dad\u2019s reaction, or the wide before it?',
    clarify: [
    'The dad\u2019s reaction. Lose a full beat there and the whole thing sings.',
    'The grade is locked \u2014 just the timing. Don\u2019t overthink it.',
    'Cut it the way you\u2019d watch it. You\u2019ve got the instinct.'],

    onReact: { from: 'BR', text: 'Great. Re-cut it and drop it here \u2014 Eve and I are watching for it.' },
    approve: [
    { from: 'BR', text: 'Pacing\u2019s tight now. The cold open lands. Approved on my end.' },
    { from: 'EP', text: 'Bottom end on the bed is much better. Ship it.' }],

    approveSys: 'Brian approved · Eve approved'
  }
};

/* ---------- Asset visual (rail + mobile expand) ---------- */
function AssetVisual({ a }) {
  if (a.type === 'image') {
    return (
      <div className="rail-asset"><img src={a.img} alt={a.name} style={{ objectFit: "contain" }} /></div>);

  }
  return (
    <div className="rail-asset video">
      <div className="mono">{a.mono}</div>
      <div className="play"><PlayIcon size={20} /></div>
      <div className="vlabel"><span>Video</span><span>{a.dur}</span></div>
    </div>);

}

function VersionRow({ v, type }) {
  return (
    <div className={`ver-row ${v.current ? 'current' : ''}`}>
      {type === 'image' && v.img ?
      <div className="ver-thumb"><img src={v.img} alt={v.name} /></div> :
      <div className="ver-thumb dark"><span className="vm">{type === 'video' ? 'BLF' : 'ELO'}</span></div>}
      <div className="ver-info">
        <span className="vn">{v.name}</span>
        <span className="vw">{v.when}</span>
      </div>
      <span className="ver-tag">{v.current ? v.tag || 'Current' : v.tag || ''}</span>
    </div>);

}

function AssetPanel({ a, versions, secondReviewer }) {
  return (
    <>
      <div>
        <div className="rail-eb" style={{ marginBottom: 12 }}>The work</div>
        <AssetVisual a={a} />
        <div className="rail-name" style={{ marginTop: 14 }}>{a.name}</div>
        <div className="rail-meta">{a.phase} · {versions.length} versions</div>
      </div>

      <div>
        <div className="rail-eb" style={{ marginBottom: 12 }}>Versions</div>
        <div className="rail-versions">
          {versions.map((v) => <VersionRow key={v.id} v={v} type={a.type} />)}
        </div>
      </div>

      <div>
        <div className="rail-eb" style={{ marginBottom: 12 }}>In the room</div>
        <div className="rail-people">
          <Reviewer p={PEOPLE.BR} />
          {secondReviewer && <Reviewer p={PEOPLE.EP} />}
          <Reviewer p={PEOPLE.MC} you />
        </div>
      </div>
    </>);

}
function Reviewer({ p, you }) {
  return (
    <div className="rp-row">
      <div className="rp-av" style={you ? { background: 'var(--bsp-yellow)', color: 'var(--bsp-navy)', borderColor: 'var(--bsp-yellow)' } : null}>{p.initials}</div>
      <div className="rp-text"><span className="n">{p.name}{you ? ' (you)' : ''}</span><span className="r">{p.role}</span></div>
    </div>);

}

/* ---------- Messages ---------- */
function FeedbackBody({ fb }) {
  if (fb.sections) {
    return (
      <div className="fb-sections">
        {fb.sections.map((s, i) =>
        <div key={i} className="fb-sec">
            <div className="fb-sec-head"><span className="fb-sec-tag">{s.tag}</span><span className="fb-sec-rule"></span></div>
            <p className="fb-prose">{s.prose}</p>
            <ul className="fb-actions">
              {s.actions.map((a, j) =>
            <li key={j} className="fb-action"><span className="num">{String(j + 1).padStart(2, '0')}</span><span>{a}</span></li>
            )}
            </ul>
          </div>
        )}
      </div>);

  }
  return (
    <>
      {fb.prose && <p className="fb-prose">{fb.prose}</p>}
      <ul className="fb-actions">
        {fb.actions.map((a, i) =>
        <li key={i} className="fb-action"><span className="num">{String(i + 1).padStart(2, '0')}</span><span>{a}</span></li>
        )}
      </ul>
    </>);

}

function Message({ m, assetType }) {
  if (m.type === 'sys') {
    return (
      <div className={`sys ${m.gold ? 'gold' : ''}`}>
        <span className="line"></span><span className="txt">{m.text}</span><span className="line"></span>
      </div>);

  }
  if (m.type === 'typing') {
    const p = PEOPLE[m.from];
    return (
      <div className="line-msg">
        <div className="avatar">{p.initials}</div>
        <div className="msg-content">
          <div className="msg-head"><span className="who">{p.name}</span></div>
          <div className="typing"><span></span><span></span><span></span></div>
        </div>
      </div>);

  }

  const me = m.from === 'MC';
  const p = PEOPLE[m.from];
  return (
    <div className={`line-msg ${me ? 'me' : ''}`}>
      <div className={`avatar ${me ? 'me' : ''}`}>{p.initials}</div>
      <div className="msg-content">
        <div className="msg-head">
          <span className="who">{me ? 'You' : p.name}</span>
          {!me && <span className="role">{p.role}</span>}
          <span className="time">{m.time}</span>
        </div>

        {m.type === 'feedback' &&
        <div className="fbcard">
            <span className="fb-eb">Feedback · {assetType === 'video' ? 'by section' : 'on the asset'}</span>
            <div className="fb-headline">{m.fb.headline}</div>
            <FeedbackBody fb={m.fb} />
          </div>
        }
        {m.type === 'note' && <p className="msg-text">{m.text}</p>}
        {m.type === 'reply' && <div className="msg-text">{m.text}</div>}
        {m.type === 'reaction' && <span className="reaction"><span className="rdot"></span>{m.label}</span>}
        {m.type === 'version' &&
        <div className="vshare">
            {assetType === 'image' ?
          <div className="vs-thumb"><img src="assets/eloise.jpg" alt={m.name} /></div> :
          <div className="vs-thumb dark"><span className="vm">BLF</span></div>}
            <div className="vs-info">
              <div className="vs-eb">You shared a new version</div>
              <div className="vs-name">{m.name}</div>
              <div className="vs-note">{m.note}</div>
            </div>
          </div>
        }
      </div>
    </div>);

}

/* ---------- Waveform ---------- */
function Waveform() {
  const bars = Array.from({ length: 30 }, (_, i) => 0.3 + i * 47 % 70 / 100);
  return <div className="waveform" aria-hidden="true">{bars.map((s, i) => <span key={i} className="wave-bar" style={{ '--s': s, animationDelay: `${-(i % 7) * 0.12}s` }} />)}</div>;
}

function fmt(s) {const m = Math.floor(s / 60);return `${m}:${String(s % 60).padStart(2, '0')}`;}

/* ---------- Composer ---------- */
function Composer({ a, voice, wrapped, onReact, onSend, onVersion, versionShared }) {
  const [draft, setDraft] = useState('');
  const [rec, setRec] = useState(false);
  const [secs, setSecs] = useState(0);
  const taRef = useRef(null);

  useEffect(() => {
    if (!rec) return;
    const id = setInterval(() => setSecs((s) => s + 1), 1000);
    return () => clearInterval(id);
  }, [rec]);
  useEffect(() => {
    const t = taRef.current;if (!t) return;
    t.style.height = 'auto';t.style.height = Math.min(t.scrollHeight, 140) + 'px';
  }, [draft]);

  const toggleMic = () => {
    if (rec) {
      setRec(false);setSecs(0);
      setDraft((d) => (d ? d.replace(/\s+$/, '') + ' ' : '') + a.transcript);
    } else {setRec(true);}
  };
  const send = () => {
    const text = draft.trim();
    if (!text) return;
    setDraft('');setRec(false);setSecs(0);
    onSend(text);
  };

  const canSend = draft.trim().length > 0;

  return (
    <div className="composer">
      <div className="quick-row">
        <button className="qchip" onClick={() => onReact('On it')} disabled={wrapped}>On it</button>
        <button className="qchip" onClick={() => onReact('Got it — thank you')} disabled={wrapped}>Got it</button>
        <button className="qchip version" onClick={onVersion} disabled={wrapped || versionShared}>
          <UploadIcon size={13} /> Share {a.nextLabel}
        </button>
      </div>
      <div className="composer-inner" data-rec={rec}>
        {!rec &&
        <textarea
          ref={taRef} className="c-textarea" rows={1}
          placeholder={wrapped ? 'This round is wrapped.' : 'Reply, or ask them a question…'}
          value={draft} onChange={(e) => setDraft(e.target.value)} disabled={wrapped}
          onKeyDown={(e) => {if (e.key === 'Enter' && !e.shiftKey && canSend) {e.preventDefault();send();}}} />

        }
        {rec &&
        <div className="c-rec">
            <Waveform />
            <div className="c-rec-meta"><span className="rdot"></span><span className="rlbl">Listening</span><span className="rtime">{fmt(secs)}</span></div>
          </div>
        }
        <div className="c-actions">
          {voice &&
          <button className={`c-mic ${rec ? 'recording' : ''}`} onClick={toggleMic} disabled={wrapped} aria-label="Voice">
              {rec ? <StopIcon size={12} /> : <MicIcon size={18} />}
            </button>
          }
          <button
            className="c-send" onClick={send} disabled={!canSend} aria-label="Send"
            style={{
              border: '1px solid ' + (canSend ? '#FFD200' : 'rgba(255,255,255,0.1)'),
              background: canSend ? '#FFD200' : 'transparent',
              color: canSend ? '#1E2A33' : 'rgba(255,255,255,0.4)',
              cursor: canSend ? 'pointer' : 'not-allowed'
            }}>
            <SendArrow size={16} /></button>
        </div>
      </div>
    </div>);

}

/* ---------- Main thread ---------- */
function Thread({ assetType, secondReviewer, voice }) {
  const a = ASSETS[assetType];

  const seed = useCallback(() => {
    const msgs = [
    { type: 'sys', gold: true, text: a.landedAgo },
    { type: 'feedback', from: a.feedback.from, time: a.feedback.time, fb: a.feedback }];

    if (secondReviewer) msgs.push({ type: 'note', from: a.note.from, time: a.note.time, text: a.note.text });
    return msgs;
  }, [assetType, secondReviewer]);

  const [messages, setMessages] = useState(seed);
  const [versions, setVersions] = useState(a.versions);
  const [clarifyIdx, setClarifyIdx] = useState(0);
  const [versionShared, setVersionShared] = useState(false);
  const [wrapped, setWrapped] = useState(false);
  const [assetOpen, setAssetOpen] = useState(false);
  const scrollRef = useRef(null);

  // Reset when tweaks change asset/reviewer
  useEffect(() => {
    setMessages(seed());
    setVersions(ASSETS[assetType].versions);
    setClarifyIdx(0);setVersionShared(false);setWrapped(false);
  }, [assetType, secondReviewer]);

  useEffect(() => {
    const el = scrollRef.current;if (el) el.scrollTop = el.scrollHeight;
  }, [messages]);

  const push = (m) => setMessages((prev) => [...prev, m]);
  const reviewerSay = (from, text, delay = 1100, after) => {
    push({ type: 'typing', from });
    setTimeout(() => {
      setMessages((prev) => [...prev.filter((x) => x.type !== 'typing'), { type: 'note', from, time: 'now', text }]);
      if (after) setTimeout(after, 500);
    }, delay);
  };

  const handleReact = (label) => {
    if (wrapped) return;
    push({ type: 'reaction', from: 'MC', label, time: 'now' });
    reviewerSay(a.onReact.from, a.onReact.text);
  };

  const handleSend = (text) => {
    if (wrapped) return;
    push({ type: 'reply', from: 'MC', text, time: 'now' });
    const line = a.clarify[Math.min(clarifyIdx, a.clarify.length - 1)];
    setClarifyIdx((i) => i + 1);
    reviewerSay('BR', line);
  };

  const handleVersion = () => {
    if (wrapped || versionShared) return;
    setVersionShared(true);
    push({ type: 'sys', gold: true, text: 'Round 2 opened' });
    push({ type: 'version', from: 'MC', time: 'now', name: a.nextLabel, note: a.nextNote });
    // add to version history
    setVersions((prev) => prev.map((v) => ({ ...v, current: false, tag: v.tag === 'Reviewed' ? 'Reviewed' : '' })).
    concat([{ id: 'new', name: a.nextLabel, when: 'Just now', img: assetType === 'image' ? 'assets/eloise.jpg' : null, dark: assetType === 'video', current: true, tag: 'You · new' }]));
    // reviewers react in sequence
    setTimeout(() => {
      reviewerSay(a.approve[0].from, a.approve[0].text, 1300, () => {
        if (secondReviewer) {
          reviewerSay(a.approve[1].from, a.approve[1].text, 1200, () => {
            setMessages((prev) => [...prev, { type: 'sys', gold: true, text: a.approveSys }]);
            setWrapped(true);
          });
        } else {
          setMessages((prev) => [...prev, { type: 'sys', gold: true, text: 'Brian approved' }]);
          setWrapped(true);
        }
      });
    }, 700);
  };

  return (
    <div className="thread">
      {/* Header */}
      <div className="th-head">
        <a className="th-back" href={HOME_HREF} aria-label="Back to home"><BackChevron /></a>
        <div className="th-title">
          <div className="t-row">
            <span className="t-name">{a.name}</span>
            <span className="t-phase">{a.phase}</span>
          </div>
          <span className="t-sub">Feedback thread</span>
        </div>
        <SurfaceNav current="thread" role="ic"/>
        <div className="th-people">
          <div className="pavatar">{PEOPLE.BR.initials}</div>
          {secondReviewer && <div className="pavatar">{PEOPLE.EP.initials}</div>}
          <div className="pavatar me">{PEOPLE.MC.initials}</div>
        </div>
      </div>

      {/* Body */}
      <div className="th-body">
        {/* Asset rail (desktop) */}
        <div className="rail">
          <div className="rail-inner">
            <AssetPanel a={a} versions={versions} secondReviewer={secondReviewer} />
          </div>
        </div>

        {/* Conversation */}
        <div className="convo">
          {/* mobile asset strip */}
          <div className={`asset-strip ${assetOpen ? 'open' : ''}`} onClick={() => setAssetOpen((o) => !o)}>
            {assetType === 'image' ?
            <div className="as-thumb"><img src={a.img} alt={a.name} /></div> :
            <div className="as-thumb dark"><span className="vm">{a.mono}</span></div>}
            <div className="as-info">
              <div className="as-name">{a.name}</div>
              <div className="as-meta">{a.phase} · {versions.length} versions</div>
            </div>
            <span className="as-chev"><Chevron size={16} /></span>
          </div>
          <div className={`asset-expand ${assetOpen ? 'open' : ''}`}>
            <div className="asset-expand-inner">
              <AssetPanel a={a} versions={versions} secondReviewer={secondReviewer} />
            </div>
          </div>

          <div className="convo-scroll" ref={scrollRef}>
            {messages.map((m, i) => <Message key={i} m={m} assetType={assetType} />)}
          </div>

          <Composer
            a={a} voice={voice} wrapped={wrapped}
            versionShared={versionShared}
            onReact={handleReact} onSend={handleSend} onVersion={handleVersion} />
          
        </div>
      </div>
    </div>);

}

/* ---------- Tweaks wrapper ---------- */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "assetType": "image",
  "secondReviewer": true,
  "voice": true
} /*EDITMODE-END*/;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  return (
    <>
      <Thread assetType={t.assetType} secondReviewer={t.secondReviewer} voice={t.voice} />
      <TweaksPanel>
        <TweakSection label="Feedback" />
        <TweakRadio label="Asset type" value={t.assetType} options={['image', 'video']} onChange={(v) => setTweak('assetType', v)} />
        <TweakSection label="Conversation" />
        <TweakToggle label="Second reviewer (Eve)" value={t.secondReviewer} onChange={(v) => setTweak('secondReviewer', v)} />
        <TweakToggle label="Voice composer" value={t.voice} onChange={(v) => setTweak('voice', v)} />
      </TweaksPanel>
    </>);

}

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