/* ============================================================
   create-550.jsx — 상품배너 550 사용자 화면 (스키마 구동 · 프로토타입 포팅)
   · 사용자화면-자동생성.html(user-generator)의 컨트롤 + 라이브 550 프리뷰 + 활성 노드를
     merged 사용자 영역으로 이식. 전역명은 S5* 로 격리, CSS는 .s550 스코프(merged/s550.css).
   · 레이아웃 선택은 부모(Schema550Create의 라디오)가 가지고, layout/layoutSub 를 prop 으로 받는다.
   · NukkiCreate 의 "상품 다장 → 자동 배치(행 구성)"는 프리뷰 안에 흡수.
   ============================================================ */
const { useState: u5, useRef: r5, useEffect: ef5 } = React;
function s5rows(n){ if(n<=0)return[2,4,4]; const r=[]; let left=n; const top=Math.min(2,left); r.push(top); left-=top; while(left>0){ const t=Math.min(4,left); r.push(t); left-=t; } return r; }

function S5Badge({ kind, children }) { return <span className={`bdg ${kind}`}>{children}</span>; }
function S5MethodBadge({ method, min, max }) {
  if (!method) return null;
  const map = { one: '택1', multi: `다중${max ? ' ' + max : ''}`, count: `개수 ${min}~${max}`, fill: '고정' };
  return <S5Badge kind="m">{map[method] || method}</S5Badge>;
}
function S5InputBadge({ input }) {
  if (!input || input === 'none' || input === 'choice') return null;
  const map = { image: ['이미지', 'img'], text: ['텍스트', 'txt'], color: ['색상', 'col'] };
  const [t, c] = map[input] || [input, ''];
  return <S5Badge kind={`in ${c}`}>{t}</S5Badge>;
}
function S5Chip({ on, onClick, label, sub, multi }) {
  return (
    <button className={`chip ${on ? 'on' : ''}`} onClick={onClick}>
      <span className={`mark ${multi ? 'box' : 'dot'}`} />
      <span className="chip-txt"><span className="chip-l">{label}</span>{sub && <span className="chip-s">{sub}</span>}</span>
    </button>);
}
function S5Block({ node, applicable = true, children }) {
  return (
    <div className={`block ${applicable ? '' : 'off'}`}>
      <div className="block-head">
        <S5Badge kind={node.role === 'required' ? 'req' : 'sel'}>{node.role === 'required' ? '필수' : '선택'}</S5Badge>
        <span className="block-name">{node.label}</span>
        <S5MethodBadge method={node.method} min={node.min} max={node.max} />
        <S5InputBadge input={node.input} />
        {node.note && <span className="block-note">{node.note}</span>}
      </div>
      <div className="block-body">{children}</div>
    </div>);
}
function S5Slot({ label, h, value, onPick, onClear }) {
  const ref = r5(null);
  const pick = (e) => {
    const f = e.target.files && e.target.files[0];
    if (f && onPick) { const rd = new FileReader(); rd.onload = () => onPick(rd.result); rd.readAsDataURL(f); }
    e.target.value = '';
  };
  return (
    <div className={`slot ${value ? 'has' : 'up'}`} style={{ height: h || 60, position: 'relative', overflow: 'hidden', padding: value ? 0 : undefined }}
      onClick={() => { if (!value && onPick && ref.current) ref.current.click(); }}>
      <input ref={ref} type="file" accept="image/*" style={{ display: 'none' }} onChange={pick} />
      {value ?
        <React.Fragment>
          <img src={value} alt="" style={{ width: '100%', height: '100%', objectFit: 'contain' }} />
          <button onClick={(e) => { e.stopPropagation(); onClear && onClear(); }} title="삭제"
            style={{ position: 'absolute', top: 4, right: 4, width: 20, height: 20, borderRadius: 6, border: 0, background: 'rgba(0,0,0,.55)', color: '#fff', cursor: 'pointer', lineHeight: 1, fontSize: 13 }}>×</button>
        </React.Fragment> :
        <React.Fragment>＋ {label}</React.Fragment>}
    </div>);
}

