// editor.jsx — edit view: the copy, the hanging card, and the settings tray

const EP_ICONS = {
  linkedin: <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor" aria-hidden><path d="M20.45 20.45h-3.55v-5.57c0-1.33-.02-3.04-1.85-3.04-1.85 0-2.13 1.45-2.13 2.94v5.67H9.36V9h3.41v1.56h.05c.48-.9 1.64-1.85 3.37-1.85 3.6 0 4.27 2.37 4.27 5.46v6.28zM5.34 7.43A2.06 2.06 0 1 1 5.34 3.3a2.06 2.06 0 0 1 0 4.13zM7.12 20.45H3.56V9h3.56v11.45zM22.22 0H1.77C.79 0 0 .77 0 1.72v20.56C0 23.23.79 24 1.77 24h20.45C23.2 24 24 23.23 24 22.28V1.72C24 .77 23.2 0 22.22 0z"/></svg>,
  instagram: <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden><rect x="3" y="3" width="18" height="18" rx="5"/><circle cx="12" cy="12" r="4"/><circle cx="17.5" cy="6.5" r="1" fill="currentColor" stroke="none"/></svg>,
  download: <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>,
  video: <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden><rect x="3" y="5" width="14" height="14" rx="2"/><polygon points="17 9 22 6 22 18 17 15" fill="currentColor" stroke="none"/></svg>,
  copy: <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden><rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>,
  check: <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="3.2" strokeLinecap="round" strokeLinejoin="round" aria-hidden><polyline points="5 12.5 10 17.5 19 7"/></svg>,
};

// ---- Colour picker -------------------------------------------------------------------------
// iPhones and computers open a good colour picker of their own. Android's is a grid of eight
// fixed colours, so on Android the app shows its own: a colour square, a hue bar and a hex box.
const USE_OWN_PICKER = /Android/i.test(navigator.userAgent) || /[?&]picker=1/.test(location.search);

function hexToHsv(hex) {
  const m = /^#?([0-9a-f]{6})$/i.exec(hex || '') ; const n = m ? parseInt(m[1], 16) : 0xff3d81;
  const r = (n >> 16) / 255, g = ((n >> 8) & 255) / 255, b = (n & 255) / 255;
  const max = Math.max(r, g, b), d = max - Math.min(r, g, b);
  let h = 0;
  if (d) { h = max === r ? ((g - b) / d) % 6 : max === g ? (b - r) / d + 2 : (r - g) / d + 4; h = (h * 60 + 360) % 360; }
  return { h, s: max ? d / max : 0, v: max };
}
function hsvToHex({ h, s, v }) {
  const f = (n) => { const k = (n + h / 60) % 6; return v - v * s * Math.max(0, Math.min(k, 4 - k, 1)); };
  return '#' + [f(5), f(3), f(1)].map(x => Math.round(x * 255).toString(16).padStart(2, '0')).join('');
}

