/* Studio 76 Atelier — THE DRESSING ROOM (virtual stylist).
   Your photo → a full-length virtual model (identity-locked) → trend chips or your own
   words → styled looks, ONE at a time. Talks only to dressing.php (keys server-side). */

const STYLES = [
  'Quiet luxury', 'Old money', 'Power tailoring', 'Soft minimal', 'Streetwear',
  'Athleisure', 'Indo-western', 'Festive', 'After dark', 'Coastal linen',
  'Denim on denim', 'Monochrome', 'Colour pop', 'Vintage revival',
];

const MKEY = 's76_dr_model';

function downscale(file, max) {
  return new Promise((res, rej) => {
    const fr = new FileReader();
    fr.onerror = () => rej(new Error('Could not read that file.'));
    fr.onload = () => {
      const img = new Image();
      img.onload = () => {
        const s = Math.min(1, max / Math.max(img.width, img.height));
        const c = document.createElement('canvas');
        c.width = Math.round(img.width * s); c.height = Math.round(img.height * s);
        c.getContext('2d').drawImage(img, 0, 0, c.width, c.height);
        res(c.toDataURL('image/jpeg', 0.85));
      };
      img.onerror = () => rej(new Error('That does not look like an image.'));
      img.src = fr.result;
    };
    fr.readAsDataURL(file);
  });
}

async function api(action, payload) {
  const r = await fetch('dressing.php', {
    method: 'POST', headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(Object.assign({ action }, payload)),
  });
  const j = await r.json().catch(() => ({}));
  if (!r.ok) throw new Error(j.error || ('Server error ' + r.status));
  return j;
}

function LookCard({ look }) {
  if (!look) return null;
  return (
    <div className="dr-look">
      <h3 className="dr-look-name">{look.name}</h3>
      <ul className="dr-pieces">
        {(look.pieces || []).map((p, i) => (
          <li key={i}><b>{p.item}</b>{p.why ? <span> — {p.why}</span> : null}</li>
        ))}
      </ul>
      <div className="dr-meta">
        {look.palette ? <span><i>Palette</i>{look.palette}</span> : null}
        {look.shoes ? <span><i>Shoes</i>{look.shoes}</span> : null}
        {look.accents ? <span><i>Accents</i>{look.accents}</span> : null}
      </div>
      {look.note ? <p className="dr-note">{look.note}</p> : null}
    </div>
  );
}

