// ═══════════════════════════════════════════════════════════════
// TSL 관리자 — App Shell
// Header (role sim) · Main tabs · Sub-tabs · Body · Tweaks
// ═══════════════════════════════════════════════════════════════

const App = () => {
  const isMobile = useIsMobile();
  // ── Simulated current role (for design review) ──
  const [role, setRole] = React.useState('master');
  // ── Tab state (mobile: 정책>보안관리, PC: 회원관리>검색) ──
  const INITIAL_TAB_MOBILE = { tab: 'policy',  subtab: 'security' };
  const INITIAL_TAB_PC     = { tab: 'members', subtab: 'search'   };
  const pickInitialTab = () => (typeof window !== 'undefined' && window.innerWidth <= 768)
    ? INITIAL_TAB_MOBILE : INITIAL_TAB_PC;
  const initial = pickInitialTab();
  const [tab, setTab] = React.useState(initial.tab);
  const [subtab, setSubtab] = React.useState(initial.subtab);
  const [tweaks, setTweaks] = React.useState(window.__TWEAKS__ || {});
  const [tweaksOpen, setTweaksOpen] = React.useState(false);
  // ── 실제 인증 상태 (/admin/me) ──
  const [authState, setAuthState] = React.useState({ loading: true, me: null, error: null });
  const authed = !!authState.me;

  async function fetchMe() {
    try {
      const res = await fetch('/admin/me', { credentials: 'same-origin' });
      if (res.status === 401) { setAuthState({ loading: false, me: null, error: null }); return; }
      const data = await res.json();
      setAuthState({ loading: false, me: data, error: null });
      if (data.role) setRole(data.role);
    } catch (e) {
      setAuthState({ loading: false, me: null, error: e.message });
    }
  }
  React.useEffect(() => { fetchMe(); }, []);

  // 초기 탭은 기기별로 결정되므로 localStorage 복원하지 않음

  async function doLogout() {
    try {
      await fetch('/admin/logout', { method: 'POST', credentials: 'same-origin' });
      await fetch('/auth/logout',  { method: 'POST', credentials: 'same-origin' });
    } catch {}
    try { localStorage.removeItem('tsl.nav'); } catch {}
    window.location.replace('/');
  }

  // Tweaks plumbing
  React.useEffect(() => {
    const handler = (e) => {
      if (!e.data || typeof e.data !== 'object') return;
      if (e.data.type === '__activate_edit_mode') setTweaksOpen(true);
      if (e.data.type === '__deactivate_edit_mode') setTweaksOpen(false);
    };
    window.addEventListener('message', handler);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', handler);
  }, []);

  // Accent hue live update
  React.useEffect(() => {
    const h = tweaks.accentHue ?? 255;
    document.documentElement.style.setProperty('--accent', `oklch(0.58 0.13 ${h})`);
    document.documentElement.style.setProperty('--accent-soft', `oklch(0.96 0.03 ${h})`);
    document.documentElement.style.setProperty('--accent-ink', `oklch(0.42 0.14 ${h})`);
  }, [tweaks.accentHue]);

  const updateTweak = (k, v) => {
    const next = { ...tweaks, [k]: v };
    setTweaks(next);
    window.parent.postMessage({ type: '__edit_mode_set_keys', edits: { [k]: v } }, '*');
  };

  // ── Compute allowed tabs/subtabs for current role + device ──
  const visibleTabs = React.useMemo(() => TABS.map(t => ({
    ...t,
    sub: t.sub.filter(s => s.roles.includes(role) && (!s.mobileOnly || isMobile)),
  })).filter(t => t.sub.length > 0), [role, isMobile]);

  // Snap tab/subtab to allowed when role changes
  React.useEffect(() => {
    const curTab = visibleTabs.find(t => t.id === tab);
    if (!curTab) { setTab(visibleTabs[0].id); setSubtab(visibleTabs[0].sub[0].id); return; }
    if (!curTab.sub.find(s => s.id === subtab)) setSubtab(curTab.sub[0].id);
  }, [role, visibleTabs]);

  const currentTab = visibleTabs.find(t => t.id === tab) || visibleTabs[0];

  // 인증 로딩 중
  if (authState.loading) {
    return (
      <div style={{ minHeight: '100vh', display: 'grid', placeItems: 'center', color: 'var(--ink-3)', fontSize: 14 }}>
        인증 확인 중…
      </div>
    );
  }

  // 미인증 — 실제 카카오 OAuth 로그인 화면 (원본 loginOverlay 재구성, preview 톤)
  if (!authed) {
    const origin = typeof window !== 'undefined' ? window.location.origin : '';
    const kakaoHref = `/auth/kakao?mode=admin&redirect_origin=${encodeURIComponent(origin)}`;
    const kakaoSwitch = `/auth/kakao?mode=admin&prompt=login&redirect_origin=${encodeURIComponent(origin)}`;
    const params = typeof window !== 'undefined' ? new URLSearchParams(window.location.search) : null;
    const err = params?.get('error');
    const errMsg = err === 'not_admin' ? '관리자 권한이 없는 계정입니다.'
      : err === 'login_failed' ? '로그인 처리에 실패했습니다. 다시 시도해주세요.'
      : null;
    return (
      <div style={{ minHeight: '100vh', display: 'grid', placeItems: 'center', background: 'var(--surface-2)', padding: 20 }}>
        <div style={{ background: '#fff', border: '1px solid var(--line)', borderRadius: 20, padding: '40px 36px', maxWidth: 380, width: '100%', boxShadow: '0 2px 24px rgba(15,23,42,0.06)', textAlign: 'center' }}>
          <img src="/uploads/tsl-logo.jpg" alt="팀시너지랩" style={{ height: 44, margin: '0 auto 16px', objectFit: 'contain', maxWidth: '100%' }} />
          <h1 style={{ fontSize: 19, fontWeight: 700, color: 'var(--ink)', marginBottom: 22 }}>관리자 로그인</h1>
          {errMsg && (
            <div style={{ marginBottom: 14, padding: '10px 14px', background: '#fef2f2', border: '1px solid #fecaca', color: '#dc2626', borderRadius: 8, fontSize: 12.5, fontWeight: 500 }}>
              {errMsg}
            </div>
          )}
          <a href={kakaoHref}
            style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8, width: '100%', padding: '13px 16px', background: '#FEE500', color: '#191919', border: 'none', borderRadius: 12, fontSize: 14.5, fontWeight: 700, cursor: 'pointer', textDecoration: 'none', fontFamily: 'inherit' }}>
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18"><path fill="#191919" d="M12 3C6.477 3 2 6.463 2 10.691c0 2.726 1.785 5.12 4.478 6.482-.163.594-.59 2.149-.676 2.484-.107.414.152.408.319.297.131-.087 2.09-1.422 2.937-1.997.607.085 1.233.13 1.872.13 5.523 0 10-3.463 10-7.396C22 6.463 17.523 3 12 3"/></svg>
            카카오 로그인
          </a>
          <a href={kakaoSwitch}
            style={{ display: 'block', marginTop: 10, padding: '11px 16px', background: '#fff', color: 'var(--ink-2)', border: '1px solid var(--line-strong)', borderRadius: 12, fontSize: 13, fontWeight: 500, cursor: 'pointer', textDecoration: 'none' }}>
            다른 계정으로 로그인
          </a>
        </div>
      </div>
    );
  }

  // ── View routing ──
  const renderContent = () => {
    const k = `${currentTab?.id}.${subtab}`;
    switch (k) {
      case 'members.search':    return <MemberSearchView />;
      case 'members.register':  return <MemberRegisterView />;
      case 'members.permissions': return <MemberPermissionsView />;
      case 'members.info':      return <MemberInfoView />;
      case 'members.penalty':   return <MemberPenaltyView />;
      case 'members.lecture':   return <LectureAccountsView />;
      case 'activity.errors':   return <ErrorsView />;
      case 'activity.chats':    return <ChatsView />;
      case 'activity.tokens':   return <TokenUsageView />;
      case 'activity.exchange': return <ExchangesView />;
      case 'policy.security':    return <SecurityView />;
      case 'policy.tokenops':    return <TokenOpsView />;
      case 'policy.categories':  return <CategoryView />;
      case 'policy.tags':        return <TagView />;
      case 'policy.appdownload': return <AppDownloadView />;
      default: return <div style={{ padding: 40, color: 'var(--ink-3)' }}>준비 중…</div>;
    }
  };

  return (
    <div style={{ minHeight: '100vh', background: 'var(--surface-2)' }}>
      {/* ─── Header ─────────────────────────────────────── */}
      <header style={{
        background: '#fff', borderBottom: '1px solid var(--line)',
        height: isMobile ? 52 : 60, display: 'flex', alignItems: 'center',
        padding: isMobile ? '0 14px' : '0 28px', gap: isMobile ? 10 : 20,
        position: 'sticky', top: 0, zIndex: 20,
      }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 14, flexShrink: 0 }}>
          <TSLLogo height={28} />
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 6, borderLeft: '1px solid var(--line)', paddingLeft: 14, height: 22 }}>
            <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink-2)', letterSpacing: '-0.01em' }}>
              관리자
            </span>
          </div>
        </div>

        <div style={{ flex: 1 }} />

        {/* PC: 헤더 우측에 뱃지 + 로그아웃. 모바일: 뱃지는 탭 행으로, 로그아웃만 헤더 우측 */}
        {authState.me && !isMobile && (
          <div style={{
            display: 'flex', alignItems: 'center',
            gap: 8, flexShrink: 0,
            padding: '4px 10px', borderRadius: 999, background: '#f6f8fa',
          }}>
            <span style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink)' }}>
              {authState.me.name || '관리자'}
            </span>
            {authState.me.role && <RoleBadge role={authState.me.role} size="md" />}
          </div>
        )}

        {/* Logout — PC·모바일 모두 헤더 우측 */}
        <button style={{
          display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
          width: isMobile ? 32 : 36, height: isMobile ? 32 : 36, borderRadius: isMobile ? 8 : 10,
          border: '1px solid var(--line-strong)', background: '#fff',
          color: 'var(--ink-3)', cursor: 'pointer', flexShrink: 0,
        }}
          onMouseEnter={e => e.currentTarget.style.background = '#f6f8fa'}
          onMouseLeave={e => e.currentTarget.style.background = '#fff'}
          onClick={doLogout}
          title="로그아웃">
          <Icon name="logout" size={isMobile ? 14 : 16} />
        </button>
      </header>

      {/* ─── Main Tabs ──────────────────────────────────── */}
      <div style={{
        background: '#fff', borderBottom: '1px solid var(--line)',
        padding: isMobile ? '0 10px' : '0 28px',
        display: 'flex', alignItems: 'center', gap: 8,
      }}>
        <div style={{ display: 'flex', gap: 2, flex: 1, minWidth: 0, overflowX: isMobile ? 'auto' : 'visible' }}>
          {visibleTabs.map(t => {
            const active = currentTab?.id === t.id;
            return (
              <button
                key={t.id}
                onClick={() => { setTab(t.id); setSubtab(t.sub[0].id); }}
                style={{
                  position: 'relative',
                  padding: isMobile ? '10px 12px' : '13px 18px',
                  border: 'none', background: 'transparent',
                  fontSize: isMobile ? 12.5 : 14, fontWeight: active ? 600 : 500,
                  color: active ? 'var(--ink)' : 'var(--ink-3)',
                  cursor: 'pointer',
                  letterSpacing: '-0.01em',
                  fontFamily: 'inherit',
                  display: 'inline-flex', alignItems: 'center', gap: isMobile ? 5 : 7,
                  whiteSpace: 'nowrap',
                }}
                onMouseEnter={e => { if (!active) e.currentTarget.style.color = 'var(--ink-2)'; }}
                onMouseLeave={e => { if (!active) e.currentTarget.style.color = 'var(--ink-3)'; }}
              >
                <span style={{ color: active ? 'var(--accent)' : 'var(--ink-4)', display: 'flex' }}>
                  <Icon name={t.icon} size={15} />
                </span>
                {t.label}
                {active && (
                  <span style={{
                    position: 'absolute', left: 14, right: 14, bottom: -1, height: 2,
                    background: 'var(--accent)', borderRadius: 2,
                  }} />
                )}
              </button>
            );
          })}
        </div>
        {isMobile && authState.me && (
          <div style={{
            display: 'flex', flexDirection: 'column', alignItems: 'center',
            gap: 2, flexShrink: 0, marginLeft: 'auto',
            padding: '3px 8px', borderRadius: 10, background: '#f6f8fa',
            lineHeight: 1,
          }}>
            <span style={{
              fontSize: 10, fontWeight: 600, color: 'var(--ink)',
              whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: 64,
            }}>
              {authState.me.name || '관리자'}
            </span>
            {authState.me.role && <RoleBadge role={authState.me.role} size="xs" />}
          </div>
        )}
      </div>

      {/* ─── Sub Tabs ──────────────────────────────────── */}
      {currentTab && (
        <div style={{
          background: 'var(--surface-2)', borderBottom: '1px solid var(--line)',
          padding: isMobile ? '8px 10px' : '10px 28px',
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          overflowX: isMobile ? 'auto' : 'visible',
        }}>
          <div style={{ display: 'flex', gap: 4 }}>
            {currentTab.sub.map(s => {
              const active = subtab === s.id;
              // 모바일에서 4자 이상 라벨은 2자마다 줄바꿈 (오류보고 → 오류\n보고)
              const displayLabel = (isMobile && s.label.length >= 4)
                ? s.label.replace(/(.{2})/g, '$1\n').replace(/\n$/, '')
                : s.label;
              return (
                <button
                  key={s.id}
                  onClick={() => setSubtab(s.id)}
                  style={{
                    padding: isMobile ? '6px 10px' : '7px 14px', borderRadius: 8, border: 'none',
                    fontSize: isMobile ? 11.5 : 13, fontWeight: 500,
                    background: active ? '#fff' : 'transparent',
                    color: active ? 'var(--ink)' : 'var(--ink-3)',
                    boxShadow: active ? '0 1px 2px rgba(15,23,42,0.06), 0 0 0 1px var(--line-strong)' : 'none',
                    cursor: 'pointer', fontFamily: 'inherit',
                    display: 'inline-flex', alignItems: 'center', gap: 6,
                    whiteSpace: 'pre-line', textAlign: 'center', lineHeight: 1.15,
                  }}
                  onMouseEnter={e => { if (!active) e.currentTarget.style.background = '#eff1f4'; }}
                  onMouseLeave={e => { if (!active) e.currentTarget.style.background = 'transparent'; }}
                >
                  {displayLabel}
                  {s.roles.length < 3 && s.roles.includes('master') && !s.roles.includes('admin') && (
                    <span title="마스터 전용" style={{
                      fontSize: 9, fontWeight: 700, padding: '1px 5px', borderRadius: 4,
                      background: 'oklch(0.95 0.05 300)', color: 'oklch(0.42 0.15 300)',
                      letterSpacing: '0.03em',
                    }}>M</span>
                  )}
                </button>
              );
            })}
          </div>

          {!isMobile && (
            <div style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, color: 'var(--ink-4)' }}>
              <span>{currentTab.label}</span>
              <Icon name="chevronR" size={11} />
              <span style={{ color: 'var(--ink-2)', fontWeight: 500 }}>
                {currentTab.sub.find(s => s.id === subtab)?.label}
              </span>
            </div>
          )}
        </div>
      )}

      {/* ─── Body ───────────────────────────────────────── */}
      <main style={{ padding: isMobile ? '12px' : '24px 28px', maxWidth: 1440, margin: '0 auto' }}>
        {renderContent()}
      </main>

      {/* ─── Tweaks Panel ──────────────────────────────── */}
      {tweaksOpen && (
        <TweaksPanel tweaks={tweaks} update={updateTweak} onClose={() => setTweaksOpen(false)} />
      )}
    </div>
  );
};