function ColorSheet({ title, value, onChange, onClose }) {
  const [hsv, setHsv] = React.useState(() => hexToHsv(value));
  const [text, setText] = React.useState(value);
  const apply = (next) => { setHsv(next); const hex = hsvToHex(next); setText(hex); onChange(hex); };
  // drag inside a box: reports where the finger is, as 0..1 across and down
  const drag = (fn) => (e) => {
    const el = e.currentTarget, move = (ev) => {
      const r = el.getBoundingClientRect();
      fn(Math.max(0, Math.min(1, (ev.clientX - r.left) / r.width)), Math.max(0, Math.min(1, (ev.clientY - r.top) / r.height)));
    };
    el.setPointerCapture(e.pointerId); move(e);
    const up = () => { el.removeEventListener('pointermove', move); el.removeEventListener('pointerup', up); el.removeEventListener('pointercancel', up); };
    el.addEventListener('pointermove', move); el.addEventListener('pointerup', up); el.addEventListener('pointercancel', up);
  };
  const hex = hsvToHex(hsv);
  return ReactDOM.createPortal(
    <div className="cp-veil" onClick={onClose}>
      <div className="cp" role="dialog" aria-modal="true" aria-label={title} onClick={e => e.stopPropagation()}>
        <div className="cp-head"><b>Colours</b><button className="cp-x" onClick={onClose} aria-label="Close">✕</button></div>
        <div className="cp-sv" style={{ background: `hsl(${hsv.h} 100% 50%)` }} onPointerDown={drag((x, y) => apply({ ...hsv, s: x, v: 1 - y }))}>
          <i style={{ left: hsv.s * 100 + '%', top: (1 - hsv.v) * 100 + '%', background: hex }}/>
        </div>
        <div className="cp-hue" onPointerDown={drag((x) => apply({ ...hsv, h: x * 359.9 }))}>
          <i style={{ left: hsv.h / 360 * 100 + '%', background: `hsl(${hsv.h} 100% 50%)` }}/>
        </div>
        <div className="cp-foot">
          <span className="cp-chip" style={{ background: hex }}/>
          <input className="cp-hex" value={text} maxLength={7} spellCheck="false" autoCapitalize="off" autoComplete="off" aria-label="Colour code"
            onChange={e => { const t = e.target.value.trim(); setText(t); const m = /^#?([0-9a-f]{6})$/i.exec(t); if (m) { const h = '#' + m[1].toLowerCase(); setHsv(hexToHsv(h)); onChange(h); } }}/>
          <button className="cp-done" onClick={onClose}>Done</button>
        </div>
      </div>
    </div>, document.body);
}

// The "+" swatch's control: the phone or computer's own picker, or ours on Android.
function PickInput({ label, value, onStart, onChange }) {
  const [open, setOpen] = React.useState(false);
  if (!USE_OWN_PICKER) return <input type="color" aria-label={label} value={value} onClick={onStart} onChange={e => onChange(e.target.value)}/>;
  return (<>
    <button type="button" className="cp-open" aria-label={label} onClick={(e) => { e.preventDefault(); onStart(); setOpen(true); }}/>
    {open && <ColorSheet title={label} value={value} onChange={onChange} onClose={() => setOpen(false)}/>}
  </>);
}


function Editor({ card, onUpdate, onPreview, onShare, onSideChange, busy, progress, link, publishing, onGetLink, missing, linkName, onLinkName, linkHint }) {
  const [tab, setTab] = React.useState('style'); // 'style' | 'share'
  // Phones: the how-to text is shown once as a pop-up before the first edit, instead of under the badge.
  const [intro, setIntro] = React.useState(() => {
    try { return window.matchMedia('(max-width: 760px)').matches && !localStorage.getItem('tinyyou_intro_seen'); } catch (e) { return false; }
  });
  const closeIntro = () => { try { localStorage.setItem('tinyyou_intro_seen', '1'); } catch (e) {} setIntro(false); };
  const [open, setOpen] = React.useState(false);   // phones only: is the settings sheet pulled up?
  const [side, setSide] = React.useState(0);       // 0 = work, 1 = kid — the tray and the card stay in step
  const theme = getTheme(card);
  // The two colour settings apply to whichever side is selected; the childhood side keeps its own.
  const sc = sideColours(card, side);
  const sideTheme = getTheme(card, side);
  const K = side === 1 ? { bg: 'kidCardBg', bgC: 'kidCardBgCustom', th: 'kidTheme', thC: 'kidThemeCustom' } : { bg: 'cardBg', bgC: 'cardBgCustom', th: 'theme', thC: 'themeCustom' };
  const office = getAura('pro', card.auraPro, card.auraProCustom);
  const aura = getAura('kid', card.auraKid, card.auraKidCustom);
  const set = (patch) => onUpdate({ ...card, ...patch });
  const locked = missing.length > 0;
  // Flip to the side that holds the missing thing and put the cursor in it.
  const goTo = (m) => {
    setOpen(false);
    setSide(m.side);
    setTimeout(() => {
      const el = document.querySelector(`.stage-card [data-field="${m.key}"]`)
        || document.querySelector(`.stage-card ${m.side === 0 ? '.photo-frame' : '.kid-photo'} .upload-btn`);
      if (el) { el.scrollIntoView({ block: 'center', behavior: 'smooth' }); el.focus({ preventScroll: true }); }
    }, 760);
  };

  return (
    <div className="stage-layout is-edit">
      {intro && (
        <div className="modal-veil" onClick={closeIntro}>
          <div className="modal intro" role="dialog" aria-modal="true" aria-labelledby="intro-title" onClick={e => e.stopPropagation()}>
            <h2 id="intro-title">Make your badge</h2>
            <ul>
              <li>Tap any field or photo on the badge to edit it.</li>
              <li>Drag a photo to frame your face.</li>
              <li>Flip the badge to meet little you.</li>
              <li>Hit <b>Preview</b> to see it swing.</li>
            </ul>
            <button className="tray-preview" autoFocus onClick={closeIntro}>Got it</button>
          </div>
        </div>
      )}
      <div className="stage-copy">
        <div className="eyebrow">✎ make your work id — saves as you type</div>
        <h1>A badge that says <em>who</em> you are.</h1>
        <p>
          Click any field or photo to edit. Drag the photo to frame your face. Flip it to meet little you, then hit <b>Preview</b> to see it swing.
        </p>
      </div>

      <div className="stage-card">
        <Card card={card} editing={true} onUpdate={onUpdate} large side={side} onFlip={() => setSide(s => 1 - s)} onSideChange={onSideChange}/>
      </div>

      <aside className={"tray " + (open ? 'is-open' : 'is-collapsed')}>
        <button className="tray-handle" onClick={() => setOpen(o => !o)} aria-expanded={open} aria-label={open ? 'Hide settings' : 'Show settings'}><i/></button>
        <div className="seg" role="tablist">
          <button role="tab" aria-selected={tab === 'style'} className={tab === 'style' ? 'on' : ''} onClick={() => { setOpen(o => tab === 'style' ? !o : true); setTab('style'); }}>Style</button>
          <button role="tab" aria-selected={tab === 'share'} className={tab === 'share' ? 'on' : ''} onClick={() => { setOpen(o => tab === 'share' ? !o : true); setTab('share'); }}>Save &amp; share</button>
        </div>
        <div className="tray-scroll">

        {tab === 'style' && (
          <React.Fragment>
            <section className="tray-sec">
              <div className="tray-row"><h3>Side</h3><span className="tray-val">Flips the card</span></div>
              <div className="seg small">
                <button className={side === 0 ? 'on' : ''} onClick={() => setSide(0)}>Professional</button>
                <button className={side === 1 ? 'on' : ''} onClick={() => setSide(1)}>Childhood</button>
              </div>
            </section>

            <section className="tray-sec">
              <div className="tray-row"><h3>Card background</h3><span className="tray-val">{getCardBg(sc).label}</span></div>
              <div className="swatches">
                {CARD_BGS.map(b => (
                  <button key={b.id} className={"sw " + (getCardBg(sc).id === b.id ? 'on' : '')} style={{ '--c': b.hex || getTheme(sc.theme === 'custom' ? { theme: 'custom', themeCustom: sc.themeCustom } : sc.theme).bg }}
                    onClick={() => set({ [K.bg]: b.id })} title={b.label} aria-label={b.label} aria-pressed={getCardBg(sc).id === b.id}/>
                ))}
                <label className={"sw custom solid " + (sc.cardBg === 'custom' ? 'on' : '')} style={sc.cardBg === 'custom' ? { '--c': sc.cardBgCustom } : null} title="Pick your own card background">
                  <span aria-hidden="true">+</span>
                  <PickInput label="Pick your own card background" value={sc.cardBgCustom || '#ffe9c7'} onStart={() => set({ [K.bg]: 'custom', [K.bgC]: sc.cardBgCustom || '#ffe9c7' })} onChange={v => set({ [K.bg]: 'custom', [K.bgC]: v })}/>
                </label>
              </div>
              <p className="tray-tip">{side === 1 ? 'Colours the childhood side only. It copies the professional side until you pick something here. The strap has its own colour, under Professional.' : 'Colours the professional side. The childhood side has its own, under Childhood.'}</p>
            </section>

            <section className="tray-sec">
              <div className="tray-row"><h3>Text colour</h3><span className="tray-val">{sideTheme.label}</span></div>
              <div className="swatches">
                {CARD_THEMES.map(t => (
                  <button key={t.id} className={"sw " + (sc.theme === t.id ? 'on' : '')} style={{ '--c': t.accent }}
                    onClick={() => set({ [K.th]: t.id })} title={t.label} aria-label={t.label} aria-pressed={sc.theme === t.id}/>
                ))}
                <label className={"sw custom solid " + (sc.theme === 'custom' ? 'on' : '')} style={sc.theme === 'custom' ? { '--c': sc.themeCustom } : null} title="Pick your own text colour">
                  <span aria-hidden="true">+</span>
                  <PickInput label="Pick your own text colour" value={sc.themeCustom || '#ff3d81'} onStart={() => set({ [K.th]: 'custom', [K.thC]: sc.themeCustom || '#ff3d81' })} onChange={v => set({ [K.th]: 'custom', [K.thC]: v })}/>
                </label>
              </div>
            </section>

            {side === 0 && (
              <section className="tray-sec">
                <div className="tray-row"><h3>Strap colour</h3><span className="tray-val">{card.strapTheme === 'custom' ? 'My own' : card.strapTheme ? (CARD_THEMES.find(t => t.id === card.strapTheme) || {}).label : 'Same as text'}</span></div>
                <div className="swatches">
                  {CARD_THEMES.map(t => (
                    <button key={t.id} className={"sw " + (card.strapTheme === t.id ? 'on' : '')} style={{ '--c': t.accent }}
                      onClick={() => set({ strapTheme: t.id })} title={t.label} aria-label={t.label + ' strap'} aria-pressed={card.strapTheme === t.id}/>
                  ))}
                  <label className={"sw custom solid " + (card.strapTheme === 'custom' ? 'on' : '')} style={card.strapTheme === 'custom' ? { '--c': card.strapCustom } : null} title="Pick your own strap colour">
                    <span aria-hidden="true">+</span>
                    <PickInput label="Pick your own strap colour" value={card.strapCustom || getStrap(card)} onStart={() => set({ strapTheme: 'custom', strapCustom: card.strapCustom || getStrap(card) })} onChange={v => set({ strapTheme: 'custom', strapCustom: v })}/>
                  </label>
                </div>
                <p className="tray-tip">One strap for both sides. It matches the text colour until you pick one here.</p>
              </section>
            )}

            {side === 0 && (
              <section className="tray-sec">
                <div className="tray-row"><h3>Page background</h3><span className="tray-val">{office.label}</span></div>
                <div className="swatches">
                  {AURA_PRESETS.pro.map(a => (
                    <button key={a.id} className={"sw " + (card.auraPro === a.id ? 'on' : '')} style={{ '--c': a.color }}
                      onClick={() => set({ auraPro: a.id })} title={a.label} aria-label={a.label} aria-pressed={card.auraPro === a.id}/>
                  ))}
                <label className={"sw custom solid " + (card.auraPro === 'custom' ? 'on' : '')} style={card.auraPro === 'custom' ? { '--c': card.auraProCustom } : null} title="Pick your own background colour">
                  <span aria-hidden="true">+</span>
                  <PickInput label="Pick your own background colour" value={card.auraProCustom || '#3b6ea5'} onStart={() => set({ auraPro: 'custom', auraProCustom: card.auraProCustom || '#3b6ea5' })} onChange={v => set({ auraPro: 'custom', auraProCustom: v })}/>
                </label>
                </div>
                <p className="tray-tip">A solid office colour sits behind the professional side. Use + to pick your own.</p>
              </section>
            )}

            {side === 1 && (
              <section className="tray-sec">
                <div className="tray-row"><h3>Aura</h3><span className="tray-val">{aura.label}</span></div>
                <div className="swatches">
                  {AURA_PRESETS.kid.map(a => (
                    <button key={a.id} className={"sw aura " + (card.auraKid === a.id ? 'on' : '')}
                      style={{ '--a': a.colors[0], '--b': a.colors[1], '--c2': a.colors[2] }}
                      onClick={() => set({ auraKid: a.id })} title={a.label} aria-label={a.label} aria-pressed={card.auraKid === a.id}/>
                  ))}
                  <label className={"sw aura custom " + (card.auraKid === 'custom' ? 'on' : '')}
                    style={card.auraKid === 'custom' ? { '--a': aura.colors[0], '--b': aura.colors[1], '--c2': aura.colors[2] } : null}
                    title="Pick your own colour">
                    <span aria-hidden="true">+</span>
                    <PickInput label="Pick your own aura colour" value={card.auraKidCustom || '#ff5fd2'} onStart={() => set({ auraKid: 'custom', auraKidCustom: card.auraKidCustom || '#ff5fd2' })} onChange={v => set({ auraKid: 'custom', auraKidCustom: v })}/>
                  </label>
                </div>
                <p className="tray-tip">Choose the aura that truly represents your childhood and your inner self. It fills the page background and moves like northern lights whenever your childhood side is showing. Use + to pick your own.</p>
              </section>
            )}
          </React.Fragment>
        )}

        {tab === 'share' && locked && (
          <section className="tray-sec">
            <div className="tray-row"><h3>Almost there</h3><span className="tray-val">{missing.length} to go</span></div>
            <p className="tray-tip" style={{ marginTop: 0, marginBottom: 10 }}>Fill these in and you can save and share your badge. Tap one to jump to it.</p>
            <div className="rows">
              {missing.map(m => (
                <button key={m.key} className="row-btn todo" onClick={() => goTo(m)}><i aria-hidden="true"/><span>Add {m.label}</span><em>{m.side === 0 ? 'Professional' : 'Childhood'}</em></button>
              ))}
            </div>
          </section>
        )}

        {tab === 'share' && !locked && (
          <React.Fragment>
            <section className="tray-sec">
              <div className="tray-row"><h3>Download</h3></div>
              <div className="rows">
                <button className="row-btn" disabled={!!busy} onClick={() => onShare('download')}>{EP_ICONS.download}<span>{busy === 'png' ? 'Saving…' : 'PNG, front and back'}</span><em>For posting</em></button>
                <button className="row-btn" disabled={!!busy} onClick={() => onShare('print')}>{EP_ICONS.download}<span>{busy === 'print' ? 'Saving…' : 'Download PDF to print'}</span><em>CMYK</em></button>
                <button className="row-btn" disabled={!!busy} onClick={() => onShare('video')}>{EP_ICONS.video}<span>{busy === 'video' ? `Recording ${progress}%` : 'Video of the flip'}</span><em>6 sec</em></button>
              </div>
            </section>
            <section className="tray-sec">
              <div className="tray-row"><h3>Your link</h3><span className="tray-val">{link.link ? (link.upToDate ? 'Up to date' : 'Changes not published') : ''}</span></div>
              <label className="link-name">
                <span>{location.host + location.pathname.replace(/index\.html$/, '')}#/c/</span>
                <input value={linkName} onChange={e => onLinkName(e.target.value)} placeholder={linkHint} maxLength={24} spellCheck={false} autoCapitalize="none" autoCorrect="off" aria-label="Name for your link"/>
              </label>
              {linkName && !wantedLinkName({ linkName }) && <p className="tray-tip link-warn">Use at least 3 letters or numbers.</p>}
              {link.link && <input className="link-box" readOnly value={link.link} onFocus={e => e.target.select()} aria-label="Your badge link"/>}
              <button className="row-btn strong" disabled={publishing} onClick={onGetLink}>
                {EP_ICONS.copy}<span>{publishing ? 'Saving…' : link.upToDate ? 'Copy link' : link.link ? 'Update link' : 'Create my link'}</span>
              </button>
              <p className="tray-tip">Pick a name for your link. Leave it blank and a new link uses your first name if it’s free. Anyone with the link can open your badge, flip it and swing it. They can’t edit or download it. Your photos are uploaded when you create the link.</p>
            </section>
            <section className="tray-sec">
              <div className="tray-row"><h3>Share</h3></div>
              <div className="rows">
                <button className="row-btn" disabled={!!busy} onClick={() => onShare('linkedin')}>{EP_ICONS.linkedin}<span>LinkedIn</span></button>
                <button className="row-btn" disabled={!!busy} onClick={() => onShare('instagram')}>{EP_ICONS.instagram}<span>Instagram</span></button>
                <button className="row-btn" onClick={() => onShare('copylink')}>{EP_ICONS.copy}<span>Copy caption</span></button>
              </div>
              <p className="tray-tip">On a phone this opens the share sheet. On a computer the files are saved and the post screen opens for you to attach them.</p>
            </section>
          </React.Fragment>
        )}

        <button className="tray-preview" onClick={onPreview}>Preview</button>
        </div>
      </aside>
    </div>
  );
}

Object.assign(window, { Editor });
