/* Custex editor — AI render node body. */
const { useState: uS, useRef: uR, useMemo: uM } = React;
const { NODE_W, PORT_FIRST, PORT_STRIDE } = window.CxGeom;

const { motifRasterDataUrlForAiRender, buildTileMotifsForLayout, layoutNodeIdForAiRender } =
  window.CxMotifPipeline;
const cxLayoutPattern = () => window.CxLayoutPattern || {};

function AiRenderBody({ node, updateNode, graph }) {
  const fileRef = uR(null);
  const d = node.data || {};
  const prompt = d.renderPrompt ?? '';
  const refUrl = d.refImageDataUrl || null;
  const renderResultUrl = d.renderImageDataUrl || d.renderImageUrl || null;
  const [busy, setBusy] = uS(false);
  const [error, setError] = uS('');
  const hasAI = !!window.CxAI?.renderMockup;
  const product = window.CxSchema.PRODUCTS.find((p) => p.id === graph?.nodes?.product?.data?.selected);
  const craft = window.CxSchema.CRAFTS.find((c) => c.id === graph?.nodes?.craft?.data?.type);
  const material = graph?.nodes?.fabric
    ? window.CxSchema.MATERIALS.find((m) => m.id === graph.nodes.fabric.data.materialId)
    : null;
  const motifNode = graph?.nodes?.motif;
  const layoutNode = graph?.nodes?.layout;
  const layoutId = layoutNodeIdForAiRender(graph);
  const layoutData = graph?.nodes?.[layoutId]?.data || {};
  const hasUpstreamMotif = uM(
    () => buildTileMotifsForLayout(graph, layoutId).length > 0,
    [
      graph,
      layoutId,
      layoutData.tile,
      layoutData.scale,
      layoutData.rotate,
      JSON.stringify(layoutData.motifControls || {}),
      motifNode?.data?.motifId,
      motifNode?.data?.generatedImageDataUrl,
      motifNode?.data?.generatedSvg,
    ]
  );

  const onFile = (e) => {
    const f = e.target.files && e.target.files[0];
    if (!f || !/^image\//.test(f.type)) return;
    const reader = new FileReader();
    reader.onload = () => {
      updateNode(node.id, { refImageDataUrl: reader.result, refImageName: f.name });
    };
    reader.readAsDataURL(f);
    e.target.value = '';
  };
  const runRender = async () => {
    if (!hasAI || busy) return;
    setBusy(true);
    setError('');
    try {
      const motifRaster = await motifRasterDataUrlForAiRender(graph);
      if (!motifRaster) {
        throw new Error(
          'No layout pattern — connect Motif → Layout → AI render and arrange the repeat in the Layout node first.'
        );
      }
      const result = await window.CxAI.renderMockup({
        prompt,
        referenceImageDataUrl: refUrl,
        motifImageDataUrl: motifRaster,
        context: {
          productId: product?.id || '',
          productName: product?.name || '',
          craftId: craft?.id || '',
          craftName: craft?.label || '',
          materialId: material?.id || '',
          materialName: material?.name || '',
          motifPrompt: motifNode?.data?.prompt || '',
          motifIds: motifNode?.data?.motifIds || [motifNode?.data?.motifId].filter(Boolean),
          layout: layoutNode?.data || {},
        },
      });
      updateNode(node.id, {
        renderImageDataUrl: result.imageDataUrl || '',
        renderImageUrl: result.imageUrl || '',
        renderPrompt: prompt,
        renderRevisedPrompt: result.revisedPrompt || '',
        renderError: '',
        renderUpdatedAt: new Date().toISOString(),
      });
    } catch (e) {
      const msg = e?.message || 'Render request failed';
      setError(msg);
      updateNode(node.id, { renderError: msg });
    } finally {
      setBusy(false);
    }
  };
  return (
    <>
      <div className="cx-field-l">Scene &amp; lighting</div>
      <textarea
        className="cx-textarea cx-textarea-compact"
        rows={3}
        placeholder="Describe the real-world shot: room, light, product framing, mood…"
        value={prompt}
        onChange={(e) => updateNode(node.id, { renderPrompt: e.target.value })}
      />
      <div className="cx-field-l">Layout pattern <span className="cx-field-optional">arranged repeat</span></div>
      <div className="cx-airender-pattern-preview">
        {React.createElement(cxLayoutPattern().CxLayoutPatternVessel || (() => null), {
          graph,
          layoutId,
          className: 'cx-airender-pattern-vessel',
          vesselStyle: { width: '100%', height: '100%' },
          emptyMessage: 'Arrange the repeat in Layout — preview matches the right panel',
        })}
      </div>
      <div className="cx-field-l">Reference photo <span className="cx-field-optional">optional</span></div>
      <div className="cx-render-upload">
        <button type="button" className="cx-render-filebtn" onClick={() => fileRef.current && fileRef.current.click()}>
          Upload image
        </button>
        <input ref={fileRef} type="file" accept="image/*" className="cx-hidden-file" onChange={onFile} />
        {refUrl && (
          <div className="cx-render-preview">
            <img src={refUrl} alt="" className="cx-render-thumb" />
            <button type="button" className="cx-render-clear" onClick={() => updateNode(node.id, { refImageDataUrl: null, refImageName: '' })}>
              Remove
            </button>
          </div>
        )}
      </div>
      <div className="cx-field-l">Result preview</div>
      <div className="cx-airender-preview">
        {busy ? (
          <div className="cx-spinner" />
        ) : renderResultUrl ? (
          <img src={renderResultUrl} alt="" className="cx-airender-preview-img" />
        ) : (
          <span className="cx-airender-preview-placeholder">No render yet</span>
        )}
      </div>
      <div className="cx-row">
        <button type="button" className="cx-btn-ghost" disabled={!hasAI || busy || !hasUpstreamMotif} onClick={runRender}>
          {busy ? 'Rendering…' : 'Render with AI'}
        </button>
        <button
          type="button"
          className="cx-btn-ghost"
          disabled={!renderResultUrl}
          onClick={() => updateNode(node.id, { renderImageDataUrl: '', renderImageUrl: '', renderError: '' })}
        >
          Clear result
        </button>
      </div>
      {error ? <p className="cx-render-note cx-render-note-err">{error}</p> : null}
      {!hasUpstreamMotif ? (
        <p className="cx-render-note cx-render-note-warn">Set up Motif → Layout → AI render. Render uses your final tiled layout (scale, repeat, rotation) — not a single motif tile.</p>
      ) : (
        <p className="cx-render-note">Same layout engine as Live preview on the right. Scene text and reference photo only control lighting and framing.</p>
      )}
    </>
  );
}
window.CxNodeBodiesAi = { AiRenderBody };
