/* ctor-note-blocks.jsx — гибкий конструктор содержимого заметки.
   Заметка = массив блоков (заголовок + текст + картинка сбоку) + выбор макета:
   «Карточки», «Анкета» (поля), «Чек-ап» (пронумерованные пункты), «Простой текст».
   Используется в NotesPanel: и в создании, и в редактировании, и в отображении.
   Экспорт → window: NoteComposer, NoteContentView, NOTE_LAYOUTS, blankNoteBlock, blocksToText */
const { useState: nbUseState, useRef: nbUseRef } = React;

const NB = { ink:'#1a1714', mut:'#8a817a', soft:'#a89e92', accent:'#e8793a', line:'#e4ddd2', fieldbg:'#f0ece5', card:'#fff', faint:'#f7f7f9' };

const NOTE_LAYOUTS = {
  cards:   { l:'Карточки',     hint:'Заголовок, текст и картинка сбоку' },
  form:    { l:'Анкета',       hint:'Поля «метка → значение»' },
  checkup: { l:'Чек-ап',       hint:'Пронумерованные пункты осмотра' },
  plain:   { l:'Простой текст', hint:'Один сплошной текст без блоков' },
};

function nbUid(p) { return (p || 'b') + Math.random().toString(36).slice(2, 8); }
function blankNoteBlock() { return { id: nbUid('blk'), title:'', text:'', image:null, imageSide:'right' }; }
function blocksToText(blocks) { return (blocks || []).map(b => [b.title, b.text].filter(Boolean).join(': ')).filter(Boolean).join('\n'); }

/* мини-иконки */
const nbIc = {
  trash: <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>,
  img: <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>,
  flip: <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="17 1 21 5 17 9"/><path d="M3 11V9a4 4 0 0 1 4-4h14"/><polyline points="7 23 3 19 7 15"/><path d="M21 13v2a4 4 0 0 1-4 4H3"/></svg>,
  up: <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><polyline points="18 15 12 9 6 15"/></svg>,
  down: <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>,
  plus: <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>,
};

/* ============ КОНСТРУКТОР (edit) ============ */
function NoteComposer({ blocks, onChange, layout, setLayout }) {
  const list = blocks && blocks.length ? blocks : [blankNoteBlock()];
  const set = (id, patch) => onChange(list.map(b => b.id === id ? { ...b, ...patch } : b));
  const add = () => onChange([...list, blankNoteBlock()]);
  const remove = (id) => onChange(list.length > 1 ? list.filter(b => b.id !== id) : [blankNoteBlock()]);
  const move = (id, dir) => {
    const i = list.findIndex(b => b.id === id); const j = i + dir;
    if (j < 0 || j >= list.length) return;
    const next = list.slice(); const t = next[i]; next[i] = next[j]; next[j] = t; onChange(next);
  };
  const plain = layout === 'plain';

  return (
    <div>
      {/* выбор макета */}
      <div style={{ fontSize:11.5, fontWeight:600, color:NB.mut, marginBottom:6 }}>Дизайн заметки</div>
      <div style={{ display:'grid', gridTemplateColumns:'repeat(auto-fit, minmax(130px, 1fr))', gap:8, marginBottom:16 }}>
        {Object.keys(NOTE_LAYOUTS).map(k => {
          const on = layout === k;
          return (
            <button key={k} onClick={() => setLayout(k)} style={{
              textAlign:'left', cursor:'pointer', fontFamily:'inherit', padding:'9px 12px', borderRadius:11,
              background: on ? '#fff0e6' : NB.card, border:'1px solid ' + (on ? NB.accent : NB.line), transition:'all .12s',
            }}>
              <div style={{ display:'flex', alignItems:'center', gap:7, marginBottom:3 }}>
                <span style={{ width:14, height:14, borderRadius:'50%', border:'2px solid ' + (on ? NB.accent : '#d4ccbf'), display:'grid', placeItems:'center', flexShrink:0 }}>
                  {on && <span style={{ width:6, height:6, borderRadius:'50%', background:NB.accent }} />}
                </span>
                <span style={{ fontSize:13, fontWeight:700, color:NB.ink }}>{NOTE_LAYOUTS[k].l}</span>
              </div>
              <div style={{ fontSize:11, color:NB.soft, lineHeight:1.35, paddingLeft:21 }}>{NOTE_LAYOUTS[k].hint}</div>
            </button>
          );
        })}
      </div>

      {plain ? (
        <textarea value={list[0].text} onChange={e => onChange([{ ...list[0], title:'', text:e.target.value }])} rows={4}
          placeholder="Например: стяжка полусухая М150, демпферная лента по периметру…"
          style={{ width:'100%', resize:'vertical', fontFamily:'inherit', fontSize:13.5, lineHeight:1.5, color:NB.ink, background:NB.fieldbg, border:'.5px solid '+NB.line, borderRadius:11, padding:'10px 13px', outline:'none' }} />
      ) : (
        <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
          {list.map((b, i) => (
            <BlockEditor key={b.id} block={b} index={i} total={list.length} layout={layout}
              onPatch={(p) => set(b.id, p)} onRemove={() => remove(b.id)} onMove={(d) => move(b.id, d)} />
          ))}
          <button onClick={add} style={{
            display:'inline-flex', alignItems:'center', gap:6, alignSelf:'flex-start', padding:'8px 14px', borderRadius:10,
            border:'1px dashed '+NB.line, background:'transparent', color:NB.accent, fontFamily:'inherit', fontSize:13, fontWeight:700, cursor:'pointer',
          }}>{nbIc.plus} Добавить блок</button>
        </div>
      )}
    </div>
  );
}

