// KLIK Configurator — interactive builder + AI photorealistic render

const { useState, useEffect, useMemo, useRef } = React;

const STORAGE_KEY = 'klik.config.v1';

const DEFAULT_CONFIG = {
  head: 'H-CHAMBER', headMat: 'brushed-copper',
  tubes: [{ id: 'T-16-S', mat: 'brushed-steel' }],
  mouthpiece: 'M-MEDIUM', mouthpieceMat: 'polished-steel',
};

function loadConfig() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (!raw) return DEFAULT_CONFIG;
    const p = JSON.parse(raw);
    if (!p.head || !p.tubes || !p.mouthpiece) return DEFAULT_CONFIG;
    return p;
  } catch(e) { return DEFAULT_CONFIG; }
}

// ─── Assembled preview SVG ──────────────────────────────────────────────────
function AssembledPreview({ config, snapKey }) {
  const allParts = window.rebuildPartsById();
  const head  = allParts[config.head];
  const mouth = allParts[config.mouthpiece];
  if (!head || !mouth) return null;

  const tubes = config.tubes.map(t => ({ part: allParts[t.id], mat: t.mat })).filter(t => t.part);
  const segments = [
    { kind:'head',  part:head,  mat:config.headMat },
    ...tubes.map(t => ({ kind:'tube', part:t.part, mat:t.mat })),
    { kind:'mouth', part:mouth, mat:config.mouthpieceMat },
  ];

  // ── Contact-point alignment ──────────────────────────────────────────────
  // Each segment is placed so its leftContact aligns exactly with the previous
  // segment's rightContact. This eliminates the hardcoded overlap that caused
  // parts to visually collide or gap.
  const placed = [];
  let cursorX = 0; // tracks the right contact x in global coordinates

  segments.forEach((s, i) => {
    const c = window.getContacts(s.kind, s.part);
    let offset;
    if (i === 0) {
      // First segment (head) — place at x=0
      offset = 0;
      cursorX = c.right; // global x of the head's right contact
    } else {
      // Place so this segment's leftContact lands on cursorX
      offset = cursorX - c.left;
      cursorX = offset + c.right; // advance cursor to this segment's right contact
    }
    placed.push({ ...s, offset });
  });

  // Total canvas width = offset of last segment + its vbWidth
  const last = placed[placed.length - 1];
  const totalW = last.offset + last.part.vbWidth;

  return (
    <svg viewBox={`0 0 ${totalW} 200`} style={{width:'100%',height:'100%',display:'block'}} preserveAspectRatio="xMidYMid meet">
      <line x1={0} y1={100} x2={totalW} y2={100} stroke="#7fd4ff" strokeWidth={0.35} strokeDasharray="6 3 1 3" opacity={0.25}/>
      {placed.map((s,i) => (
        <g key={i} transform={`translate(${s.offset} 0)`} className="klik-segment">
          {s.kind==='head'  && <window.HeadGeo        part={s.part} material={s.mat}/>}
          {s.kind==='tube'  && <window.TubeGeo         part={s.part} material={s.mat}/>}
          {s.kind==='mouth' && <window.MouthpieceGeo   part={s.part} material={s.mat}/>}
        </g>
      ))}
    </svg>
  );
}

