// crm-marketing-builder.jsx — block-based email template designer
// Template = { version:1, blocks:[{id,type,props}] }. The C# MarketingRenderer
// is the source of truth for final email HTML; the canvas here is an
// approximate on-screen preview (exact fidelity is verified by Test Send).

const MKT_BLOCK_DEFS = {
  header:    { label: 'Header',    icon: '🏷️', defaults: { logoUrl: '', bgColor: '#162534' } },
  heading:   { label: 'Heading',   icon: '🔠', defaults: { text: 'Headline goes here', size: 24, align: 'left', color: '#0E1411' } },
  paragraph: { label: 'Paragraph', icon: '📝', defaults: { html: 'Write your message here. Use the toolbar for <b>bold</b>, <i>italics</i> and links, and insert merge tokens like {{firstName}}.', align: 'left' } },
  image:     { label: 'Image',     icon: '🖼️', defaults: { url: '', alt: '', link: '', widthPct: 100 } },
  button:    { label: 'Button',    icon: '🔘', defaults: { label: 'Learn more', url: 'https://www.ctrny.com', bgColor: '#BC141E', textColor: '#FFFFFF', radius: 6, align: 'center' } },
  divider:   { label: 'Divider',   icon: '➖', defaults: { color: '#E5E5E0' } },
  spacer:    { label: 'Spacer',    icon: '↕️', defaults: { height: 24 } },
  columns2:  { label: '2 Columns', icon: '🔳', defaults: { left: { kind: 'text', html: 'Left column text' }, right: { kind: 'text', html: 'Right column text' } } },
  footer:    { label: 'Footer',    icon: '⚓', defaults: { address: 'CTR/NY · New York', note: '' } },
};
const MKT_PALETTE = ['header', 'heading', 'paragraph', 'image', 'button', 'divider', 'spacer', 'columns2'];
const MKT_TOKENS = ['{{firstName}}', '{{name}}', '{{company}}', '{{email}}'];

function mktNewBlock(type) {
  return { id: 'b' + Math.random().toString(36).slice(2, 9), type,
           props: JSON.parse(JSON.stringify(MKT_BLOCK_DEFS[type].defaults)) };
}

function mktParseBlocks(blocksJson) {
  let blocks = [];
  try { blocks = (JSON.parse(blocksJson || '{}').blocks || []).filter(b => MKT_BLOCK_DEFS[b.type]); } catch {}
  if (!blocks.some(b => b.type === 'footer')) blocks = [...blocks, mktNewBlock('footer')];
  return blocks;
}

// Approximate canvas rendering of one block (email-ish, not exact)
function MktBlockPreview({ block }) {
  const p = block.props || {};
  const frag = html => <span dangerouslySetInnerHTML={{ __html: html || '' }} />;
  switch (block.type) {
    case 'header':
      return <div style={{background:p.bgColor||'#162534',padding:'20px 32px',textAlign:'center'}}>
        {p.logoUrl ? <img src={p.logoUrl} alt="logo" style={{height:40}} /> :
          <span style={{color:'rgba(255,255,255,.55)',fontSize:12}}>Header — set a logo in the panel →</span>}
      </div>;
    case 'heading':
      return <div style={{padding:'24px 32px 8px',textAlign:p.align||'left'}}>
        <div style={{fontSize:(p.size||24)+'px',fontWeight:700,color:p.color||'#0E1411',lineHeight:1.25}}>{frag(p.text)}</div>
      </div>;
    case 'paragraph':
      return <div style={{padding:'10px 32px',textAlign:p.align||'left',fontSize:14,lineHeight:1.65,color:'#333F4B'}}>{frag(p.html)}</div>;
    case 'image': {
      const w = Math.round(536 * (p.widthPct||100) / 100);
      return <div style={{padding:'10px 32px',textAlign:'center'}}>
        {p.url ? <img src={p.url} alt={p.alt||''} style={{width:w,maxWidth:'100%'}} /> :
          <div style={{border:'2px dashed #CBD5E1',borderRadius:8,padding:'34px 10px',color:'#94A3B8',fontSize:12}}>Image — upload in the panel →</div>}
      </div>;
    }
    case 'button':
      return <div style={{padding:'16px 32px',textAlign:p.align||'center'}}>
        <span style={{display:'inline-block',background:p.bgColor||'#BC141E',color:p.textColor||'#fff',
          borderRadius:(p.radius??6)+'px',padding:'12px 28px',fontSize:14,fontWeight:700}}>{p.label||'Button'}</span>
      </div>;
    case 'divider':
      return <div style={{padding:'16px 32px'}}><div style={{borderTop:'1px solid '+(p.color||'#E5E5E0')}} /></div>;
    case 'spacer':
      return <div style={{height:(p.height||24)+'px',background:'repeating-linear-gradient(45deg,transparent,transparent 6px,rgba(0,0,0,.02) 6px,rgba(0,0,0,.02) 12px)'}} />;
    case 'columns2': {
      const cell = side => (side||{}).kind === 'image'
        ? (side.url ? <img src={side.url} alt={side.alt||''} style={{width:'100%'}} /> :
            <div style={{border:'2px dashed #CBD5E1',borderRadius:8,padding:'24px 6px',color:'#94A3B8',fontSize:11,textAlign:'center'}}>Image</div>)
        : <div style={{fontSize:14,lineHeight:1.6,color:'#333F4B'}}>{frag((side||{}).html)}</div>;
      return <div style={{padding:'10px 32px',display:'flex',gap:'4%'}}>
        <div style={{width:'48%'}}>{cell(p.left)}</div><div style={{width:'48%'}}>{cell(p.right)}</div>
      </div>;
    }
    case 'footer':
      return <div style={{background:'#F8FAFC',borderTop:'1px solid #E8EDF2',padding:'20px 32px',textAlign:'center',fontSize:11,lineHeight:1.7,color:'#94A3B8'}}>
        {p.address || 'CTR/NY'}<br/>
        {p.note || 'You received this email because you have a business relationship with CTR/NY.'}<br/>
        <span style={{textDecoration:'underline',color:'#64748B'}}>Unsubscribe</span>
        <span style={{marginLeft:6,fontSize:10,background:'#E8EDF2',borderRadius:4,padding:'1px 5px',color:'#64748B'}}>auto link</span>
      </div>;
    default: return null;
  }
}

