/* global React, Dot, Badge, hashStr */
// VT shared primitives: equipment icon, waveform, video frame placeholder, roof map, timeline

const { useState: _useS, useEffect: _useE, useRef: _useR, useMemo: _useM } = React;

// ─── Equipment Icon (deterministic pictograms, no emoji) ────────
function EquipIcon({ cat, size = 16, ...p }) {
  const sw = 1.4;
  const S = { width: size, height: size, viewBox: '0 0 20 20', fill: 'none', stroke: 'currentColor', strokeWidth: sw, strokeLinecap: 'round', strokeLinejoin: 'round', ...p };
  switch (cat) {
    case 'pac_air_eau':
    case 'pac_air_air':
      return <svg {...S}><rect x="2" y="6" width="16" height="8" rx="1"/><path d="M5 9h2M5 11h2M9 9v2M11 9v2M13 9v2M15 9v2"/></svg>;
    case 'panneau_pv':
      return <svg {...S}><path d="M3 4h14l-1.5 12h-11z"/><path d="M6.5 4v12M10 4v12M13.5 4v12M4 8h12M4.5 12h11"/></svg>;
    case 'chaudiere':
      return <svg {...S}><rect x="4" y="3" width="12" height="14" rx="1"/><circle cx="10" cy="10" r="3"/><path d="M8 6h4"/></svg>;
    case 'ballon_thermo':
      return <svg {...S}><rect x="6" y="3" width="8" height="14" rx="1"/><path d="M9 3v1M11 3v1M8 8h4M8 11h4M8 14h4"/></svg>;
    case 'groupe_froid':
    case 'clim':
      return <svg {...S}><rect x="2" y="5" width="16" height="6" rx="1"/><path d="M5 13v2M10 13v2M15 13v2M5 8h10"/></svg>;
    case 'cta':
      return <svg {...S}><path d="M2 6h16M2 10h16M2 14h16"/></svg>;
    case 'onduleur':
      return <svg {...S}><rect x="3" y="4" width="14" height="12" rx="1"/><path d="M6 10h3l1-2 2 4 1-2h2"/></svg>;
    case 'compteur':
      return <svg {...S}><rect x="3" y="4" width="14" height="12" rx="1"/><rect x="6" y="7" width="8" height="3"/><circle cx="8" cy="13" r="0.7"/><circle cx="12" cy="13" r="0.7"/></svg>;
    case 'enveloppe':
      return <svg {...S}><path d="M2 10 10 3l8 7v7H2z"/><path d="M6 17v-4h8v4"/></svg>;
    default:
      return <svg {...S}><rect x="3" y="3" width="14" height="14" rx="1"/></svg>;
  }
}

// ─── Waveform (deterministic, can animate) ─────────────────────
function Waveform({ seed = 'w', width = 300, height = 48, bars = 80, color = 'currentColor', bg = 'var(--line)', progress = 0, animate = false, segments = [], onClick }) {
  const [tick, setTick] = _useS(0);
  _useE(() => {
    if (!animate) return;
    const id = setInterval(() => setTick(t => t + 1), 80);
    return () => clearInterval(id);
  }, [animate]);
  const heights = _useM(() => {
    const h = hashStr(seed);
    return Array.from({ length: bars }, (_, i) => {
      const a = Math.sin((i * 0.37 + ((h >> (i % 16)) & 7) * 0.2)) * 0.4 + 0.55;
      const b = Math.cos((i * 0.19 + ((h >> ((i * 3) % 24)) & 15) * 0.1)) * 0.3;
      return Math.max(0.1, Math.min(1, a + b));
    });
  }, [seed, bars]);
  const w = width / bars;
  const progressBar = Math.floor(progress * bars);
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} style={{ display: 'block', cursor: onClick ? 'pointer' : 'default' }} onClick={onClick}>
      {heights.map((H, i) => {
        const jitter = animate && i > progressBar - 3 && i < progressBar + 8 ? (Math.sin((tick + i) * 0.6) * 0.15) : 0;
        const h = Math.max(1, (H + jitter) * (height - 4));
        const y = (height - h) / 2;
        const active = i <= progressBar;
        return <rect key={i} x={i * w + w * 0.18} y={y} width={w * 0.64} height={h} fill={active ? color : bg} rx="0.5" />;
      })}
      {/* Speaker segments overlay */}
      {segments.map((s, i) => (
        <rect key={i} x={s.start * width} y={height - 2} width={(s.end - s.start) * width} height={2} fill={s.color || 'var(--plasma)'} />
      ))}
    </svg>
  );
}

