// Main RCG Dashboard app: Cloudflare Access identity + dashboard shell + routing.
//
// Auth model: this app is deployed behind Cloudflare Access. CF Access exposes
// the signed-in user at /cdn-cgi/access/get-identity. We trust that response
// (Cloudflare guarantees it; you can't reach the page without an Access JWT)
// and skip the in-app login screen. The LoginScreen component remains as a
// dev-mode fallback when running locally without Access.

const { useState: auState, useEffect: auEffect, useMemo: auMemo, useRef: auRef } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accentMode": "red",
  "showSparklines": true,
  "density": "comfortable",
  "wordmark": "RCG"
}/*EDITMODE-END*/;

// Tabs that render the client-style dashboard (Overview, Paid, Email, etc.).
// Used both for clients and for RCG-as-self when an internal user is viewing
// the firm's own data.
const CLIENT_TABS = [
  { id: 'overview', label: 'Overview', icon: 'LayoutDashboard' },
  { id: 'paid', label: 'Paid Media', icon: 'Target' },
  { id: 'email', label: 'Email', icon: 'Mail' },
  { id: 'web', label: 'Website & SEO', icon: 'Globe' },
  { id: 'crm', label: 'CRM Pipeline', icon: 'GitBranch' },
  { id: 'report', label: 'Monthly Report', icon: 'FileText' },
];

// Internal-only tools, shown as a second sidebar section for RCG team members.
const INTERNAL_TABS = [
  { id: 'prospects', label: 'Prospect Research', icon: 'Search' },
  { id: 'performance', label: 'RCG Performance', icon: 'TrendingUp' },
  { id: 'roster', label: 'Client Roster', icon: 'Users' },
];

const CLIENT_TAB_IDS = new Set(CLIENT_TABS.map((t) => t.id));
const INTERNAL_TAB_IDS = new Set(INTERNAL_TABS.map((t) => t.id));

function useToasts() {
  const [toasts, setToasts] = auState([]);
  const idRef = auRef(0);
  function push(msg, kind) {
    const id = ++idRef.current;
    setToasts((t) => [...t, { id, msg, kind }]);
    setTimeout(() => setToasts((t) => t.filter((x) => x.id !== id)), 3000);
  }
  return [toasts, push];
}

// Resolve which client a non-RCG email belongs to. Falls back to first client.
function resolveClientId(email) {
  const lower = email.toLowerCase();
  const match = window.RCG_CLIENTS.find((c) => lower.includes(c.name.split(' ')[0].toLowerCase()));
  return match ? match.id : (window.RCG_CLIENTS[0]?.id || 'acme');
}

function userFromIdentity(identity) {
  const email = identity.email || '';
  const isRcg = email.toLowerCase().endsWith('@rottmancreative.com');
  const name = identity.name
    || email.split('@')[0].split('.').map((s) => s[0].toUpperCase() + s.slice(1)).join(' ')
    || 'User';
  return {
    type: isRcg ? 'internal' : 'client',
    name,
    email,
    clientId: isRcg ? null : resolveClientId(email),
  };
}