// Small contentEditable rich fragment editor (bold/italic/link + merge tokens)
function MktRichInput({ value, onChange }) {
  const { useRef, useEffect } = React;
  const ref = useRef(null);
  useEffect(() => {
    if (ref.current && ref.current.innerHTML !== (value || '')) ref.current.innerHTML = value || '';
  }, []);
  const exec = (cmd, arg) => { document.execCommand(cmd, false, arg); ref.current && onChange(ref.current.innerHTML); };
  const insertToken = t => { document.execCommand('insertText', false, t); ref.current && onChange(ref.current.innerHTML); };
  return (
    <div>
      <div style={{display:'flex',gap:4,marginBottom:6,flexWrap:'wrap'}}>
        <button type="button" className="btn btn-ghost btn-sm" style={{fontWeight:800}} onMouseDown={e=>{e.preventDefault();exec('bold');}}>B</button>
        <button type="button" className="btn btn-ghost btn-sm" style={{fontStyle:'italic'}} onMouseDown={e=>{e.preventDefault();exec('italic');}}>I</button>
        <button type="button" className="btn btn-ghost btn-sm" onMouseDown={e=>{e.preventDefault();const u=prompt('Link URL (https://…)');if(u)exec('createLink',u);}}>🔗</button>
        <select className="search-input" style={{height:28,fontSize:11,width:120}} value=""
          onChange={e => { if (e.target.value) insertToken(e.target.value); e.target.value=''; }}>
          <option value="">+ token…</option>
          {MKT_TOKENS.map(t => <option key={t} value={t}>{t}</option>)}
        </select>
      </div>
      <div ref={ref} contentEditable suppressContentEditableWarning
        onInput={e => onChange(e.currentTarget.innerHTML)}
        style={{minHeight:90,border:'1px solid var(--folio-border-strong,#CBD5E1)',borderRadius:8,
                padding:'10px 12px',fontSize:13,lineHeight:1.6,background:'#fff',outline:'none'}} />
    </div>
  );
}

