/* global React */
// XMLStructureEditor.jsx — Feature 2: LLM-structured XML view, edit sections

const { useState: useStateX, useMemo: useMemoX, useEffect: useEffectX } = React;

function XMLStructureEditor({
  title, setTitle, genres, setGenres,
  sections, setSections,
  selected, setSelected,
  lyrics,
  structuring, onStructure,
  blockTypes,
}) {
  const [view, setView] = useStateX('visual'); // visual | xml
  const [newGenre, setNewGenre] = useStateX('');
  const [openSectionId, setOpenSectionId] = useStateX(null);
  const [contextLoading, setContextLoading] = useStateX(false);

  const totalSec = sections.reduce((a, b) => a + (b.dur || 0), 0);
  const fmt = (s) => `${Math.floor(s/60)}:${(s|0)%60 < 10 ? '0' : ''}${(s|0)%60}`;

  const addSection = (typeId) => {
    const def = blockTypes.find((b) => b.id === typeId);
    const id = 's' + Math.random().toString(36).slice(2, 8);
    setSections([...sections, { id, type: typeId, lines: '', context: '', vaab: '', dur: def?.defaultDur || 15 }]);
    setSelected(id);
  };
  const updateSection = (id, patch) => {
    setSections(sections.map((s) => (s.id === id ? { ...s, ...patch } : s)));
  };
  const deleteSection = (id) => {
    setSections(sections.filter((s) => s.id !== id));
  };

  const openSection = sections.find((s) => s.id === openSectionId);

  const generateContext = async () => {
    if (!openSection) return;
    setContextLoading(true);
    try {
      // Send earlier sections' guides so the tone stays continuous.
      const idx = sections.findIndex((s) => s.id === openSection.id);
      const earlier = sections.slice(0, idx).filter((s) => s.context && s.context.trim());
      const previous_contexts = earlier.length
        ? earlier.map((s, i) => `[${i + 1}. ${s.type}] ${s.context.trim()}`).join('\n')
        : '(none yet)';

      const reply = await window.MM_BACKEND.runPrompt('block_style', {
        lyrics,
        genres: genres.join(', ') || 'unspecified',
        section_type: openSection.type,
        section_lines: openSection.lines || '(empty)',
        previous_contexts,
      });
      updateSection(openSection.id, { context: String(reply || '').trim() });
    } catch (e) {
      console.error('block_style failed', e);
    }
    setContextLoading(false);
  };

  const addGenre = () => {
    const g = newGenre.trim();
    if (!g) return;
    if (!genres.includes(g)) setGenres([...genres, g]);
    setNewGenre('');
  };

  const xmlString = useMemoX(() => {
    const esc = (s = '') => String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    const lines = [];
    lines.push('<song>');
    lines.push(`  <title>${esc(title || 'Untitled')}</title>`);
    if (genres.length) lines.push(`  <genres>${genres.map(esc).join(', ')}</genres>`);
    lines.push('  <structure>');
    sections.forEach((s) => {
      lines.push(`    <${s.type} duration="${s.dur}s">`);
      if (s.lines && s.lines.trim()) {
        s.lines.split('\n').forEach((l) => {
          if (l.trim()) lines.push(`      <line>${esc(l.trim())}</line>`);
        });
      } else {
        lines.push(`      <!-- (no lyric assigned) -->`);
      }
      lines.push(`    </${s.type}>`);
    });
    lines.push('  </structure>');
    lines.push('</song>');
    return lines.join('\n');
  }, [title, genres, sections]);

  return (
    <div className="panel">
      <div className="panel-head">
        <span className="num">02</span>
        <span className="title">Structure</span>
        <span className="hint">— LLM returns XML, you may edit</span>
        <div className="right">
          <button className="btn primary sm" onClick={onStructure} disabled={structuring || !lyrics.trim()}>
            {structuring ? <><span className="spin" style={{margin:0,width:10,height:10,borderWidth:1.2}} /> Structuring</> : '✦ Structure with LLM'}
          </button>
        </div>
      </div>

      <div className="panel-body">
        <div className="structure-area">

          {/* Title + Genre */}
          <SongIdCard title={title} setTitle={setTitle}
                      genres={genres} setGenres={setGenres}
                      newGenre={newGenre} setNewGenre={setNewGenre} addGenre={addGenre} />

          {/* XML / Sections */}
          <div className="xml-card">
            <div className="head">
              <span className="title">song.xml</span>
              <span className="by">— responds in XML</span>
              <div className="toggle-view">
                <button className={view === 'visual' ? 'on' : ''} onClick={() => setView('visual')}>Visual</button>
                <button className={view === 'xml' ? 'on' : ''} onClick={() => setView('xml')}>Code</button>
              </div>
            </div>
            <div className="body">
              {view === 'visual' ? (
                <>
                  <div className="sections">
                    {sections.length === 0 && (
                      <EmptyStructureHint structuring={structuring} hasLyrics={!!lyrics.trim()} />
                    )}
                    {sections.map((s) => (
                      <SectionRow key={s.id}
                                  section={s}
                                  selected={selected === s.id}
                                  onSelect={() => setSelected(s.id)}
                                  onUpdate={(p) => updateSection(s.id, p)}
                                  onDelete={() => deleteSection(s.id)}
                                  onOpen={() => { setSelected(s.id); setOpenSectionId(s.id); }}
                                  blockTypes={blockTypes} />
                    ))}
                  </div>
                  <div className="add-section-row">
                    <span className="lbl">Add</span>
                    {blockTypes.map((b) => (
                      <button key={b.id} className="add-btn" onClick={() => addSection(b.id)}>
                        <span className="plus">+</span>{b.label}
                      </button>
                    ))}
                  </div>
                </>
              ) : (
                <CodeView xml={xmlString} />
              )}
            </div>
          </div>

          {/* Timeline */}
          <Timeline sections={sections} blockTypes={blockTypes}
                    totalSec={totalSec} fmt={fmt}
                    selected={selected} setSelected={setSelected} />
        </div>
      </div>

      {openSection && (
        <SectionEditorDialog
          section={openSection}
          blockTypes={blockTypes}
          onClose={() => setOpenSectionId(null)}
          onUpdate={(p) => updateSection(openSection.id, p)}
          onDelete={() => { deleteSection(openSection.id); setOpenSectionId(null); }}
          contextLoading={contextLoading}
          onGenerateContext={generateContext}
          fullLyrics={lyrics}
          genres={genres} />
      )}
    </div>
  );
}

