/* ============================================================
   SaveViewModal — RC-RPT-062 · Named Views
   Replaces the window.prompt() for "Save View" in the header.
   Shows existing views, warns on collisions, lets users delete.
   Uses the same P2Shell visual pattern.
   ============================================================ */

/* Utility — shallow diff of two tweak objects (omits UI-only keys) */
const diffTweaks = (a = {}, b = {}) => {
  const IGNORE = new Set(['__activeView']);
  const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
  const changed = [];
  for (const k of keys) {
    if (IGNORE.has(k)) continue;
    const av = a[k], bv = b[k];
    const asStr = (v) => Array.isArray(v) ? v.join(',') : typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v ?? '');
    if (asStr(av) !== asStr(bv)) changed.push({ key: k, from: av, to: bv });
  }
  return changed;
};
const LABELS_FOR_KEY = {
  reportTypeId: 'Report type', activePage: 'Active page', role: 'Role',
  changeMode: 'Change mode', comparison: 'Comparison', datePreset: 'Date preset',
  granularity: 'Granularity', theme: 'Theme', currency: 'Currency',
  customScorecards: 'Metrics', customChartPanels: 'Charts',
  customDateRange: 'Custom date range', spadsCampaignType: 'SPADS scope',
};
const fmtVal = (v) => {
  if (v == null || v === '') return '—';
  if (Array.isArray(v)) return v.length + ' item' + (v.length === 1 ? '' : 's');
  if (typeof v === 'object') return '(config)';
  return String(v);
};

