// sketchy.jsx — lo-fi wireframe primitives + lang/anno contexts
// Loaded BEFORE wf-*.jsx files. Exports to window.

// ─── Contexts ──────────────────────────────────────────────────────
const LangContext = React.createContext('mn');
const LangSetContext = React.createContext(() => {}); // setter so the Nav toggle can flip language
const AnnoContext = React.createContext(true);

// <L mn="..." en="..." /> — picks one based on context
function L({ mn, en }) {
  const lang = React.useContext(LangContext);
  return lang === 'mn' ? mn : en;
}

// <Anno> — margin annotation, only shows when annotations enabled
function Anno({ mn, en, color = 'red', style, children }) {
  const show = React.useContext(AnnoContext);
  if (!show) return null;
  const c = color === 'blue' ? '#2b4ec9' : '#c92b2b';
  return (
    <span className="anno" style={{ color: c, ...style }}>
      {children ?? <L mn={mn} en={en} />}
    </span>
  );
}

// AnnoArrow — small arrow + label, absolutely positioned via style prop
function AnnoArrow({ mn, en, dir = 'left', color = 'red', children, style }) {
  const show = React.useContext(AnnoContext);
  if (!show) return null;
  const c = color === 'blue' ? '#2b4ec9' : '#c92b2b';
  return (
    <div className="anno" style={{ position: 'absolute', color: c, display: 'flex', alignItems: 'center', gap: 4, ...style }}>
      {dir === 'left' && <span style={{ fontSize: 18, lineHeight: 1 }}>↳</span>}
      <span style={{ whiteSpace: 'pre-line' }}>{children ?? <L mn={mn} en={en} />}</span>
      {dir === 'right' && <span style={{ fontSize: 18, lineHeight: 1 }}>↲</span>}
    </div>
  );
}

// ─── Wobble path generator ─────────────────────────────────────────
// Deterministic per-corner-coords so the same box renders identically.
function roughPath(x, y, w, h, jitter = 1.6, seed = 0) {
  const seg = Math.max(8, Math.round((w + h) / 30));
  const r = (i, side) =>
    (Math.sin((i + 1) * 1.7 + side * 2.3 + seed * 0.9) +
      Math.sin((i + 1) * 0.7 + side * 1.1 + seed * 1.7)) *
    0.5 *
    jitter;
  const pts = [];
  for (let i = 0; i <= seg; i++) { const t = i / seg; pts.push([x + t * w, y + r(i, 0)]); }
  for (let i = 1; i <= seg; i++) { const t = i / seg; pts.push([x + w + r(i, 1), y + t * h]); }
  for (let i = 1; i <= seg; i++) { const t = i / seg; pts.push([x + w - t * w, y + h + r(i, 2)]); }
  for (let i = 1; i <  seg; i++) { const t = i / seg; pts.push([x + r(i, 3), y + h - t * h]); }
  return 'M' + pts.map((p) => p[0].toFixed(2) + ',' + p[1].toFixed(2)).join(' L') + ' Z';
}

function roughLine(x1, y1, x2, y2, jitter = 1.4, seed = 0) {
  const dx = x2 - x1, dy = y2 - y1;
  const len = Math.hypot(dx, dy);
  const seg = Math.max(6, Math.round(len / 18));
  const nx = -dy / len, ny = dx / len;
  const pts = [];
  for (let i = 0; i <= seg; i++) {
    const t = i / seg;
    const j = (Math.sin(i * 1.7 + seed) + Math.sin(i * 0.6 + seed * 2)) * 0.5 * jitter;
    pts.push([x1 + dx * t + nx * j, y1 + dy * t + ny * j]);
  }
  return 'M' + pts.map((p) => p[0].toFixed(2) + ',' + p[1].toFixed(2)).join(' L');
}