// ─── AI Render Panel ────────────────────────────────────────────────────────
function RenderPanel({ config }) {
  const [status, setStatus] = useState('idle'); // idle | loading | done | error
  const [imgUrl, setImgUrl] = useState(null);
  const [prompt, setPrompt] = useState('');
  const [err, setErr] = useState('');

  const allParts = window.rebuildPartsById();
  const head  = allParts[config.head];
  const mouth = allParts[config.mouthpiece];
  const mats  = window.MATERIALS;

  async function generateRender() {
    if (!head || !mouth) return;
    setStatus('loading'); setErr(''); setImgUrl(null);

    const tubeData = config.tubes.map(t => {
      const p = allParts[t.id];
      return p ? { diameter: p.diameter, length: p.lengthIn, mat: t.mat } : null;
    }).filter(Boolean);

    const headMatName  = mats[config.headMat]?.name  || config.headMat;
    const mouthMatName = mats[config.mouthpieceMat]?.name || config.mouthpieceMat;
    const tubeDesc = tubeData.map(t => `${t.diameter}mm × ${t.length} ${mats[t.mat]?.name||t.mat}`).join(' + ');

    // Build the prompt client-side for the image generation API
    const renderPrompt = `Ultra-photorealistic professional product photography of a precision modular pipe on a dark matte obsidian surface. The assembled pipe consists of a ${headMatName} ${head.name} bowl head on the left (${head.capacity} capacity), connected via a visible N52 neodymium magnetic ring joint with a silicone O-ring to ${tubeDesc} tube, then connected to a ${mouthMatName} ${mouth.name} tapered mouthpiece. The magnetic joints are clearly visible as precision-machined rings. Shot at a 3/4 angle, soft studio rim lighting, razor-sharp focus, product catalog photography, neutral charcoal gradient background, 8K detail, --ar 16:9`;

    setPrompt(renderPrompt);

    try {
      // Call our backend render endpoint
      const res = await fetch('/api/render', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          headName: head.name, headMat: config.headMat,
          tubes: tubeData, mouthpieceName: mouth.name, mouthpieceMat: config.mouthpieceMat
        }),
      });
      const data = await res.json();
      if (data.success && data.url) {
        setImgUrl(data.url);
        setStatus('done');
      } else {
        // Backend unavailable — use Genspark image generation directly from frontend
        await generateDirectly(renderPrompt);
      }
    } catch(e) {
      await generateDirectly(renderPrompt);
    }
  }

  async function generateDirectly(renderPrompt) {
    // Call Genspark public image generation
    try {
      const res = await fetch('https://www.genspark.ai/api/image-generation/generate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          model: 'nano-banana-2',
          prompt: renderPrompt,
          aspect_ratio: '16:9',
          image_size: '1k',
        }),
      });
      if (!res.ok) throw new Error('API error');
      const data = await res.json();
      const url = data.image_urls?.[0] || data.image_urls_nowatermark?.[0];
      if (url) { setImgUrl(url); setStatus('done'); }
      else throw new Error('No image URL');
    } catch(e) {
      setStatus('error');
      setErr('Render service unavailable. The prompt is shown below — paste it into any image generation tool.');
    }
  }

  return (
    <div className="klik-render-panel">
      <div className="klik-render-header">
        <div>
          <div className="klik-render-eyebrow">AI PHOTOREALISTIC RENDER</div>
          <div className="klik-render-subtitle">Generate a studio-quality photo of your build</div>
        </div>
        <button
          className={"klik-render-btn " + (status==='loading' ? 'is-loading' : '')}
          onClick={generateRender}
          disabled={status==='loading'}
        >
          {status==='loading' ? (
            <><span className="klik-render-spinner"/>RENDERING…</>
          ) : (
            <>✦ GENERATE RENDER</>
          )}
        </button>
      </div>

      {status==='idle' && (
        <div className="klik-render-placeholder">
          <div className="klik-render-ph-inner">
            <svg width="48" height="48" viewBox="0 0 48 48" fill="none">
              <rect x="4" y="12" width="40" height="28" rx="2" stroke="#7fd4ff" strokeWidth="1" strokeDasharray="3 2" opacity="0.4"/>
              <circle cx="16" cy="22" r="4" stroke="#7fd4ff" strokeWidth="1" opacity="0.5"/>
              <path d="M4 32 L14 22 L22 30 L30 20 L44 32" stroke="#7fd4ff" strokeWidth="1" opacity="0.5"/>
              <path d="M20 24 L26 18 L34 26" stroke="#e8a878" strokeWidth="0.8" opacity="0.6"/>
            </svg>
            <div className="klik-render-ph-label">Click GENERATE RENDER to create a photorealistic image of your KLIK configuration</div>
          </div>
        </div>
      )}

      {status==='loading' && (
        <div className="klik-render-placeholder klik-render-placeholder--loading">
          <div className="klik-render-ph-inner">
            <div className="klik-render-pulse-ring"/>
            <div className="klik-render-ph-label">Generating photorealistic render…<br/><span style={{fontSize:'10px',opacity:0.5}}>Usually takes 20–40 seconds</span></div>
          </div>
        </div>
      )}

      {status==='done' && imgUrl && (
        <div className="klik-render-result">
          <img src={imgUrl} alt="AI photorealistic render of your KLIK configuration" className="klik-render-img"/>
          <div className="klik-render-result-foot">
            <span className="klik-render-eyebrow">AI-GENERATED RENDER · SYSTEM.01</span>
            <a href={imgUrl} target="_blank" rel="noopener" className="klik-render-download">↗ OPEN FULL SIZE</a>
          </div>
        </div>
      )}

      {status==='error' && (
        <div className="klik-render-error">
          <div className="klik-render-error-label">⚠ {err}</div>
          {prompt && <div className="klik-render-prompt-box"><div className="klik-render-prompt-label">PROMPT</div><div className="klik-render-prompt-text">{prompt}</div></div>}
        </div>
      )}
    </div>
  );
}

