/* global React, Icon, IconBtn, db, qrEncode */
const { useState, useEffect, useMemo, useRef, useCallback } = React;

// ============================================================
// QR generator — text/URL/Wi-Fi/vCard into a scannable QR code.
// Renders as inline SVG so it scales cleanly and exports.
// ============================================================
const QR_MODES = [
  { id: 'text',  label: 'Text/URL', icon: 'link',     hint: 'Plain text or any URL — works with most camera apps.' },
  { id: 'wifi',  label: 'Wi-Fi',    icon: 'wifi',     hint: 'Generates a JOIN-the-network code. Scanning offers a one-tap connect.' },
  { id: 'vcard', label: 'Contact',  icon: 'contact_page', hint: 'A minimal vCard: name, phone, email, organization.' },
  { id: 'email', label: 'Email',    icon: 'mail',     hint: 'Pre-fills To, subject and body in the scanner\u2019s email app.' },
  { id: 'sms',   label: 'SMS',      icon: 'sms',      hint: 'Pre-fills a text message to the given number.' },
];
const EC_OPTIONS = [
  { id: 'L', label: 'Low',     desc: '~7% recoverable',  color: 'hsl(168, 60%, 50%)' },
  { id: 'M', label: 'Medium',  desc: '~15% recoverable', color: 'hsl(212, 85%, 60%)' },
  { id: 'Q', label: 'Quartile',desc: '~25% recoverable', color: 'hsl(28, 90%, 60%)' },
  { id: 'H', label: 'High',    desc: '~30% recoverable', color: 'hsl(8, 78%, 58%)' },
];

