/* ============================================================
   CNX admin — Audit log + User management
   ============================================================ */
const { useState: useSA, useMemo: useMA } = React;

const ACTION_LABEL = { create: '생성', update: '수정', delete: '삭제', submit: '제출', status: '상태변경', 'todo.complete': '할 일 완료', 'todo.uncomplete': '할 일 취소' };
const PAGE_SIZE = 8;

/* ============================================================
   AUDIT LOG
   ============================================================ */
function AuditLog({ user, toast, project }) {
  const [q, setQ] = useSA('');
  const [action, setAction] = useSA('');
  const [role, setRole] = useSA('');
  const [page, setPage] = useSA(1);
  const { loading, error, data, reload } = useAsync(() => window.api.getAuditLogs({ q, action, role }), [q, action, role]);

  const total = data ? data.length : 0;
  const pages = Math.max(1, Math.ceil(total / PAGE_SIZE));
  const view = useMA(() => (data || []).slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE), [data, page]);
  React.useEffect(() => { setPage(1); }, [q, action, role]);

  return (
    <div className="page-wrap">
      <div className="page-head"><div className="page-title">{project ? '활동 로그' : '감사 로그'}</div>
        <div className="page-desc">{project ? `'${project.name}' 운영 활동 이력 — 생성·수정·삭제·제출·상태 변경 기록.` : '모든 생성·수정·삭제·제출·상태 변경 이력을 기록합니다. (CNX 전체 조회)'}</div></div>

      <div className="toolbar">
        <div className="search-box"><Icon.search /><input placeholder="담당자·대상·엔티티 검색" value={q} onChange={(e) => setQ(e.target.value)} /></div>
        <select className="select-sm" value={action} onChange={(e) => setAction(e.target.value)}>
          <option value="">전체 액션</option>
          {Object.entries(ACTION_LABEL).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
        </select>
        <select className="select-sm" value={role} onChange={(e) => setRole(e.target.value)}>
          <option value="">전체 역할</option><option value="CNX">CNX</option><option value="LGE">LGE</option>
        </select>
        {(q || action || role) && <Btn size="sm" variant="soft" onClick={() => { setQ(''); setAction(''); setRole(''); }}>필터 초기화</Btn>}
        <span className="muted" style={{ fontSize: 12.5, marginLeft: 'auto' }}>{total}건</span>
      </div>

      {loading && <div className="tbl-wrap"><table className="tbl"><tbody>{[0, 1, 2, 3, 4].map((i) => <tr key={i}><td colSpan="6"><Skel h={18} /></td></tr>)}</tbody></table></div>}
      {error && <ErrorState onRetry={reload} msg={error} />}
      {!loading && !error && total === 0 && <EmptyState icon={<Icon.shield />} title="해당하는 로그가 없습니다" desc="필터 조건을 변경해 보세요." />}

      {!loading && !error && total > 0 && (
        <div className="tbl-wrap">
          <table className="tbl">
            <thead><tr><th>담당자</th><th>액션</th><th>엔티티</th><th>대상 / 변경 내용</th><th>시각</th></tr></thead>
            <tbody>
              {view.map((a) => (
                <tr key={a.id}>
                  <td><div className="actor"><Avatar name={a.actor} color={a.role === 'CNX' ? 'var(--cnx-blue)' : 'var(--lg-red)'} size={28} /><div><div className="nm">{a.actor}</div><RoleBadge role={a.role} /></div></div></td>
                  <td><span className={`action-chip ac-${String(a.action).replace(/\./g, '-')}`}>{ACTION_LABEL[a.action] || a.action}</span></td>
                  <td style={{ fontWeight: 600, color: 'var(--ink)' }}>{a.entity}</td>
                  <td>
                    <div style={{ fontWeight: 600, color: 'var(--ink)', marginBottom: 3 }}>{a.target}</div>
                    <div className="diff">
                      {a.before != null && <span className="before">{a.before}</span>}
                      {a.before != null && a.after != null && <Icon.arrowR />}
                      {a.after != null && <span className="after">{a.after}</span>}
                      {a.before == null && a.after == null && <span className="muted">—</span>}
                    </div>
                  </td>
                  <td className="muted" style={{ whiteSpace: 'nowrap', fontSize: 12.5 }}>{fmtDateTime(a.at)}</td>
                </tr>
              ))}
            </tbody>
          </table>
          <div className="pager">
            <span>{(page - 1) * PAGE_SIZE + 1}–{Math.min(page * PAGE_SIZE, total)} / {total}건</span>
            <div className="pgs">
              <button disabled={page === 1} onClick={() => setPage((p) => p - 1)}><Icon.chevL style={{ width: 15, height: 15 }} /></button>
              {Array.from({ length: pages }).map((_, i) => <button key={i} className={page === i + 1 ? 'on' : ''} onClick={() => setPage(i + 1)}>{i + 1}</button>)}
              <button disabled={page === pages} onClick={() => setPage((p) => p + 1)}><Icon.chevR style={{ width: 15, height: 15 }} /></button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

/* ============================================================
   USER MANAGEMENT
   ============================================================ */
const ALL_ROLES = ['ADMIN', 'CNX', 'LGE'];

function UserManagement({ user, toast }) {
  const [q, setQ] = useSA('');
  const [role, setRole] = useSA('');
  const [create, setCreate] = useSA(false);
  const { loading, error, data, reload } = useAsync(() => window.api.getUsers(), []);

  const view = useMA(() => (data || []).filter((u) => {
    if (role && u.role !== role) return false;
    if (q && !(u.name + u.email).toLowerCase().includes(q.toLowerCase())) return false;
    return true;
  }), [data, q, role]);

  const toggleStatus = async (u) => {
    try { await window.api.setUserStatus(u.id, u.status === 'active' ? 'inactive' : 'active'); toast(`${u.name} ${u.status === 'active' ? '비활성화' : '활성화'}됨`); reload(); }
    catch (e) { toast(e.message || '상태 변경 실패'); }
  };
  const changeRole = async (u, newRole) => {
    if (newRole === u.role) return;
    try { await window.api.updateUserRole(u.id, newRole); toast(`${u.name} 역할을 ${newRole}(으)로 변경`); reload(); }
    catch (e) { toast(e.message || '역할 변경 실패'); reload(); }
  };
  const remove = async (u) => {
    if (!window.confirm(`${u.name} 계정을 삭제할까요?`)) return;
    try { await window.api.deleteUser(u.id); toast(`${u.name} 삭제됨`); reload(); }
    catch (e) { toast(e.message || '삭제 실패'); }
  };
  const onCreate = async (body) => { await window.api.createUser(body); setCreate(false); toast('사용자가 생성되었습니다'); reload(); };

  return (
    <div className="page-wrap">
      <div className="page-head"><div className="flex between center wrap-flex" style={{ gap: 12 }}>
        <div><div className="page-title">사용자 관리</div><div className="page-desc">팀원 계정과 초대 코드를 관리합니다. 마지막 관리자는 강등·삭제할 수 없습니다.</div></div>
        <Btn variant="primary" icon={<Icon.plus />} onClick={() => setCreate(true)}>사용자 추가</Btn>
      </div></div>

      <div className="toolbar">
        <div className="search-box"><Icon.search /><input placeholder="이름·이메일 검색" value={q} onChange={(e) => setQ(e.target.value)} /></div>
        <select className="select-sm" value={role} onChange={(e) => setRole(e.target.value)}><option value="">전체 역할</option>{ALL_ROLES.map((r) => <option key={r} value={r}>{r}</option>)}</select>
        <span className="muted" style={{ fontSize: 12.5, marginLeft: 'auto' }}>{view.length}명</span>
      </div>

      {loading && <div className="tbl-wrap"><table className="tbl"><tbody>{[0, 1, 2, 3].map((i) => <tr key={i}><td colSpan="5"><Skel h={18} /></td></tr>)}</tbody></table></div>}
      {error && <ErrorState onRetry={reload} msg={error} />}
      {!loading && !error && view.length === 0 && <EmptyState icon={<Icon.users />} title="사용자가 없습니다" desc="조건에 맞는 사용자가 없습니다." />}

      {!loading && !error && view.length > 0 && (
        <div className="tbl-wrap">
          <table className="tbl">
            <thead><tr><th>사용자</th><th>역할</th><th>상태</th><th>등록일</th><th style={{ textAlign: 'right' }}>관리</th></tr></thead>
            <tbody>
              {view.map((u) => {
                const self = u.id === user.id;
                return (
                <tr key={u.id}>
                  <td><div className="actor"><Avatar name={u.name} color={roleColor(u.role)} initial={u.initial} size={32} /><div><div className="nm">{u.name}{self && <span className="muted" style={{ fontSize: 11, marginLeft: 6 }}>(나)</span>}</div><div className="muted" style={{ fontSize: 12 }}>{u.email}</div></div></div></td>
                  <td>
                    {self
                      ? <RoleBadge role={u.role} />
                      : <select className="select-sm role-select" value={u.role} onChange={(e) => changeRole(u, e.target.value)}>{ALL_ROLES.map((r) => <option key={r} value={r}>{r}</option>)}</select>}
                  </td>
                  <td><span className="status-dot-row"><span className={`status-dot ${u.status === 'active' ? 'on' : 'off'}`} />{u.status === 'active' ? '활성' : '비활성'}</span></td>
                  <td className="muted" style={{ fontSize: 12.5 }}>{u.createdAt}</td>
                  <td style={{ textAlign: 'right' }}>
                    {self
                      ? <span className="muted" style={{ fontSize: 12 }}>본인 계정</span>
                      : <span className="flex" style={{ gap: 6, justifyContent: 'flex-end' }}>
                          <Btn size="sm" variant={u.status === 'active' ? 'soft' : 'soft'} onClick={() => toggleStatus(u)}>{u.status === 'active' ? '비활성화' : '활성화'}</Btn>
                          <Btn size="sm" variant="danger" onClick={() => remove(u)}>삭제</Btn>
                        </span>}
                  </td>
                </tr>
              );})}
            </tbody>
          </table>
        </div>
      )}

      <InviteCodes toast={toast} />

      {create && <UserCreateModal onClose={() => setCreate(false)} onSave={onCreate} />}
    </div>
  );
}

/* ---- Invite codes ---- */
function InviteCodes({ toast }) {
  const [count, setCount] = useSA(1);
  const [role, setRole] = useSA('LGE');
  const [showUsed, setShowUsed] = useSA(false);
  const [busy, setBusy] = useSA(false);
  const { loading, error, data, reload } = useAsync(() => window.api.getInvites(showUsed), [showUsed]);
  const list = data || [];
  const counts = useMA(() => ({
    total: list.length,
    pending: list.filter((i) => i.status === 'pending').length,
    used: list.filter((i) => i.status === 'used').length,
  }), [list]);

  const mint = async () => {
    setBusy(true);
    try { const made = await window.api.mintInvites(Number(count) || 1, role); toast(`${made.length}개 코드 발급됨`); reload(); }
    catch (e) { toast(e.message || '발급 실패'); }
    finally { setBusy(false); }
  };
  const revoke = async (code) => {
    try { await window.api.revokeInvite(code); toast(`${code} 무효화됨`); reload(); }
    catch (e) { toast(e.message || '무효화 실패'); }
  };
  const copy = (code) => { try { navigator.clipboard.writeText(code); toast(`${code} 복사됨`); } catch (e) { /* ignore */ } };

  return (
    <div className="card" style={{ marginTop: 22 }}>
      <div className="flex between center" style={{ padding: '16px 18px', borderBottom: '1px solid var(--line)' }}>
        <div className="flex center" style={{ gap: 8 }}>
          <b style={{ fontSize: 14 }}>초대 코드</b>
          <span className="muted" style={{ fontSize: 12 }}>발급 {counts.total} · pending {counts.pending} · used {counts.used}</span>
        </div>
        <label className="flex center muted" style={{ gap: 6, fontSize: 12.5, cursor: 'pointer' }}>
          <input type="checkbox" checked={showUsed} onChange={(e) => setShowUsed(e.target.checked)} /> 사용된 코드도 표시
        </label>
      </div>

      <div className="flex center" style={{ gap: 8, padding: '14px 18px', borderBottom: '1px solid var(--line)', flexWrap: 'wrap' }}>
        <label className="muted" style={{ fontSize: 12.5 }}>생성할 코드 수</label>
        <input className="input" style={{ width: 70 }} type="number" min="1" max="20" value={count} onChange={(e) => setCount(e.target.value)} />
        <select className="select-sm" value={role} onChange={(e) => setRole(e.target.value)}>{ALL_ROLES.map((r) => <option key={r} value={r}>{r}</option>)}</select>
        <Btn variant="primary" size="sm" icon={<Icon.plus />} disabled={busy} onClick={mint}>코드 생성</Btn>
      </div>

      {loading && <div style={{ padding: 18 }}><Skel h={18} /></div>}
      {error && <div style={{ padding: 18 }}><ErrorState onRetry={reload} msg={error} /></div>}
      {!loading && !error && list.length === 0 && <div className="muted" style={{ padding: '28px 18px', textAlign: 'center', fontSize: 13 }}>발급된 코드가 없습니다. 위에서 새로 생성하세요.</div>}
      {!loading && !error && list.length > 0 && (
        <table className="tbl">
          <thead><tr><th>코드</th><th>역할</th><th>상태</th><th>사용자</th><th style={{ textAlign: 'right' }}>관리</th></tr></thead>
          <tbody>
            {list.map((i) => (
              <tr key={i.code}>
                <td><code className="invite-code" onClick={() => copy(i.code)} title="클릭하여 복사">{i.code}</code></td>
                <td><RoleBadge role={i.role} /></td>
                <td><span className={`invite-status is-${i.status}`}>{i.status}</span></td>
                <td className="muted" style={{ fontSize: 12.5 }}>{i.usedByEmail || '—'}</td>
                <td style={{ textAlign: 'right' }}>
                  {i.status === 'pending'
                    ? <Btn size="sm" variant="danger" onClick={() => revoke(i.code)}>무효화</Btn>
                    : <span className="muted" style={{ fontSize: 12 }}>—</span>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
    </div>
  );
}

function UserCreateModal({ onClose, onSave }) {
  const [f, setF] = useSA({ name: '', email: '', role: 'LGE', initPw: '' });
  const set = (k) => (e) => setF((p) => ({ ...p, [k]: e.target.value }));
  const [busy, setBusy] = useSA(false); const [err, setErr] = useSA('');
  const submit = async () => {
    if (!f.name.trim() || !f.email.trim()) return setErr('이름과 이메일을 입력하세요.');
    if (!/.+@.+\..+/.test(f.email)) return setErr('올바른 이메일 형식이 아닙니다.');
    setBusy(true); setErr('');
    await onSave({ name: f.name.trim(), email: f.email.trim(), role: f.role, password: f.initPw });
  };
  return (
    <Modal title="사용자 추가" sub="이메일·이름·역할·초기 비밀번호를 설정합니다." onClose={onClose}
      footer={<><Btn onClick={onClose}>취소</Btn><Btn variant="primary" disabled={busy} icon={<Icon.check />} onClick={submit}>생성</Btn></>}>
      <div className="frow"><label className="flabel">이름</label><input className="input" value={f.name} onChange={set('name')} placeholder="홍길동" /></div>
      <div className="frow"><label className="flabel">이메일</label><input className="input" value={f.email} onChange={set('email')} placeholder="name@company.com" /></div>
      <div className="frow fgrid">
        <div><label className="flabel">역할</label><select className="select" value={f.role} onChange={set('role')}><option value="LGE">LGE (조회·선택·제출)</option><option value="CNX">CNX (콘텐츠 관리)</option><option value="ADMIN">ADMIN (시스템 관리)</option></select></div>
        <div><label className="flabel">초기 비밀번호</label><input className="input" value={f.initPw} onChange={set('initPw')} placeholder="임시 비밀번호" /></div>
      </div>
      {err && <div className="login-err" style={{ marginTop: 4 }}>{err}</div>}
    </Modal>
  );
}

/* ============================================================
   EPISODE LOG — cross-project submissions, browsed by submitter
   ============================================================ */
function EpisodeLog({ user, toast, navigate }) {
  const { loading, error, data, reload } = useAsync(() => window.api.getEpisodeLog(), []);
  const [selUser, setSelUser] = useSA(null);
  const [detail, setDetail] = useSA(null);   // clicked submission

  const users = useMA(() => {
    const m = {};
    (data || []).forEach((s) => {
      if (!m[s.submittedById]) m[s.submittedById] = { id: s.submittedById, name: s.actor, role: s.role, count: 0 };
      m[s.submittedById].count++;
    });
    return Object.values(m).sort((a, b) => b.count - a.count);
  }, [data]);

  React.useEffect(() => { if (selUser == null && users.length) setSelUser(users[0].id); }, [users]);

  const subs = useMA(() => (data || []).filter((s) => s.submittedById === selUser), [data, selUser]);

  return (
    <div className="page-wrap">
      <div className="page-head"><div className="page-title">에피소드 로그</div>
        <div className="page-desc">모든 프로젝트의 에피소드 제출 이력 — 담당자별로 누가 · 언제 · 어떤 테마의 어떤 에피소드를 제출했는지.</div>
      </div>

      {loading && <div className="card" style={{ padding: 24 }}><Skel w="30%" /><Skel w="60%" h={12} style={{ marginTop: 10 }} /></div>}
      {error && <ErrorState onRetry={reload} msg={error} />}
      {!loading && !error && (data || []).length === 0 && (
        <EmptyState icon={<Icon.checkCircle />} title="제출 이력이 없습니다" desc="LGE가 에피소드를 제출하면 여기에 담당자별로 기록됩니다." />
      )}

      {!loading && !error && (data || []).length > 0 && (
        <div className="eplog">
          <aside className="eplog-users">
            {users.map((u) => (
              <button key={u.id} className={`eplog-user ${u.id === selUser ? 'on' : ''}`} onClick={() => setSelUser(u.id)}>
                <Avatar name={u.name} color={u.role === 'CNX' ? 'var(--cnx-blue)' : 'var(--lg-red)'} size={32} />
                <div className="eu-id"><div className="nm">{u.name}</div><RoleBadge role={u.role} /></div>
                <span className="eu-cnt">{u.count}</span>
              </button>
            ))}
          </aside>

          <div className="eplog-detail">
            {subs.length === 0 && <div className="muted" style={{ fontSize: 13, padding: 20 }}>선택한 담당자의 제출 이력이 없습니다.</div>}
            <div className="log-list">
              {subs.map((s) => {
                const first = s.items[0] || {};
                const firstTitle = first.episodeTitle || (first.episodeId ? '(삭제된 에피소드)' : '');
                return (
                  <button className="log-row" key={s.id} onClick={() => setDetail(s)}>
                    <Avatar name={s.actor} color={s.role === 'CNX' ? 'var(--cnx-blue)' : 'var(--lg-red)'} size={36} />
                    <div className="lr-id">
                      <div className="lr-who"><span className="elc-proj"><Icon.layers style={{ width: 14, height: 14 }} />{s.projectName}</span></div>
                      <div className="log-when">{fmtDateTime(s.at)}</div>
                      {firstTitle && <div className="lr-preview">{firstTitle}{s.items.length > 1 ? ` 외 ${s.items.length - 1}건` : ''}</div>}
                    </div>
                    <span className="sub-count">에피소드 {s.items.length}개</span>
                    <Icon.chevR className="lr-chev" style={{ width: 18, height: 18 }} />
                  </button>
                );
              })}
            </div>
          </div>
        </div>
      )}

      {detail && (() => {
        const s = detail;
        const personaN = s.items.filter((it) => it.personaName).length;
        return (
          <Drawer onClose={() => setDetail(null)}
            head={
              <div>
                <div className="flex between center">
                  <span className="det-wk">제출 상세</span>
                  <button className="icon-btn" onClick={() => setDetail(null)}><Icon.x /></button>
                </div>
                <div className="log-dh-who" style={{ marginTop: 10 }}>
                  <Avatar name={s.actor} color={s.role === 'CNX' ? 'var(--cnx-blue)' : 'var(--lg-red)'} size={36} />
                  <div><span className="who">{s.actor}</span> <RoleBadge role={s.role} /></div>
                </div>
                <div className="log-dh-when">{fmtDateTime(s.at)}</div>
              </div>
            }
            footer={
              <span className="muted" style={{ fontSize: 12.5 }}>총 에피소드 {s.items.length}개 · 페르소나 지정 {personaN}개</span>
            }>
            {s.note && (
              <div className="log-note">
                <div className="ln-label">소비자 메시지</div>
                <div className="ln-quote">“{s.note}”</div>
              </div>
            )}
            <div className="log-content-title"><Icon.layers style={{ width: 16, height: 16 }} />{s.projectName}</div>
            {window.groupByMonthTheme(s.items).map(([key, rows]) => (
              <div className="log-group" key={key}>
                <div className="log-group-head"><Icon.layers style={{ width: 13, height: 13 }} />{key}</div>
                {rows.map((it, ri) => <window.EpisodeDetailBlock key={(it.episodeId || '') + ri} it={it} />)}
              </div>
            ))}
          </Drawer>
        );
      })()}
    </div>
  );
}

Object.assign(window, { AuditLog, UserManagement, EpisodeLog });