// ─── Video Frame Placeholder (stylized SVG, no emoji, no gradient slop) ──
// Uses synthetic "scene" imagery based on scene type
function VideoFrame({ scene = 'utility_room', width = '100%', height = '100%', overlay, timestamp, style }) {
  return (
    <div style={{
      position: 'relative', width, height,
      background: 'var(--ink)',
      overflow: 'hidden',
      borderRadius: 4,
      ...style,
    }}>
      <SceneSvg scene={scene} />
      {/* Overlays */}
      {overlay}
      {/* Scanline */}
      <div style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        background: 'repeating-linear-gradient(0deg, rgba(255,255,255,0.03) 0, rgba(255,255,255,0.03) 1px, transparent 1px, transparent 3px)',
      }} />
      {/* Timestamp */}
      {timestamp !== undefined && (
        <div className="mono" style={{
          position: 'absolute', bottom: 8, right: 10,
          fontSize: 10, color: 'var(--signal)', letterSpacing: '0.05em',
          textShadow: '0 1px 3px rgba(0,0,0,0.8)',
        }}>{formatTS(timestamp)}</div>
      )}
    </div>
  );
}

// Generative "photo" of the scene — no real image, everything is drawn
function SceneSvg({ scene }) {
  // A tiny palette
  const metal = '#6b7280';
  const metalDark = '#374151';
  const wall = '#1f2937';
  const accent = '#0d3b2c'; // daikin green
  const plate = '#9ca3af';
  const text = '#e5e7eb';

  if (scene === 'utility_room') {
    // Shows PAC Daikin on wall
    return (
      <svg viewBox="0 0 400 225" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }}>
        <defs>
          <pattern id="wall-tex" width="10" height="10" patternUnits="userSpaceOnUse">
            <rect width="10" height="10" fill="#243040"/>
            <path d="M0 5h10M5 0v10" stroke="rgba(0,0,0,0.15)" strokeWidth="0.3"/>
          </pattern>
        </defs>
        <rect width="400" height="225" fill="url(#wall-tex)"/>
        {/* Floor */}
        <rect x="0" y="185" width="400" height="40" fill="#111827"/>
        <path d="M0 185 400 185" stroke="#374151" strokeWidth="0.5"/>
        {/* PAC unit mounted on wall */}
        <rect x="95" y="70" width="155" height="95" fill={metal} rx="3"/>
        <rect x="95" y="70" width="155" height="12" fill={metalDark}/>
        {/* Top vents */}
        {Array.from({length: 14}).map((_, i) => <rect key={i} x={100 + i * 10.5} y="73" width="7" height="6" fill="#0b0b0b" opacity="0.8"/>)}
        {/* Bottom louvers */}
        {Array.from({length: 20}).map((_, i) => <rect key={i} x={100} y={90 + i * 3.5} width="145" height="1.4" fill="#4b5563"/>)}
        {/* Badge */}
        <rect x="100" y="88" width="40" height="12" fill={accent}/>
        <text x="120" y="97" textAnchor="middle" fontSize="8" fontFamily="monospace" fill="#fff" fontWeight="700">DAIKIN</text>
        {/* Data plate */}
        <rect x="160" y="145" width="82" height="16" fill={plate} rx="1"/>
        <text x="201" y="153" textAnchor="middle" fontSize="5.5" fontFamily="monospace" fill="#111">EBLQ011CAW1</text>
        <text x="201" y="158.5" textAnchor="middle" fontSize="4.2" fontFamily="monospace" fill="#374151">S/N DK-2021-8837491</text>
        {/* Pipes */}
        <rect x="248" y="100" width="5" height="85" fill="#d97706"/>
        <rect x="256" y="100" width="5" height="85" fill="#2563eb"/>
        <rect x="264" y="100" width="5" height="85" fill="#78716c"/>
        {/* Shadow under */}
        <ellipse cx="172" cy="185" rx="85" ry="4" fill="rgba(0,0,0,0.4)"/>
        {/* Light from above */}
        <path d="M0 0 L400 0 L400 70 L0 70Z" fill="rgba(255,255,255,0.02)"/>
      </svg>
    );
  }

  if (scene === 'roof_drone') {
    return (
      <svg viewBox="0 0 400 225" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }}>
        {/* Sky */}
        <rect width="400" height="80" fill="#3b4a5c"/>
        <rect x="0" y="80" width="400" height="145" fill="#2a2a1a"/>
        {/* Roof tiles */}
        <g transform="translate(50,95) skewX(-18)">
          {Array.from({length: 10}).map((_, r) => (
            <g key={r}>
              {Array.from({length: 14}).map((__, c) => (
                <rect key={c} x={c * 22} y={r * 12} width="20" height="10" fill={r % 2 ? '#7f3d1f' : '#8a4524'} stroke="#4a1f10" strokeWidth="0.3"/>
              ))}
            </g>
          ))}
        </g>
        {/* Neighbor house silhouettes */}
        <rect x="0" y="60" width="60" height="25" fill="#1a1f2a"/>
        <rect x="340" y="65" width="60" height="22" fill="#1a1f2a"/>
        {/* Satellite crosshair overlay */}
        <g stroke="#7fffb7" strokeWidth="0.8" fill="none" opacity="0.6">
          <path d="M200 40v30M200 180v20M50 112h30M320 112h30"/>
          <rect x="80" y="90" width="240" height="45" strokeDasharray="3 2"/>
        </g>
      </svg>
    );
  }

  if (scene === 'meter_box') {
    return (
      <svg viewBox="0 0 400 225" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }}>
        <rect width="400" height="225" fill="#1f2937"/>
        <rect x="130" y="35" width="140" height="155" fill="#f59e0b" rx="2"/>
        <rect x="145" y="58" width="110" height="65" fill="#1a1a1a" rx="1"/>
        <text x="200" y="82" textAnchor="middle" fontSize="9" fontFamily="monospace" fill="#7fffb7">123456789</text>
        <text x="200" y="100" textAnchor="middle" fontSize="5.5" fontFamily="monospace" fill="#a7f3d0">0612 487 330 001</text>
        <rect x="150" y="135" width="100" height="8" fill="#d1d5db"/>
        <text x="200" y="142" textAnchor="middle" fontSize="5" fontFamily="monospace" fill="#111">LINKY G3 — Enedis</text>
        {Array.from({length: 4}).map((_, i) => <circle key={i} cx={165 + i * 25} cy="165" r="5" fill="#7fffb7" opacity={0.3 + i * 0.2}/>)}
      </svg>
    );
  }

  if (scene === 'boiler') {
    return (
      <svg viewBox="0 0 400 225" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }}>
        <rect width="400" height="225" fill="#1a1f2a"/>
        <rect x="130" y="30" width="140" height="170" fill="#d4d4d8" rx="1"/>
        <rect x="145" y="50" width="110" height="40" fill="#0a0a0a"/>
        <circle cx="165" cy="70" r="7" fill="#dc2626"/>
        <rect x="180" y="62" width="55" height="16" fill="#171717"/>
        <text x="207" y="74" textAnchor="middle" fontSize="7" fontFamily="monospace" fill="#7fffb7">62°C</text>
        <text x="200" y="115" textAnchor="middle" fontSize="8" fontFamily="monospace" fontWeight="700" fill="#52525b">FRISQUET</text>
        <text x="200" y="128" textAnchor="middle" fontSize="5" fontFamily="monospace" fill="#71717a">Hydroconfort · 2008</text>
        <rect x="155" y="145" width="90" height="40" fill="#a1a1aa"/>
        <rect x="145" y="190" width="110" height="10" fill="#525252"/>
        {/* rust spots */}
        <circle cx="148" cy="180" r="4" fill="#92400e" opacity="0.5"/>
        <circle cx="258" cy="188" r="3" fill="#92400e" opacity="0.6"/>
      </svg>
    );
  }

  if (scene === 'facade') {
    return (
      <svg viewBox="0 0 400 225" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }}>
        <rect width="400" height="225" fill="#7c9eb8"/>
        <rect y="150" width="400" height="75" fill="#3f5a3f"/>
        {/* house */}
        <polygon points="100,100 200,40 300,100 300,190 100,190" fill="#c4a78c"/>
        <polygon points="100,100 200,40 300,100" fill="#5a3a2a"/>
        {/* roof tiles lines */}
        {Array.from({length: 8}).map((_, i) => <path key={i} d={`M${105 + i * 5} ${95 - i * 4} L${295 - i * 5} ${95 - i * 4}`} stroke="#3d2818" strokeWidth="0.5" fill="none"/>)}
        <rect x="135" y="125" width="30" height="45" fill="#78350f"/>
        <rect x="230" y="115" width="35" height="40" fill="#1e3a5f" stroke="#f5f5f4" strokeWidth="1.5"/>
        <rect x="180" y="130" width="40" height="55" fill="#3f2818" stroke="#f5f5f4" strokeWidth="1"/>
        <circle cx="215" cy="158" r="1.5" fill="#f5f5f4"/>
      </svg>
    );
  }

  // Default dark frame
  return (
    <svg viewBox="0 0 400 225" preserveAspectRatio="xMidYMid slice" style={{ position: 'absolute', inset: 0, width: '100%', height: '100%' }}>
      <rect width="400" height="225" fill="#111827"/>
      <text x="200" y="115" textAnchor="middle" fontSize="8" fontFamily="monospace" fill="#4b5563">— no signal —</text>
    </svg>
  );
}