function QRTool() {
  const [mode, setMode] = useState('text');
  const [ec, setEc] = useState('M');
  const [fields, setFields] = useState({
    text:   '',
    wifi:   { ssid: '', password: '', auth: 'WPA', hidden: false },
    vcard:  { name: '', org: '', phone: '', email: '' },
    email:  { to: '', subject: '', body: '' },
    sms:    { to: '', body: '' },
  });
  const [history, setHistory] = useState([]);
  const [error, setError] = useState(null);

  // Load history
  useEffect(() => {
    db.kv.get('qrHistory').then(rec => {
      if (Array.isArray(rec?.v)) setHistory(rec.v);
    });
  }, []);
  const saveHistory = (h) => { setHistory(h); db.kv.put({ k: 'qrHistory', v: h.slice(0, 20) }); };

  // Build the encoded text from the active mode + fields
  const encoded = useMemo(() => {
    const f = fields;
    switch (mode) {
      case 'text':  return f.text;
      case 'wifi':  {
        const esc = (s) => String(s).replace(/([\\;,":])/g, '\\$1');
        const w = f.wifi;
        if (!w.ssid) return '';
        return `WIFI:T:${w.auth};S:${esc(w.ssid)};P:${esc(w.password)};${w.hidden ? 'H:true;' : ''};`;
      }
      case 'vcard': {
        const v = f.vcard;
        if (!v.name && !v.email && !v.phone) return '';
        return [
          'BEGIN:VCARD',
          'VERSION:3.0',
          v.name && `FN:${v.name}`,
          v.org && `ORG:${v.org}`,
          v.phone && `TEL:${v.phone}`,
          v.email && `EMAIL:${v.email}`,
          'END:VCARD',
        ].filter(Boolean).join('\n');
      }
      case 'email': {
        const e = f.email;
        if (!e.to) return '';
        const params = new URLSearchParams();
        if (e.subject) params.set('subject', e.subject);
        if (e.body) params.set('body', e.body);
        const q = params.toString();
        return `mailto:${e.to}${q ? '?' + q : ''}`;
      }
      case 'sms': {
        const s = f.sms;
        if (!s.to) return '';
        return `SMSTO:${s.to}:${s.body || ''}`;
      }
      default: return '';
    }
  }, [mode, fields]);

  // Compute matrix
  const matrix = useMemo(() => {
    if (!encoded) return null;
    try {
      setError(null);
      return qrEncode(encoded, ec);
    } catch (e) {
      setError(e.message || 'Unable to encode.');
      return null;
    }
  }, [encoded, ec]);

  // Save to history when user explicitly hits "Save"
  const saveToHistory = () => {
    if (!encoded || !matrix) return;
    const label = mode === 'text' ? encoded.slice(0, 60)
                : mode === 'wifi' ? `Wi-Fi · ${fields.wifi.ssid}`
                : mode === 'vcard' ? `Contact · ${fields.vcard.name || fields.vcard.email}`
                : mode === 'email' ? `Email · ${fields.email.to}`
                : mode === 'sms' ? `SMS · ${fields.sms.to}`
                : encoded.slice(0, 60);
    saveHistory([{ mode, ec, fields: structuredClone(fields), label, ts: Date.now() }, ...history]);
  };
  const recall = (h) => { setMode(h.mode); setEc(h.ec); setFields(h.fields); };
  const removeHistory = (i) => saveHistory(history.filter((_, idx) => idx !== i));

  // Download SVG
  const downloadSVG = () => {
    if (!matrix) return;
    const svg = matrixToSVGString(matrix);
    const blob = new Blob([svg], { type: 'image/svg+xml' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a'); a.href = url; a.download = `qr-${Date.now()}.svg`;
    document.body.appendChild(a); a.click(); a.remove();
    setTimeout(() => URL.revokeObjectURL(url), 1000);
  };
  // Download PNG (rasterized from SVG via canvas)
  const downloadPNG = async () => {
    if (!matrix) return;
    const size = matrix.length;
    const scale = 16; // ~16px per module → crisp scan
    const c = document.createElement('canvas');
    c.width = c.height = (size + 8) * scale;
    const g = c.getContext('2d');
    g.fillStyle = '#fff';
    g.fillRect(0, 0, c.width, c.height);
    g.fillStyle = '#000';
    for (let y = 0; y < size; y++) for (let x = 0; x < size; x++) {
      if (matrix[y][x]) g.fillRect((x + 4) * scale, (y + 4) * scale, scale, scale);
    }
    c.toBlob(blob => {
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a'); a.href = url; a.download = `qr-${Date.now()}.png`;
      document.body.appendChild(a); a.click(); a.remove();
      setTimeout(() => URL.revokeObjectURL(url), 1000);
    }, 'image/png');
  };
  const copySVG = async () => {
    if (!matrix) return;
    try { await navigator.clipboard.writeText(matrixToSVGString(matrix)); } catch {}
  };

  const updateField = (k, patch) => {
    setFields(prev => typeof prev[k] === 'object'
      ? { ...prev, [k]: { ...prev[k], ...patch } }
      : { ...prev, [k]: patch }
    );
  };

  return (
    <div className="qr-tool">
      <div className="qr-form">
        <header className="qr-form-head">
          <h1>QR generator</h1>
          <p>Local-only. Nothing about your code leaves this browser.</p>
        </header>

        {/* Mode tabs */}
        <div className="qr-modes">
          {QR_MODES.map(m => (
            <button key={m.id} className={`qr-mode ${mode === m.id ? 'is-active' : ''}`} onClick={() => setMode(m.id)}>
              <Icon name={m.icon} />
              <span>{m.label}</span>
            </button>
          ))}
        </div>
        <p className="qr-mode-hint">{QR_MODES.find(m => m.id === mode).hint}</p>

        {/* Form per mode */}
        <div className="qr-fields">
          {mode === 'text' && (
            <label className="qr-field qr-field-wide">
              <span>Content</span>
              <textarea
                className="lh-input qr-textarea"
                placeholder="https://example.com or any text…"
                value={fields.text}
                onChange={e => updateField('text', e.target.value)}
                rows={4}
              />
            </label>
          )}
          {mode === 'wifi' && (
            <>
              <label className="qr-field">
                <span>Network name (SSID)</span>
                <input className="lh-input" value={fields.wifi.ssid} onChange={e => updateField('wifi', { ssid: e.target.value })} />
              </label>
              <label className="qr-field">
                <span>Password</span>
                <input className="lh-input" value={fields.wifi.password} onChange={e => updateField('wifi', { password: e.target.value })} type="text" />
              </label>
              <label className="qr-field">
                <span>Security</span>
                <select className="lh-input" value={fields.wifi.auth} onChange={e => updateField('wifi', { auth: e.target.value })}>
                  <option value="WPA">WPA / WPA2</option>
                  <option value="WEP">WEP</option>
                  <option value="nopass">None</option>
                </select>
              </label>
              <label className="qr-field-check">
                <input type="checkbox" checked={fields.wifi.hidden} onChange={e => updateField('wifi', { hidden: e.target.checked })} />
                <span>Network is hidden</span>
              </label>
            </>
          )}
          {mode === 'vcard' && (
            <>
              <label className="qr-field"><span>Full name</span>
                <input className="lh-input" value={fields.vcard.name} onChange={e => updateField('vcard', { name: e.target.value })} /></label>
              <label className="qr-field"><span>Organization</span>
                <input className="lh-input" value={fields.vcard.org} onChange={e => updateField('vcard', { org: e.target.value })} /></label>
              <label className="qr-field"><span>Phone</span>
                <input className="lh-input" value={fields.vcard.phone} onChange={e => updateField('vcard', { phone: e.target.value })} /></label>
              <label className="qr-field"><span>Email</span>
                <input className="lh-input" type="email" value={fields.vcard.email} onChange={e => updateField('vcard', { email: e.target.value })} /></label>
            </>
          )}
          {mode === 'email' && (
            <>
              <label className="qr-field"><span>To</span>
                <input className="lh-input" type="email" value={fields.email.to} onChange={e => updateField('email', { to: e.target.value })} /></label>
              <label className="qr-field"><span>Subject</span>
                <input className="lh-input" value={fields.email.subject} onChange={e => updateField('email', { subject: e.target.value })} /></label>
              <label className="qr-field qr-field-wide"><span>Body</span>
                <textarea className="lh-input qr-textarea" rows={3} value={fields.email.body} onChange={e => updateField('email', { body: e.target.value })} /></label>
            </>
          )}
          {mode === 'sms' && (
            <>
              <label className="qr-field"><span>Phone number</span>
                <input className="lh-input" value={fields.sms.to} onChange={e => updateField('sms', { to: e.target.value })} /></label>
              <label className="qr-field qr-field-wide"><span>Message</span>
                <textarea className="lh-input qr-textarea" rows={3} value={fields.sms.body} onChange={e => updateField('sms', { body: e.target.value })} /></label>
            </>
          )}
        </div>

        {/* EC level */}
        <div className="qr-ec">
          <div className="qr-ec-label">Error correction</div>
          <div className="qr-ec-grid">
            {EC_OPTIONS.map(o => (
              <button
                key={o.id}
                className={`qr-ec-btn ${ec === o.id ? 'is-active' : ''}`}
                onClick={() => setEc(o.id)}
                style={ec === o.id ? { '--ec-color': o.color } : {}}
              >
                <div className="qr-ec-id">{o.id}</div>
                <div className="qr-ec-name">{o.label}</div>
                <div className="qr-ec-desc">{o.desc}</div>
              </button>
            ))}
          </div>
        </div>
      </div>

      <div className="qr-preview">
        <div className="qr-preview-stage">
          {matrix ? (
            <QRRender matrix={matrix} />
          ) : error ? (
            <div className="qr-preview-empty">
              <Icon name="error" />
              <div className="title">Couldn't encode</div>
              <div className="sub">{error}</div>
            </div>
          ) : (
            <div className="qr-preview-empty">
              <Icon name="qr_code_2" />
              <div className="title">Your QR will appear here</div>
              <div className="sub">Fill in the form on the left to generate.</div>
            </div>
          )}
        </div>

        {matrix && (
          <div className="qr-preview-info">
            <div>{matrix.length}×{matrix.length} · EC {ec} · {encoded.length} chars</div>
          </div>
        )}

        <div className="qr-preview-actions">
          <button className="lh-btn primary" onClick={downloadPNG} disabled={!matrix}>
            <Icon name="download" />Download PNG
          </button>
          <button className="lh-btn ghost" onClick={downloadSVG} disabled={!matrix}>
            <Icon name="image" />SVG
          </button>
          <button className="lh-btn ghost" onClick={copySVG} disabled={!matrix} title="Copy SVG to clipboard">
            <Icon name="content_copy" />Copy
          </button>
          <button className="lh-btn ghost" onClick={saveToHistory} disabled={!matrix}>
            <Icon name="bookmark_add" />Save
          </button>
        </div>

        {history.length > 0 && (
          <div className="qr-history">
            <div className="qr-history-head">Saved</div>
            <ul>
              {history.map((h, i) => (
                <li key={i}>
                  <button className="qr-history-row" onClick={() => recall(h)}>
                    <Icon name={QR_MODES.find(m => m.id === h.mode)?.icon || 'qr_code_2'} />
                    <span className="qr-history-row-label">{h.label}</span>
                  </button>
                  <button className="qr-history-del" onClick={() => removeHistory(i)} title="Remove">
                    <Icon name="close" />
                  </button>
                </li>
              ))}
            </ul>
          </div>
        )}
      </div>
    </div>
  );
}

// ============================================================
// QRRender — renders the boolean matrix as a single <path> SVG
// for fast painting at any scale.
// ============================================================
function QRRender({ matrix }) {
  const size = matrix.length;
  const padding = 2; // quiet zone in modules (we use 2 for screen; export uses 4)
  const totalSize = size + padding * 2;

  // Build a single path with M+h+v commands per dark module (small, scales fine).
  const path = useMemo(() => {
    const parts = [];
    for (let y = 0; y < size; y++) for (let x = 0; x < size; x++) {
      if (matrix[y][x]) parts.push(`M${x + padding},${y + padding}h1v1h-1z`);
    }
    return parts.join('');
  }, [matrix]);

  return (
    <svg
      className="qr-svg"
      viewBox={`0 0 ${totalSize} ${totalSize}`}
      xmlns="http://www.w3.org/2000/svg"
      shapeRendering="crispEdges"
    >
      <rect width={totalSize} height={totalSize} fill="#fff" />
      <path d={path} fill="#000" />
    </svg>
  );
}

function matrixToSVGString(matrix) {
  const size = matrix.length;
  const padding = 4;
  const totalSize = size + padding * 2;
  let path = '';
  for (let y = 0; y < size; y++) for (let x = 0; x < size; x++) {
    if (matrix[y][x]) path += `M${x + padding},${y + padding}h1v1h-1z`;
  }
  return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${totalSize} ${totalSize}" shape-rendering="crispEdges"><rect width="${totalSize}" height="${totalSize}" fill="#fff"/><path d="${path}" fill="#000"/></svg>`;
}

window.QRTool = QRTool;