// ─── SketchBox — div with hand-drawn rect border ───────────────────
function SketchBox({
  children,
  style,
  className,
  jitter = 1.6,
  seed = 0,
  fill = 'transparent',
  fillColor = null,
  stroke = '#1a1a1f',
  strokeWidth = 1.4,
  dashed = false,
  doubled = false,
  inset = 2, // padding inside SVG so stroke isn't clipped
  ...rest
}) {
  const ref = React.useRef(null);
  const [size, setSize] = React.useState({ w: 0, h: 0 });
  React.useLayoutEffect(() => {
    if (!ref.current) return;
    const el = ref.current;
    const measure = () => setSize({ w: el.offsetWidth, h: el.offsetHeight });
    measure();
    const ro = new ResizeObserver(measure);
    ro.observe(el);
    return () => ro.disconnect();
  }, []);
  return (
    <div ref={ref} className={className} style={{ position: 'relative', ...style }} {...rest}>
      {size.w > 0 && (
        <svg
          style={{ position: 'absolute', inset: 0, pointerEvents: 'none', overflow: 'visible' }}
          width={size.w} height={size.h}
          viewBox={`0 0 ${size.w} ${size.h}`}
          fill="none"
        >
          {fillColor && <path d={roughPath(inset, inset, size.w - inset * 2, size.h - inset * 2, jitter, seed)} fill={fillColor} stroke="none" />}
          <path
            d={roughPath(inset, inset, size.w - inset * 2, size.h - inset * 2, jitter, seed)}
            stroke={stroke}
            strokeWidth={strokeWidth}
            strokeDasharray={dashed ? '5,4' : undefined}
            strokeLinejoin="round"
            strokeLinecap="round"
          />
          {doubled && (
            <path
              d={roughPath(inset + 3, inset + 3, size.w - inset * 2 - 6, size.h - inset * 2 - 6, jitter * 0.7, seed + 4)}
              stroke={stroke}
              strokeWidth={strokeWidth * 0.7}
              strokeLinejoin="round"
              strokeLinecap="round"
            />
          )}
        </svg>
      )}
      {children}
    </div>
  );
}

// SketchLine — hand-drawn horizontal/vertical line element
function SketchLine({ orientation = 'h', length = '100%', jitter = 1.2, seed = 0, stroke = '#1a1a1f', strokeWidth = 1.3, style, dashed = false }) {
  const isH = orientation === 'h';
  return (
    <div style={{ position: 'relative', width: isH ? length : 4, height: isH ? 4 : length, ...style }}>
      <svg
        style={{ position: 'absolute', inset: 0, overflow: 'visible' }}
        width="100%" height="100%" preserveAspectRatio="none"
      >
        <line
          x1={isH ? '0' : '2'} y1={isH ? '2' : '0'}
          x2={isH ? '100%' : '2'} y2={isH ? '2' : '100%'}
          stroke={stroke} strokeWidth={strokeWidth}
          strokeDasharray={dashed ? '5,4' : undefined}
          strokeLinecap="round"
        />
      </svg>
    </div>
  );
}

// Placeholder — dashed box with X and a label inside
function Placeholder({ label, sublabel, style, jitter = 1.4, ratio, mn, en }) {
  return (
    <SketchBox style={{ ...style }} dashed jitter={jitter} stroke="#6b6b7a">
      <div style={{ position: 'absolute', inset: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', textAlign: 'center', padding: 8, color: '#6b6b7a' }}>
        <svg width="100%" height="100%" style={{ position: 'absolute', inset: 0, pointerEvents: 'none', opacity: 0.35 }} preserveAspectRatio="none">
          <line x1="6%" y1="6%" x2="94%" y2="94%" stroke="#6b6b7a" strokeWidth="1" />
          <line x1="94%" y1="6%" x2="6%" y2="94%" stroke="#6b6b7a" strokeWidth="1" />
        </svg>
        <div className="mono" style={{ position: 'relative', maxWidth: '90%' }}>
          {mn || en ? <L mn={mn} en={en} /> : label}
        </div>
        {sublabel && <div className="mono" style={{ position: 'relative', marginTop: 4, opacity: 0.7 }}>{sublabel}</div>}
      </div>
    </SketchBox>
  );
}

// Scribble — fake squiggly text line (for ipsum body copy)
function Scribble({ length = 100, lines = 1, gap = 6, density = 1, color = '#1a1a1f', strokeWidth = 1.2, style }) {
  const items = [];
  for (let i = 0; i < lines; i++) {
    const w = i === lines - 1 && lines > 1 ? length * (0.5 + Math.sin(i + 1) * 0.2) : length;
    items.push(
      <svg key={i} width={w} height={6} style={{ display: 'block', overflow: 'visible' }}>
        <path
          d={(() => {
            const seg = Math.max(8, Math.floor(w / 6 * density));
            const pts = [];
            for (let k = 0; k <= seg; k++) {
              const t = k / seg;
              const y = 3 + Math.sin(k * 1.2 + i * 0.8) * 1.4;
              pts.push([t * w, y]);
            }
            return 'M' + pts.map((p) => p[0].toFixed(2) + ',' + p[1].toFixed(2)).join(' L');
          })()}
          fill="none" stroke={color} strokeWidth={strokeWidth} strokeLinecap="round"
        />
      </svg>
    );
  }
  return <div style={{ display: 'flex', flexDirection: 'column', gap, ...style }}>{items}</div>;
}

// Avatar — circle placeholder
function Avatar({ size = 32, label, style }) {
  return (
    <div style={{ position: 'relative', width: size, height: size, flex: '0 0 auto', ...style }}>
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ overflow: 'visible' }}>
        {(() => {
          const cx = size / 2, cy = size / 2, r = size / 2 - 1;
          const seg = 24;
          const pts = [];
          for (let i = 0; i <= seg; i++) {
            const a = (i / seg) * Math.PI * 2;
            const rr = r + Math.sin(i * 1.7) * 0.6;
            pts.push([cx + Math.cos(a) * rr, cy + Math.sin(a) * rr]);
          }
          return <path d={'M' + pts.map((p) => p[0].toFixed(2) + ',' + p[1].toFixed(2)).join(' L') + ' Z'} fill="#eae6dc" stroke="#1a1a1f" strokeWidth="1.2" />;
        })()}
        {label && (
          <text x="50%" y="54%" textAnchor="middle" dominantBaseline="middle" style={{ fontSize: size * 0.4, fontFamily: 'Patrick Hand, cursive', fill: '#1a1a1f' }}>{label}</text>
        )}
      </svg>
    </div>
  );
}