function DressingRoom() {
  const [stage, setStage] = React.useState('capture');   // capture -> model -> room
  const [photo, setPhoto] = React.useState(null);
  const [model, setModel] = React.useState(null);        // {id, dataUrl}
  const [styles, setStyles] = React.useState([]);
  const [custom, setCustom] = React.useState('');
  const [closet, setCloset] = React.useState('');
  const [look, setLook] = React.useState(null);          // {look, dataUrl}
  const [seen, setSeen] = React.useState([]);
  const [tweak, setTweak] = React.useState('');
  const [busy, setBusy] = React.useState('');
  const [err, setErr] = React.useState('');
  const [saved, setSaved] = React.useState(null);
  const fileRef = React.useRef(null);
  const camRef = React.useRef(null);

  React.useEffect(() => {
    try {
      const m = JSON.parse(localStorage.getItem(MKEY) || 'null');
      if (m && m.dataUrl) { setModel(m); setStage('model'); }
    } catch (e) {}
  }, []);

  const fail = (e) => { setErr(e.message || String(e)); setBusy(''); };

  async function onFile(file) {
    if (!file) return;
    setErr('');
    try { setPhoto(await downscale(file, 1280)); } catch (e) { fail(e); }
  }

  async function makeModel() {
    if (!photo) return;
    setBusy('Sketching your model — 20 seconds or so…'); setErr('');
    try {
      const r = await api('model', { photo });
      const m = { id: r.id, dataUrl: r.dataUrl };
      setModel(m); setStage('model'); setBusy('');
      try { localStorage.setItem(MKEY, JSON.stringify(m)); } catch (e) {}
    } catch (e) { fail(e); }
  }

  async function dressMe(surprise) {
    if (!model) return;
    setBusy(surprise ? 'The stylist is choosing for you…' : 'Styling your look…'); setErr('');
    try {
      const r = await api('outfit', {
        model_id: model.id, model: model.dataUrl, styles, custom, closet,
        avoid: seen, surprise: !!surprise,
      });
      setLook(r); setStage('room'); setBusy(''); setTweak(''); setSaved(null);
      if (r.look && r.look.name) setSeen((s) => [...s.slice(-7), r.look.name]);
    } catch (e) { fail(e); }
  }

  async function doTweak() {
    if (!look || !tweak.trim()) return;
    setBusy('Adjusting…'); setErr('');
    try {
      const r = await api('refine', { image: look.dataUrl, instructions: tweak.trim(), aspect: '3:4' });
      setLook((l) => ({ ...l, dataUrl: r.dataUrl })); setBusy(''); setTweak('');
    } catch (e) { fail(e); }
  }

  async function saveLook() {
    if (!look) return;
    setBusy('Saving to your lookbook…'); setErr('');
    try {
      const s = await api('save_start', { spec: { garment_type: (look.look && look.look.name) || 'Styled look' } });
      await api('save_item', { setid: s.setid, key: 'look', label: (look.look && look.look.name) || 'The look', dataUrl: look.dataUrl });
      await api('save_item', { setid: s.setid, key: 'model', label: 'The model', dataUrl: model.dataUrl });
      setSaved(s.url); setBusy('');
    } catch (e) { fail(e); }
  }

  function retake() {
    setModel(null); setPhoto(null); setLook(null); setSeen([]); setStage('capture');
    try { localStorage.removeItem(MKEY); } catch (e) {}
  }

  const chip = (s) => (
    <button key={s} type="button"
      className={'dr-chip' + (styles.includes(s) ? ' on' : '')}
      onClick={() => setStyles((cur) => cur.includes(s) ? cur.filter((x) => x !== s) : [...cur, s].slice(-4))}>
      {s}
    </button>
  );

  return (
    <div className="bz">
      <header className="bz-head">
        <a className="bz-logo" href="/">Studio<span> 76</span></a>
        <div className="bz-headlinks">
          <a href="/atelier.html">The Atelier</a>
          <a href="/apparel.html">Apparel bench</a>
          <a href="/tryiton.html">Try it on</a>
        </div>
      </header>

      <p className="bz-eyebrow">The Dressing Room</p>
      <h1 className="dr-h1">Your stylist, <i>who has actually met you.</i></h1>
      <p className="dr-sub">One photo becomes your virtual model. Then the room dresses you: one considered look at a time, never a lineup.</p>

      {err ? <div className="dr-err">{err}</div> : null}
      {busy ? <div className="dr-busy"><span className="dr-spin" />{busy}</div> : null}

      {stage === 'capture' && (
        <div className="dr-grid">
          <div>
            <div className="bz-drop dz" onClick={() => fileRef.current && fileRef.current.click()}
              onDragOver={(e) => e.preventDefault()}
              onDrop={(e) => { e.preventDefault(); onFile(e.dataTransfer.files && e.dataTransfer.files[0]); }}>
              {photo
                ? <img className="dz-img" src={photo} alt="Your photo" />
                : <div className="dz-empty">
                    <p className="dz-t">Drop your photo here</p>
                    <p className="dz-s">or tap to choose · we keep nothing</p>
                  </div>}
            </div>
            <input ref={fileRef} type="file" accept="image/*" hidden onChange={(e) => onFile(e.target.files[0])} />
            <input ref={camRef} type="file" accept="image/*" capture="user" hidden onChange={(e) => onFile(e.target.files[0])} />
            <div className="dr-row">
              <button className="dr-btn ghost" type="button" onClick={() => camRef.current && camRef.current.click()}>Take a shot</button>
              <button className="dr-btn gold" type="button" disabled={!photo || !!busy} onClick={makeModel}>Create my model</button>
            </div>
          </div>
          <aside className="dr-guide">
            <p className="dr-guide-k">The ideal shot</p>
            <ul>
              <li>Full length — head to toe in frame</li>
              <li>Phone upright, a friend or a timer</li>
              <li>A plain wall, soft even light</li>
              <li>Arms relaxed, standing natural</li>
              <li>Fitted basics help the fit read true</li>
            </ul>
            <p className="dr-guide-s">Not full length? Use it anyway — the bench extends the frame and you can retake later.</p>
          </aside>
        </div>
      )}

      {stage === 'model' && model && (
        <div className="dr-grid">
          <figure className="dr-fig">
            <img src={model.dataUrl} alt="Your virtual model" />
            <figcaption>Your model · ready to be styled</figcaption>
          </figure>
          <div>
            <p className="dr-k">The style rail</p>
            <div className="dr-chips">{STYLES.map(chip)}</div>
            <p className="dr-k">In your words <span className="dr-opt">optional</span></p>
            <input className="dr-in" value={custom} maxLength={200} onChange={(e) => setCustom(e.target.value)}
              placeholder="date night but comfortable · a wedding in Jaipur · first day at a new job" />
            <p className="dr-k">Your closet <span className="dr-opt">optional</span></p>
            <textarea className="dr-in dr-ta" value={closet} maxLength={400} onChange={(e) => setCloset(e.target.value)}
              placeholder="pieces you own and love — a camel overcoat, white leather sneakers, that emerald kurta…" />
            <div className="dr-row">
              <button className="dr-btn gold" type="button" disabled={!!busy} onClick={() => dressMe(false)}>Dress me</button>
              <button className="dr-btn ghost" type="button" disabled={!!busy} onClick={() => dressMe(true)}>Surprise me</button>
              <button className="dr-btn bare" type="button" onClick={retake}>Retake photo</button>
            </div>
          </div>
        </div>
      )}

      {stage === 'room' && look && (
        <div className="dr-grid dr-room">
          <figure className="dr-fig">
            <img src={look.dataUrl} alt={(look.look && look.look.name) || 'Your look'} />
            <figcaption>{(look.look && look.look.name) || 'The look'}</figcaption>
          </figure>
          <div>
            <LookCard look={look.look} />
            <div className="dr-row">
              <button className="dr-btn gold" type="button" disabled={!!busy} onClick={() => dressMe(false)}>Another option</button>
              <button className="dr-btn ghost" type="button" disabled={!!busy} onClick={saveLook}>Save this look</button>
              <button className="dr-btn bare" type="button" disabled={!!busy} onClick={() => setStage('model')}>Change the brief</button>
            </div>
            <div className="dr-tweak">
              <input className="dr-in" value={tweak} maxLength={300} onChange={(e) => setTweak(e.target.value)}
                placeholder="make the trousers wide-leg · swap to gold accents · softer colours" />
              <button className="dr-btn ghost" type="button" disabled={!tweak.trim() || !!busy} onClick={doTweak}>Tweak it</button>
            </div>
            {saved ? <p className="dr-saved">Saved — <a href={saved}>your look, shareable</a></p> : null}
          </div>
        </div>
      )}
    </div>
  );
}

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