// ── DEV-MODE FALLBACK LOGIN ──────────────────────────────
// Only used when /cdn-cgi/access/get-identity is unreachable (i.e. running
// locally with `wrangler pages dev` without Access). In production, Access
// blocks the request before this ever renders.
function LoginScreen({ onAuth, pushToast }) {
  const [mode, setMode] = auState('client');
  const [email, setEmail] = auState('');
  const [password, setPassword] = auState('');
  const [err, setErr] = auState('');

  function submit(e) {
    if (e) e.preventDefault();
    setErr('');
    if (!email || !password) { setErr('Email and password are required.'); return; }
    if (!/.+@.+\..+/.test(email)) { setErr('Enter a valid email address.'); return; }
    const isRcg = email.toLowerCase().endsWith('@rottmancreative.com');
    if (mode === 'team' && !isRcg) { setErr('Team login requires a @rottmancreative.com email.'); return; }
    if (mode === 'client' && isRcg) { setErr('Use the Team tab for a Rottman Creative email.'); return; }
    onAuth(userFromIdentity({ email, name: null }));
  }

  return (
    <div className="login-wrap">
      <form className="login-card" onSubmit={submit}>
        <div className="login-mark">
          <img src="assets/logo-small-box-black.png" alt="" style={{ width: 28, height: 28, display: 'block' }} />
          <span style={{ fontFamily: 'var(--serif)', textTransform: 'uppercase', fontSize: 16, letterSpacing: '-0.015em', color: 'var(--rich-black)' }}>
            Rottman Creative
          </span>
        </div>

        <h1 className="login-title">Sign in to your <span style={{ color: 'var(--brand-red)', fontStyle: 'italic', textTransform: 'none' }}>dashboard</span></h1>
        <p className="login-sub">Dev-mode sign-in. Production uses Cloudflare Access.</p>

        <div className="login-tabs" role="tablist">
          <button type="button" className={`login-tab ${mode === 'client' ? 'active' : ''}`} onClick={() => { setMode('client'); setErr(''); }}>
            <span style={{ display: 'inline-block', transform: 'translateY(0.1em)' }}>Client Login</span>
          </button>
          <button type="button" className={`login-tab ${mode === 'team' ? 'active' : ''}`} onClick={() => { setMode('team'); setErr(''); }}>
            <span style={{ display: 'inline-block', transform: 'translateY(0.1em)' }}>Team Login</span>
          </button>
        </div>

        <div className="field" style={{ marginBottom: 14 }}>
          <label>Email</label>
          <input type="email" placeholder={mode === 'team' ? 'you@rottmancreative.com' : 'you@yourcompany.com'} value={email} onChange={(e) => setEmail(e.target.value)} autoComplete="email" />
          {mode === 'team' && <div className="help">@rottmancreative.com email required</div>}
        </div>

        <div className="field" style={{ marginBottom: 18 }}>
          <label>Password</label>
          <input type="password" placeholder="••••••••" value={password} onChange={(e) => setPassword(e.target.value)} autoComplete="current-password" />
        </div>

        {err && <div className="field err" style={{ marginBottom: 14 }}>{err}</div>}

        <Pill type="submit" variant="filled" style={{ width: '100%', minHeight: 44 }}>Sign in</Pill>

        <div className="login-footer">
          <span>© 2026 Rottman Creative Group</span>
          <button type="button" className="tlink" style={{ fontSize: 11 }} onClick={(e) => { e.preventDefault(); pushToast('Reset link sent.', 'success'); }}>
            Forgot password?
          </button>
        </div>
      </form>
    </div>
  );
}

// ── SIDEBAR ───────────────────────────────────────────────
function Sidebar({ user, currentEntity, tabId, onSelectTab, onSwitchEntity, wordmark }) {
  const isInternal = user.type === 'internal';
  const isViewingClient = isInternal && currentEntity && !currentEntity.isSelf;
  const entityEyebrow = isViewingClient ? 'Viewing as client' : (isInternal ? 'Firm' : 'Your account');

  // Client-style tabs are visible to everyone; the section label changes
  // based on whose data is being shown.
  const dashboardSectionLabel = isInternal
    ? (isViewingClient ? currentEntity.name : 'Rottman Creative')
    : currentEntity?.name || 'Dashboard';

  return (
    <aside className="sidebar">
      <div className="sidebar-head">
        <div className="sidebar-mark">
          <img src="assets/logo-small-box-black.png" alt="" />
        </div>
        <span className="sidebar-wordmark">{wordmark}</span>
      </div>

      <div className="sidebar-scroll">
        <div className="sidebar-entity">
          <p className="sidebar-entity-eyebrow">{entityEyebrow}</p>
          <h2 className="sidebar-entity-name">{currentEntity?.name || '—'}</h2>
          {isInternal && currentEntity?.industry && (
            <div className="sidebar-entity-meta">{currentEntity.industry} · {currentEntity.size}</div>
          )}
        </div>

        {isViewingClient && (
          <div className="sidebar-banner">
            This is exactly what {currentEntity.name} sees.
            <br />
            <button onClick={() => onSwitchEntity('rcg')}>← Back to Rottman Creative</button>
          </div>
        )}

        <div className="sidebar-section">
          <div className="sidebar-section-label">Dashboard</div>
          {CLIENT_TABS.map((t) => (
            <button
              key={t.id}
              className={`sidebar-item ${tabId === t.id ? 'active' : ''}`}
              onClick={() => onSelectTab(t.id)}
            >
              <Icon name={t.icon} size={14} /> {t.label}
            </button>
          ))}
        </div>

        {isInternal && (
          <div className="sidebar-section">
            <div className="sidebar-section-label">Internal Tools</div>
            {INTERNAL_TABS.map((t) => (
              <button
                key={t.id}
                className={`sidebar-item ${tabId === t.id ? 'active' : ''}`}
                onClick={() => onSelectTab(t.id)}
              >
                <Icon name={t.icon} size={14} /> {t.label}
              </button>
            ))}
          </div>
        )}
      </div>

      {isInternal && (
        <div className="sidebar-foot">
          <Dropdown
            align="left"
            direction="up"
            trigger={
              <button className="dd-trigger" style={{ width: '100%', justifyContent: 'space-between' }}>
                <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
                  <Icon name="Eye" size={13} />
                  View as
                </span>
                <Icon name="ChevronUp" size={13} />
              </button>
            }
          >
            <div className="dd-section">View</div>
            <button className={`dd-item ${currentEntity?.isSelf ? 'active' : ''}`} onClick={() => onSwitchEntity('rcg')}>
              <Icon name="Home" size={14} /> Rottman Creative
            </button>
            <div className="dd-rule" />
            <div className="dd-section">View as client</div>
            {window.RCG_CLIENTS.filter((c) => !c.isSelf).map((c) => (
              <button key={c.id} className={`dd-item ${currentEntity?.id === c.id ? 'active' : ''}`} onClick={() => onSwitchEntity(c.id)}>
                <Icon name="ArrowRight" size={14} /> {c.name}
              </button>
            ))}
          </Dropdown>
        </div>
      )}
    </aside>
  );
}

