/* Main App wiring + Tweaks panel — the single source of page state.
   RC-PAGE-014 — URL state round-trip (deep-link).
   RC-RPT-070 — Reset / Save as default (localStorage-backed). */

const DEFAULT_TWEAKS = /*EDITMODE-BEGIN*/{
  "reportTypeId": "retail",
  "activePage": "range",
  "role": "admin",
  "changeMode": "pct",
  "comparison": "py",
  "datePreset": "mtd",
  "granularity": "day",
  "theme": "light",
  "currency": "USD",
  "customScorecards": null,
  "customChartPanels": null,
  "customDateRange": null,
  "spadsCampaignType": "all",
  "vendorDataView": "mfg"
}/*EDITMODE-END*/;
const URL_KEYS = ['reportTypeId', 'activePage', 'datePreset', 'granularity', 'comparison', 'changeMode', 'currency', 'spadsCampaignType', 'vendorDataView'];
/* Short aliases to keep URL readable. */
const URL_ALIAS = {
  reportTypeId: 'rt', activePage: 'p',
  datePreset: 'dr', granularity: 'g',
  comparison: 'cmp', changeMode: 'ch',
  currency: 'cur', spadsCampaignType: 'spct',
  vendorDataView: 'vdv',
};
const URL_ALIAS_REV = Object.fromEntries(Object.entries(URL_ALIAS).map(([k, v]) => [v, k]));

function readUrlState() {
  const out = {};
  try {
    const q = new URLSearchParams(window.location.search);
    for (const [key, val] of q.entries()) {
      const full = URL_ALIAS_REV[key] || (URL_KEYS.includes(key) ? key : null);
      if (full) out[full] = val;
    }
    // Back-compat: ?report=Retail+Performance|Sponsored+Ads
    const r = q.get('report');
    const rmap = { 'Retail Performance': 'retail', 'Sponsored Ads': 'spads', 'Retail + Ads': 'retail', 'Share of Voice': 'retail' };
    if (r && rmap[r] && !out.reportTypeId) out.reportTypeId = rmap[r];
    // Composite: viewBy comma-list
    const vb = q.get('vb');
    if (vb) out.__viewBy = vb.split('.').filter(Boolean);
    // Section collapse: ?cx=time,metric  (collapsed section slugs)
    const cx = q.get('cx');
    if (cx != null) out.__collapsed = cx.split(',').filter(Boolean);
    // Custom scorecards list
    const sc = q.get('sc');
    if (sc) out.__scorecards = sc.split(',').filter(Boolean);
  } catch (e) {}
  return out;
}

function writeUrlState(tweaks, viewBy, collapsedSet, report) {
  try {
    const q = new URLSearchParams();
    for (const k of URL_KEYS) {
      const v = tweaks[k];
      if (v != null && v !== '' && v !== DEFAULT_TWEAKS[k]) q.set(URL_ALIAS[k], v);
    }
    // viewBy only if not report default
    if (viewBy && report && viewBy.join('|') !== report.defaultViewBy.join('|')) {
      q.set('vb', viewBy.join('.'));
    }
    if (collapsedSet && collapsedSet.size > 0) q.set('cx', [...collapsedSet].join(','));
    if (tweaks.customScorecards && tweaks.customScorecards.length) q.set('sc', tweaks.customScorecards.join(','));
    const search = q.toString();
    const url = search ? `${window.location.pathname}?${search}` : window.location.pathname;
    window.history.replaceState(null, '', url + window.location.hash);
  } catch (e) {}
}