function Create550({ guide, layout, layoutSub, onGenerate, schema }) {
  const S5SCH = schema || window.SCHEMA_550;
  const [st, setSt] = u5({ images: [], logoCount: 1, logoKind: 'horiz', logoImgs: [], imgmark: [], extra: null, extraSub: 'gift', extraText: '', extraImg: null, colorImg: null, flagCount: 0, hex: '' });
  const set = (patch) => setSt((s) => ({ ...s, ...patch }));
  const imgRef = r5(null);
  const onPick = (e) => {
    const files = Array.from(e.target.files || []);
    files.forEach((f) => { const r = new FileReader(); r.onload = () => setSt((s) => ({ ...s, images: [...s.images, r.result] })); r.readAsDataURL(f); });
    e.target.value = '';
  };
  const removeImg = (i) => setSt((s) => ({ ...s, images: s.images.filter((_, k) => k !== i) }));
  const setLogoImg = (i, url) => setSt((s) => { const a = s.logoImgs.slice(); a[i] = url; return { ...s, logoImgs: a }; });

  const logoAxis = S5SCH.axes.find((a) => a.id === 'logo');
  const markAxis = S5SCH.axes.find((a) => a.id === 'imgmark');
  const extraAxis = S5SCH.axes.find((a) => a.id === 'extra');
  const layoutAxis = S5SCH.axes.find((a) => a.id === 'layout');
  const extraOK = extraAxis.appliesTo.includes(layout);
  const extraOpt = extraAxis.options.find((o) => o.id === st.extra);
  const layoutLabel = (layoutAxis.options.find((o) => o.id === layout) || {}).label || layout;
  const placeDesc = (layout === 'nukki' || layout === 'split-nukki') && st.images.length > 0
    ? s5rows(st.images.length).map((c, i) => `${i + 1}행 ${c}개`).join(', ')
    : st.images.length > 0 ? '분할 영역에 순서대로' : '';

  // 레이아웃이 부가정보 미적용으로 바뀌면 해제
  ef5(() => { if (!extraOK && st.extra) set({ extra: null }); }, [layout]);

  const sel = { ...st, layout, layoutSub };

  return (
    <div className="s550"><div className="wrap">
      <div className="left">
        {/* 메인 이미지 — 업로드 시 자동 배치 */}
        <S5Block node={S5SCH.required[1]}>
          <input ref={imgRef} type="file" accept="image/*" multiple style={{ display: 'none' }} onChange={onPick} />
          {st.images.length === 0 ?
            <div className="slot up" onClick={() => imgRef.current.click()}>＋ 상품 이미지 업로드 <span>여러 장 가능 · 누끼 권장</span></div> :
            <div className="thumbs">
              {st.images.map((src, i) => <div className="thumb" key={i}><img src={src} alt="" /><button onClick={() => removeImg(i)}>×</button></div>)}
              <button className="thumb-add" onClick={() => imgRef.current.click()}>＋</button>
            </div>}
          <div className="autoplace">업로드한 <b>{st.images.length}장</b>은 <b>{layoutLabel}</b>에 맞춰 <b>자동 배치</b>됩니다{placeDesc ? ' · ' + placeDesc : ''}</div>
        </S5Block>

        {/* 로고 */}
        <S5Block node={logoAxis}>
          <div className="seg">
            {[0, 1, 2].map((n) => <button key={n} className={st.logoCount === n ? 'on' : ''} onClick={() => set({ logoCount: n })}>{n === 0 ? '없음' : n + '개'}</button>)}
          </div>
          {st.logoCount > 0 &&
            <div className="nest">
              <div className="nest-l">형태 — 택1</div>
              <div className="chips">{logoAxis.options.map((o) => <S5Chip key={o.id} on={st.logoKind === o.id} label={o.label} sub={o.sub} onClick={() => set({ logoKind: o.id })} />)}</div>
              <div className="row2" style={{ marginTop: 10 }}>{Array.from({ length: st.logoCount }).map((_, i) => <S5Slot key={i} label={i === 0 ? '브랜드' : '광고주'} h={50} value={st.logoImgs[i]} onPick={(url) => setLogoImg(i, url)} onClear={() => setLogoImg(i, null)} />)}</div>
            </div>}
        </S5Block>

        {/* 이미지 표기 */}
        <S5Block node={markAxis}>
          <div className="chips">
            {markAxis.options.map((o) => { const on = st.imgmark.includes(o.id); return <S5Chip key={o.id} multi on={on} label={o.label} sub={o.sub} onClick={() => set({ imgmark: on ? st.imgmark.filter((x) => x !== o.id) : [...st.imgmark, o.id] })} />; })}
          </div>
        </S5Block>

        {/* 부가정보 (제약) */}
        <S5Block node={extraAxis} applicable={extraOK}>
          {!extraOK ?
            <div className="constraint-msg">현재 <b>{layoutLabel}</b>에는 부가정보를 넣을 수 없습니다. <span>(누끼형 · 풀이미지형 전용)</span></div> :
            <>
              <div className="chips">
                <S5Chip on={st.extra === null} label="없음" onClick={() => set({ extra: null })} />
                {extraAxis.options.map((o) => <S5Chip key={o.id} on={st.extra === o.id} label={o.label} sub={o.sub} onClick={() => set({ extra: o.id, extraSub: o.options ? o.options[0].id : null })} />)}
              </div>
              {extraOpt && extraOpt.options &&
                <div className="nest">
                  <div className="nest-l">{extraOpt.label} — 종류 택1</div>
                  <div className="chips">{extraOpt.options.map((c) => <S5Chip key={c.id} on={st.extraSub === c.id} label={c.label} sub={c.sub} onClick={() => set({ extraSub: c.id })} />)}</div>
                  {extraOpt.input === 'image' && <div className="row2" style={{ marginTop: 10 }}><S5Slot label={`${(extraOpt.options.find((c) => c.id === st.extraSub) || {}).label || ''} 이미지`} h={52} value={st.extraImg} onPick={(url) => set({ extraImg: url })} onClear={() => set({ extraImg: null })} /></div>}
                  {extraOpt.input === 'text' &&
                    <div className="textfield" style={{ marginTop: 10 }}>
                      <input className="tf" placeholder={extraOpt.placeholder} value={st.extraText} maxLength={8} onChange={(e) => set({ extraText: e.target.value })} />
                      <div className="tf-note">{extraOpt.note}</div>
                    </div>}
                  {extraOpt.input === 'color' &&
                    <div className="colorchip" style={{ marginTop: 10 }}>
                      <S5Slot label="색상 추출용 이미지 업로드" h={50} value={st.colorImg} onPick={(url) => set({ colorImg: url })} onClear={() => set({ colorImg: null })} />
                      <div className="or-div"><span>또는 직접 입력</span></div>
                      <div className="hexrow"><span className="hash">#</span><input className="tf hex" placeholder="FF7A3D" maxLength={6} value={st.hex} onChange={(e) => set({ hex: e.target.value.replace(/[^0-9a-fA-F]/g, '') })} /><span className="hex-sw" style={{ background: st.hex.length >= 3 ? '#' + st.hex : 'transparent' }} /></div>
                      <div className="tf-note">추출용 이미지를 올리거나 헥사코드를 직접 입력하세요</div>
                    </div>}
                </div>}
              {extraOpt && !extraOpt.options && extraOpt.method === 'multi' &&
                <div className="nest">
                  <div className="nest-l">{extraOpt.label} — 개수 (최대 {extraOpt.max})</div>
                  <div className="seg">{[0, 1, 2].map((n) => <button key={n} className={st.flagCount === n ? 'on' : ''} onClick={() => set({ flagCount: n })}>{n === 0 ? '없음' : n + '개'}</button>)}</div>
                </div>}
            </>}
        </S5Block>

        <button className="btn btn-primary btn-lg btn-block" style={{ marginTop: 6, borderRadius: '6px' }} disabled={!st.images.length}
          onClick={() => onGenerate({ content: {}, image: st.images[0], images: st.images, sty: window.STYLE_A, schema550: sel })}>
          <S2Icon name="sparkles" size={17} /> 배너 생성하기
        </button>
      </div>

      <div className="right">
        <div className="preview-card">
          <S5Preview sel={sel} extraOK={extraOK} extraOpt={extraOpt} canvas={S5SCH.canvas} />
          <S5Summary sel={sel} extraOK={extraOK} extraOpt={extraOpt} layoutAxis={layoutAxis} logoAxis={logoAxis} canvas={S5SCH.canvas} />
        </div>
      </div>
    </div></div>);
}