// ── SLIM TOP BAR ──────────────────────────────────────────
function Topbar({ user, currentEntity, tabId, onOpenConnect, onSignOut }) {
  const isInternal = user.type === 'internal';
  const tab = [...CLIENT_TABS, ...INTERNAL_TABS].find((t) => t.id === tabId);
  return (
    <header className="topbar">
      <div className="topbar-title">
        <span className="crumb">{currentEntity?.name || 'Dashboard'} · </span>
        {tab?.label || ''}
      </div>
      <div className="topbar-actions">
        {isInternal && currentEntity?.isSelf && (
          <span className="badge-internal">
            <Icon name="Shield" size={11} /> RCG Internal
          </span>
        )}
        <button className="tlink" onClick={onOpenConnect} style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12 }}>
          <Icon name="Plug" size={13} /> Connect Sources
        </button>
        <Dropdown trigger={<div className="avatar">{user.name.split(' ').map((s) => s[0]).slice(0, 2).join('')}</div>}>
          <div className="dd-section">{user.name}</div>
          <div style={{ padding: '0 14px 8px', fontSize: 11.5, color: 'var(--ink-stone)' }}>{user.email}</div>
          <div className="dd-rule" />
          <button className="dd-item"><Icon name="User" size={14} /> Profile</button>
          <button className="dd-item"><Icon name="Settings" size={14} /> Settings</button>
          <div className="dd-rule" />
          <button className="dd-item" onClick={onSignOut}><Icon name="LogOut" size={14} /> Sign out</button>
        </Dropdown>
      </div>
    </header>
  );
}

// ── DASHBOARD ROOT ───────────────────────────────────────
// `entityId` is the id of the RCG_CLIENTS entry whose data is being shown.
// For internal users it defaults to 'rcg' (the firm itself). For client users
// it's always their own clientId. Internal Tools tabs (prospects/perf/roster)
// don't change the entity — they replace the page content but the sidebar
// header keeps showing the current entity.
function Dashboard({ user, onSignOut, tweaks, setTweak, pushToast }) {
  const initialEntityId = user.type === 'client' ? user.clientId : 'rcg';
  const [entityId, setEntityId] = auState(initialEntityId);
  const [tabId, setTabId] = auState('overview');
  const [switching, setSwitching] = auState(false);
  const [connectOpen, setConnectOpen] = auState(false);

  const isInternal = user.type === 'internal';
  const currentEntity = window.RCG_CLIENTS.find((c) => c.id === entityId) || window.RCG_CLIENTS[0];

  function selectTab(nextTabId) {
    if (nextTabId === tabId) return;
    // Defense-in-depth: client users can't reach internal-tools tabs even by
    // bypassing the sidebar (which doesn't render them anyway).
    if (!isInternal && INTERNAL_TAB_IDS.has(nextTabId)) return;
    setTabId(nextTabId);
  }

  function switchEntity(id) {
    if (id === entityId && CLIENT_TAB_IDS.has(tabId)) return;
    setSwitching(true);
    setTimeout(() => {
      setEntityId(id);
      setTabId('overview');
      setSwitching(false);
    }, 350);
  }

  function selectClientFromRoster(id) { switchEntity(id); }

  function renderTab() {
    if (CLIENT_TAB_IDS.has(tabId)) {
      switch (tabId) {
        case 'overview': return <OverviewTab client={currentEntity} onConnect={() => setConnectOpen(true)} />;
        case 'paid': return <PaidTab client={currentEntity} />;
        case 'email': return <EmailTab client={currentEntity} />;
        case 'web': return <WebSeoTab client={currentEntity} />;
        case 'crm': return <CrmTab client={currentEntity} />;
        case 'report': return <MonthlyReportTab client={currentEntity} pushToast={pushToast} />;
        default: return null;
      }
    }
    if (isInternal && INTERNAL_TAB_IDS.has(tabId)) {
      switch (tabId) {
        case 'prospects': return <ProspectResearchTab pushToast={pushToast} />;
        case 'performance': return <RcgPerformanceTab />;
        case 'roster': return <ClientRosterTab onSelectClient={selectClientFromRoster} />;
        default: return null;
      }
    }
    return null;
  }

  return (
    <div className="app-layout">
      <Sidebar
        user={user}
        currentEntity={currentEntity}
        tabId={tabId}
        onSelectTab={selectTab}
        onSwitchEntity={switchEntity}
        wordmark={tweaks.wordmark || 'Rottman Creative'}
      />

      <div className="app-main">
        <Topbar
          user={user}
          currentEntity={currentEntity}
          tabId={tabId}
          onOpenConnect={() => setConnectOpen(true)}
          onSignOut={onSignOut}
        />

        <div className="page-wrap" key={tabId + entityId}>
          {switching
            ? <div style={{ padding: 80, textAlign: 'center', color: 'var(--ink-stone)' }}>
                <div className="spin" style={{ margin: '0 auto 18px' }} />
                <div className="meta">Loading dashboard</div>
              </div>
            : renderTab()
          }
        </div>
      </div>

      {connectOpen && (
        <ConnectSourcesScreen onClose={() => setConnectOpen(false)} pushToast={pushToast} />
      )}
    </div>
  );
}