/* ---------- Persisted/tweakable state ---------- */
const App = () => {
  const urlState = React.useMemo(() => readUrlState(), []);

  /* RC-RPT-062 — persistence precedence stack:
     URL  >  last-state  >  named view  >  default  >  seed
     Each layer merges over the previous. Lower layers provide fallback,
     upper layers win on conflict. */
  const [tweaks, setTweaks] = React.useState(() => {
    // 5 — seed (baked-in defaults)
    let base = DEFAULT_TWEAKS;
    try {
      // 4 — user default (Save as default)
      const userDefaults = localStorage.getItem('rc2_user_defaults');
      if (userDefaults) base = { ...base, ...JSON.parse(userDefaults) };

      // 3 — named view (if URL selects one via ?view=name; else active view pointer)
      const q = new URLSearchParams(window.location.search);
      const viewName = q.get('view') || localStorage.getItem('rc2_active_view');
      if (viewName) {
        const views = JSON.parse(localStorage.getItem('rc2_named_views') || '{}');
        if (views[viewName]) base = { ...base, ...views[viewName], __activeView: viewName };
      }

      // 2 — last-state (per-user auto-save)
      const saved = localStorage.getItem('rc2_tweaks');
      if (saved) base = { ...base, ...JSON.parse(saved) };
    } catch (e) {}

    // 1 — URL overrides everything (deep-link is truth for this session)
    for (const k of URL_KEYS) if (urlState[k] != null) base = { ...base, [k]: urlState[k] };
    if (urlState.__scorecards) base = { ...base, customScorecards: urlState.__scorecards };
    return base;
  });
  const [editMode, setEditMode] = React.useState(false);
  const [telemetryOpen, setTelemetryOpen] = React.useState(false);
  const [shareOpen, setShareOpen] = React.useState(false);
  const [saveAsDefaultOpen, setSaveAsDefaultOpen] = React.useState(false);
  /* RC-RPT-062 — named views state (persisted in localStorage). */
  const [namedViews, setNamedViews] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem('rc2_named_views') || '{}'); }
    catch (e) { return {}; }
  });
  const saveNamedView = (name) => {
    setNamedViews(prev => {
      const next = { ...prev, [name]: { ...tweaks, __activeView: undefined } };
      try {
        localStorage.setItem('rc2_named_views', JSON.stringify(next));
        localStorage.setItem('rc2_active_view', name);
      } catch (e) {}
      return next;
    });
    setTweaks(prev => ({ ...prev, __activeView: name }));
    window.rcTrack && window.rcTrack('RC-RPT-062', 'save-named-view', { name });
  };
  const switchNamedView = (name) => {
    const view = namedViews[name];
    if (!view) return;
    setTweaks(prev => ({ ...prev, ...view, __activeView: name }));
    try {
      localStorage.setItem('rc2_active_view', name);
      localStorage.setItem('rc2_tweaks', JSON.stringify({ ...tweaks, ...view }));
    } catch (e) {}
    window.rcTrack && window.rcTrack('RC-RPT-062', 'switch-named-view', { name });
  };
  const deleteNamedView = (name) => {
    setNamedViews(prev => {
      const next = { ...prev };
      delete next[name];
      try { localStorage.setItem('rc2_named_views', JSON.stringify(next)); } catch (e) {}
      return next;
    });
    // if deleting the active view, clear the active flag
    if (tweaks.__activeView === name) {
      setTweaks(prev => ({ ...prev, __activeView: undefined }));
      try { localStorage.removeItem('rc2_active_view'); } catch (e) {}
    }
    window.rcTrack && window.rcTrack('RC-RPT-062', 'delete-named-view', { name });
  };
  /* RC-PAGE-002 — ephemeral per-section state for loading/error demo. */
  const [sectionStates, setSectionStates] = React.useState({
    time: 'ready', range: 'ready', metric: 'ready', dimension: 'ready',
  });
  const setSectionState = (key, val) =>
    setSectionStates(prev => ({ ...prev, [key]: val }));
  const retrySection = (key) => {
    setSectionState(key, 'loading');
    setTimeout(() => setSectionState(key, 'ready'), 1400);
  };
  /* RC-RPT-023 / RC-RPT-071 / RC-SHARE-010 — role-derived suppression flags */
  const viewerDisabled = tweaks.role === 'viewer';
  const canEdit = !viewerDisabled;
  const [viewerBannerDismissed, setViewerBannerDismissed] = React.useState(false);
  // Reset banner whenever the user re-enters viewer mode (fresh session feel)
  React.useEffect(() => {
    if (tweaks.role !== 'viewer') setViewerBannerDismissed(false);
  }, [tweaks.role]);
  const [metricsModal, setMetricsModal] = React.useState(false);
  const [chartsModal, setChartsModal] = React.useState(false);
  const [dateModal, setDateModal] = React.useState(false);
  const setTweak = (key, val) => {
    setTweaks(prev => {
      const next = { ...prev, [key]: val };
      try { localStorage.setItem('rc2_tweaks', JSON.stringify(next)); } catch (e) {}
      // persist to disk via host (for editor tweak panel)
      window.parent.postMessage({ type: '__edit_mode_set_keys', edits: { [key]: val } }, '*');
      // RC-MX-040 — tag state changes with the spec they belong to.
      const featureIdByKey = {
        reportTypeId:     'RC-RPT-010',
        activePage:       'RC-PAGE-014',
        datePreset:       'RC-PAGE-010',
        customDateRange:  'RC-PAGE-010',
        granularity:      'RC-PAGE-012',
        comparison:       'RC-PAGE-013',
        changeMode:       'RC-RPT-007',
        currency:         'RC-RPT-030',
        customScorecards: 'RC-PAGE-020',
        customChartPanels:'RC-SEC-010',
        spadsCampaignType:'RC-RPT3-SPADS-007',
        role:             'RC-RPT-071',
        theme:            'RC-CORE-010',
        vendorDataView:   'RC-RPT3-RSA-009',
      };
      const fid = featureIdByKey[key] || 'RC-APP-TWEAK';
      window.rcTrack && window.rcTrack(fid, 'set', { key, value: val });
      return next;
    });
  };

  // Initialize view-by — honor URL override
  const baseReport = REPORT_TYPES[tweaks.reportTypeId] || REPORT_TYPES.retail;
  /* RC-RPT3-RSA-009 — apply vendor data-source variant when the merchant is a Vendor
     and the active report is RSA (combined). vendorVariants live on the report type
     definition in fixtures; see RC-RPT3-RSA-004/005. */
  const vendorVariant = (
    baseReport.id === 'combined' &&
    merchant && merchant.isVendor &&
    baseReport.vendorVariants && baseReport.vendorVariants[tweaks.vendorDataView]
  ) ? baseReport.vendorVariants[tweaks.vendorDataView] : null;
  const report = vendorVariant
    ? { ...baseReport, itemColumns: vendorVariant.itemColumns, compareRoster: vendorVariant.compareRoster, trendMatrixRows: vendorVariant.compareRoster, __variant: vendorVariant.label }
    : baseReport;
  const [viewBy, setViewBy] = React.useState(() => urlState.__viewBy || report.defaultViewBy);
  /* RC-RPT3-X-001..003 — cross-report clone parity:
     On report-type switch we preserve chrome (date/currency/theme/comparison/changeMode — already
     kept because we don't touch those keys) and reset type-specific state. If the prior viewBy
     had dims the new report doesn't recognize, we trim them and fire a compatibility toast so the
     user knows what dropped. */
  const prevReportIdRef = React.useRef(tweaks.reportTypeId);
  React.useEffect(() => {
    const prevId = prevReportIdRef.current;
    if (prevId === tweaks.reportTypeId) return;
    const prevReport = REPORT_TYPES[prevId];
    const nextReport = REPORT_TYPES[tweaks.reportTypeId];
    prevReportIdRef.current = tweaks.reportTypeId;
    if (!prevReport || !nextReport) { setViewBy(nextReport?.defaultViewBy || []); return; }
    const priorDims = viewBy || [];
    const validDims = priorDims.filter(d => nextReport.viewByDims.includes(d));
    const droppedDims = priorDims.filter(d => !nextReport.viewByDims.includes(d));
    setViewBy(validDims.length ? validDims : nextReport.defaultViewBy);
    if (droppedDims.length && window.__rcToast && window.__rcToast.push) {
      window.__rcToast.push({
        kind: 'info',
        title: `Switched to ${nextReport.name}`,
        detail: droppedDims.length === 1
          ? `"${droppedDims[0]}" isn't available in this report — reset to ${validDims.length ? 'remaining dimensions' : 'defaults'}.`
          : `${droppedDims.length} dimensions aren't available here (${droppedDims.join(', ')}) — reset to ${validDims.length ? 'remaining dimensions' : 'defaults'}.`,
        timeout: 5200,
      });
    }
    window.rcTrack && window.rcTrack('RC-RPT3-X-003', 'report-type-clone', {
      from: prevId, to: tweaks.reportTypeId, droppedDims,
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [tweaks.reportTypeId]);

  /* ---------- Section collapse — persisted + URL ---------- */
  const [collapsedSections, setCollapsedSections] = React.useState(() => {
    if (urlState.__collapsed) return new Set(urlState.__collapsed);
    try {
      const saved = localStorage.getItem('rc2_collapsed');
      if (saved) return new Set(JSON.parse(saved));
    } catch (e) {}
    return new Set();
  });
  const toggleCollapsed = (slug) => {
    setCollapsedSections(prev => {
      const next = new Set(prev);
      const wasCollapsed = next.has(slug);
      if (wasCollapsed) next.delete(slug); else next.add(slug);
      try { localStorage.setItem('rc2_collapsed', JSON.stringify([...next])); } catch (e) {}
      window.rcTrack && window.rcTrack('RC-SEC-003', wasCollapsed ? 'expand' : 'collapse', { slug });
      return next;
    });
  };

  /* ---------- URL round-trip: write on every change ---------- */
  React.useEffect(() => {
    writeUrlState(tweaks, viewBy, collapsedSections, report);
  }, [tweaks, viewBy, collapsedSections, report]);

  // Customizable sets — fall back to report-type defaults when user hasn't overridden.
  const currentScorecards = tweaks.customScorecards && tweaks.customScorecards.length
    ? tweaks.customScorecards
    : report.scorecards;
  const currentChartPanelIds = tweaks.customChartPanels && tweaks.customChartPanels.length
    ? tweaks.customChartPanels
    : report.chartPanels.map(p => p.id);
  // Reset overrides when report type changes so each type shows its native defaults first.
  React.useEffect(() => {
    if (tweaks.customScorecards) setTweak('customScorecards', null);
    if (tweaks.customChartPanels) setTweak('customChartPanels', null);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [tweaks.reportTypeId]);

  // Full metric roster for the Add Metrics modal — everything we have labels for.
  const allMetricIds = Object.keys(METRIC_LABELS);
  // Custom-range label for the SectionControls date button
  const customDateLabel = tweaks.customDateRange
    ? `${tweaks.customDateRange.start} → ${tweaks.customDateRange.end}`
    : null;

  const [merchantId, setMerchantId] = React.useState(() => {
    try {
      const q = new URLSearchParams(window.location.search);
      const m = q.get('merchant');
      if (m) {
        const hit = MERCHANTS.find(x => x.name === m || x.id === m);
        if (hit) return hit.id;
      }
    } catch (e) {}
    return DEFAULT_MERCHANT.id;
  });
  const merchant = MERCHANTS.find(m => m.id === merchantId) || DEFAULT_MERCHANT;

  // Set global role for role-gated components
  window.__role = tweaks.role;

  // Apply theme
  React.useEffect(() => {
    document.documentElement.setAttribute('data-rc-theme', tweaks.theme);
  }, [tweaks.theme]);

  // Edit-mode protocol (Tweaks panel toggle)
  React.useEffect(() => {
    const handler = (e) => {
      if (e.data?.type === '__activate_edit_mode') setEditMode(true);
      if (e.data?.type === '__deactivate_edit_mode') setEditMode(false);
    };
    window.addEventListener('message', handler);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', handler);
  }, []);

  /* RC-MX-040 — ⌥E toggles the telemetry events panel (dev-only). */
  React.useEffect(() => {
    const handler = (e) => {
      if (e.altKey && (e.key === 'e' || e.key === 'E' || e.code === 'KeyE')) {
        e.preventDefault();
        setTelemetryOpen(v => !v);
      }
    };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, []);

  const resetFilters = () => {
    setTweak('datePreset', 'mtd');
    setTweak('granularity', 'day');
    setTweak('comparison', 'py');
    setViewBy(report.defaultViewBy);
  };

  return (
    <div style={{ display: 'flex', height: '100vh', background: 'var(--rc-bg)', color: 'var(--rc-text)' }}>
      <IconRail active="reports" theme={tweaks.theme} onThemeToggle={() => setTweak('theme', tweaks.theme === 'dark' ? 'light' : 'dark')} />
      <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0, overflow: 'hidden' }}>
        <TopBar
          report={report} merchant={merchant} role={tweaks.role}
          onReportTypeChange={(id) => setTweak('reportTypeId', id)}
          onMerchantChange={(id) => setMerchantId(id)}
        />
        <ReportHeader
          report={report}
          merchant={merchant}
          activePage={tweaks.activePage}
          onTabChange={(p) => setTweak('activePage', p)}
          spadsCampaignType={tweaks.spadsCampaignType}
          setSpadsCampaignType={(v) => setTweak('spadsCampaignType', v)}
          vendorDataView={tweaks.vendorDataView}
          setVendorDataView={(v) => setTweak('vendorDataView', v)}
          namedViews={namedViews}
          activeView={tweaks.__activeView}
          currentTweaks={tweaks}
          viewUnsaved={(() => {
            if (!tweaks.__activeView) return false;
            const saved = namedViews[tweaks.__activeView];
            if (!saved) return false;
            // Compare only user-facing tweak keys (ignore __activeView)
            const keys = new Set([...Object.keys(saved), ...Object.keys(tweaks)]);
            for (const k of keys) {
              if (k === '__activeView') continue;
              const a = saved[k], b = tweaks[k];
              const s = (v) => Array.isArray(v) ? v.join(',') : typeof v === 'object' && v !== null ? JSON.stringify(v) : String(v ?? '');
              if (s(a) !== s(b)) return true;
            }
            return false;
          })()}
          onSaveView={saveNamedView}
          onSwitchView={switchNamedView}
          onDeleteView={deleteNamedView}
          onShare={() => { window.rcTrack && window.rcTrack('RC-RPT-020', 'share-modal-open'); setShareOpen(true); }}
          onCopyUrl={() => {
            try {
              navigator.clipboard.writeText(window.location.href);
              window.rcTrack && window.rcTrack('RC-PAGE-014', 'copy-url');
            } catch (e) {}
          }}
          onResetDefaults={() => {
            try {
              localStorage.removeItem('rc2_tweaks');
              localStorage.removeItem('rc2_collapsed');
            } catch (e) {}
            // clear URL params
            history.replaceState(null, '', window.location.pathname);
            setTweaks({ ...DEFAULT_TWEAKS });
            setCollapsedSections(new Set());
            window.rcTrack && window.rcTrack('RC-RPT-070', 'reset-defaults');
          }}
          onSaveDefaults={() => { window.rcTrack && window.rcTrack('RC-PAGE-041', 'save-as-default-open'); setSaveAsDefaultOpen(true); }}
        />
        <div data-rc-scroll style={{ flex: 1, overflow: 'auto', background: 'var(--rc-bg)', padding: 16 }}>
          {tweaks.role === 'viewer' && !viewerBannerDismissed && (
            <div style={{
              display: 'flex', alignItems: 'center', gap: 10,
              padding: '10px 14px', marginBottom: 12,
              background: 'linear-gradient(90deg, color-mix(in srgb, #f59e0b 14%, var(--rc-card)) 0%, var(--rc-card) 100%)',
              border: '1px solid color-mix(in srgb, #f59e0b 45%, var(--rc-border))',
              borderLeft: '3px solid #f59e0b',
              borderRadius: 8,
              fontSize: 12, color: 'var(--rc-text)',
              fontFamily: 'Inter',
            }} title="RC-RPT-023 / RC-SHARE-010 — Viewer mode UI suppression">
              <div style={{
                width: 28, height: 28, borderRadius: 6,
                background: 'color-mix(in srgb, #f59e0b 22%, var(--rc-card))',
                display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                flexShrink: 0,
              }}>
                <Icon name="eye" size={14} color="#b45309" />
              </div>
              <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: 1 }}>
                <div style={{ fontWeight: 600, color: 'var(--rc-text)' }}>
                  You're viewing this report in view-only mode.
                </div>
                <div style={{ color: 'var(--rc-text-sub)', fontSize: 11 }}>
                  Browse and export, but changes to metrics, date range, comparison, or layout are disabled.
                  Shared by <b>owner@mixshift.io</b>.
                </div>
              </div>
              <button
                onClick={() => {
                  window.__rcToast && window.__rcToast.push && window.__rcToast.push({
                    kind: 'success',
                    title: 'Request sent',
                    detail: 'The owner will be notified that you want edit access.',
                    timeout: 3500,
                  });
                }}
                style={{
                  padding: '5px 10px', border: '1px solid var(--rc-border)',
                  borderRadius: 6, background: 'var(--rc-card)',
                  color: 'var(--rc-text)', fontSize: 11, fontWeight: 500,
                  cursor: 'pointer', fontFamily: 'inherit', whiteSpace: 'nowrap',
                }}
                onMouseEnter={e => e.currentTarget.style.background = 'var(--rc-hover)'}
                onMouseLeave={e => e.currentTarget.style.background = 'var(--rc-card)'}>
                Request edit access
              </button>
              <button
                onClick={() => setViewerBannerDismissed(true)}
                title="Dismiss for this session"
                style={{
                  width: 24, height: 24, padding: 0,
                  border: 0, borderRadius: 4,
                  background: 'transparent', color: 'var(--rc-text-sub)',
                  cursor: 'pointer',
                  display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
                }}
                onMouseEnter={e => e.currentTarget.style.background = 'var(--rc-hover)'}
                onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                <Icon name="x" size={12} />
              </button>
            </div>
          )}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            {/* PAGE 1 — Performance Over Time
                RC-PAGE-012 — granularity is controlled inside the chart-scope panel
                (see RC-SEC-010), not on the section header. */}
            <PageSection id="rc-page-time" title="Performance Over Time" report={report}
              canEdit={canEdit}
              state={sectionStates.time} skeletonKind="chart"
              onRetry={() => retrySection('time')}
              sectionConfig={{ panelIds: currentChartPanelIds, granularity: tweaks.granularity }}
              onCustomize={() => setChartsModal(true)} customizeLabel="Charts"
              compactControls={<SectionControls
                datePreset={tweaks.datePreset} setDatePreset={v => setTweak('datePreset', v)}
                comparison={tweaks.comparison} setComparison={v => setTweak('comparison', v)}
                onCustomDate={() => setDateModal(true)} customDateLabel={customDateLabel}
                viewerDisabled={viewerDisabled} />
              }>
              <PageOverTime reportType={report} granularity={tweaks.granularity}
                comparison={tweaks.comparison} changeMode={tweaks.changeMode} role={tweaks.role}
                panelIds={currentChartPanelIds}
                onReorderPanels={(ids) => setTweak('customChartPanels', ids)}
                datePreset={tweaks.datePreset} customDateLabel={customDateLabel}
                viewerDisabled={viewerDisabled} />
            </PageSection>

            {/* PAGE 2 — Performance Over Range */}
            <PageSection id="rc-page-range" title="Performance Over Range" report={report}
              canEdit={canEdit}
              state={sectionStates.range} skeletonKind="scorecards"
              onRetry={() => retrySection('range')}
              sectionConfig={{ scorecardIds: currentScorecards, currency: tweaks.currency, changeMode: tweaks.changeMode }}
              onCustomize={() => setMetricsModal(true)} customizeLabel="Metrics"
              compactControls={<SectionControls
                datePreset={tweaks.datePreset} setDatePreset={v => setTweak('datePreset', v)}
                comparison={tweaks.comparison} setComparison={v => setTweak('comparison', v)}
                onCustomDate={() => setDateModal(true)} customDateLabel={customDateLabel}
                viewerDisabled={viewerDisabled} />
              }>
              <PageOverRange reportType={report} merchant={merchant}
                comparison={tweaks.comparison} currency={tweaks.currency}
                scorecardIds={currentScorecards}
                onReorderScorecards={(ids) => setTweak('customScorecards', ids)}
                viewerDisabled={viewerDisabled}
                changeMode={tweaks.changeMode} setChangeMode={v => setTweak('changeMode', v)} />
            </PageSection>

            {/* PAGE 3 — Performance by Metric */}
            <PageSection id="rc-page-metric" title="Performance by Metric" report={report}
              canEdit={canEdit}
              state={sectionStates.metric} skeletonKind="table"
              onRetry={() => retrySection('metric')}
              sectionConfig={{ changeMode: tweaks.changeMode }}
              compactControls={<SectionControls
                datePreset={tweaks.datePreset} setDatePreset={v => setTweak('datePreset', v)}
                comparison={tweaks.comparison} setComparison={v => setTweak('comparison', v)}
                onCustomDate={() => setDateModal(true)} customDateLabel={customDateLabel}
                viewerDisabled={viewerDisabled} />
              }>
              <PageByMetric reportType={report} comparison={tweaks.comparison}
                changeMode={tweaks.changeMode} granularity={tweaks.granularity}
                viewerDisabled={viewerDisabled} />
            </PageSection>

            {/* PAGE 4 — Performance by Dimension */}
            <PageSection id="rc-page-dimension" title="Performance by Dimension" report={report}
              canEdit={canEdit}
              state={sectionStates.dimension} skeletonKind="table"
              onRetry={() => retrySection('dimension')}
              sectionConfig={{ viewBy: viewBy, changeMode: tweaks.changeMode }}
              compactControls={<SectionControls
                datePreset={tweaks.datePreset} setDatePreset={v => setTweak('datePreset', v)}
                comparison={tweaks.comparison} setComparison={v => setTweak('comparison', v)}
                onCustomDate={() => setDateModal(true)} customDateLabel={customDateLabel}
                viewBy={viewBy} setViewBy={setViewBy} reportType={report}
                viewerDisabled={viewerDisabled} />
              }>
              <PageByDimension reportType={report} viewBy={viewBy}
                comparison={tweaks.comparison}
                changeMode={tweaks.changeMode} setChangeMode={v => setTweak('changeMode', v)}
                viewerDisabled={viewerDisabled} />
            </PageSection>
          </div>
        </div>
      </div>
      {editMode && <TweaksPanel tweaks={tweaks} setTweak={setTweak} close={() => setEditMode(false)}
        sectionStates={sectionStates} setSectionState={setSectionState}
        telemetryOpen={telemetryOpen} setTelemetryOpen={setTelemetryOpen}
        merchant={merchant} setMerchantId={setMerchantId} />}
      <TelemetryEventsPanel open={telemetryOpen} onClose={() => setTelemetryOpen(false)} />
      <ShareReportModal
        open={shareOpen}
        onClose={() => setShareOpen(false)}
        title={`Share ${report.name}`}
      />
      <SaveAsDefaultConfirmModal
        open={saveAsDefaultOpen}
        onClose={() => setSaveAsDefaultOpen(false)}
        currentState={tweaks}
        existingDefault={(() => {
          try {
            const raw = localStorage.getItem('rc2_user_defaults');
            return raw ? JSON.parse(raw) : null;
          } catch (e) { return null; }
        })()}
        onConfirm={() => {
          try {
            localStorage.setItem('rc2_user_defaults', JSON.stringify(tweaks));
            window.__rcToast && window.__rcToast.push && window.__rcToast.push({
              kind: 'success',
              title: 'Page defaults saved',
              detail: 'Date range, metrics, charts, and layout will open this way next time.',
              timeout: 3500,
            });
            window.rcTrack && window.rcTrack('RC-PAGE-041', 'save-as-default-confirm');
          } catch (e) {}
        }}
      />
      <AddMetricsModal
        open={metricsModal}
        onClose={() => setMetricsModal(false)}
        allMetrics={allMetricIds}
        selectedIds={currentScorecards}
        comparisonLabel={`${report.name} · vs ${tweaks.comparison === 'py' ? 'Prior Year' : tweaks.comparison === 'pp' ? 'Prior Period' : 'No comparison'}`}
        currency={tweaks.currency}
        onSave={(ids) => setTweak('customScorecards', ids)}
      />
      <AvailableChartsModal
        open={chartsModal}
        onClose={() => setChartsModal(false)}
        selectedIds={currentChartPanelIds}
        onSave={(ids) => setTweak('customChartPanels', ids)}
      />
      <DateRangePickerModal
        open={dateModal}
        onClose={() => setDateModal(false)}
        initialPreset={tweaks.datePreset}
        initialStart={tweaks.customDateRange?.start ? new Date(tweaks.customDateRange.start) : undefined}
        initialEnd={tweaks.customDateRange?.end ? new Date(tweaks.customDateRange.end) : undefined}
        compareMode={tweaks.comparison === 'none' ? 'pp' : tweaks.comparison}
        onSave={(res) => {
          if (!res) return;
          const fmt = (d) => d ? `${String(d.getMonth()+1).padStart(2,'0')}/${String(d.getDate()).padStart(2,'0')}/${d.getFullYear()}` : null;
          if (res.preset && res.preset !== 'custom') {
            setTweak('datePreset', res.preset);
            setTweak('customDateRange', null);
          } else if (res.start && res.end) {
            setTweak('datePreset', 'custom');
            setTweak('customDateRange', { start: fmt(res.start), end: fmt(res.end) });
          }
          if (res.compare) setTweak('comparison', res.compare);
        }}
      />
      <RCToastHost />
    </div>
  );
};