/* ---- 550 캔버스 라이브 프리뷰 ---- */
function S5Preview({ sel, extraOK, extraOpt, canvas }) {
  const L = sel.layout;
  const imgs = sel.images || [];
  const has = imgs.length > 0;
  const tile = (src) => (src ? { backgroundImage: `url(${src})`, backgroundSize: 'cover', backgroundPosition: 'center' } : {});
  const productGrid = () => {
    const rows = s5rows(imgs.length); let idx = 0;
    return (
      <div className="pgrid">
        {rows.map((cnt, ri) => <div className="prow" key={ri}>{Array.from({ length: cnt }).map((_, ci) => { const src = imgs.length ? imgs[(idx++) % imgs.length] : null; return <div className="ptile" key={ci} style={tile(src)}>{!src && <i />}</div>; })}</div>)}
      </div>);
  };
  const zStyle = (i, base) => ({ ...base, ...(has ? tile(imgs[i % imgs.length]) : {}) });
  const zones = (() => {
    if (L === 'nukki') return <div className="z fill" style={{ inset: 0 }}>{has ? productGrid() : <span>모델 / 상품</span>}</div>;
    if (L === 'split-nukki') return (<>
      <div className="z fill" style={{ left: 0, top: 0, bottom: 0, width: '60%' }}>{has ? productGrid() : <span>누끼 상품</span>}</div>
      <div className="z fill alt" style={{ right: 0, top: 0, bottom: 0, width: '40%', ...(has ? tile(imgs[imgs.length - 1]) : {}) }}>{!has && <span>화보</span>}</div>
    </>);
    if (L === 'full') return <div className="z fill" style={{ inset: 0, ...(has ? tile(imgs[0]) : {}) }}>{!has && <span>화보</span>}</div>;
    if (L === 'split') {
      if (sel.layoutSub === 's2') return (<>
        <div className="z fill" style={zStyle(0, { left: 0, top: 0, bottom: 0, width: '50%' })}>{!has && <span>화보</span>}</div>
        <div className="z fill alt" style={zStyle(1, { right: 0, top: 0, bottom: 0, width: '50%' })}>{!has && <span>화보</span>}</div>
      </>);
      if (sel.layoutSub === 's3') return (<>
        <div className="z fill" style={zStyle(0, { left: 0, top: 0, width: '100%', height: '50%' })}>{!has && <span>화보</span>}</div>
        <div className="z fill alt" style={zStyle(1, { left: 0, bottom: 0, width: '50%', height: '50%' })}>{!has && <span>화보</span>}</div>
        <div className="z fill" style={zStyle(2, { right: 0, bottom: 0, width: '50%', height: '50%' })}>{!has && <span>화보</span>}</div>
      </>);
      return (<>
        <div className="z fill" style={zStyle(0, { left: 0, top: 0, width: '50%', height: '50%' })}>{!has && <span>화보</span>}</div>
        <div className="z fill alt" style={zStyle(1, { right: 0, top: 0, width: '50%', height: '50%' })}>{!has && <span>화보</span>}</div>
        <div className="z fill alt" style={zStyle(2, { left: 0, bottom: 0, width: '50%', height: '50%' })}>{!has && <span>화보</span>}</div>
        <div className="z fill" style={zStyle(3, { right: 0, bottom: 0, width: '50%', height: '50%' })}>{!has && <span>화보</span>}</div>
      </>);
    }
    return null;
  })();
  const extraLabel = extraOK && extraOpt ? (
    extraOpt.input === 'text' ? (sel.extraText || extraOpt.label) :
    extraOpt.options ? ((extraOpt.options.find((c) => c.id === sel.extraSub) || {}).label || extraOpt.label) : extraOpt.label) : null;
  return (
    <div className="canvas550" style={{ aspectRatio: canvas ? `${canvas.w} / ${canvas.h}` : '1 / 1' }}>
      {zones}
      <div className="safe-box" />
      {sel.logoCount > 0 && <div className="ov-logo">{Array.from({ length: sel.logoCount }).map((_, i) => <div key={i} className={`logo-chip ${sel.logoKind}`}>LOGO</div>)}</div>}
      {extraLabel && <div className="ov-extra" style={{ top: sel.logoCount > 0 ? '24%' : '11%' }}>{extraOpt.id === 'colorchip' ? <div className="chips-col">{Array.from({ length: 5 }).map((_, i) => <i key={i} />)}</div> : <span className="extra-pill">{extraLabel}</span>}</div>}
      {sel.imgmark.length > 0 && <div className="ov-mark">{sel.imgmark.map((m) => <span key={m}>{m === 'plus' ? '+' : 'OR'}</span>)}</div>}
    </div>);
}

