/* global React */
/* SamAttachmentSheet — attach-a-photo/file sheet for the Sam orb runtime.
 * No imports, no build step: this file defines globals loaded alongside the runtime.
 * The parent owns ALL network + microphone behavior. This sheet only reports
 * selections/intent upward and renders whatever result the parent hands back.
 */

var SAM_ATTACH_MAX_BYTES = 25 * 1024 * 1024;
var SAM_ATTACH_FILE_ACCEPT =
  '.jpg,.jpeg,.png,.webp,.gif,.heic,.heif,.pdf,.docx,.xlsx,.csv,.tsv,.txt,.md';

function samAttachFormatSize(bytes) {
  if (typeof bytes !== 'number' || !isFinite(bytes) || bytes < 0) return '';
  if (bytes < 1024) return bytes + ' B';
  if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(0) + ' KB';
  return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
}

function samAttachIsHeic(file) {
  if (!file) return false;
  var name = String(file.name || '').toLowerCase();
  var type = String(file.type || '').toLowerCase();
  return /\.(heic|heif)$/.test(name) || type.indexOf('heic') > -1 || type.indexOf('heif') > -1;
}

/* Only same-origin, scheme-less paths under the attachments route may be linked. */
function samAttachSafeHref(url) {
  if (typeof url !== 'string') return null;
  if (url.indexOf('/api/sam-voice/attachments/') !== 0) return null;
  if (url.indexOf(':') > -1 || url.indexOf('//') === 0 || url.indexOf('\\') > -1) return null;
  return url;
}