// ─── Time formatting ───────────────────────────────────
function formatTS(seconds) {
  const h = Math.floor(seconds / 3600);
  const m = Math.floor((seconds % 3600) / 60);
  const s = Math.floor(seconds % 60);
  if (h) return `${h}:${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`;
  return `${String(m).padStart(2,'0')}:${String(s).padStart(2,'0')}`;
}
function formatDuration(seconds) {
  const h = Math.floor(seconds / 3600);
  const m = Math.floor((seconds % 3600) / 60);
  if (h) return `${h}h ${m}min`;
  if (m) return `${m} min`;
  return `${Math.floor(seconds)}s`;
}

// ─── Confidence meter ───────────────────────────────────
function Confidence({ value, width = 40, label = true }) {
  const pct = Math.round(value * 100);
  const tone = value > 0.85 ? 'var(--signal)' : value > 0.7 ? 'var(--copper)' : 'var(--amber)';
  return (
    <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
      <div style={{ width, height: 4, background: 'var(--line)', borderRadius: 2, overflow: 'hidden' }}>
        <div style={{ width: `${pct}%`, height: '100%', background: tone }}/>
      </div>
      {label && <span className="mono" style={{ fontSize: 10, color: 'var(--ink-4)' }}>{pct}%</span>}
    </div>
  );
}

