/* global React, I, fmt, SEED, Badge, Button, PhoneShell, api */
/* v2.0.1 - ErrorScreen inline SVG fix - 2026-05-12T22:15:00Z */
const { useState, useEffect, useRef, useMemo } = React;

// ─── PDF preview modal ────────────────────────────────────────
function PDFPreviewModal({ hardware, onClose }) {
  const subtotal = hardware.items.reduce((a, i) => a + i.qty * i.unit, 0);
  const extras = (hardware.extras || []).reduce((a, e) => a + e.value, 0);
  const total = subtotal + extras;
  return (
    <div onClick={onClose} style={{
      position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.7)',
      backdropFilter: 'blur(6px)', WebkitBackdropFilter: 'blur(6px)',
      zIndex: 30, display: 'flex', flexDirection: 'column',
      animation: 'vrvIn .25s ease-out',
    }}>
      <div style={{
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        padding: '14px 16px', flex: '0 0 auto',
      }}>
        <div style={{ color: '#fff', fontSize: 13, fontWeight: 600 }}>
          Original PDF - Page 1 of 3
        </div>
        <button onClick={onClose} aria-label="Close" style={{
          width: 36, height: 36, borderRadius: '50%', border: 0,
          background: 'rgba(255,255,255,0.12)', color: '#fff', cursor: 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          <I.X size={18}/>
        </button>
      </div>
      <div onClick={(e) => e.stopPropagation()} style={{
        flex: 1, margin: '0 12px 12px', borderRadius: 8, overflow: 'auto',
        background: '#e8e6e1', padding: 14, color: '#1a1a1a',
        fontFamily: 'Inter, system-ui', fontSize: 9, lineHeight: '13px',
        boxShadow: '0 8px 32px rgba(0,0,0,0.5)',
      }}>
        <div style={{
          background: '#fff', padding: 16, minHeight: '100%',
          boxShadow: '0 1px 0 rgba(0,0,0,0.08)',
        }}>
          {/* Letterhead */}
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', borderBottom: '2px solid #0061a8', paddingBottom: 8, marginBottom: 14 }}>
            <div>
              <div style={{ fontSize: 14, fontWeight: 800, color: '#0061a8', letterSpacing: '0.5px' }}>DAIKIN</div>
              <div style={{ color: '#666', fontSize: 8, marginTop: 1 }}>AUSTRALIA PTY LTD</div>
            </div>
            <div style={{ textAlign: 'right' }}>
              <div style={{ fontWeight: 700, fontSize: 11, color: '#0061a8' }}>QUOTATION</div>
              <div style={{ color: '#444', fontSize: 8, marginTop: 1 }}>Ref: {hardware.reference}</div>
              <div style={{ color: '#444', fontSize: 8 }}>Date: {hardware.quoteDate}</div>
            </div>
          </div>
          {/* Address block */}
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 14, marginBottom: 14, fontSize: 8.5, lineHeight: '12px' }}>
            <div>
              <div style={{ fontWeight: 700, color: '#666', marginBottom: 2 }}>FROM</div>
              <div>Daikin Australia Pty Ltd</div>
              <div>62 Stradbroke St, Heatherton VIC 3202</div>
              <div>ABN 62 000 069 826</div>
              <div>quotes@daikin.com.au</div>
            </div>
            <div>
              <div style={{ fontWeight: 700, color: '#666', marginBottom: 2 }}>FOR</div>
              <div>Frostbite Air Conditioning Services</div>
              <div>Project: {hardware.project}</div>
              <div>Attn: David Chen</div>
              <div>david@frostbiteac.com.au</div>
            </div>
          </div>
          {/* Schedule table */}
          <div style={{ fontWeight: 700, fontSize: 9, color: '#0061a8', marginBottom: 4 }}>EQUIPMENT SCHEDULE</div>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 8, lineHeight: '12px' }}>
            <thead>
              <tr style={{ background: '#0061a8', color: '#fff' }}>
                <th style={{ padding: '4px 6px', textAlign: 'left', fontWeight: 600 }}>Model</th>
                <th style={{ padding: '4px 6px', textAlign: 'left', fontWeight: 600 }}>Description</th>
                <th style={{ padding: '4px 6px', textAlign: 'right', fontWeight: 600 }}>Qty</th>
                <th style={{ padding: '4px 6px', textAlign: 'right', fontWeight: 600 }}>Unit</th>
                <th style={{ padding: '4px 6px', textAlign: 'right', fontWeight: 600 }}>Total</th>
              </tr>
            </thead>
            <tbody>
              {hardware.items.map((it, i) => (
                <tr key={it.id} style={{ borderBottom: '1px solid #ddd', background: i % 2 ? '#fafafa' : '#fff' }}>
                  <td style={{ padding: '5px 6px', fontFamily: 'ui-monospace, Menlo, monospace', fontSize: 7.5, fontWeight: 600 }}>{it.code}</td>
                  <td style={{ padding: '5px 6px' }}>
                    <div style={{ fontWeight: 600 }}>{it.name}</div>
                    <div style={{ color: '#666', fontSize: 7 }}>{it.desc}</div>
                  </td>
                  <td style={{ padding: '5px 6px', textAlign: 'right' }}>{it.qty}</td>
                  <td style={{ padding: '5px 6px', textAlign: 'right', fontVariantNumeric: 'tabular-nums' }}>${it.unit.toLocaleString()}</td>
                  <td style={{ padding: '5px 6px', textAlign: 'right', fontVariantNumeric: 'tabular-nums', fontWeight: 600 }}>${(it.qty * it.unit).toLocaleString()}</td>
                </tr>
              ))}
            </tbody>
          </table>
          {/* Extras + total */}
          <div style={{ marginTop: 10, paddingTop: 8, borderTop: '1px solid #ccc', display: 'flex', justifyContent: 'flex-end' }}>
            <table style={{ fontSize: 8.5, lineHeight: '14px', minWidth: 180 }}>
              <tbody>
                <tr><td style={{ paddingRight: 16, color: '#444' }}>Equipment subtotal</td><td style={{ textAlign: 'right', fontVariantNumeric: 'tabular-nums' }}>${subtotal.toLocaleString()}</td></tr>
                {hardware.extras?.map((e) => (
                  <tr key={e.name}><td style={{ paddingRight: 16, color: '#444' }}>{e.name}</td><td style={{ textAlign: 'right', fontVariantNumeric: 'tabular-nums' }}>${e.value.toLocaleString()}</td></tr>
                ))}
                <tr style={{ borderTop: '1px solid #999' }}>
                  <td style={{ paddingRight: 16, fontWeight: 700, paddingTop: 4 }}>Total (ex GST)</td>
                  <td style={{ textAlign: 'right', fontVariantNumeric: 'tabular-nums', fontWeight: 700, paddingTop: 4, color: '#0061a8' }}>${total.toLocaleString()}</td>
                </tr>
              </tbody>
            </table>
          </div>
          <div style={{ marginTop: 12, fontSize: 7.5, color: '#888', lineHeight: '11px' }}>
            Quotation valid for 30 days. All prices in AUD, exclusive of GST. Delivery 4-6 weeks from order. Subject to Daikin Australia standard terms and conditions.
          </div>
        </div>
      </div>
    </div>
  );
}