const SaveViewModal = ({ open, onClose, activeView, namedViews = {}, currentTweaks = {}, onSave, onSwitch, onDelete }) => {
  const [name, setName] = React.useState(activeView || '');
  const [touched, setTouched] = React.useState(false);
  const inputRef = React.useRef(null);

  // Reset state when modal opens
  React.useEffect(() => {
    if (open) {
      setName(activeView || '');
      setTouched(false);
      // autofocus
      setTimeout(() => inputRef.current && inputRef.current.select(), 50);
    }
  }, [open, activeView]);

  React.useEffect(() => {
    if (!open) return;
    const h = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', h);
    return () => document.removeEventListener('keydown', h);
  }, [open, onClose]);

  if (!open) return null;

  const trimmed = name.trim();
  const existing = Object.keys(namedViews);
  const nameExists = existing.includes(trimmed);
  const isOverwrite = nameExists && trimmed !== activeView;
  const isUpdate = nameExists && trimmed === activeView;
  const canSave = trimmed.length > 0 && trimmed.length <= 40;

  const handleSave = () => {
    if (!canSave) return;
    onSave && onSave(trimmed);
    onClose();
  };

  const primaryLabel = isUpdate ? 'Update view' : isOverwrite ? 'Overwrite' : 'Save view';

  return (
    <div onClick={onClose} style={{
      position: 'fixed', inset: 0, zIndex: 230,
      background: 'rgba(15,23,42,0.48)', backdropFilter: 'blur(2px)',
      display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20,
      fontFamily: 'Inter',
    }}>
      <div onClick={e => e.stopPropagation()} style={{
        width: 520, maxWidth: '100%', maxHeight: '90vh',
        background: 'var(--rc-card)', borderRadius: 14,
        border: '1px solid var(--rc-border)',
        boxShadow: '0 30px 60px -15px rgba(15,23,42,0.4)',
        overflow: 'hidden', display: 'flex', flexDirection: 'column',
      }}>
        {/* Header */}
        <div style={{
          padding: '16px 22px', borderBottom: '1px solid var(--rc-border)',
          display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: 12,
          flexShrink: 0,
        }}>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontFamily: 'Poppins', fontSize: 17, fontWeight: 700, letterSpacing: '-0.01em', color: 'var(--rc-text)' }}>
              Save view
            </div>
            <div style={{ fontSize: 12, color: 'var(--rc-text-sub)', marginTop: 3 }}>
              Capture current tweaks, metrics, dates, and filters as a named preset.
            </div>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0 }}>
            <IconBtn name="x" title="Close" onClick={onClose} />
          </div>
        </div>

        {/* Body */}
        <div style={{ flex: 1, overflow: 'auto', padding: 22, display: 'flex', flexDirection: 'column', gap: 20 }}>
          {/* Name field */}
          <div>
            <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
              <label style={{ fontSize: 12, fontWeight: 600, color: 'var(--rc-text)' }}>View name</label>
              <span style={{ fontSize: 10, color: 'var(--rc-text-mute)', fontFamily: 'JetBrains Mono, monospace' }}>
                {trimmed.length}/40
              </span>
            </div>
            <input
              ref={inputRef}
              value={name}
              onChange={e => { setName(e.target.value); setTouched(true); }}
              onKeyDown={e => { if (e.key === 'Enter' && canSave) handleSave(); }}
              placeholder="e.g. Weekly review, Q4 campaigns, Brand-only"
              maxLength={40}
              style={{
                width: '100%', padding: '9px 12px',
                fontSize: 13, fontFamily: 'inherit',
                border: `1px solid ${touched && !canSave ? 'var(--rc-red)' : (isOverwrite ? '#f59e0b' : 'var(--rc-border)')}`,
                borderRadius: 8, outline: 'none',
                background: 'var(--rc-card)', color: 'var(--rc-text)',
                boxSizing: 'border-box',
              }}
            />
            {/* Inline feedback */}
            {touched && trimmed.length === 0 && (
              <div style={{ marginTop: 6, fontSize: 11, color: 'var(--rc-red)' }}>Name is required.</div>
            )}
            {isOverwrite && (
              <div style={{
                marginTop: 8, padding: '8px 10px',
                background: 'color-mix(in srgb, #f59e0b 10%, var(--rc-card))',
                border: '1px solid color-mix(in srgb, #f59e0b 35%, transparent)',
                borderRadius: 6, fontSize: 11, color: '#b45309',
                display: 'flex', alignItems: 'flex-start', gap: 6,
              }}>
                <Icon name="alert" size={11} color="#b45309" />
                <span>A view named <strong>“{trimmed}”</strong> already exists. Saving will overwrite it.</span>
              </div>
            )}
            {isUpdate && (
              <div style={{
                marginTop: 8, padding: '8px 10px',
                background: 'color-mix(in srgb, var(--rc-green) 10%, var(--rc-card))',
                border: '1px solid color-mix(in srgb, var(--rc-green) 25%, transparent)',
                borderRadius: 6, fontSize: 11, color: 'var(--rc-green-ink)',
                display: 'flex', alignItems: 'flex-start', gap: 6,
              }}>
                <Icon name="check" size={11} color="var(--rc-green-ink)" />
                <span>You're updating the currently active view with your latest changes.</span>
              </div>
            )}
          </div>

          {/* Diff preview — only when overwriting or updating an existing view */}
          {(isOverwrite || isUpdate) && namedViews[trimmed] && (() => {
            const changed = diffTweaks(namedViews[trimmed], currentTweaks);
            return (
              <div style={{
                padding: '10px 12px', borderRadius: 8,
                background: isOverwrite
                  ? 'color-mix(in srgb, #f59e0b 5%, var(--rc-card))'
                  : 'color-mix(in srgb, var(--rc-green) 4%, var(--rc-card))',
                border: '1px solid ' + (isOverwrite
                  ? 'color-mix(in srgb, #f59e0b 25%, transparent)'
                  : 'color-mix(in srgb, var(--rc-green) 20%, transparent)'),
              }}>
                <div style={{
                  display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                  marginBottom: 6,
                }}>
                  <span style={{
                    fontSize: 10, fontWeight: 600,
                    color: 'var(--rc-text-mute)',
                    fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.05em',
                  }}>
                    {changed.length === 0 ? 'NO CHANGES' : `${changed.length} CHANGE${changed.length === 1 ? '' : 'S'} vs “${trimmed}”`}
                  </span>
                  {changed.length > 0 && (
                    <button onClick={() => { onSwitch && onSwitch(trimmed); onClose(); }}
                      style={{
                        padding: '2px 8px', fontSize: 10, fontWeight: 500,
                        border: '1px solid var(--rc-border)', borderRadius: 4,
                        background: 'var(--rc-card)', color: 'var(--rc-text-sub)',
                        cursor: 'pointer', fontFamily: 'inherit',
                      }}
                      title="Discard your edits and load the saved view">
                      Revert
                    </button>
                  )}
                </div>
                {changed.length === 0 ? (
                  <div style={{ fontSize: 11, color: 'var(--rc-text-sub)' }}>
                    Current state matches the saved view — nothing will change.
                  </div>
                ) : (
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 4, maxHeight: 120, overflow: 'auto' }}>
                    {changed.slice(0, 8).map(c => (
                      <div key={c.key} style={{
                        display: 'grid', gridTemplateColumns: '110px 1fr auto 1fr',
                        gap: 6, alignItems: 'center',
                        fontSize: 11, fontFamily: 'JetBrains Mono, monospace',
                      }}>
                        <span style={{ color: 'var(--rc-text-sub)', fontWeight: 500 }}>
                          {LABELS_FOR_KEY[c.key] || c.key}
                        </span>
                        <span style={{
                          color: 'var(--rc-text-mute)', textDecoration: 'line-through',
                          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
                        }}>{fmtVal(c.from)}</span>
                        <span style={{ color: 'var(--rc-text-mute)' }}>→</span>
                        <span style={{
                          color: 'var(--rc-text)', fontWeight: 600,
                          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
                        }}>{fmtVal(c.to)}</span>
                      </div>
                    ))}
                    {changed.length > 8 && (
                      <div style={{ fontSize: 10, color: 'var(--rc-text-mute)', marginTop: 2 }}>
                        +{changed.length - 8} more change{changed.length - 8 === 1 ? '' : 's'}
                      </div>
                    )}
                  </div>
                )}
              </div>
            );
          })()}

          {/* What gets saved */}
          <div style={{
            padding: '10px 12px', borderRadius: 8,
            background: 'var(--rc-subtle)',
            border: '1px solid var(--rc-border)',
          }}>
            <div style={{
              fontSize: 10, fontWeight: 600, color: 'var(--rc-text-mute)',
              fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.05em',
              marginBottom: 6,
            }}>INCLUDED IN THIS VIEW</div>
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5 }}>
              {['Date range', 'Comparison', 'Granularity', 'Metrics', 'Charts', 'View by', 'Filters', 'Change mode', 'Currency'].map(t => (
                <span key={t} style={{
                  fontSize: 10, padding: '3px 8px', borderRadius: 4,
                  background: 'var(--rc-card)', border: '1px solid var(--rc-border)',
                  color: 'var(--rc-text-sub)', fontWeight: 500,
                }}>{t}</span>
              ))}
            </div>
          </div>

          {/* Existing views list */}
          {existing.length > 0 && (
            <div>
              <div style={{
                fontSize: 10, fontWeight: 600, color: 'var(--rc-text-mute)',
                fontFamily: 'JetBrains Mono, monospace', letterSpacing: '0.05em',
                marginBottom: 8,
              }}>SAVED VIEWS ({existing.length})</div>
              <div style={{
                border: '1px solid var(--rc-border)', borderRadius: 8,
                overflow: 'hidden',
              }}>
                {existing.map((vname, i) => {
                  const isActive = vname === activeView;
                  return (
                    <div key={vname} style={{
                      display: 'flex', alignItems: 'center', gap: 8,
                      padding: '8px 12px',
                      borderBottom: i < existing.length - 1 ? '1px solid var(--rc-border)' : 'none',
                      background: vname === trimmed && trimmed !== activeView ? 'color-mix(in srgb, #f59e0b 8%, transparent)' : 'transparent',
                    }}>
                      <Icon name={isActive ? 'check' : 'bookmark'} size={12}
                        color={isActive ? 'var(--rc-green)' : 'var(--rc-text-mute)'} />
                      <button
                        onClick={() => { onSwitch && onSwitch(vname); onClose(); }}
                        title="Switch to this view"
                        style={{
                          flex: 1, textAlign: 'left', minWidth: 0,
                          background: 'transparent', border: 0, padding: 0,
                          fontSize: 12, fontWeight: isActive ? 600 : 500,
                          color: 'var(--rc-text)', cursor: 'pointer', fontFamily: 'inherit',
                          whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis',
                        }}>
                        {vname}
                        {isActive && (
                          <span style={{
                            marginLeft: 8, fontSize: 10, fontWeight: 500,
                            color: 'var(--rc-green-ink)',
                          }}>active</span>
                        )}
                      </button>
                      <button
                        onClick={() => setName(vname)}
                        title="Use this name"
                        style={{
                          padding: '3px 8px', fontSize: 10, fontWeight: 500,
                          border: '1px solid var(--rc-border)', borderRadius: 4,
                          background: 'var(--rc-card)', color: 'var(--rc-text-sub)',
                          cursor: 'pointer', fontFamily: 'inherit',
                        }}>Use name</button>
                      <button
                        onClick={() => { onDelete && onDelete(vname); }}
                        title="Delete this view"
                        style={{
                          width: 22, height: 22, padding: 0,
                          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                          border: '1px solid var(--rc-border)', borderRadius: 4,
                          background: 'var(--rc-card)', color: 'var(--rc-text-mute)',
                          cursor: 'pointer',
                        }}
                        onMouseEnter={e => { e.currentTarget.style.color = 'var(--rc-red)'; e.currentTarget.style.borderColor = 'var(--rc-red)'; }}
                        onMouseLeave={e => { e.currentTarget.style.color = 'var(--rc-text-mute)'; e.currentTarget.style.borderColor = 'var(--rc-border)'; }}>
                        <Icon name="x" size={10} />
                      </button>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {/* Precedence note */}
          <div style={{
            fontSize: 10, color: 'var(--rc-text-mute)',
            fontFamily: 'JetBrains Mono, monospace',
            padding: '6px 10px',
            background: 'var(--rc-subtle)',
            borderRadius: 6,
            display: 'flex', alignItems: 'center', gap: 6,
          }}>
            <Icon name="info" size={10} />
            <span>Load order: URL &gt; last-state &gt; named view &gt; default &gt; seed</span>
          </div>
        </div>

        {/* Footer */}
        <div style={{
          padding: '14px 22px', borderTop: '1px solid var(--rc-border)',
          background: 'var(--rc-subtle)',
          display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 12,
          flexShrink: 0,
        }}>
          <div style={{ fontSize: 11, color: 'var(--rc-text-mute)' }}>
            Views are saved locally. Share a view via URL: <code style={{
              fontFamily: 'JetBrains Mono, monospace', fontSize: 10,
              padding: '1px 5px', background: 'var(--rc-card)', borderRadius: 3,
              border: '1px solid var(--rc-border)',
            }}>?view={trimmed || 'name'}</code>
          </div>
          <div style={{ display: 'flex', gap: 8 }}>
            <Btn variant="outline" size="sm" onClick={onClose}>Cancel</Btn>
            <Btn variant="primary" size="sm"
              disabled={!canSave}
              onClick={handleSave}>{primaryLabel}</Btn>
          </div>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { SaveViewModal });