function SamAttachmentSheet({
  open, onClose, file, onFile, note, onNote, busy, progress,
  result, error, onSubmit, onRetry, accent = '#5FE3EF',
}) {
  const closeRef = React.useRef(null);
  const restoreRef = React.useRef(null);
  const cameraRef = React.useRef(null);
  const photosRef = React.useRef(null);
  const filesRef = React.useRef(null);
  const [previewUrl, setPreviewUrl] = React.useState('');

  React.useEffect(() => {
    if (!open) return undefined;
    restoreRef.current = document.activeElement;
    const id = window.setTimeout(() => { if (closeRef.current) closeRef.current.focus(); }, 0);
    return () => {
      window.clearTimeout(id);
      const prev = restoreRef.current;
      restoreRef.current = null;
      if (prev && typeof prev.focus === 'function') prev.focus();
    };
  }, [open]);

  React.useEffect(() => {
    if (!open) return undefined;
    const onKey = (event) => {
      if (event.key !== 'Escape' || busy) return;
      event.stopPropagation();
      if (onClose) onClose();
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [open, busy, onClose]);

  React.useEffect(() => {
    const isImage = file && String(file.type || '').indexOf('image/') === 0;
    if (!isImage || samAttachIsHeic(file)) { setPreviewUrl(''); return undefined; }
    const url = URL.createObjectURL(file);
    setPreviewUrl(url);
    return () => { URL.revokeObjectURL(url); setPreviewUrl(''); };
  }, [file]);

  if (!open) return null;

  const pick = (ref) => { if (ref.current) ref.current.click(); };
  const take = (event) => {
    const picked = event.target.files && event.target.files[0];
    event.target.value = '';
    if (picked && onFile) onFile(picked);
  };

  const oversize = Boolean(file && file.size > SAM_ATTACH_MAX_BYTES);
  const status = result && result.status ? String(result.status) : '';
  const isReady = status === 'ready';
  const isErrored = status === 'error';
  const warnings = result && Array.isArray(result.warnings) ? result.warnings : [];
  const href = result ? samAttachSafeHref(result.source_url) : null;
  const pct = typeof progress === 'number' && isFinite(progress)
    ? Math.max(0, Math.min(100, Math.round(progress <= 1 ? progress * 100 : progress)))
    : null;

  const font = '"Inter Tight", "Inter", -apple-system, system-ui, sans-serif';
  const pill = {
    appearance: 'none', WebkitAppearance: 'none', flex: '1 1 30%', minWidth: 0, minHeight: 44,
    padding: '10px 8px', borderRadius: 14, border: '1px solid ' + accent + '66',
    background: 'rgba(22,11,4,0.72)', color: '#ffe0c5', font: '600 12px/1.2 ' + font,
    letterSpacing: '0.03em', cursor: 'pointer', touchAction: 'manipulation',
  };
  const label = { font: '600 9px/1.2 ' + font, letterSpacing: '0.2em', textTransform: 'uppercase', color: accent };

  return (
    <div style={{ position: 'fixed', inset: 0, zIndex: 60, display: 'flex', alignItems: 'flex-end', justifyContent: 'center', background: 'rgba(0,0,0,0.55)' }}>
      <div role="dialog" aria-modal="true" aria-label="Attach to Sam" style={{
        width: '100%', maxWidth: 400, maxHeight: '90dvh', overflowY: 'auto', boxSizing: 'border-box',
        padding: '14px 16px calc(16px + env(safe-area-inset-bottom))',
        borderRadius: '18px 18px 0 0', border: '0.5px solid ' + accent + '55', borderBottom: 0,
        background: 'rgba(18,10,4,0.94)', backdropFilter: 'blur(20px) saturate(140%)',
        WebkitBackdropFilter: 'blur(20px) saturate(140%)', color: '#fbe3c8', font: '14px/1.45 ' + font,
        boxShadow: '0 -10px 40px rgba(0,0,0,0.5)',
      }}>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
          <h2 style={{ margin: 0, font: '650 15px/1.2 ' + font, letterSpacing: '-0.01em' }}>Attach to Sam</h2>
          <button ref={closeRef} type="button" onClick={() => onClose && onClose()} disabled={busy}
            style={{ minHeight: 44, minWidth: 44, borderRadius: 12, border: '1px solid rgba(255,255,255,0.12)', background: 'transparent', color: '#ffd6b5', font: '600 12px/1.2 ' + font, cursor: busy ? 'default' : 'pointer', opacity: busy ? 0.5 : 1 }}>Close</button>
        </div>

        <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
          <button type="button" style={pill} disabled={busy} onClick={() => pick(cameraRef)}>Camera</button>
          <button type="button" style={pill} disabled={busy} onClick={() => pick(photosRef)}>Photos</button>
          <button type="button" style={pill} disabled={busy} onClick={() => pick(filesRef)}>Files</button>
        </div>
        <input ref={cameraRef} type="file" accept="image/*" capture="environment" aria-label="Take a photo with the camera" onChange={take} style={{ display: 'none' }} />
        <input ref={photosRef} type="file" accept="image/*" aria-label="Choose a photo from your library" onChange={take} style={{ display: 'none' }} />
        <input ref={filesRef} type="file" accept={SAM_ATTACH_FILE_ACCEPT} aria-label="Choose a file" onChange={take} style={{ display: 'none' }} />

        <p style={{ margin: '8px 0 0', font: '11px/1.4 ' + font, color: 'rgba(245,220,195,0.62)' }}>
          Up to 25 MB. Photos, PDFs, documents, spreadsheets, or plain text.
        </p>

        {file && (
          <div style={{ marginTop: 12, padding: 10, borderRadius: 14, border: '0.5px solid rgba(255,255,255,0.1)', background: 'rgba(255,255,255,0.03)' }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              {previewUrl
                ? <img src={previewUrl} alt="Selected image preview" style={{ width: 52, height: 52, objectFit: 'cover', borderRadius: 10, flex: '0 0 auto' }} />
                : null}
              <div style={{ minWidth: 0, flex: 1 }}>
                <div style={{ overflowWrap: 'anywhere', font: '500 13px/1.35 ' + font }}>{file.name}</div>
                <div style={{ font: '11px/1.3 ' + font, color: 'rgba(245,220,195,0.6)' }}>
                  {samAttachFormatSize(file.size)}{!previewUrl && samAttachIsHeic(file) ? ' · preview not supported' : ''}
                </div>
              </div>
              <button type="button" onClick={() => onFile && onFile(null)} disabled={busy}
                style={{ minHeight: 44, minWidth: 44, borderRadius: 12, border: '1px solid rgba(255,255,255,0.12)', background: 'transparent', color: '#ffd6b5', font: '600 12px/1.2 ' + font, cursor: busy ? 'default' : 'pointer', opacity: busy ? 0.5 : 1 }}>Remove</button>
            </div>
            {oversize && <div role="alert" style={{ marginTop: 8, font: '12px/1.4 ' + font, color: '#ffb59a' }}>That file is over 25 MB. Pick a smaller one.</div>}
          </div>
        )}

        <label style={{ display: 'block', marginTop: 12 }}>
          <span style={label}>Context (optional)</span>
          <textarea value={note || ''} maxLength={1000} rows={2} disabled={busy}
            onChange={(event) => onNote && onNote(event.target.value)}
            style={{ display: 'block', width: '100%', boxSizing: 'border-box', marginTop: 6, padding: '10px 12px', borderRadius: 12, border: '1px solid ' + accent + '44', background: 'rgba(15,9,5,0.92)', color: '#fbe3c8', font: '13px/1.4 ' + font, resize: 'vertical' }} />
        </label>

        <button type="button" onClick={() => onSubmit && onSubmit()} disabled={!file || busy || oversize}
          style={{ width: '100%', minHeight: 44, marginTop: 12, borderRadius: 14, border: 0, background: (!file || busy || oversize) ? 'rgba(255,255,255,0.12)' : accent, color: (!file || busy || oversize) ? 'rgba(245,220,195,0.5)' : '#1a0a02', font: '700 14px/1.2 ' + font, cursor: (!file || busy || oversize) ? 'default' : 'pointer', touchAction: 'manipulation' }}>
          Read and save
        </button>

        {busy && (
          <div role="status" style={{ marginTop: 10, font: '12px/1.4 ' + font, color: '#ffd6b5' }}>
            {typeof progress==='string'&&progress ? progress : 'Reading your file…'}{pct === null ? '' : ' · '+pct+'%'}
          </div>
        )}

        {error && (
          <div role="alert" style={{ marginTop: 10, padding: 10, borderRadius: 12, border: '1px solid rgba(255,140,110,0.4)', background: 'rgba(80,20,10,0.35)', color: '#ffbba4', font: '12px/1.4 ' + font }}>
            <div style={{ overflowWrap: 'anywhere' }}>{typeof error === 'string' ? error : (error.message || 'That did not go through.')}</div>
            {onRetry && (
              <button type="button" onClick={() => onRetry()} disabled={busy}
                style={{ minHeight: 44, marginTop: 8, padding: '0 14px', borderRadius: 999, border: '1px solid ' + accent + '99', background: 'rgba(22,11,4,0.72)', color: '#ffe0c5', font: '650 12px/1.2 ' + font, cursor: 'pointer' }}>Retry</button>
            )}
          </div>
        )}

        {result && (
          <div style={{ marginTop: 10, padding: 10, borderRadius: 12, border: '0.5px solid rgba(255,255,255,0.1)', background: 'rgba(255,255,255,0.03)' }}>
            <div style={{ display: 'flex', gap: 8, alignItems: 'baseline', flexWrap: 'wrap' }}>
              <span style={label}>{isReady ? 'Ready' : isErrored ? 'Error' : (status || 'Status unknown')}</span>
              {result.filename && <span style={{ font: '12px/1.3 ' + font, color: 'rgba(245,220,195,0.7)', overflowWrap: 'anywhere' }}>{result.filename}</span>}
            </div>
            {result.message && <div style={{ marginTop: 6, font: '13px/1.4 ' + font, overflowWrap: 'anywhere' }}>{result.message}</div>}
            {warnings.length > 0 && (
              <ul style={{ margin: '6px 0 0', paddingLeft: 18, font: '12px/1.4 ' + font, color: '#ffcfae' }}>
                {warnings.map((warning, index) => <li key={index} style={{ overflowWrap: 'anywhere' }}>{String(warning)}</li>)}
              </ul>
            )}
            {result.preview && (
              <pre style={{ margin: '8px 0 0', maxHeight: 160, overflow: 'auto', whiteSpace: 'pre-wrap', overflowWrap: 'anywhere', font: '12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace', color: 'rgba(245,220,195,0.82)' }}>{String(result.preview)}</pre>
            )}
            {href && (
              <a href={href} download style={{ display: 'inline-block', marginTop: 8, minHeight: 44, lineHeight: '44px', color: accent, font: '600 12px/44px ' + font }}>Download original</a>
            )}
          </div>
        )}
      </div>
    </div>
  );
}