function BlockEditor({ block, index, total, layout, onPatch, onRemove, onMove }) {
  const fileRef = nbUseRef(null);
  const onFile = (f) => { if (!f || !/image\//.test(f.type)) return; const r = new FileReader(); r.onload = () => onPatch({ image:{ url:r.result, name:f.name } }); r.readAsDataURL(f); };
  const titlePh = layout === 'form' ? 'Метка поля (напр. «Материал»)' : layout === 'checkup' ? 'Пункт осмотра' : 'Заголовок блока';
  const textPh = layout === 'form' ? 'Значение / описание' : 'Текст описания';
  return (
    <div style={{ borderRadius:13, border:'.5px solid '+NB.line, background:NB.card, padding:'12px 13px' }}>
      <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:9 }}>
        <span style={{ fontSize:10.5, fontWeight:800, letterSpacing:'.03em', textTransform:'uppercase', color:NB.soft, background:NB.fieldbg, padding:'2px 9px', borderRadius:980 }}>
          {layout === 'checkup' ? 'Пункт ' + (index+1) : 'Блок ' + (index+1)}
        </span>
        <div style={{ flex:1 }} />
        <button onClick={() => onMove(-1)} disabled={index===0} title="Выше" style={miniBtn(index===0)}>{nbIc.up}</button>
        <button onClick={() => onMove(1)} disabled={index===total-1} title="Ниже" style={miniBtn(index===total-1)}>{nbIc.down}</button>
        <button onClick={onRemove} title="Удалить блок" style={{ ...miniBtn(false), color:'#d05858' }}>{nbIc.trash}</button>
      </div>
      <div style={{ display:'flex', gap:12, alignItems:'flex-start', flexDirection: block.imageSide === 'left' ? 'row-reverse' : 'row' }}>
        <div style={{ flex:1, minWidth:0, display:'flex', flexDirection:'column', gap:8 }}>
          <input value={block.title} onChange={e => onPatch({ title:e.target.value })} placeholder={titlePh}
            style={{ width:'100%', fontFamily:'inherit', fontSize:13.5, fontWeight:700, color:NB.ink, background:NB.fieldbg, border:'.5px solid '+NB.line, borderRadius:9, padding:'8px 11px', outline:'none' }} />
          <textarea value={block.text} onChange={e => onPatch({ text:e.target.value })} rows={2} placeholder={textPh}
            style={{ width:'100%', resize:'vertical', fontFamily:'inherit', fontSize:13, lineHeight:1.5, color:NB.ink, background:NB.fieldbg, border:'.5px solid '+NB.line, borderRadius:9, padding:'8px 11px', outline:'none' }} />
        </div>
        {/* картинка сбоку */}
        <div style={{ width:108, flexShrink:0 }}>
          {block.image ? (
            <div style={{ position:'relative' }}>
              <img src={block.image.url} alt="" style={{ width:108, height:84, objectFit:'cover', borderRadius:9, border:'.5px solid '+NB.line, display:'block' }} />
              <button onClick={() => onPatch({ image:null })} title="Убрать картинку" style={{ position:'absolute', top:-6, right:-6, width:20, height:20, borderRadius:'50%', border:'1.5px solid #fff', background:NB.ink, color:'#fff', cursor:'pointer', fontSize:11, lineHeight:1, display:'grid', placeItems:'center' }}>✕</button>
              <button onClick={() => onPatch({ imageSide: block.imageSide==='left'?'right':'left' })} title="Сторона картинки" style={{ position:'absolute', bottom:5, right:5, width:22, height:22, borderRadius:7, border:'none', background:'rgba(26,23,20,.74)', color:'#fff', cursor:'pointer', display:'grid', placeItems:'center' }}>{nbIc.flip}</button>
            </div>
          ) : (
            <button onClick={() => fileRef.current && fileRef.current.click()} style={{
              width:108, height:84, borderRadius:9, border:'1.5px dashed '+NB.line, background:NB.faint, cursor:'pointer',
              display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center', gap:5, color:NB.soft, fontFamily:'inherit', fontSize:10.5, fontWeight:600,
            }}>{nbIc.img}<span>Картинка</span></button>
          )}
          <input ref={fileRef} type="file" accept="image/jpeg,image/png,image/webp" style={{ display:'none' }} onChange={e => { onFile(e.target.files[0]); e.target.value=''; }} />
        </div>
      </div>
    </div>
  );
}
function miniBtn(disabled) { return { width:26, height:26, borderRadius:7, border:'.5px solid '+NB.line, background:'#fff', color:disabled?'#d4ccbf':NB.mut, cursor:disabled?'default':'pointer', display:'grid', placeItems:'center', opacity:disabled?0.5:1 }; }