// ─── Roof Map (generative top-down satellite, with panel layout overlay) ──
function RoofMap({ width = 360, height = 220, usableArea = 85, panels = 16, rows = 2, cols = 8, orientation = 'S', tilt = 30, highlightPanel = null, showShadow = true }) {
  // rotation based on orientation
  const orientAngle = { N: 180, NE: 135, E: 90, SE: 45, S: 0, SO: -45, O: -90, NO: -135 }[orientation] || 0;
  const cx = width / 2, cy = height / 2;
  const houseW = 140, houseH = 90;
  const panelW = (houseW - 20) / cols - 1;
  const panelH = (houseH - 20) / rows - 1;
  return (
    <svg width={width} height={height} viewBox={`0 0 ${width} ${height}`} style={{ display: 'block', background: '#e8edd8', borderRadius: 4 }}>
      {/* Satellite base: parcellaire */}
      <defs>
        <pattern id="terrain" width="6" height="6" patternUnits="userSpaceOnUse">
          <rect width="6" height="6" fill="#e8edd8"/>
          <circle cx="2" cy="3" r="0.3" fill="#b4c070"/>
          <circle cx="4.5" cy="1" r="0.3" fill="#94a855"/>
        </pattern>
      </defs>
      <rect width={width} height={height} fill="url(#terrain)"/>
      {/* Neighbor houses */}
      <rect x="10" y="20" width="55" height="38" fill="#b87060" opacity="0.4"/>
      <rect x={width - 70} y="30" width="50" height="50" fill="#a66850" opacity="0.4"/>
      <rect x="20" y={height - 55} width="70" height="30" fill="#c2a890" opacity="0.35"/>
      {/* Road */}
      <rect x="0" y={height - 28} width={width} height="12" fill="#9a9a8a"/>
      <path d={`M0 ${height - 22}L${width} ${height - 22}`} stroke="#e0e0d0" strokeWidth="0.8" strokeDasharray="8 6"/>
      {/* Roof (centered, rotated by orientation) */}
      <g transform={`translate(${cx},${cy}) rotate(${orientAngle})`}>
        {/* Roof base */}
        <rect x={-houseW/2} y={-houseH/2} width={houseW} height={houseH} fill="#7a4028" stroke="#4a2818" strokeWidth="0.8"/>
        {/* Roof ridge */}
        <path d={`M${-houseW/2} 0 L${houseW/2} 0`} stroke="#3a1818" strokeWidth="1.2"/>
        {/* Tile texture */}
        {Array.from({length: 12}).map((_, i) => <path key={i} d={`M${-houseW/2} ${-houseH/2 + i * 4} L${houseW/2} ${-houseH/2 + i * 4}`} stroke="rgba(0,0,0,0.15)" strokeWidth="0.3"/>)}
        {Array.from({length: 12}).map((_, i) => <path key={i} d={`M${-houseW/2} ${0 + i * 4} L${houseW/2} ${0 + i * 4}`} stroke="rgba(0,0,0,0.15)" strokeWidth="0.3"/>)}
        {/* Panels on south half (y > 0) */}
        {Array.from({length: rows * cols}).map((_, i) => {
          const r = Math.floor(i / cols);
          const c = i % cols;
          const isHighlight = highlightPanel === i;
          const x = -houseW/2 + 10 + c * (panelW + 1);
          const y = 4 + r * (panelH + 1);
          return (
            <g key={i}>
              <rect x={x} y={y} width={panelW} height={panelH} fill={isHighlight ? '#2dd4bf' : '#0f2540'} stroke="#7fb8d9" strokeWidth="0.3"/>
              {/* cells */}
              {Array.from({length: 6}).map((_, j) => <path key={j} d={`M${x + (j + 1) * panelW / 6} ${y} L${x + (j + 1) * panelW / 6} ${y + panelH}`} stroke="rgba(127,184,217,0.3)" strokeWidth="0.2"/>)}
              <path d={`M${x} ${y + panelH/2} L${x + panelW} ${y + panelH/2}`} stroke="rgba(127,184,217,0.3)" strokeWidth="0.2"/>
            </g>
          );
        })}
        {/* Velux on north half */}
        <rect x={-20} y={-houseH/2 + 10} width="14" height="10" fill="#a8c5e0" stroke="#3a5870" strokeWidth="0.3"/>
        <rect x={10} y={-houseH/2 + 10} width="14" height="10" fill="#a8c5e0" stroke="#3a5870" strokeWidth="0.3"/>
      </g>
      {/* Shadow cast by chimney (if showShadow) */}
      {showShadow && (
        <ellipse cx={cx + 35} cy={cy + 55} rx="14" ry="4" fill="rgba(0,0,0,0.25)"/>
      )}
      {/* Compass */}
      <g transform={`translate(${width - 28},28)`}>
        <circle r="14" fill="rgba(255,255,255,0.85)" stroke="#111"/>
        <path d={`M0 -10 L3 0 L0 3 L-3 0 Z`} fill="var(--rouge)"/>
        <text y="-4" textAnchor="middle" fontSize="6" fontFamily="monospace" fontWeight="700">N</text>
      </g>
    </svg>
  );
}

Object.assign(window, { EquipIcon, Waveform, VideoFrame, SceneSvg, formatTS, formatDuration, Confidence, RoofMap });