function SectionEditorDialog({ section, blockTypes, onClose, onUpdate, onDelete,
                               contextLoading, onGenerateContext, fullLyrics, genres }) {
  const def = blockTypes.find((b) => b.id === section.type);
  return (
    <div className="dialog-veil" onClick={onClose}>
      <div className="dialog" onClick={(e) => e.stopPropagation()}>
        <div className="dialog-head">
          <span className="dialog-num">SECTION</span>
          <span className="dialog-typ">
            <span className="swatch" style={{ background: def?.color }} />
            <select value={section.type} onChange={(e) => onUpdate({ type: e.target.value })}>
              {blockTypes.map((b) => <option key={b.id} value={b.id}>{b.label}</option>)}
            </select>
          </span>
          <span className="dialog-ttl">{def?.label} editor</span>
          <button className="dialog-close" onClick={onClose}>
            <svg width="14" height="14" viewBox="0 0 14 14" stroke="currentColor" strokeWidth="1.4" fill="none">
              <path d="M3 3l8 8M11 3l-8 8"/>
            </svg>
          </button>
        </div>

        <div className="dialog-body">
          <div className="d-field">
            <div className="d-label">Lyric lines · preview</div>
            <textarea className="d-textarea lyrics"
                      value={section.lines}
                      onChange={(e) => onUpdate({ lines: e.target.value })}
                      placeholder="The lyric lines for this section…"
                      rows={6} />
            <div className="d-meta">
              {(section.lines || '').split('\n').filter((l) => l.trim()).length} lines
              · drawn from your full lyric ({fullLyrics.trim().split(/\s+/).length} words)
            </div>
          </div>

          <div className="d-field">
            <div className="d-label-row">
              <div className="d-label">Context · vaab · sonic notes</div>
              <button className="btn ghost sm" onClick={onGenerateContext} disabled={contextLoading}>
                {contextLoading
                  ? <><span className="spin" style={{margin:0,width:9,height:9,borderWidth:1.2}}/> Thinking</>
                  : '✦ Generate with LLM'}
              </button>
            </div>
            <textarea className="d-textarea"
                      value={section.context || ''}
                      onChange={(e) => onUpdate({ context: e.target.value })}
                      placeholder="Describe what this section should feel like — emotional core, dynamics, instrumentation cues. Or click ✦ to let the LLM read your full lyrics + genre and draft this for you."
                      rows={4} />
          </div>

          <div className="d-field-row">
            <div className="d-field">
              <div className="d-label">Vaab (rasa)</div>
              <input className="d-input" value={section.vaab || ''}
                     onChange={(e) => onUpdate({ vaab: e.target.value })}
                     placeholder="e.g. Shringar, Karuna" />
            </div>
            <div className="d-field">
              <div className="d-label">Duration</div>
              <div className="d-dur">
                <input className="d-input" type="number" min={1}
                       value={section.dur}
                       onChange={(e) => onUpdate({ dur: Math.max(1, parseInt(e.target.value) || 0) })} />
                <span className="d-unit">seconds</span>
              </div>
            </div>
          </div>
        </div>

        <div className="dialog-foot">
          <button className="btn ghost sm" onClick={onDelete}>Delete section</button>
          <button className="btn primary sm" onClick={onClose}>Done</button>
        </div>
      </div>
    </div>
  );
}