/* ---------- Tweaks Panel ---------- */
const TweaksPanel = ({ tweaks, setTweak, close, sectionStates, setSectionState, telemetryOpen, setTelemetryOpen, merchant, setMerchantId }) => {
  return (
    <div style={{
      position: 'fixed', right: 16, bottom: 16, width: 300, zIndex: 100,
      background: 'var(--rc-card)', border: '1px solid var(--rc-border)',
      borderRadius: 12, boxShadow: '0 20px 45px -12px rgba(15,23,42,0.25)',
      overflow: 'hidden', fontFamily: 'Inter',
    }}>
      <div style={{ padding: '10px 12px', borderBottom: '1px solid var(--rc-border)',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        background: 'var(--rc-subtle)' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
          <Icon name="settings" size={13} color="var(--rc-text)" />
          <span style={{ fontSize: 12, fontWeight: 600, fontFamily: 'Poppins', color: 'var(--rc-text)' }}>Tweaks</span>
        </div>
        <IconBtn name="x" title="Close" onClick={close} size={24} />
      </div>
      <div style={{ padding: 12, display: 'flex', flexDirection: 'column', gap: 12, maxHeight: '70vh', overflow: 'auto' }}>
        <TweakRow label="Report Type">
          <Segmented
            tabs={[{value:'retail',label:'Retail'},{value:'spads',label:'SP Ads'},{value:'combined',label:'Combined'}]}
            active={tweaks.reportTypeId} onChange={v => setTweak('reportTypeId', v)} size="sm" />
        </TweakRow>
        {setMerchantId && (
          <TweakRow label="Merchant Account" hint="RC-RPT3-RSA-009">
            <Segmented
              tabs={[{value:'seller',label:'Seller'},{value:'vendor',label:'Vendor'}]}
              active={merchant && merchant.isVendor ? 'vendor' : 'seller'}
              onChange={v => setMerchantId(v === 'vendor' ? 'aop-us-v' : 'hydrapak-us')}
              size="sm" />
          </TweakRow>
        )}
        <TweakRow label="Active Page">
          <Segmented
            tabs={[{value:'time',label:'Time'},{value:'range',label:'Range'},{value:'metric',label:'Metric'},{value:'dimension',label:'Dim'}]}
            active={tweaks.activePage} onChange={v => setTweak('activePage', v)} size="sm" />
        </TweakRow>
        <TweakRow label="User Role" hint="RC-RPT-071">
          <Segmented
            tabs={[{value:'admin',label:'Admin'},{value:'editor',label:'Editor'},{value:'viewer',label:'Viewer'}]}
            active={tweaks.role} onChange={v => setTweak('role', v)} size="sm" />
        </TweakRow>
        <TweakRow label="Change Display">
          <Segmented
            tabs={[{value:'pct',label:'%'},{value:'net',label:'Net'},{value:'pts',label:'pts'}]}
            active={tweaks.changeMode} onChange={v => setTweak('changeMode', v)} size="sm" />
        </TweakRow>
        <TweakRow label="Comparison">
          <Segmented
            tabs={[{value:'none',label:'None'},{value:'pp',label:'Prior Period'},{value:'py',label:'Prior Year'}]}
            active={tweaks.comparison} onChange={v => setTweak('comparison', v)} size="sm" />
        </TweakRow>
        <TweakRow label="Date Preset">
          <select value={tweaks.datePreset} onChange={e => setTweak('datePreset', e.target.value)}
            style={selectStyle}>
            {DATE_PRESETS.map(p => <option key={p.value} value={p.value}>{p.label}</option>)}
          </select>
        </TweakRow>
        <TweakRow label="Granularity">
          <Segmented
            tabs={[{value:'day',label:'Day'},{value:'week',label:'Week'},{value:'month',label:'Month'}]}
            active={tweaks.granularity} onChange={v => setTweak('granularity', v)} size="sm" />
        </TweakRow>
        <TweakRow label="Theme">
          <Segmented
            tabs={[{value:'light',label:'Light'},{value:'dark',label:'Dark'}]}
            active={tweaks.theme} onChange={v => setTweak('theme', v)} size="sm" />
        </TweakRow>
        <TweakRow label="Currency">
          <select value={tweaks.currency || 'USD'} onChange={e => setTweak('currency', e.target.value)}
            style={selectStyle}>
            {['USD','EUR','GBP','JPY','CAD','AUD'].map(c => <option key={c} value={c}>{c}</option>)}
          </select>
        </TweakRow>
        <TweakRow label="Customizations">
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            <button onClick={() => setTweak('customScorecards', null)}
              style={{ ...selectStyle, width: 'auto', padding: '5px 10px', cursor: 'pointer',
                opacity: tweaks.customScorecards ? 1 : 0.4 }}
              disabled={!tweaks.customScorecards}>
              Reset metrics
            </button>
            <button onClick={() => setTweak('customChartPanels', null)}
              style={{ ...selectStyle, width: 'auto', padding: '5px 10px', cursor: 'pointer',
                opacity: tweaks.customChartPanels ? 1 : 0.4 }}
              disabled={!tweaks.customChartPanels}>
              Reset charts
            </button>
            <button onClick={() => { setTweak('customDateRange', null); setTweak('datePreset', 'mtd'); }}
              style={{ ...selectStyle, width: 'auto', padding: '5px 10px', cursor: 'pointer',
                opacity: tweaks.customDateRange ? 1 : 0.4 }}
              disabled={!tweaks.customDateRange}>
              Reset date
            </button>
          </div>
        </TweakRow>
        <TweakRow label="Viewer Lock Screen" hint="RC-SHARE-002">
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap' }}>
            <button
              onClick={() => {
                // Show the lock screen in-place. window.open is blocked in sandboxed
                // iframes, so we flip a global flag + re-render instead of navigating.
                window.__rcForceLocked = true;
                window.dispatchEvent(new CustomEvent('rc:force-lock'));
              }}
              style={{ ...selectStyle, width: 'auto', padding: '5px 10px', cursor: 'pointer',
                display: 'inline-flex', alignItems: 'center', gap: 5 }}>
              <Icon name="lock" size={10} /> Preview
            </button>
            <span style={{ fontSize: 10, color: 'var(--rc-text-mute)', alignSelf: 'center',
              fontFamily: 'JetBrains Mono' }}>pw: demo123</span>
          </div>
        </TweakRow>
        <TweakRow label="Telemetry" hint="RC-MX-040">
          <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
            <button onClick={() => setTelemetryOpen && setTelemetryOpen(!telemetryOpen)}
              style={{
                ...selectStyle, width: 'auto', padding: '5px 10px',
                cursor: 'pointer', display: 'inline-flex', alignItems: 'center', gap: 5,
                background: telemetryOpen
                  ? 'color-mix(in srgb, var(--rc-chart-1) 12%, var(--rc-card))'
                  : 'var(--rc-card)',
                borderColor: telemetryOpen ? 'var(--rc-chart-1)' : 'var(--rc-border)',
                color: telemetryOpen ? 'var(--rc-chart-1)' : 'var(--rc-text)',
              }}>
              <span style={{ width: 6, height: 6, borderRadius: 3,
                background: telemetryOpen ? '#22c55e' : 'var(--rc-text-mute)' }} />
              {telemetryOpen ? 'Events panel open' : 'Open events panel'}
            </button>
            <span style={{ fontSize: 10, color: 'var(--rc-text-mute)', fontFamily: 'JetBrains Mono' }}>⌥E</span>
          </div>
        </TweakRow>
        {sectionStates && setSectionState && (
          <TweakRow label="Section State (demo)" hint="RC-PAGE-002">
            <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
              {[
                { key: 'time',      label: 'Over Time' },
                { key: 'range',     label: 'Over Range' },
                { key: 'metric',    label: 'By Metric' },
                { key: 'dimension', label: 'By Dimension' },
              ].map(s => (
                <div key={s.key} style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                  <span style={{ fontSize: 10.5, color: 'var(--rc-text-sub)', minWidth: 78 }}>{s.label}</span>
                  <Segmented size="sm"
                    tabs={[
                      { value: 'ready',   label: 'Ready' },
                      { value: 'loading', label: 'Load' },
                      { value: 'error',   label: 'Err' },
                    ]}
                    active={sectionStates[s.key]}
                    onChange={v => setSectionState(s.key, v)} />
                </div>
              ))}
            </div>
          </TweakRow>
        )}
      </div>
    </div>
  );
};

const TweakRow = ({ label, hint, children }) => (
  <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
    <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between' }}>
      <span style={{ fontSize: 11, fontWeight: 500, color: 'var(--rc-text-sub)' }}>{label}</span>
      {hint && <span style={{ fontSize: 9, color: 'var(--rc-text-mute)', fontFamily: 'JetBrains Mono' }}>{hint}</span>}
    </div>
    <div>{children}</div>
  </div>
);

const selectStyle = {
  width: '100%', padding: '6px 8px', background: 'var(--rc-card)',
  border: '1px solid var(--rc-border)', borderRadius: 6,
  fontSize: 12, color: 'var(--rc-text)', fontFamily: 'inherit',
};

/* Mount — wraps App in the RC-SHARE-002 viewer-password gate. */
const Root = () => {
  const [locked, setLocked] = React.useState(
    (typeof window.isViewerLocked === 'function' && window.isViewerLocked()) ||
    window.__rcForceLocked === true
  );
  React.useEffect(() => {
    const onForce = () => setLocked(true);
    window.addEventListener('rc:force-lock', onForce);
    return () => window.removeEventListener('rc:force-lock', onForce);
  }, []);
  if (locked && window.ViewerPasswordChallenge) {
    return (
      <window.ViewerPasswordChallenge
        reportName="Retail Performance — Retail Core"
        ownerName="Timurtek Bizel"
        onUnlock={() => {
          window.__rcForceLocked = false;
          setLocked(false);
        }}
      />
    );
  }
  return <App />;
};

ReactDOM.createRoot(document.getElementById('root')).render(<Root />);