/* ============ ОТОБРАЖЕНИЕ (read) ============ */
function NoteContentView({ layout, blocks, text, onImage }) {
  // legacy: нет блоков → обычный текст
  if (!blocks || !blocks.length || layout === 'plain') {
    const t = (blocks && blocks.length) ? blocksToText(blocks) : text;
    return <div style={{ fontSize:13.5, color:'#3a3a3e', lineHeight:1.55, whiteSpace:'pre-wrap' }}>{t}</div>;
  }
  if (layout === 'form') return (
    <div style={{ display:'flex', flexDirection:'column', gap:1, border:'.5px solid '+NB.line, borderRadius:11, overflow:'hidden' }}>
      {blocks.map((b, i) => (
        <div key={b.id} style={{ display:'flex', gap:12, alignItems:'flex-start', padding:'9px 12px', background: i%2 ? '#fff' : NB.faint }}>
          <div style={{ width:150, flexShrink:0, fontSize:12.5, fontWeight:700, color:NB.ink }}>{b.title || '—'}</div>
          <div style={{ flex:1, minWidth:0, fontSize:13, color:'#3a3a3e', lineHeight:1.5, whiteSpace:'pre-wrap' }}>{b.text}</div>
          {b.image && <img src={b.image.url} alt="" onClick={()=>onImage&&onImage(b.image)} style={{ width:56, height:44, objectFit:'cover', borderRadius:7, border:'.5px solid '+NB.line, cursor:onImage?'zoom-in':'default', flexShrink:0 }} />}
        </div>
      ))}
    </div>
  );
  if (layout === 'checkup') return (
    <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
      {blocks.map((b, i) => (
        <div key={b.id} style={{ display:'flex', gap:11, alignItems:'flex-start' }}>
          <span style={{ width:22, height:22, flexShrink:0, borderRadius:'50%', background:'#fff0e6', color:NB.accent, fontSize:11.5, fontWeight:800, display:'grid', placeItems:'center', marginTop:1 }}>{i+1}</span>
          <div style={{ flex:1, minWidth:0, display:'flex', gap:12, alignItems:'flex-start', flexDirection: b.imageSide==='left'?'row-reverse':'row' }}>
            <div style={{ flex:1, minWidth:0 }}>
              {b.title && <div style={{ fontSize:13.5, fontWeight:700, color:NB.ink, marginBottom:2 }}>{b.title}</div>}
              {b.text && <div style={{ fontSize:13, color:'#3a3a3e', lineHeight:1.5, whiteSpace:'pre-wrap' }}>{b.text}</div>}
            </div>
            {b.image && <img src={b.image.url} alt="" onClick={()=>onImage&&onImage(b.image)} style={{ width:96, height:72, objectFit:'cover', borderRadius:9, border:'.5px solid '+NB.line, cursor:onImage?'zoom-in':'default', flexShrink:0 }} />}
          </div>
        </div>
      ))}
    </div>
  );
  // cards (default)
  return (
    <div style={{ display:'flex', flexDirection:'column', gap:10 }}>
      {blocks.map(b => (
        <div key={b.id} style={{ display:'flex', gap:14, alignItems:'flex-start', flexDirection: b.imageSide==='left'?'row-reverse':'row', background:NB.faint, borderRadius:11, padding: b.image ? '11px 13px' : '0', border: b.image ? '.5px solid '+NB.line : 'none' }}>
          <div style={{ flex:1, minWidth:0 }}>
            {b.title && <div style={{ fontSize:14.5, fontWeight:700, color:NB.ink, marginBottom:3, letterSpacing:'-.01em' }}>{b.title}</div>}
            {b.text && <div style={{ fontSize:13, color:'#3a3a3e', lineHeight:1.55, whiteSpace:'pre-wrap' }}>{b.text}</div>}
          </div>
          {b.image && <img src={b.image.url} alt="" onClick={()=>onImage&&onImage(b.image)} style={{ width:128, height:96, objectFit:'cover', borderRadius:10, border:'.5px solid '+NB.line, cursor:onImage?'zoom-in':'default', flexShrink:0 }} />}
        </div>
      ))}
    </div>
  );
}

Object.assign(window, { NoteComposer, NoteContentView, NOTE_LAYOUTS, blankNoteBlock, blocksToText });