function SongIdCard({ title, setTitle, genres, setGenres, newGenre, setNewGenre, addGenre }) {
  return (
    <div className="song-id">
      <div className="label">Song ID</div>
      <input className="title-input" value={title} onChange={(e) => setTitle(e.target.value)}
             placeholder="Untitled composition" />
      <div className="genre-tags">
        {genres.map((g) => (
          <span key={g} className="genre-tag">
            {g}
            <span className="x" onClick={() => setGenres(genres.filter((x) => x !== g))}>×</span>
          </span>
        ))}
        <input
          value={newGenre}
          onChange={(e) => setNewGenre(e.target.value)}
          onKeyDown={(e) => { if (e.key === 'Enter') addGenre(); }}
          placeholder="+ genre"
          style={{
            background: 'transparent', border: '1px dashed var(--line-2)',
            color: 'var(--ink)', padding: '3px 9px', borderRadius: 2,
            fontFamily: 'var(--f-mono)', fontSize: 10.5, width: 90,
          }}
        />
      </div>
    </div>
  );
}

function EmptyStructureHint({ structuring, hasLyrics }) {
  return (
    <div style={{
      padding: '32px 16px', textAlign: 'center', color: 'var(--ink-4)',
      fontFamily: 'var(--f-display)', fontStyle: 'italic', fontSize: 14, lineHeight: 1.5,
    }}>
      {structuring
        ? 'Reading your lyrics…'
        : hasLyrics
          ? 'Click "Structure with LLM" to identify Intro, Verse, Chorus, Bridge, Outro and Build sections automatically.'
          : 'Write some lyrics first, or add sections manually below.'}
    </div>
  );
}

function SectionRow({ section, selected, onSelect, onUpdate, onDelete, blockTypes, onOpen }) {
  const def = blockTypes.find((b) => b.id === section.type);
  const preview = (section.lines || '').split('\n').find((l) => l.trim()) || '';
  return (
    <div className={`section-row${selected ? ' selected' : ''}`} onClick={onSelect}>
      <span className="grip">⋮⋮</span>
      <span className="typ" onClick={(e) => e.stopPropagation()}>
        <span className="swatch" style={{ background: def?.color }} />
        <select className="type-select"
                value={section.type}
                onChange={(e) => onUpdate({ type: e.target.value })}>
          {blockTypes.map((b) => (
            <option key={b.id} value={b.id}>{b.label}</option>
          ))}
        </select>
      </span>
      <button className="desc-open"
              onClick={(e) => { e.stopPropagation(); onOpen(); }}
              title="Open editor — preview lyrics, add context & vaab">
        <span className="desc-text">
          {preview || <em>Click to add lyrics & context…</em>}
        </span>
        {section.context && <span className="ctx-dot" title="Has context" />}
        <svg width="11" height="11" viewBox="0 0 12 12" fill="none" stroke="currentColor" strokeWidth="1.3" strokeLinecap="round" style={{flexShrink:0,opacity:.5}}>
          <path d="M3 3h6v6M3 9l6-6"/>
        </svg>
      </button>
      <span className="dur">
        <input value={section.dur}
               onChange={(e) => onUpdate({ dur: Math.max(1, parseInt(e.target.value) || 0) })}
               onClick={(e) => e.stopPropagation()} />
        s
      </span>
      <button className="x" onClick={(e) => { e.stopPropagation(); onDelete(); }} title="Remove">
        <svg width="10" height="10" viewBox="0 0 10 10" stroke="currentColor" strokeWidth="1.3" fill="none">
          <path d="M2 2l6 6M8 2l-6 6"/>
        </svg>
      </button>
    </div>
  );
}

function CodeView({ xml }) {
  // crude syntax highlighter
  const html = xml
    .replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
    .replace(/(&lt;!--[\s\S]*?--&gt;)/g, '<span class="com">$1</span>')
    .replace(/(&lt;\/?)([\w-]+)/g, '$1<span class="tag">$2</span>')
    .replace(/(\w+)=(&quot;|")([^&"]*)(&quot;|")/g,
             '<span class="attr">$1</span>=<span class="str">"$3"</span>');
  return <pre className="xml-code" dangerouslySetInnerHTML={{ __html: html }} />;
}

function Timeline({ sections, blockTypes, totalSec, fmt, selected, setSelected }) {
  return (
    <div className="timeline">
      <div className="row">
        <span className="lbl">Timeline</span>
        <span className="total"><span className="lbl">total</span>{fmt(totalSec)}</span>
      </div>
      <div className="timeline-bar">
        {sections.length === 0 && (
          <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center',
                        fontFamily: 'var(--f-mono)', fontSize: 10, color: 'var(--ink-4)',
                        letterSpacing: '.12em', textTransform: 'uppercase' }}>
            no sections
          </div>
        )}
        {sections.map((s) => {
          const def = blockTypes.find((b) => b.id === s.type);
          const w = totalSec > 0 ? (s.dur / totalSec) * 100 : 0;
          return (
            <div key={s.id}
                 className={`timeline-seg${selected && selected !== s.id ? ' dim' : ''}`}
                 onClick={() => setSelected(s.id)}
                 style={{ width: `${w}%`, background: def?.color }}
                 title={`${s.type} · ${s.dur}s`}>
              {w > 6 ? s.type : ''}
            </div>
          );
        })}
      </div>
      <div className="timeline-ticks">
        <span>0:00</span><span>{fmt(totalSec)}</span>
      </div>
    </div>
  );
}

window.XMLStructureEditor = XMLStructureEditor;