// ── Role simulator (for design review) ────────────────────
const RoleSimulator = ({ role, onChange }) => {
  const meta = {
    normal: { label: '일반',   tone: 'neutral' },
    admin:  { label: '관리자', tone: 'blue' },
    master: { label: '마스터', tone: 'purple' },
  };
  return (
    <div style={{
      display: 'inline-flex', alignItems: 'center', gap: 8,
      padding: '4px 4px 4px 10px', height: 34,
      background: 'oklch(0.97 0.02 60)',
      border: '1px dashed oklch(0.78 0.12 60)',
      borderRadius: 10, flexShrink: 0,
    }} title="디자인 리뷰용 · 권한 시뮬레이션">
      <span style={{
        fontSize: 10, fontWeight: 700, letterSpacing: '0.04em',
        color: 'oklch(0.50 0.14 60)', textTransform: 'uppercase',
      }}>Preview as</span>
      <div style={{ display: 'flex', gap: 2, background: '#fff', borderRadius: 7, padding: 2 }}>
        {ROLE_SIM.map(r => {
          const active = role === r.id;
          const t = TONE_PALETTE[meta[r.id].tone];
          return (
            <button key={r.id} onClick={() => onChange(r.id)} style={{
              padding: '4px 10px', borderRadius: 5, border: 'none',
              fontSize: 11.5, fontWeight: active ? 700 : 500,
              background: active ? t.bg : 'transparent',
              color: active ? t.fg : 'var(--ink-3)',
              cursor: 'pointer', fontFamily: 'inherit',
              transition: 'all 0.12s',
            }}>{r.label}</button>
          );
        })}
      </div>
    </div>
  );
};