// Chip / button placeholder pill
function Chip({ children, filled = false, style, mn, en }) {
  return (
    <SketchBox
      style={{ display: 'inline-flex', padding: '6px 12px', ...style }}
      jitter={1.1}
      fillColor={filled ? '#1a1a1f' : null}
      stroke="#1a1a1f"
    >
      <span style={{ fontFamily: 'Patrick Hand, cursive', fontSize: 14, color: filled ? '#faf7f0' : '#1a1a1f', position: 'relative' }}>
        {(mn || en) ? <L mn={mn} en={en} /> : children}
      </span>
    </SketchBox>
  );
}

// Headline text helper — H1-ish, hand drawn weight
function Headline({ children, size = 36, color = '#1a1a1f', style }) {
  return (
    <div style={{ fontFamily: 'Patrick Hand, cursive', fontSize: size, lineHeight: 1.05, color, letterSpacing: '-0.01em', ...style }}>
      {children}
    </div>
  );
}

// Caret label / mono section tag in margin
function Tag({ children, mn, en, color = '#6b6b7a', style }) {
  return (
    <div className="mono" style={{ color, ...style }}>
      {(mn || en) ? <L mn={mn} en={en} /> : children}
    </div>
  );
}

// ─── Device frames ─────────────────────────────────────────────────
// DesktopFrame — laptop window with traffic lights, gives content area
function DesktopFrame({ children, label, mn, en, width = 720, height = 460, scrollH }) {
  return (
    <div style={{ width, position: 'relative' }}>
      <SketchBox style={{ width: '100%', padding: 0 }} jitter={1.2}>
        {/* Title bar */}
        <div style={{ position: 'relative', height: 22, borderBottom: '1px dashed #1a1a1f', display: 'flex', alignItems: 'center', padding: '0 10px', gap: 6 }}>
          <span style={{ width: 8, height: 8, borderRadius: '50%', border: '1.2px solid #1a1a1f', display: 'inline-block' }} />
          <span style={{ width: 8, height: 8, borderRadius: '50%', border: '1.2px solid #1a1a1f', display: 'inline-block' }} />
          <span style={{ width: 8, height: 8, borderRadius: '50%', border: '1.2px solid #1a1a1f', display: 'inline-block' }} />
          <span className="mono" style={{ marginLeft: 'auto', opacity: 0.7 }}>{(mn || en) ? <L mn={mn} en={en} /> : label || 'andaaa.com'}</span>
        </div>
        <div style={{ position: 'relative', height, overflow: 'hidden' }}>
          {scrollH
            ? <div style={{ position: 'absolute', inset: 0, overflow: 'hidden' }}>{children}</div>
            : children}
        </div>
      </SketchBox>
    </div>
  );
}

// PhoneFrame — minimal phone outline with status bar
function PhoneFrame({ children, label, mn, en, width = 200, height = 420 }) {
  return (
    <div style={{ width, position: 'relative' }}>
      <SketchBox style={{ width: '100%', padding: 0, borderRadius: 0 }} jitter={1.3}>
        <div style={{ position: 'relative', height: 18, borderBottom: '1px dashed #1a1a1f', display: 'flex', alignItems: 'center', padding: '0 14px', justifyContent: 'space-between' }}>
          <span className="mono" style={{ fontSize: 8 }}>9:41</span>
          <span className="mono" style={{ fontSize: 8, opacity: 0.7 }}>{(mn || en) ? <L mn={mn} en={en} /> : (label || 'andaaa')}</span>
          <span className="mono" style={{ fontSize: 8 }}>●●●</span>
        </div>
        <div style={{ position: 'relative', height, overflow: 'hidden' }}>{children}</div>
      </SketchBox>
    </div>
  );
}