// ─── AI Loading Pipeline with real status polling ──────────────────────────────────────
function LoaderScreen({ onDone, onError, isError, quoteId, progress }) {
  const stages = SEED.loaderStages;
  const [active, setActive] = useState(0);
  const [status, setStatus] = useState(null);
  const [pollError, setPollError] = useState(null);
  const [backendDone, setBackendDone] = useState(false); // Backend finished, now animating remaining stages
  const [hasError, setHasError] = useState(false);
  const pollInterval = useRef(null);
  const mounted = useRef(true);

  // Map backend status to stage index (0-3 for real backend stages)
  const statusToStage = {
    'uploaded': 0,
    'document_uploaded': 0,
    'documents_uploaded': 1,
    'reading_pdf': 1,
    'extracting_hardware': 2,
    'validating_quote': 3,
    'hardware_extracted': 3,  // Backend done at stage 3
    'complete': 3,
    'failed_invalid_pdf': -1,
    'failed_processing': -2,
    'failed_api_error': -3,
    'failed_rate_limit': -4,
  };

  // Poll the API for status
  useEffect(() => {
    mounted.current = true;

    const pollStatus = async () => {
      if (!quoteId || !mounted.current || backendDone) return;

      try {
        const response = await api.getQuoteStatus(quoteId);
        if (!mounted.current) return;

        // API returns {success, data: {current_status, ...}}
        const statusData = response.data || response;
        const currentStatus = statusData.current_status || statusData.status;

        setStatus(statusData);

        const stageIndex = statusToStage[currentStatus] ?? active;

        // Only move forward, never backward
        if (stageIndex >= 0 && stageIndex > active) {
          setActive(stageIndex);
        }

        // Backend finished - stop polling and start animating remaining stages
        if (currentStatus === 'complete' || currentStatus === 'hardware_extracted') {
          clearInterval(pollInterval.current);
          setBackendDone(true);
          // Move to stage 4 to start the animation sequence
          setActive(prev => Math.max(prev, 3));
        }

        // Handle errors
        if (currentStatus?.startsWith('failed_')) {
          clearInterval(pollInterval.current);
          setHasError(true);
          setTimeout(() => {
            if (mounted.current) onError(currentStatus);
          }, 500);
        }
      } catch (err) {
        console.error('Status poll error:', err);
        setPollError(err.message);
        // Continue polling on error - don't stop
      }
    };

    // Start polling
    pollStatus();
    pollInterval.current = setInterval(pollStatus, 1200);

    return () => {
      mounted.current = false;
      clearInterval(pollInterval.current);
    };
  }, [quoteId, backendDone]);

  // Animate through remaining stages (4-7) after backend completes
  useEffect(() => {
    if (!backendDone || hasError) return;

    // If we've completed all stages, call onDone
    if (active >= stages.length) {
      const t = setTimeout(() => {
        if (mounted.current) onDone();
      }, 600);
      return () => clearTimeout(t);
    }

    // Animate through stages 4-7 with realistic timing
    if (active >= 3) {
      const durations = [0, 0, 0, 0, 600, 500, 700, 550]; // Timing for stages 4-7
      const dur = durations[active] || 500;
      const t = setTimeout(() => {
        if (mounted.current) setActive(a => a + 1);
      }, dur);
      return () => clearTimeout(t);
    }
  }, [active, backendDone, hasError, onDone, stages.length]);

  // Fallback: If no quoteId, use simulated timing (for demo/prototype mode)
  useEffect(() => {
    if (quoteId) return; // Skip if using real API

    if (active >= stages.length) {
      const t = setTimeout(() => isError ? onError() : onDone(), 500);
      return () => clearTimeout(t);
    }
    // Variable timing per stage for realism
    const dur = [550, 800, 1100, 700, 950, 850, 1100, 700][active] || 800;
    const t = setTimeout(() => setActive(a => a + 1), dur);
    return () => clearTimeout(t);
  }, [active, isError, onDone, onError, quoteId]);

  const phase = active < 2 ? 'Reviewing' : active < 5 ? 'Thinking' : 'Creating';

  return (
    <div style={{ width: '100%', height: '100%', position: 'relative', background: '#171717', overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
      {/* Ambient glow that intensifies through stages */}
      <div style={{
        position: 'absolute', top: 140, left: '50%', transform: 'translateX(-50%)',
        width: 320, height: 320, borderRadius: '50%',
        background: 'radial-gradient(circle, rgba(254,194,48,0.18), transparent 60%)',
        opacity: 0.4 + (active / stages.length) * 0.6, transition: 'opacity .8s ease',
        pointerEvents: 'none',
      }}/>

      <div style={{ padding: '86px 24px 12px', position: 'relative', zIndex: 1 }}>
        <div style={{ color: '#FEC230', fontSize: 11, fontWeight: 700, letterSpacing: '0.12em', textTransform: 'uppercase' }}>
          {phase}
        </div>
        <div style={{ color: '#fff', fontSize: 22, fontWeight: 700, lineHeight: '28px', letterSpacing: '-0.3px', marginTop: 6 }}>
          Building your quote
        </div>
        <div style={{ color: '#B8B8B8', fontSize: 13, marginTop: 4 }}>
          {Math.min(active, stages.length)} of {stages.length} stages complete
        </div>

        {/* Progress bar */}
        <div style={{ marginTop: 16, height: 4, background: '#262626', borderRadius: 2, overflow: 'hidden' }}>
          <div style={{
            width: `${(Math.min(active, stages.length) / stages.length) * 100}%`,
            height: '100%', background: 'linear-gradient(90deg, #DC6C3D, #FEC230)',
            transition: 'width .55s cubic-bezier(.2,.8,.2,1)',
            boxShadow: '0 0 12px rgba(254,194,48,0.5)',
          }}/>
        </div>
      </div>

      <div style={{ flex: 1, overflowY: 'auto', padding: '16px 20px 32px', position: 'relative', zIndex: 1 }}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
          {stages.map((s, i) => {
            const state = i < active ? 'done' : i === active ? 'active' : 'pending';
            return <LoaderStage key={s.key} stage={s} state={state} index={i} last={i === stages.length - 1}/>;
          })}
        </div>
      </div>
    </div>
  );
}

function LoaderStage({ stage, state, index, last }) {
  return (
    <div style={{
      display: 'flex', gap: 14, padding: '8px 4px',
      opacity: state === 'pending' ? 0.45 : 1,
      transition: 'opacity .4s ease',
    }}>
      {/* Tick column with connecting line */}
      <div style={{ position: 'relative', display: 'flex', flexDirection: 'column', alignItems: 'center', flex: '0 0 24px' }}>
        <div style={{
          width: 24, height: 24, borderRadius: '50%',
          background: state === 'done' ? '#FEC230' : state === 'active' ? 'rgba(254,194,48,0.16)' : '#262626',
          border: state === 'active' ? '1.5px solid #FEC230' : '1px solid #404040',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          color: state === 'done' ? '#000' : '#FEC230',
          transition: 'all .3s ease', position: 'relative', zIndex: 1,
          boxShadow: state === 'active' ? '0 0 14px rgba(254,194,48,0.5)' : 'none',
        }}>
          {state === 'done' ? <I.Check size={14} strokeWidth={3}/> :
           state === 'active' ? <SpinningDot/> :
           <span style={{ width: 5, height: 5, borderRadius: '50%', background: '#525252' }}/>}
        </div>
        {!last && (
          <div style={{
            position: 'absolute', top: 24, bottom: -12, left: '50%', transform: 'translateX(-50%)',
            width: 1.5, background: state === 'done' ? '#FEC230' : '#404040',
            transition: 'background .35s ease',
          }}/>
        )}
      </div>
      <div style={{ flex: 1, paddingTop: 1 }}>
        <div style={{
          color: state === 'pending' ? '#808080' : '#fff',
          fontSize: 14, fontWeight: state === 'active' ? 600 : 500, lineHeight: '20px',
        }}>{stage.title}{state === 'active' && <ShimmerDots/>}</div>
        <div style={{ color: '#808080', fontSize: 12, lineHeight: '18px', marginTop: 2 }}>{stage.hint}</div>
      </div>
    </div>
  );
}

function SpinningDot() {
  return (
    <span style={{
      width: 10, height: 10, borderRadius: '50%',
      border: '1.5px solid #FEC230', borderTopColor: 'transparent',
      animation: 'vrvSpin 0.7s linear infinite', display: 'inline-block',
    }}/>
  );
}

function ShimmerDots() {
  return (
    <span style={{ marginLeft: 4, display: 'inline-flex', gap: 2 }}>
      {[0, 1, 2].map(i => (
        <span key={i} style={{
          width: 3, height: 3, borderRadius: '50%', background: '#FEC230',
          animation: `vrvBounce 1.2s ${i * 0.15}s ease-in-out infinite`,
        }}/>
      ))}
    </span>
  );
}

// ─── Error screen ──────────────────────────────────────────────
function ErrorScreen({ onRetry, filename, errorType, progress }) {
  const errorMessages = {
    'failed_invalid_pdf': {
      title: "We couldn't identify this as a manufacturer quote",
      description: "Please upload the original manufacturer VRV/VRF quote PDF and try again.",
      icon: 'warning',
      color: '#F97322',
      showFilename: true,
      showTips: true,
    },
    'failed_processing': {
      title: "Something went wrong processing your file",
      description: "Please try again. If the problem persists, contact support.",
      icon: 'warning',
      color: '#F97322',
      showFilename: true,
      showTips: false,
    },
    'failed_api_error': {
      title: "AI service temporarily busy",
      description: "Google's AI service is experiencing high demand. Please wait 30 seconds and try again.",
      icon: 'server',
      color: '#EF4444',
      showFilename: false,
      showTips: false,
    },
    'failed_rate_limit': {
      title: "AI service temporarily busy",
      description: "Google's AI service is experiencing high demand. Please wait 30 seconds and try again.",
      icon: 'clock',
      color: '#F59E0B',
      showFilename: false,
      showTips: false,
    },
  };

  const error = errorMessages[errorType] || errorMessages['failed_invalid_pdf'];

  // Simple emoji icon - guaranteed to work
  const renderIcon = () => {
    return (
      <span style={{ fontSize: 42, lineHeight: 1 }}>⚠️</span>
    );
  };

  return (
    <PhoneShell title="Couldn't process" onBack={onRetry} progress={progress}>
      <div style={{ padding: '32px 24px', display: 'flex', flexDirection: 'column', alignItems: 'center', textAlign: 'center', gap: 14, marginTop: 20 }}>
        <div style={{
          width: 88, height: 88, borderRadius: '50%',
          background: `${error.color}14`, border: `1px solid ${error.color}52`,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}>
          {renderIcon()}
        </div>
        <div style={{ color: '#fff', fontSize: 20, fontWeight: 700, lineHeight: '28px', letterSpacing: '-0.3px', marginTop: 6 }}>
          {error.title.split('\n').map((line, i) => <span key={i}>{line}<br/></span>)}
        </div>
        <div style={{ color: '#B8B8B8', fontSize: 14, lineHeight: '22px', maxWidth: 280 }}>
          {error.description}
        </div>

        {error.showFilename && filename && (
          <div style={{
            marginTop: 12, padding: '10px 12px', background: '#262626', borderRadius: 8,
            border: '1px solid #404040', display: 'flex', alignItems: 'center', gap: 10, width: '100%',
          }}>
            <div style={{
              width: 28, height: 36, background: '#404040', borderRadius: 3,
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              fontSize: 8, fontWeight: 700, color: error.color, flex: '0 0 28px',
            }}>PDF</div>
            <div style={{ flex: 1, textAlign: 'left', minWidth: 0 }}>
              <div style={{ color: '#fff', fontSize: 13, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{filename}</div>
              <div style={{ color: error.color, fontSize: 11, marginTop: 2 }}>Not recognised as a VRV/VRF quote</div>
            </div>
          </div>
        )}

        {error.showTips && (
          <div style={{
            marginTop: 16, padding: 12, background: '#1f1f1f',
            border: '1px solid #404040', borderRadius: 8, textAlign: 'left', width: '100%',
          }}>
            <div style={{ color: '#D4D4D4', fontSize: 12, fontWeight: 600, marginBottom: 8 }}>Common issues</div>
            <ul style={{ margin: 0, padding: '0 0 0 18px', color: '#B8B8B8', fontSize: 12, lineHeight: '20px' }}>
              <li>This looks like site photos or a brochure, not a quote</li>
              <li>The PDF is scanned without a recognisable schedule</li>
              <li>Manufacturer brand isn't supported yet</li>
            </ul>
          </div>
        )}

        <div style={{ width: '100%', marginTop: 8 }}>
          <Button variant="primary" full onClick={onRetry}>
            {errorType === 'failed_api_error' || errorType === 'failed_rate_limit' ? 'Try again' : 'Upload another PDF'}
          </Button>
        </div>
      </div>
    </PhoneShell>
  );
}

// ─── Compact hardware item card ──
function HardwareItemCard({ item, expanded, onToggle, onChange, onDelete }) {
  const [swipeX, setSwipeX] = useState(0);
  const startX = useRef(null);
  const startSwipeX = useRef(0);

  const onPointerDown = (e) => { startX.current = e.clientX; startSwipeX.current = swipeX; };
  const onPointerMove = (e) => {
    if (startX.current == null) return;
    setSwipeX(Math.max(-70, Math.min(0, startSwipeX.current + (e.clientX - startX.current))));
  };
  const onPointerUp = () => { startX.current = null; setSwipeX(s => s < -35 ? -70 : 0); };
  const handleClick = () => { if (swipeX !== 0) { setSwipeX(0); return; } onToggle(); };

  // Format category nicely
  const categoryLabel = (item.category || '').replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase()) || '';

  return (
    <div style={{ position: 'relative', overflow: 'hidden', borderRadius: 6 }}>
      {/* Delete reveal */}
      <button onClick={onDelete} aria-label="Delete" style={{
        position: 'absolute', top: 0, right: 0, bottom: 0, width: 70,
        background: '#EF4444', color: '#fff', border: 0, cursor: 'pointer',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: 'inherit', fontSize: 12, fontWeight: 600,
      }}>
        <I.Trash size={16}/>
      </button>

      {/* Card */}
      <div
        onPointerDown={onPointerDown}
        onPointerMove={onPointerMove}
        onPointerUp={onPointerUp}
        onPointerCancel={onPointerUp}
        style={{
          position: 'relative', background: '#1f1f1f',
          borderRadius: 6, transform: `translateX(${swipeX}px)`,
          transition: startX.current == null ? 'transform .2s ease' : 'none',
          touchAction: 'pan-y',
        }}
      >
        <button onClick={handleClick} style={{
          width: '100%', textAlign: 'left', cursor: 'pointer', fontFamily: 'inherit',
          background: 'transparent', border: 0, padding: '10px 12px', display: 'block',
        }}>
          {/* Single row: Qty + Model + Capacity */}
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span style={{
              color: '#FEC230', fontSize: 13, fontWeight: 700, minWidth: 28,
              fontVariantNumeric: 'tabular-nums',
            }}>{item.qty}×</span>
            <span style={{
              color: '#fff', fontSize: 13, fontWeight: 600,
              fontFamily: 'ui-monospace, Menlo, monospace',
              flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
            }}>{item.code || item.model_number}</span>
            {item.capacity_kw && (
              <span style={{
                color: '#06B6D4', fontSize: 12, fontWeight: 600,
                background: 'rgba(6,182,212,0.12)', padding: '2px 6px', borderRadius: 4,
              }}>{item.capacity_kw}kW</span>
            )}
            <I.ChevronDown size={16} color="#666" style={{
              transform: expanded ? 'rotate(180deg)' : 'none',
              transition: 'transform .2s',
            }}/>
          </div>
          {/* Description line */}
          {(item.name || item.description) && (
            <div style={{
              color: '#888', fontSize: 11, marginTop: 4, marginLeft: 36,
              overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
            }}>{item.name || item.description}</div>
          )}
        </button>

        {/* Expanded edit panel */}
        {expanded && (
          <div style={{ padding: '8px 12px 12px', borderTop: '1px solid #333' }}>
            <div style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
              <EditField label="Qty" value={item.qty} onChange={(v) => onChange({ qty: Math.max(0, parseInt(v) || 0) })} type="number"/>
              {categoryLabel && <span style={{ color: '#666', fontSize: 11 }}>{categoryLabel}</span>}
              <div style={{ flex: 1 }}/>
              <button onClick={(e) => { e.stopPropagation(); onDelete(); }} style={{
                padding: '6px 12px', borderRadius: 4, border: 0,
                background: 'rgba(239,68,68,0.15)', color: '#EF4444', fontSize: 12, fontWeight: 600,
                cursor: 'pointer', fontFamily: 'inherit',
              }}>Remove</button>
              <button onClick={(e) => { e.stopPropagation(); onToggle(); }} style={{
                padding: '6px 12px', borderRadius: 4, border: 0,
                background: '#FEC230', color: '#000', fontSize: 12, fontWeight: 600,
                cursor: 'pointer', fontFamily: 'inherit',
              }}>
                Done
              </button>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

function EditField({ label, value, onChange, type = 'text', prefix }) {
  return (
    <label style={{ flex: 1, display: 'block' }} onClick={(e) => e.stopPropagation()}>
      <div style={{ color: '#808080', fontSize: 10, textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: 4 }}>{label}</div>
      <div style={{
        display: 'flex', alignItems: 'center', gap: 4,
        background: '#1f1f1f', border: '1px solid #525252', borderRadius: 6, padding: '8px 10px',
      }}>
        {prefix && <span style={{ color: '#808080', fontSize: 13 }}>{prefix}</span>}
        <input
          type={type}
          value={value}
          onChange={(e) => onChange(e.target.value)}
          onClick={(e) => e.stopPropagation()}
          style={{
            flex: 1, width: '100%', minWidth: 0, background: 'transparent', border: 0, outline: 'none',
            color: '#fff', fontSize: 13, fontWeight: 600, fontVariantNumeric: 'tabular-nums',
            fontFamily: 'inherit', padding: 0,
          }}
        />
      </div>
    </label>
  );
}

// ─── V3 Pricing Slider Component ─────────────────────────────
function V3PricingSlider({ value, onChange, min, max, step = 0.5, label, displayValue, color = '#FEC230' }) {
  const sliderRef = React.useRef(null);
  const [dragging, setDragging] = React.useState(false);

  const progress = (value - min) / (max - min);

  const handleMove = (clientX) => {
    if (!sliderRef.current) return;
    const rect = sliderRef.current.getBoundingClientRect();
    const x = Math.max(0, Math.min(clientX - rect.left, rect.width));
    const rawValue = min + (x / rect.width) * (max - min);
    // Snap to step
    const snapped = Math.round(rawValue / step) * step;
    const clamped = Math.max(min, Math.min(max, snapped));
    onChange(clamped);
  };

  const handlePointerDown = (e) => {
    setDragging(true);
    handleMove(e.clientX);
    e.target.setPointerCapture(e.pointerId);
  };

  const handlePointerMove = (e) => {
    if (dragging) handleMove(e.clientX);
  };

  const handlePointerUp = (e) => {
    setDragging(false);
    e.target.releasePointerCapture(e.pointerId);
  };

  return (
    <div style={{ marginBottom: 20 }}>
      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 8 }}>
        <span style={{ color: '#B8B8B8', fontSize: 12 }}>{label}</span>
        <span style={{ color: color, fontSize: 14, fontWeight: 700 }}>{displayValue}</span>
      </div>
      <div
        ref={sliderRef}
        onPointerDown={handlePointerDown}
        onPointerMove={handlePointerMove}
        onPointerUp={handlePointerUp}
        style={{
          height: 32, background: '#262626', borderRadius: 6, cursor: 'pointer',
          position: 'relative', touchAction: 'none',
        }}
      >
        {/* Track fill */}
        <div style={{
          position: 'absolute', left: 0, top: 0, bottom: 0,
          width: `${progress * 100}%`, background: color,
          borderRadius: 6, opacity: 0.3,
        }}/>
        {/* Thumb */}
        <div style={{
          position: 'absolute', top: '50%', transform: 'translate(-50%, -50%)',
          left: `${progress * 100}%`,
          width: 20, height: 20, borderRadius: '50%',
          background: color, boxShadow: '0 2px 6px rgba(0,0,0,0.3)',
        }}/>
      </div>
    </div>
  );
}

// ─── Hardware Summary ─────────────────────────────────────────
function HardwareScreen({ onBack, onContinue, hardware, quoteId, progress }) {
  const [items, setItems] = useState(hardware?.items || []);
  const [extras, setExtras] = useState(hardware?.extras || []);
  const [manufacturerTotal, setManufacturerTotal] = useState(hardware?.manufacturer_total || 0);
  const [expandedId, setExpandedId] = useState(null);
  const [loading, setLoading] = useState(false);

  // V3 Pricing State
  const [multiplier, setMultiplier] = useState(3.5);
  const [totalRunMeters, setTotalRunMeters] = useState(15);
  const [v3Pricing, setV3Pricing] = useState(null);
  const [pricingLoading, setPricingLoading] = useState(false);

  // Load hardware data from API if we have a quoteId
  useEffect(() => {
    if (quoteId && (!hardware || !hardware.items || hardware.items.length === 0)) {
      loadHardware();
    }
  }, [quoteId]);

  // Update items when hardware prop changes
  useEffect(() => {
    if (hardware?.items) {
      setItems(hardware.items);
    }
    if (hardware?.extras) {
      setExtras(hardware.extras);
    }
    if (hardware?.manufacturer_total) {
      setManufacturerTotal(hardware.manufacturer_total);
    }
  }, [hardware]);

  const loadHardware = async () => {
    try {
      setLoading(true);
      const response = await api.getHardware(quoteId);
      // API returns {success, data: {items, manufacturer_total, ...}}
      const data = response.data || response;
      if (data.items) {
        setItems(data.items);
      }
      if (data.extras) {
        setExtras(data.extras);
      }
      if (data.manufacturer_total) {
        setManufacturerTotal(data.manufacturer_total);
      }
    } catch (err) {
      console.error('Failed to load hardware:', err);
    } finally {
      setLoading(false);
    }
  };

  // Use manufacturer_total from API - this is the lump sum from the supplier quote
  const total = useMemo(
    () => manufacturerTotal || extras.reduce((a, e) => a + e.value, 0),
    [manufacturerTotal, extras]
  );

  // V3 Pricing: Fetch allocation and pricing when sliders change
  useEffect(() => {
    if (!quoteId || total <= 0) return;

    const fetchV3Pricing = async () => {
      setPricingLoading(true);
      try {
        const data = await api.calculateV3Pricing(quoteId, totalRunMeters, multiplier);
        if (data.success) {
          setV3Pricing(data.data);
        }
      } catch (err) {
        console.error('V3 pricing error:', err);
      } finally {
        setPricingLoading(false);
      }
    };

    // Debounce the API call
    const timer = setTimeout(fetchV3Pricing, 300);
    return () => clearTimeout(timer);
  }, [quoteId, total, multiplier, totalRunMeters]);

  const updateItem = (id, patch) => setItems(prev => prev.map(it => it.id === id ? { ...it, ...patch } : it));
  const removeItem = (id) => {
    setItems(prev => prev.filter(it => it.id !== id));
    if (expandedId === id) setExpandedId(null);
  };

  if (loading) {
    return (
      <PhoneShell title="Extracted Hardware" onBack={onBack} progress={progress}>
        <div style={{ padding: '48px 24px', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 16 }}>
          <div style={{
            width: 48, height: 48, border: '3px solid #404040', borderTopColor: '#FEC230',
            borderRadius: '50%', animation: 'vrvSpin 1s linear infinite',
          }}/>
          <div style={{ color: '#B8B8B8', fontSize: 14 }}>Loading hardware data...</div>
        </div>
      </PhoneShell>
    );
  }

  return (
    <PhoneShell
      title="Extracted Hardware"
      onBack={onBack}
      progress={progress}
    >
      <div style={{ padding: '12px 16px 120px' }}>
        {/* V3 Pricing Section - moved above hardware schedule */}
        <div style={{ marginBottom: 16 }}>
          <div style={{ color: '#D4D4D4', fontSize: 12, fontWeight: 700, letterSpacing: '0.02em', marginBottom: 12, marginLeft: 2 }}>PRICING</div>

          <div style={{ background: '#1f1f1f', border: '1px solid #404040', borderRadius: 8, padding: 16 }}>
            {/* Supplied quote total - moved inside pricing card */}
            <div style={{
              display: 'flex', justifyContent: 'space-between', alignItems: 'center',
              paddingBottom: 16, marginBottom: 16, borderBottom: '1px solid #404040',
            }}>
              <div>
                <div style={{ color: '#808080', fontSize: 11, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase' }}>
                  Supplied quote total
                </div>
                <div style={{ color: '#B8B8B8', fontSize: 12, marginTop: 2 }}>{items.length} hardware {items.length === 1 ? 'line' : 'lines'}{extras.length > 0 ? ` - ${extras.length} ${extras.length === 1 ? 'extra' : 'extras'}` : ''} - ex GST</div>
              </div>
              <div style={{ color: '#fff', fontSize: 22, fontWeight: 700, fontVariantNumeric: 'tabular-nums', letterSpacing: '-0.5px' }}>
                {fmt(total)}
              </div>
            </div>

            {/* Total Value Slider */}
            <V3PricingSlider
              value={multiplier}
              onChange={setMultiplier}
              min={1}
              max={6}
              step={0.1}
              label="Total value multiplier"
              displayValue={`×${multiplier.toFixed(1)}`}
              color="#FEC230"
            />

            {/* Midpoint marker - show ×3.5 as the sweet spot */}
            <div style={{
              display: 'flex', justifyContent: 'center',
              marginTop: -12, marginBottom: 16,
              fontSize: 10, color: '#666'
            }}>
              <span style={{
                padding: '2px 6px', background: '#262626', borderRadius: 4,
                color: multiplier >= 3 && multiplier <= 4 ? '#FEC230' : '#666',
              }}>
                Sweet spot: ×3 - ×4
              </span>
            </div>

            {/* Total Run Slider */}
            <V3PricingSlider
              value={totalRunMeters}
              onChange={setTotalRunMeters}
              min={5}
              max={100}
              step={1}
              label="How long is the total run?"
              displayValue={`${totalRunMeters}m`}
              color="#4FC3F7"
            />

            {/* V3 Quote Total */}
            <div style={{
              marginTop: 16, paddingTop: 16, borderTop: '1px solid #404040',
              display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            }}>
              <div>
                <div style={{ color: '#808080', fontSize: 11, fontWeight: 600, letterSpacing: '0.04em', textTransform: 'uppercase' }}>
                  Quote total
                </div>
                <div style={{ color: '#B8B8B8', fontSize: 11, marginTop: 2 }}>
                  {pricingLoading ? 'Calculating...' : v3Pricing ? `~${v3Pricing.pricing.grossMarginPercent.toFixed(0)}% margin` : ''}
                </div>
              </div>
              <div style={{
                color: '#FEC230', fontSize: 28, fontWeight: 700,
                fontVariantNumeric: 'tabular-nums', letterSpacing: '-0.5px',
                opacity: pricingLoading ? 0.5 : 1,
              }}>
                {v3Pricing ? fmt(v3Pricing.pricing.totalQuoteValue) : fmt(total * multiplier)}
              </div>
            </div>

            {/* Quick breakdown */}
            {v3Pricing && !pricingLoading && (
              <div style={{ marginTop: 12, fontSize: 11, color: '#808080' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
                  <span>Hardware</span>
                  <span style={{ color: '#B8B8B8' }}>{fmt(v3Pricing.pricing.breakdown.hardware)}</span>
                </div>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
                  <span>Materials ({v3Pricing.allocation.materials.length} items)</span>
                  <span style={{ color: '#B8B8B8' }}>{fmt(v3Pricing.pricing.breakdown.materials)}</span>
                </div>
                <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
                  <span>Labour ({v3Pricing.pricing.technicianHours}h × 2 techs)</span>
                  <span style={{ color: '#B8B8B8' }}>{fmt(v3Pricing.pricing.breakdown.labour)}</span>
                </div>
                <div style={{ display: 'flex', justifyContent: 'space-between' }}>
                  <span>Profit</span>
                  <span style={{ color: '#4CAF50' }}>{fmt(v3Pricing.pricing.breakdown.profit)}</span>
                </div>
              </div>
            )}
          </div>
        </div>

        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', margin: '4px 2px 8px' }}>
          <div style={{ color: '#D4D4D4', fontSize: 12, fontWeight: 700, letterSpacing: '0.02em' }}>HARDWARE SCHEDULE</div>
          <span style={{ color: '#808080', fontSize: 11 }}>{items.length} {items.length === 1 ? 'line' : 'lines'} - swipe to delete</span>
        </div>

        <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
          {items.map(item => (
            <HardwareItemCard
              key={item.id}
              item={item}
              expanded={expandedId === item.id}
              onToggle={() => setExpandedId(id => id === item.id ? null : item.id)}
              onChange={(patch) => updateItem(item.id, patch)}
              onDelete={() => removeItem(item.id)}
            />
          ))}
        </div>

        {/* Extras */}
        {extras.length > 0 && (
          <div style={{ marginTop: 16 }}>
            <div style={{ color: '#D4D4D4', fontSize: 12, fontWeight: 700, letterSpacing: '0.02em', marginBottom: 8, marginLeft: 2 }}>EXTRAS</div>
            <div style={{ background: '#262626', border: '1px solid #404040', borderRadius: 8, overflow: 'hidden' }}>
              {extras.map((e, i) => (
                <div key={i} style={{
                  padding: '10px 14px', display: 'flex', justifyContent: 'space-between',
                  borderBottom: i < extras.length - 1 ? '1px solid #404040' : 0,
                }}>
                  <span style={{ color: '#D4D4D4', fontSize: 13 }}>{e.name}</span>
                  <span style={{ color: '#fff', fontSize: 13, fontWeight: 600, fontVariantNumeric: 'tabular-nums' }}>{fmt(e.value)}</span>
                </div>
              ))}
            </div>
          </div>
        )}

      </div>

      {/* Sticky footer CTA */}
      <div style={{
        position: 'absolute', bottom: 0, left: 0, right: 0, padding: '12px 16px 16px',
        background: 'linear-gradient(to top, rgba(23,23,23,1) 60%, rgba(23,23,23,0))',
        display: 'flex', gap: 8,
      }}>
        <Button
          variant="primary"
          full
          disabled={pricingLoading}
          onClick={() => onContinue({
            hardwareTotal: total,
            multiplier,
            totalRunMeters,
            v3Pricing,
            hardwareItems: items.filter(it => !it.deleted),
          })}
        >
          {pricingLoading ? 'Calculating...' : 'Next'}
        </Button>
      </div>
    </PhoneShell>
  );
}

window.LoaderScreen = LoaderScreen;
window.ErrorScreen = ErrorScreen;
window.HardwareScreen = HardwareScreen;