function S5Summary({ sel, extraOK, extraOpt, layoutAxis, logoAxis, canvas }) {
  const items = [];
  if (canvas) items.push(['사이즈', `${canvas.w} × ${canvas.h}`]);
  items.push(['레이아웃', (layoutAxis.options.find((o) => o.id === sel.layout) || {}).label + (sel.layout === 'split' ? ` · ${({ s2: '2', s3: '3', s4: '4' })[sel.layoutSub]}분할` : '')]);
  items.push(['로고', sel.logoCount === 0 ? '없음' : `${sel.logoCount}개 · ${logoAxis.options.find((o) => o.id === sel.logoKind).label}`]);
  items.push(['이미지 표기', sel.imgmark.length ? sel.imgmark.map((m) => m === 'plus' ? '+' : 'OR').join(' · ') : '없음']);
  items.push(['부가정보', !extraOK ? '적용 불가' : !extraOpt ? '없음' : (extraOpt.label + (extraOpt.options ? ` · ${(extraOpt.options.find((c) => c.id === sel.extraSub) || {}).label}` : ''))]);
  return (
    <div className="summary">
      <div className="summary-h">활성 노드</div>
      <div className="summary-list">{items.map(([k, v]) => <div key={k} className="srow"><span className="sk">{k}</span><span className="sv">{v}</span></div>)}</div>
    </div>);
}

Object.assign(window, { Create550 });