// ─── Option card ────────────────────────────────────────────────────────────
function OptCard({ active, onClick, children, accent='#7fd4ff' }) {
  return (
    <button onClick={onClick} className={"klik-opt "+(active?'is-active':'')} style={{borderColor:active?accent:'rgba(127,212,255,0.18)'}}>
      {children}
      {active && <span className="klik-opt-tick" style={{background:accent}}/>}
    </button>
  );
}

// ─── Material picker ────────────────────────────────────────────────────────
function MaterialPicker({ value, onChange, label='MATERIAL' }) {
  return (
    <div className="klik-mat-row">
      <div className="klik-mat-label">{label}</div>
      <div className="klik-mat-swatches">
        {Object.entries(window.MATERIALS).map(([key,m]) => (
          <button key={key} onClick={() => onChange(key)} className={"klik-swatch "+(value===key?'is-active':'')} title={m.name} style={{background:m.swatch}}>
            {value===key && <span className="klik-swatch-tick"/>}
          </button>
        ))}
      </div>
    </div>
  );
}

// ─── Step ───────────────────────────────────────────────────────────────────
function Step({ n, title, subtitle, children }) {
  return (
    <section className="klik-step">
      <div className="klik-step-head">
        <span className="klik-step-num">{n}</span>
        <div><h3 className="klik-step-title">{title}</h3><div className="klik-step-sub">{subtitle}</div></div>
      </div>
      <div className="klik-step-body">{children}</div>
    </section>
  );
}