function MktBlockProps({ block, onChange, onUploadImage }) {
  if (!block) return <div style={{color:'var(--g400)',fontSize:12,padding:'18px 4px'}}>Select a block on the canvas to edit it.</div>;
  const p = block.props || {};
  const set = (k, v) => onChange({ ...block, props: { ...p, [k]: v } });
  const setSide = (side, k, v) => onChange({ ...block, props: { ...p, [side]: { ...(p[side]||{}), [k]: v } } });
  const field = (label, el) => <div className="field" style={{marginBottom:10}}><label>{label}</label>{el}</div>;
  const text = (label, k, ph) => field(label, <input value={p[k]||''} placeholder={ph||''} onChange={e=>set(k,e.target.value)} />);
  const color = (label, k, dflt) => field(label,
    <input type="color" value={/^#[0-9a-fA-F]{6}$/.test(p[k]||'') ? p[k] : dflt} onChange={e=>set(k,e.target.value)} style={{height:34,padding:2,width:64}} />);
  const num = (label, k, min, max) => field(label,
    <input type="number" min={min} max={max} value={p[k]??''} onChange={e=>set(k,parseInt(e.target.value)||min)} />);
  const alignSel = () => field('Alignment',
    <select value={p.align||'left'} onChange={e=>set('align',e.target.value)}>
      <option value="left">Left</option><option value="center">Center</option>
    </select>);
  const imgUpload = (k) => field('Image',
    <div>
      {p[k] && <img src={p[k]} alt="" style={{maxWidth:'100%',borderRadius:6,marginBottom:6}} />}
      <input type="file" accept="image/*" onChange={async e => {
        const f = e.target.files[0];
        if (f) { const r = await onUploadImage(f); if (r) set(k, r); }
        e.target.value = '';
      }} />
    </div>);

  switch (block.type) {
    case 'header': return <div>{imgUpload('logoUrl')}{color('Background', 'bgColor', '#162534')}</div>;
    case 'heading': return <div>
      {field('Text', <MktRichInput value={p.text} onChange={v=>set('text',v)} />)}
      {num('Size (px)', 'size', 12, 48)}{alignSel()}{color('Color', 'color', '#0E1411')}
    </div>;
    case 'paragraph': return <div>
      {field('Text', <MktRichInput value={p.html} onChange={v=>set('html',v)} />)}
      {alignSel()}
    </div>;
    case 'image': return <div>
      {imgUpload('url')}
      {text('Alt text', 'alt')}
      {text('Link URL (optional)', 'link', 'https://…')}
      {num('Width %', 'widthPct', 10, 100)}
    </div>;
    case 'button': return <div>
      {text('Label', 'label')}
      {text('URL', 'url', 'https://…')}
      {color('Button color', 'bgColor', '#BC141E')}{color('Text color', 'textColor', '#FFFFFF')}
      {num('Corner radius', 'radius', 0, 30)}{alignSel()}
    </div>;
    case 'divider': return <div>{color('Line color', 'color', '#E5E5E0')}</div>;
    case 'spacer': return <div>{num('Height (px)', 'height', 4, 120)}</div>;
    case 'columns2': return <div>
      {['left','right'].map(side => <div key={side} style={{border:'1px solid var(--folio-border,#E8EDF2)',borderRadius:8,padding:10,marginBottom:10}}>
        <div style={{fontSize:11,fontWeight:700,textTransform:'uppercase',color:'var(--g400)',marginBottom:6}}>{side} column</div>
        {field('Type', <select value={(p[side]||{}).kind||'text'} onChange={e=>setSide(side,'kind',e.target.value)}>
          <option value="text">Text</option><option value="image">Image</option>
        </select>)}
        {((p[side]||{}).kind||'text') === 'text'
          ? field('Text', <MktRichInput value={(p[side]||{}).html} onChange={v=>setSide(side,'html',v)} />)
          : <div>
              {field('Image', <div>
                {(p[side]||{}).url && <img src={p[side].url} alt="" style={{maxWidth:'100%',borderRadius:6,marginBottom:6}} />}
                <input type="file" accept="image/*" onChange={async e => {
                  const f = e.target.files[0];
                  if (f) { const r = await onUploadImage(f); if (r) setSide(side,'url',r); }
                  e.target.value = '';
                }} />
              </div>)}
              {field('Alt text', <input value={(p[side]||{}).alt||''} onChange={e=>setSide(side,'alt',e.target.value)} />)}
            </div>}
      </div>)}
    </div>;
    case 'footer': return <div>
      {text('Company address line', 'address', 'CTR/NY · New York')}
      {field('Note', <textarea rows={3} value={p.note||''} placeholder="You received this email because…" onChange={e=>set('note',e.target.value)} />)}
      <div style={{fontSize:11,color:'var(--g400)',lineHeight:1.5}}>The unsubscribe link is added automatically and can't be removed — it's required for compliance.</div>
    </div>;
    default: return null;
  }
}

function TemplateBuilder({ template, onSave, onClose, showToast }) {
  const { useState, useRef } = React;
  const [name, setName] = useState(template?.name || '');
  const [blocks, setBlocks] = useState(() => mktParseBlocks(template?.blocksJson));
  const [selId, setSelId] = useState(null);
  const [saving, setSaving] = useState(false);
  const [previewHtml, setPreviewHtml] = useState(null);
  const dragRef = useRef(null);

  const sel = blocks.find(b => b.id === selId) || null;
  const setBlock = (nb) => setBlocks(bs => bs.map(b => b.id === nb.id ? nb : b));
  const footerIdx = blocks.findIndex(b => b.type === 'footer');

  const addBlock = (type) => {
    const nb = mktNewBlock(type);
    setBlocks(bs => {
      const fi = bs.findIndex(b => b.type === 'footer');
      const next = [...bs];
      next.splice(fi < 0 ? next.length : fi, 0, nb);   // insert above footer
      return next;
    });
    setSelId(nb.id);
  };
  const removeBlock = (id) => setBlocks(bs => bs.filter(b => b.id !== id || b.type === 'footer'));
  const dupBlock = (b) => {
    const nb = { ...mktNewBlock(b.type), props: JSON.parse(JSON.stringify(b.props)) };
    setBlocks(bs => { const i = bs.findIndex(x => x.id === b.id); const next=[...bs]; next.splice(i+1,0,nb); return next; });
  };
  const move = (id, dir) => setBlocks(bs => {
    const i = bs.findIndex(b => b.id === id);
    const j = i + dir;
    if (i < 0 || j < 0 || j >= bs.length || bs[i].type === 'footer' || bs[j].type === 'footer') return bs;
    const next = [...bs]; [next[i], next[j]] = [next[j], next[i]]; return next;
  });
  const dropOn = (targetId) => {
    const fromId = dragRef.current;
    dragRef.current = null;
    if (!fromId || fromId === targetId) return;
    setBlocks(bs => {
      const from = bs.findIndex(b => b.id === fromId);
      const to = bs.findIndex(b => b.id === targetId);
      if (from < 0 || to < 0 || bs[from].type === 'footer' || bs[to].type === 'footer') return bs;
      const next = [...bs];
      const [m] = next.splice(from, 1);
      next.splice(to, 0, m);
      return next;
    });
  };

  const uploadImage = async (file) => {
    try { return (await CRM.MarketingAPI.uploadAsset(file)).url; }
    catch (e) { showToast('Image upload failed: ' + e.message, 'error'); return null; }
  };

  const blocksJson = () => JSON.stringify({ version: 1, blocks });

  const save = async () => {
    if (!name.trim()) return showToast('Template name is required.', 'error');
    setSaving(true);
    try { await onSave({ name: name.trim(), blocksJson: blocksJson() }); }
    finally { setSaving(false); }
  };

  const showServerPreview = async () => {
    try { setPreviewHtml(await CRM.MarketingAPI.previewHtml(blocksJson())); }
    catch (e) { showToast('Preview failed: ' + e.message, 'error'); }
  };

  return (
    <div className="modal-overlay" style={{zIndex:200}}>
      <div className="modal-panel" style={{maxWidth:1180,width:'96vw'}}>
        <div className="modal-hd" style={{display:'flex',alignItems:'center',gap:12}}>
          <div className="modal-title" style={{flex:'0 0 auto'}}>🧩 Template designer</div>
          <input value={name} onChange={e=>setName(e.target.value)} placeholder="Template name"
            style={{flex:1,maxWidth:340,height:32,border:'1px solid var(--folio-border-strong,#CBD5E1)',borderRadius:8,padding:'0 10px',fontSize:13}} />
          <button className="btn btn-ghost btn-sm" onClick={showServerPreview}>👁 Preview email</button>
          <button className="btn btn-primary btn-sm" onClick={save} disabled={saving}>{saving ? 'Saving…' : '💾 Save template'}</button>
          <button className="btn btn-ghost btn-sm" onClick={onClose}>✕</button>
        </div>
        <div style={{display:'grid',gridTemplateColumns:'150px 1fr 300px',gap:0,height:'calc(100vh - 130px)'}}>

          {/* Palette */}
          <div style={{borderRight:'1px solid var(--folio-border,#E8EDF2)',padding:12,overflowY:'auto'}}>
            <div style={{fontSize:10.5,fontWeight:700,textTransform:'uppercase',letterSpacing:'.06em',color:'var(--g400)',marginBottom:8}}>Blocks</div>
            {MKT_PALETTE.map(t => (
              <button key={t} className="btn btn-ghost btn-sm" style={{width:'100%',justifyContent:'flex-start',marginBottom:6,display:'flex',gap:8}}
                onClick={() => addBlock(t)}>
                <span>{MKT_BLOCK_DEFS[t].icon}</span>{MKT_BLOCK_DEFS[t].label}
              </button>
            ))}
            <div style={{fontSize:10.5,color:'var(--g400)',marginTop:10,lineHeight:1.5}}>Click to add · drag blocks on the canvas to reorder.</div>
          </div>

          {/* Canvas */}
          <div style={{background:'#F1F5F9',overflowY:'auto',padding:'22px 12px'}}>
            <div style={{width:600,maxWidth:'100%',margin:'0 auto',background:'#fff',borderRadius:8,overflow:'hidden',boxShadow:'0 4px 16px rgba(16,30,46,.10)'}}>
              {blocks.map(b => (
                <div key={b.id}
                  draggable={b.type !== 'footer'}
                  onDragStart={() => { dragRef.current = b.id; }}
                  onDragOver={e => e.preventDefault()}
                  onDrop={() => dropOn(b.id)}
                  onClick={() => setSelId(b.id)}
                  style={{position:'relative',cursor:'pointer',
                    outline: selId === b.id ? '2px solid var(--folio-accent-500,#35C1E8)' : '1px dashed transparent',
                    outlineOffset:-2}}>
                  <MktBlockPreview block={b} />
                  {selId === b.id && (
                    <div style={{position:'absolute',top:4,right:4,display:'flex',gap:2,background:'rgba(255,255,255,.95)',borderRadius:6,padding:2,boxShadow:'0 2px 8px rgba(0,0,0,.15)'}}
                      onClick={e => e.stopPropagation()}>
                      {b.type !== 'footer' && <React.Fragment>
                        <button className="btn btn-ghost btn-sm" style={{padding:'2px 7px'}} title="Move up" onClick={()=>move(b.id,-1)}>▲</button>
                        <button className="btn btn-ghost btn-sm" style={{padding:'2px 7px'}} title="Move down" onClick={()=>move(b.id,1)}>▼</button>
                        <button className="btn btn-ghost btn-sm" style={{padding:'2px 7px'}} title="Duplicate" onClick={()=>dupBlock(b)}>⧉</button>
                        <button className="btn btn-ghost btn-sm" style={{padding:'2px 7px',color:'#DC2626'}} title="Delete" onClick={()=>{removeBlock(b.id); if(selId===b.id) setSelId(null);}}>🗑</button>
                      </React.Fragment>}
                      {b.type === 'footer' && <span style={{fontSize:10,color:'var(--g400)',padding:'4px 6px'}}>footer · pinned</span>}
                    </div>
                  )}
                </div>
              ))}
              {blocks.length <= 1 && (
                <div style={{padding:'50px 20px',textAlign:'center',color:'#94A3B8',fontSize:13}}>
                  Add blocks from the left to design your email.
                </div>
              )}
            </div>
            <div style={{textAlign:'center',fontSize:11,color:'var(--g400)',marginTop:10}}>
              Canvas is an approximation — exact rendering is verified by <b>Test Send</b>.
            </div>
          </div>

          {/* Props */}
          <div style={{borderLeft:'1px solid var(--folio-border,#E8EDF2)',padding:14,overflowY:'auto'}}>
            <div style={{fontSize:10.5,fontWeight:700,textTransform:'uppercase',letterSpacing:'.06em',color:'var(--g400)',marginBottom:8}}>
              {sel ? MKT_BLOCK_DEFS[sel.type].label + ' settings' : 'Settings'}
            </div>
            <MktBlockProps block={sel} onChange={setBlock} onUploadImage={uploadImage} />
          </div>
        </div>

        {previewHtml && (
          <div className="modal-overlay" style={{zIndex:300}} onClick={() => setPreviewHtml(null)}>
            <div className="modal-panel" style={{maxWidth:700,width:'92vw'}} onClick={e=>e.stopPropagation()}>
              <div className="modal-hd"><div className="modal-title">Email preview (server-rendered)</div>
                <button className="btn btn-ghost btn-sm" style={{marginLeft:'auto'}} onClick={()=>setPreviewHtml(null)}>✕</button></div>
              <iframe title="preview" srcDoc={previewHtml} style={{width:'100%',height:'70vh',border:0,background:'#F1F5F9'}} />
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { TemplateBuilder });