// ChatBubble — used in messenger / chat-metaphor screens
function ChatBubble({ from = 'andaa', children, mn, en, style, jitter = 1.2, width }) {
  const isUser = from === 'user';
  return (
    <div style={{ display: 'flex', justifyContent: isUser ? 'flex-end' : 'flex-start', width: '100%', ...style }}>
      <SketchBox
        style={{ maxWidth: width || '78%', padding: '8px 12px', borderRadius: 14 }}
        jitter={jitter}
        fillColor={isUser ? '#eae6dc' : 'transparent'}
        stroke="#1a1a1f"
      >
        <div style={{ fontFamily: 'Patrick Hand, cursive', fontSize: 14, color: '#1a1a1f', position: 'relative', lineHeight: 1.25 }}>
          {(mn || en) ? <L mn={mn} en={en} /> : children}
        </div>
      </SketchBox>
    </div>
  );
}

// CornerSticker — small star/burst sticker (e.g. "Most loved")
function Burst({ children, mn, en, style, size = 56, color = '#1a1a1f' }) {
  const pts = [];
  const spikes = 12;
  for (let i = 0; i < spikes * 2; i++) {
    const r = i % 2 === 0 ? size / 2 : size / 2 - 4;
    const a = (i / (spikes * 2)) * Math.PI * 2 + Math.sin(i) * 0.05;
    pts.push([size / 2 + Math.cos(a) * r, size / 2 + Math.sin(a) * r]);
  }
  return (
    <div style={{ position: 'absolute', width: size, height: size, ...style }}>
      <svg width={size} height={size} style={{ position: 'absolute', inset: 0, overflow: 'visible' }}>
        <path d={'M' + pts.map((p) => p[0].toFixed(2) + ',' + p[1].toFixed(2)).join(' L') + ' Z'} fill="none" stroke={color} strokeWidth="1.3" strokeLinejoin="round" />
      </svg>
      <div style={{ position: 'absolute', inset: 0, display: 'flex', alignItems: 'center', justifyContent: 'center', textAlign: 'center', padding: 6, fontFamily: 'Caveat, cursive', fontWeight: 600, fontSize: 13, color, transform: 'rotate(-8deg)' }}>
        {(mn || en) ? <L mn={mn} en={en} /> : children}
      </div>
    </div>
  );
}

// VariantHeader — sits at top of an artboard inside DC label area; not used as
// we rely on DCArtboard label. But we expose a small reasoning block.
function Reasoning({ title, children }) {
  const show = React.useContext(AnnoContext);
  if (!show) return null;
  return (
    <div style={{ padding: 10, marginTop: 6, position: 'relative' }}>
      <div className="mono" style={{ marginBottom: 4, color: '#c92b2b' }}>{title || 'WHY'}</div>
      <div style={{ fontFamily: 'Caveat, cursive', fontSize: 15, color: '#1a1a1f', lineHeight: 1.2 }}>{children}</div>
    </div>
  );
}

// Tradeoff block — pros/cons side by side
function Tradeoff({ pros = [], cons = [] }) {
  const show = React.useContext(AnnoContext);
  const lang = React.useContext(LangContext);
  if (!show) return null;
  const t = (o) => typeof o === 'string' ? o : (lang === 'mn' ? o.mn : o.en);
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12, padding: '6px 10px 10px', fontFamily: 'Caveat, cursive', fontSize: 14, lineHeight: 1.15 }}>
      <div>
        <div className="mono" style={{ color: '#2b4ec9', marginBottom: 2 }}>+ {lang === 'mn' ? 'Давуу' : 'PROS'}</div>
        {pros.map((p, i) => <div key={i} style={{ color: '#2b4ec9' }}>· {t(p)}</div>)}
      </div>
      <div>
        <div className="mono" style={{ color: '#c92b2b', marginBottom: 2 }}>− {lang === 'mn' ? 'Сул' : 'CONS'}</div>
        {cons.map((p, i) => <div key={i} style={{ color: '#c92b2b' }}>· {t(p)}</div>)}
      </div>
    </div>
  );
}

// ─── Export to window ──────────────────────────────────────────────
Object.assign(window, {
  LangContext, LangSetContext, AnnoContext,
  L, Anno, AnnoArrow,
  SketchBox, SketchLine, Placeholder, Scribble, Avatar, Chip, Headline, Tag,
  DesktopFrame, PhoneFrame, ChatBubble, Burst,
  Reasoning, Tradeoff,
  roughPath, roughLine,
});