// ── Tweaks panel ──────────────────────────────────────────
const TweaksPanel = ({ tweaks, update, onClose }) => (
  <div style={{
    position: 'fixed', bottom: 20, right: 20, width: 280,
    background: '#fff', border: '1px solid var(--line-strong)',
    borderRadius: 14, boxShadow: '0 12px 40px rgba(15,23,42,0.16)',
    padding: 16, zIndex: 1000,
  }}>
    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 14 }}>
      <div style={{ fontSize: 14, fontWeight: 700 }}>Tweaks</div>
      <button onClick={onClose} style={{
        border: 'none', background: 'transparent', color: 'var(--ink-3)',
        cursor: 'pointer', padding: 4, borderRadius: 6,
      }}><Icon name="close" size={14} /></button>
    </div>

    <TweakRow label="액센트 색상">
      <input type="range" min="0" max="360" step="5"
        value={tweaks.accentHue ?? 255}
        onChange={e => update('accentHue', Number(e.target.value))}
        style={{ width: '100%' }}
      />
      <div style={{ fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--mono)', textAlign: 'right' }}>
        hue {tweaks.accentHue ?? 255}°
      </div>
    </TweakRow>

    <TweakRow label="밀도">
      <div style={{ display: 'flex', gap: 4 }}>
        {[['comfortable', '여유'], ['compact', '조밀']].map(([v, l]) => (
          <button key={v} onClick={() => update('density', v)} style={{
            flex: 1, padding: '6px 8px', borderRadius: 8, fontSize: 12,
            border: `1px solid ${tweaks.density === v ? 'var(--accent)' : 'var(--line-strong)'}`,
            background: tweaks.density === v ? 'var(--accent-soft)' : '#fff',
            color: tweaks.density === v ? 'var(--accent-ink)' : 'var(--ink-2)',
            cursor: 'pointer', fontWeight: 500, fontFamily: 'inherit',
          }}>{l}</button>
        ))}
      </div>
    </TweakRow>

    <TweakRow label="상태 표시">
      <div style={{ display: 'flex', gap: 4 }}>
        {[['dot', '점'], ['pill', '필']].map(([v, l]) => (
          <button key={v} onClick={() => update('statusStyle', v)} style={{
            flex: 1, padding: '6px 8px', borderRadius: 8, fontSize: 12,
            border: `1px solid ${tweaks.statusStyle === v ? 'var(--accent)' : 'var(--line-strong)'}`,
            background: tweaks.statusStyle === v ? 'var(--accent-soft)' : '#fff',
            color: tweaks.statusStyle === v ? 'var(--accent-ink)' : 'var(--ink-2)',
            cursor: 'pointer', fontWeight: 500, fontFamily: 'inherit',
          }}>{l}</button>
        ))}
      </div>
    </TweakRow>
  </div>
);

const TweakRow = ({ label, children }) => (
  <div style={{ marginBottom: 12 }}>
    <div style={{ fontSize: 11, color: 'var(--ink-3)', marginBottom: 6, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '0.04em' }}>
      {label}
    </div>
    {children}
  </div>
);

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