// ── ROOT APP ─────────────────────────────────────────────
function App() {
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [user, setUser] = auState(null);
  const [authState, setAuthState] = auState('loading'); // 'loading' | 'authed' | 'devfallback'
  const [toasts, pushToast] = useToasts();

  // On mount, ask Cloudflare Access who the user is. If we're behind Access
  // this resolves to the signed-in identity; if not (local dev), it 404s and
  // we fall back to the in-app login form.
  auEffect(() => {
    let cancelled = false;
    (async () => {
      try {
        const res = await fetch('/cdn-cgi/access/get-identity', { credentials: 'include' });
        if (!res.ok) throw new Error('not-behind-access');
        const identity = await res.json();
        if (cancelled) return;
        if (!identity || !identity.email) throw new Error('no-identity');
        setUser(userFromIdentity(identity));
        setAuthState('authed');
      } catch {
        if (cancelled) return;
        setAuthState('devfallback');
      }
    })();
    return () => { cancelled = true; };
  }, []);

  function signOut() {
    // Cloudflare Access logout clears the Access JWT and bounces back to the
    // configured logout URL. Locally we just clear the in-memory user.
    if (authState === 'authed') {
      window.location.href = '/cdn-cgi/access/logout';
      return;
    }
    setUser(null);
  }

  auEffect(() => {
    const root = document.documentElement;
    if (tweaks.density === 'compact') {
      root.style.setProperty('--card-pad', '20px');
    } else {
      root.style.removeProperty('--card-pad');
    }
  }, [tweaks.density]);

  let body;
  if (authState === 'loading') {
    body = (
      <div style={{ minHeight: '100vh', display: 'grid', placeItems: 'center' }}>
        <div style={{ textAlign: 'center', color: 'var(--ink-stone)' }}>
          <div className="spin" style={{ margin: '0 auto 18px' }} />
          <div className="meta">Signing you in</div>
        </div>
      </div>
    );
  } else if (!user) {
    body = <LoginScreen onAuth={(u) => { setUser(u); }} pushToast={pushToast} />;
  } else {
    body = <Dashboard user={user} onSignOut={signOut} tweaks={tweaks} setTweak={setTweak} pushToast={pushToast} />;
  }

  return (
    <React.Fragment>
      {body}
      <Toast toasts={toasts} />
      <TweaksPanel title="Tweaks">
        <TweakSection label="Identity">
          <TweakText label="Wordmark text" value={tweaks.wordmark} onChange={(v) => setTweak('wordmark', v)} />
        </TweakSection>
        <TweakSection label="Display">
          <TweakRadio
            label="Density"
            value={tweaks.density}
            options={[{ value: 'comfortable', label: 'Comfy' }, { value: 'compact', label: 'Compact' }]}
            onChange={(v) => setTweak('density', v)}
          />
          <TweakToggle label="KPI sparklines" value={tweaks.showSparklines} onChange={(v) => setTweak('showSparklines', v)} />
        </TweakSection>
        <TweakSection label="Quick demo">
          <TweakButton label="Sign in as Acme (client)" onClick={() => { setUser({ type: 'client', name: 'Sarah Patel', email: 'sarah@acmecorp.com', clientId: 'acme' }); setAuthState('devfallback'); }} />
          <TweakButton label="Sign in as RCG (internal)" onClick={() => { setUser({ type: 'internal', name: 'Jacken Rottman', email: 'jacken@rottmancreative.com', clientId: null }); setAuthState('devfallback'); }} />
          <TweakButton label="Sign out" onClick={() => setUser(null)} secondary />
        </TweakSection>
      </TweaksPanel>
    </React.Fragment>
  );
}

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