// ─── Main configurator ──────────────────────────────────────────────────────
function Configurator() {
  const [config, setConfig]   = useState(loadConfig);
  const [snapKey, setSnapKey] = useState(0);
  // Re-read catalog every render so admin edits propagate
  const catalog   = window._getCatalog();
  const allParts  = window.rebuildPartsById();

  useEffect(() => {
    try { localStorage.setItem(STORAGE_KEY, JSON.stringify(config)); } catch(e) {}
  }, [config]);

  const bump = () => setSnapKey(k => k+1);

  // Ensure selected parts still exist in catalog
  useEffect(() => {
    const ap = window.rebuildPartsById();
    let changed = false;
    let next = {...config};
    if (!ap[config.head]) { next.head = catalog.heads[0]?.id || next.head; changed=true; }
    if (!ap[config.mouthpiece]) { next.mouthpiece = catalog.mouthpieces[0]?.id || next.mouthpiece; changed=true; }
    next.tubes = config.tubes.filter(t => ap[t.id]);
    if (next.tubes.length === 0) { next.tubes = [{id:catalog.tubes[0]?.id, mat:'brushed-steel'}]; changed=true; }
    if (changed) setConfig(next);
  }, [catalog]);

  const head  = allParts[config.head];
  const mouth = allParts[config.mouthpiece];
  const tubes = config.tubes.map(t => allParts[t.id]).filter(Boolean);

  const totalLengthMm = useMemo(() => {
    if (!head || !mouth) return 0;
    const headLen  = head.id.includes('COMPACT') ? 60 : head.id.includes('WIDE') ? 90 : 80;
    const mouthLen = mouth.id.includes('SMALL') ? 50 : mouth.id.includes('LARGE') ? 70 : 60;
    return headLen + tubes.reduce((s,t)=>s+t.lengthMm,0) + mouthLen;
  }, [config]);

  const totalWeight = useMemo(() => {
    if (!head || !mouth) return 0;
    return head.weight + tubes.reduce((s,t)=>s+t.weight,0) + mouth.weight + tubes.length*8;
  }, [config]);

  const totalPrice = useMemo(() => {
    if (!head || !mouth) return 0;
    return head.price + tubes.reduce((s,t)=>s+t.price,0) + mouth.price + 18;
  }, [config]);

  const setHead     = id  => { setConfig(c=>({...c,head:id})); bump(); };
  const setHeadMat  = mat => { setConfig(c=>({...c,headMat:mat})); bump(); };
  const setTube     = (idx,id)  => { setConfig(c=>({...c,tubes:c.tubes.map((t,i)=>i===idx?{...t,id}:t)})); bump(); };
  const setTubeMat  = (idx,mat) => { setConfig(c=>({...c,tubes:c.tubes.map((t,i)=>i===idx?{...t,mat}:t)})); bump(); };
  const addTube     = () => { if(config.tubes.length<4) { setConfig(c=>({...c,tubes:[...c.tubes,{id:catalog.tubes[0]?.id||'T-16-S',mat:'brushed-steel'}]})); bump(); }};
  const removeTube  = idx => { if(config.tubes.length>1) { setConfig(c=>({...c,tubes:c.tubes.filter((_,i)=>i!==idx)})); bump(); }};
  const setMouth    = id  => { setConfig(c=>({...c,mouthpiece:id})); bump(); };
  const setMouthMat = mat => { setConfig(c=>({...c,mouthpieceMat:mat})); bump(); };
  const reset = () => { setConfig(DEFAULT_CONFIG); bump(); };

  if (!head || !mouth) return <div style={{color:'var(--bp-text-dim)',padding:32,fontFamily:'var(--bp-mono)',fontSize:13}}>No parts in catalog. Go to <a href="/admin" style={{color:'var(--bp-line)'}}>Admin</a> to add parts.</div>;

  return (
    <div style={{display:'flex',flexDirection:'column',gap:32}}>
      <div className="klik-config">
        {/* LEFT: preview */}
        <div className="klik-preview-pane">
          <div className="klik-preview-header">
            <div className="klik-preview-eyebrow">KLIK / LIVE BUILD</div>
            <div className="klik-preview-id">CFG-{(snapKey%9999).toString().padStart(4,'0')}</div>
          </div>
          <div className="klik-preview-stage" key={snapKey}>
            <AssembledPreview config={config} snapKey={snapKey}/>
          </div>
          <div className="klik-preview-foot">
            <div className="klik-foot-col">
              <div className="klik-foot-label">TOTAL LENGTH</div>
              <div className="klik-foot-val">{totalLengthMm} <span className="klik-foot-unit">mm</span></div>
              <div className="klik-foot-sub">{(totalLengthMm/25.4).toFixed(2)}″</div>
            </div>
            <div className="klik-foot-col">
              <div className="klik-foot-label">WEIGHT</div>
              <div className="klik-foot-val">{totalWeight} <span className="klik-foot-unit">g</span></div>
              <div className="klik-foot-sub">{(totalWeight/28.35).toFixed(2)} oz</div>
            </div>
            <div className="klik-foot-col">
              <div className="klik-foot-label">PARTS</div>
              <div className="klik-foot-val">{2+tubes.length}</div>
              <div className="klik-foot-sub">{tubes.length+1} joints</div>
            </div>
            <div className="klik-foot-col klik-foot-price">
              <div className="klik-foot-label">PRICE</div>
              <div className="klik-foot-val">${totalPrice}</div>
              <div className="klik-foot-sub">incl. hardware</div>
            </div>
          </div>
        </div>

        {/* RIGHT: steps */}
        <div className="klik-steps-pane">
          <div className="klik-steps-header">
            <div>
              <div className="klik-steps-eyebrow">SYSTEM.01 / BUILDER</div>
              <h2 className="klik-steps-title">Configure your KLIK</h2>
            </div>
            <button className="klik-reset" onClick={reset}>↻ Reset</button>
          </div>

          <Step n="01" title="Head" subtitle="The bowl. Where it starts.">
            <div className="klik-opts klik-opts-3">
              {catalog.heads.map(h => (
                <OptCard key={h.id} active={config.head===h.id} onClick={()=>setHead(h.id)}>
                  <div className="klik-opt-thumb">
                    <svg viewBox={`0 0 ${h.vbWidth} 200`} style={{width:'100%',height:'100%'}}>
                      <window.HeadGeo part={h} material={config.headMat}/>
                    </svg>
                  </div>
                  <div className="klik-opt-name">{h.name}</div>
                  <div className="klik-opt-meta">{h.capacity} · ${h.price}</div>
                </OptCard>
              ))}
            </div>
            <MaterialPicker value={config.headMat} onChange={setHeadMat}/>
          </Step>

          <Step n="02" title="Tubes" subtitle={`Stack up to 4. Currently ${tubes.length}.`}>
            {config.tubes.map((t,idx) => {
              const tubePart = allParts[t.id];
              return (
                <div key={idx} className="klik-tube-slot">
                  <div className="klik-tube-slot-head">
                    <span className="klik-tube-slot-num">T{idx+1}</span>
                    {config.tubes.length>1 && <button className="klik-tube-remove" onClick={()=>removeTube(idx)}>× remove</button>}
                  </div>
                  <div className="klik-opts klik-opts-4 klik-opts-compact">
                    {catalog.tubes.map(tb => (
                      <OptCard key={tb.id} active={t.id===tb.id} onClick={()=>setTube(idx,tb.id)}>
                        <div className="klik-tube-thumb">
                          <svg viewBox={`0 0 ${tb.vbWidth} 200`} preserveAspectRatio="xMidYMid meet" style={{width:'100%',height:'100%'}}>
                            <window.TubeGeo part={tb} material={t.mat}/>
                          </svg>
                        </div>
                        <div className="klik-opt-name-sm">{tb.diameter}mm · {tb.lengthIn}</div>
                        <div className="klik-opt-meta-sm">${tb.price}</div>
                      </OptCard>
                    ))}
                  </div>
                  <MaterialPicker value={t.mat} onChange={(m)=>setTubeMat(idx,m)} label={`T${idx+1} MATERIAL`}/>
                </div>
              );
            })}
            {config.tubes.length<4 && catalog.tubes.length>0 && (
              <button className="klik-add-tube" onClick={addTube}>+ Add another tube ({4-config.tubes.length} remaining)</button>
            )}
          </Step>

          <Step n="03" title="Mouthpiece" subtitle="Three sizes. Three draws.">
            <div className="klik-opts klik-opts-3">
              {catalog.mouthpieces.map(m => (
                <OptCard key={m.id} active={config.mouthpiece===m.id} onClick={()=>setMouth(m.id)}>
                  <div className="klik-opt-thumb">
                    <svg viewBox={`0 0 ${m.vbWidth} 200`} preserveAspectRatio="xMidYMid meet" style={{width:'100%',height:'100%'}}>
                      <window.MouthpieceGeo part={m} material={config.mouthpieceMat}/>
                    </svg>
                  </div>
                  <div className="klik-opt-name">{m.name}</div>
                  <div className="klik-opt-meta">{m.desc.split('.')[0]} · ${m.price}</div>
                </OptCard>
              ))}
            </div>
            <MaterialPicker value={config.mouthpieceMat} onChange={setMouthMat}/>
          </Step>

          <div className="klik-cta-row">
            <button className="klik-cta-primary">
              <span>RESERVE THIS BUILD — ${totalPrice}</span>
              <span className="klik-cta-arrow">→</span>
            </button>
            <button className="klik-cta-secondary">SHARE</button>
          </div>
          <div className="klik-cta-note">Ships in 4–6 weeks · 5yr warranty on hardware · Free replacements on magnets &amp; o-rings</div>
        </div>
      </div>

      {/* AI RENDER PANEL — full width below configurator */}
      <RenderPanel config={config}/>
    </div>
  );
}

Object.assign(window, { Configurator, AssembledPreview, RenderPanel });
