function cleanThreadPartText(value) {
  return String(value || '')
    .replace(/\r\n/g, '\n')
    .replace(/^\s*\d+(?:\/\d+)?\.\s*/, '')
    .trim();
}

function parseDraftThreadParts(value) {
  const raw = String(value || '').replace(/\r\n/g, '\n').trim();
  if (!raw) return [];
  const blocks = raw.split(/\n+(?=\d+(?:\/\d+)?\.\s)/);
  if (blocks.length > 1) return blocks.map(cleanThreadPartText).filter(Boolean);
  return raw.split(/\n{2,}/).map(cleanThreadPartText).filter(Boolean);
}

function splitDraftThreadPart(text, max = 500) {
  const cleaned = cleanThreadPartText(text);
  if (!cleaned) return [];
  if (cleaned.length <= max) return [cleaned];

  const sentences = cleaned.match(/[^.!?]+[.!?]*/g) || [cleaned];
  const result = [];
  let current = '';

  for (const rawSentence of sentences) {
    const sentence = rawSentence.trim();
    if (!sentence) continue;
    const next = current ? current + ' ' + sentence : sentence;
    if (next.length <= max) {
      current = next;
    } else {
      if (current) result.push(current);
      current = sentence;
    }
  }

  if (current) result.push(current);
  return result;
}

function packDraftThreadParts(value, max = 500, firstMax = 120) {
  const parts = parseDraftThreadParts(value).flatMap(part => splitDraftThreadPart(part, max));
  if (!parts.length) return [];

  const firstChunks = splitDraftThreadPart(parts[0], firstMax);
  const packed = [];
  if (firstChunks[0]) packed.push(firstChunks[0]);

  let current = '';
  const remaining = firstChunks.slice(1).concat(parts.slice(1));
  for (const part of remaining.flatMap(part => splitDraftThreadPart(part, max))) {
    const next = current ? current + '\n\n' + part : part;
    if (next.length <= max) {
      current = next;
    } else {
      if (current) packed.push(current);
      current = part;
    }
  }

  if (current) packed.push(current);
  return packed;
}

function packDraftThreadText(value, max = 500) {
  return packDraftThreadParts(value, max).join('\n\n');
}

function countDraftReplies(value, max = 500) {
  return packDraftThreadParts(value, max).length;
}
// Comments (auto-reply rules) + Accounts + Post Detail pages

function CommentsPage({ state, setState }) {
  const { ACCOUNTS, COMMENT_RULES } = window.SAJU;
  const [acctFilter, setAcctFilter] = React.useState(state.selectedAccount || 'all');
  const rules = COMMENT_RULES.filter(r => acctFilter === 'all' || r.account === acctFilter);

  return (
    <>
      <div className="page-header">
        <div>
          <h1 className="page-title">자동 댓글 설정</h1>
          <div className="page-subtitle">규칙 기반 답글 · 생년월일 감지 · AI 생성 템플릿 — 기능 구현 예정</div>
        </div>
        <div style={{display:'flex',gap:8}}>
          <select className="select" style={{width:'auto'}} value={acctFilter} onChange={e=>setAcctFilter(e.target.value)}>
            <option value="all">전체 계정</option>
            {ACCOUNTS.map(a=><option key={a.id} value={a.id}>{a.handle}</option>)}
          </select>
          <button className="btn primary" onClick={() => setOpen(true)}><Icon name="plus" size={13}/>계정 추가</button>
        </div>
      </div>

      <div className="kpi-grid">
        <div className="kpi"><div className="kpi-label">활성 규칙</div><div className="kpi-value">3<span className="unit">개</span></div><div className="kpi-hint">전체 계정 기준</div></div>
        <div className="kpi"><div className="kpi-label">24h 답글 생성</div><div className="kpi-value">1,604</div><div className="kpi-hint">자동 1,292 · 보류 12</div></div>
        <div className="kpi"><div className="kpi-label">생년월일 인식률</div><div className="kpi-value">92<span className="unit">%</span></div><div className="kpi-hint">최근 7일 평균</div></div>
        <div className="kpi"><div className="kpi-label">수동 검토 대기</div><div className="kpi-value">12<span className="unit">건</span></div><div className="kpi-hint">민감 키워드 포함</div></div>
      </div>

      <div className="split-3">
        <div className="card">
          <div className="card-header">
            <div>
              <div className="card-title">규칙 목록</div>
              <div className="card-sub">트리거 패턴이 감지되면 지정된 템플릿으로 답글을 생성합니다</div>
            </div>
          </div>
          <table className="table">
            <thead>
              <tr>
                <th>이름</th>
                <th>계정</th>
                <th>트리거</th>
                <th>템플릿</th>
                <th style={{textAlign:'right'}}>답글 수</th>
                <th style={{width:80}}>상태</th>
                <th style={{width:60}}></th>
              </tr>
            </thead>
            <tbody>
              {rules.map(r => {
                const acc = ACCOUNTS.find(a=>a.id===r.account);
                return (
                  <tr key={r.id}>
                    <td style={{fontWeight:500}}>{r.name}</td>
                    <td><div style={{display:'flex',alignItems:'center',gap:6}}><AccountAvatar acc={acc} size={16}/><span style={{fontSize:11.5}}>{acc.handle}</span></div></td>
                    <td><code style={{fontFamily:'var(--font-mono)', fontSize:11, background:'var(--bg-elevated)', padding:'2px 6px', borderRadius:4, color:'var(--fg-muted)'}}>{r.trigger}</code></td>
                    <td style={{color:'var(--fg-muted)', fontSize:12}}>{r.template}</td>
                    <td className="mono" style={{textAlign:'right', fontSize:12}}>{r.replies.toLocaleString()}</td>
                    <td>
                      <div style={{display:'flex', alignItems:'center', gap:6}}>
                        <span className={`switch ${r.status==='active'?'on':''}`}></span>
                        <span style={{fontSize:11, color: r.status==='active'?'var(--status-published-fg)':'var(--fg-faint)'}}>{r.status==='active'?'활성':'일시정지'}</span>
                      </div>
                    </td>
                    <td><button className="btn ghost icon sm"><Icon name="more" size={13}/></button></td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>

        <div style={{display:'flex', flexDirection:'column', gap:16}}>
          <div className="card">
            <div className="card-header"><div className="card-title">규칙 템플릿 (플레이스홀더)</div></div>
            <div className="card-body" style={{display:'flex', flexDirection:'column', gap:10}}>
              {[
                { name:'생년월일 감지 + 띠별 3줄', desc:'YYYY.MM.DD 또는 나이 추출' },
                { name:'인사 답글 (이모지)', desc:'안녕/hi 등 감지' },
                { name:'민감 키워드 보류', desc:'금융·추천 등은 수동 검토로' },
                { name:'AI 자유 답글', desc:'LLM에 컨텍스트 전달 (계획)' },
              ].map((t,i)=>(
                <div key={i} style={{padding:10, border:'1px dashed var(--border)', borderRadius:'var(--r-md)'}}>
                  <div style={{fontSize:12.5, fontWeight:500}}>{t.name}</div>
                  <div style={{fontSize:11, color:'var(--fg-subtle)', marginTop:3}}>{t.desc}</div>
                </div>
              ))}
              <div style={{fontSize:11, color:'var(--fg-faint)', marginTop:4}}>※ 이 영역은 메뉴·페이지 구성용 골격입니다. 로직은 추후 연결.</div>
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

function AccountsPage({ state, setState }) {
  const { ACCOUNTS } = window.SAJU;
  const [open, setOpen] = React.useState(false);
  const [saving, setSaving] = React.useState(false);
  const [editingId, setEditingId] = React.useState(null);
  const ACCOUNT_PRESETS = {
    global: {
      platform: 'threads',
      accountName: '',
      handle: '',
      externalId: '',
      locale: 'en',
      language: 'English',
      pipeline: 'global',
      platforms: 'instagram, tiktok, youtube_shorts, threads',
      threadsTokenEnv: 'THREADS_TOKEN_EN_SAJU',
      youtubeRefreshTokenEnv: 'YOUTUBE_REFRESH_TOKEN_EN_SAJU',
      youtubeLoginHint: '',
      tiktokRefreshTokenEnv: 'TIKTOK_REFRESH_TOKEN_EN_SAJU',
      tiktokOpenId: '',
      instagramAccessTokenEnv: 'INSTAGRAM_ACCESS_TOKEN_EN_SAJU',
      instagramBusinessAccountIdEnv: 'INSTAGRAM_BUSINESS_ACCOUNT_ID_EN_SAJU',
    },
    spanish: {
      platform: 'threads',
      accountName: '',
      handle: '',
      externalId: '',
      locale: 'es',
      language: 'Spanish',
      pipeline: 'global',
      platforms: 'instagram, tiktok, youtube_shorts, threads',
      threadsTokenEnv: 'THREADS_TOKEN_ES_SAJU',
      youtubeRefreshTokenEnv: 'YOUTUBE_REFRESH_TOKEN_ES_SAJU',
      youtubeLoginHint: '',
      tiktokRefreshTokenEnv: 'TIKTOK_REFRESH_TOKEN_ES_SAJU',
      tiktokOpenId: '',
      instagramAccessTokenEnv: 'INSTAGRAM_ACCESS_TOKEN_ES_SAJU',
      instagramBusinessAccountIdEnv: 'INSTAGRAM_BUSINESS_ACCOUNT_ID_ES_SAJU',
    },
    korean: {
      platform: 'threads',
      accountName: '명운당',
      handle: '',
      externalId: '',
      locale: 'ko',
      language: 'Korean',
      pipeline: 'global',
      platforms: 'instagram, tiktok, youtube_shorts, threads',
      threadsTokenEnv: 'THREADS_TOKEN_KO_SAJU',
      youtubeRefreshTokenEnv: 'YOUTUBE_REFRESH_TOKEN_KO_SAJU',
      youtubeLoginHint: '',
      tiktokRefreshTokenEnv: 'TIKTOK_REFRESH_TOKEN_KO_SAJU',
      tiktokOpenId: '',
      instagramAccessTokenEnv: 'INSTAGRAM_ACCESS_TOKEN_KO_SAJU',
      instagramBusinessAccountIdEnv: 'INSTAGRAM_BUSINESS_ACCOUNT_ID_KO_SAJU',
    },
    china: {
      platform: 'other',
      accountName: '',
      handle: '',
      externalId: '',
      locale: 'zh-CN',
      language: 'Chinese',
      pipeline: 'china',
      platforms: 'xiaohongshu, douyin, wechat',
      threadsTokenEnv: '',
      youtubeRefreshTokenEnv: '',
      youtubeLoginHint: '',
      tiktokRefreshTokenEnv: '',
      tiktokOpenId: '',
      instagramAccessTokenEnv: '',
      instagramBusinessAccountIdEnv: '',
    },
  };
  const getPresetForm = React.useCallback((presetName = 'korean') => ({
    ...(ACCOUNT_PRESETS[presetName] || ACCOUNT_PRESETS.korean),
  }), []);
  const detectPreset = React.useCallback((account) => {
    const locale = String(account?.locale || '').toLowerCase();
    const language = String(account?.language || '').toLowerCase();
    const pipeline = String(account?.pipeline || '').toLowerCase();
    if (pipeline === 'china' || locale.startsWith('zh') || language.includes('chinese')) return 'china';
    if (locale.startsWith('ko') || language.includes('korean') || language.includes('한국')) return 'korean';
    if (locale.startsWith('es') || language.includes('spanish')) return 'spanish';
    return 'global';
  }, []);
  const [preset, setPreset] = React.useState('korean');
  const [form, setForm] = React.useState(() => getPresetForm('korean'));

  function resetForm() {
    setEditingId(null);
    setPreset('korean');
    setForm(getPresetForm('korean'));
  }

  function openNewAccount() {
    resetForm();
    setOpen(true);
  }

  function applyPreset(nextPreset) {
    setPreset(nextPreset);
    setForm((current) => ({
      ...getPresetForm(nextPreset),
      accountName: current.accountName,
      handle: current.handle,
      externalId: current.externalId,
    }));
  }

  function editAccount(acc) {
    setPreset(detectPreset(acc));
    setEditingId(acc.id);
    setForm({
      platform: acc.platform || 'threads',
      accountName: acc.name || acc.handle || '',
      handle: acc.handle || '',
      externalId: acc.externalId || '',
      locale: acc.locale || 'es',
      language: acc.language || '',
      pipeline: acc.pipeline || 'global',
      platforms: Array.isArray(acc.platforms) ? acc.platforms.join(', ') : '',
      threadsTokenEnv: acc.threadsTokenEnv || '',
      youtubeRefreshTokenEnv: acc.youtubeRefreshTokenEnv || '',
      youtubeLoginHint: acc.youtubeLoginHint || '',
      tiktokRefreshTokenEnv: acc.tiktokRefreshTokenEnv || '',
      tiktokOpenId: acc.tiktokOpenId || '',
      instagramAccessTokenEnv: acc.instagramAccessTokenEnv || '',
      instagramBusinessAccountIdEnv: acc.instagramBusinessAccountIdEnv || '',
    });
    setOpen(true);
  }

  async function addAccount(event) {
    event.preventDefault();
    if (!form.accountName.trim()) return alert('계정 이름을 입력해 주세요.');
    setSaving(true);
    try {
      const res = await fetch('/api/admin/social-accounts', {
        method: editingId ? 'PATCH' : 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          id: editingId,
          platform: form.platform,
          account_name: form.accountName.trim(),
          account_handle: form.handle.trim() || null,
          account_id_external: form.externalId.trim() || null,
          locale: form.locale.trim() || null,
          language: form.language.trim() || null,
          pipeline: form.pipeline.trim() || null,
          platforms: form.platforms
            .split(',')
            .map((value) => value.trim())
            .filter(Boolean),
          threads_token_env: form.threadsTokenEnv.trim() || null,
          youtube_refresh_token_env: form.youtubeRefreshTokenEnv.trim() || null,
          youtube_login_hint: form.youtubeLoginHint.trim() || null,
          tiktok_refresh_token_env: form.tiktokRefreshTokenEnv.trim() || null,
          tiktok_open_id: form.tiktokOpenId.trim() || null,
          instagram_access_token_env: form.instagramAccessTokenEnv.trim() || null,
          instagram_business_account_id_env: form.instagramBusinessAccountIdEnv.trim() || null,
        }),
      });
      const data = await res.json().catch(() => null);
      if (!res.ok || !data?.ok) throw new Error(data?.error || '계정 추가 실패');
      await window.refreshSajuData?.();
      setOpen(false);
      resetForm();
    } catch (error) {
      alert(error?.message || '계정 추가 실패');
    } finally {
      setSaving(false);
    }
  }
  return (
    <>
      <div className="page-header">
        <div>
          <h1 className="page-title">계정 관리</h1>
          <div className="page-subtitle">Threads 계정 연결 · 토큰 · 운영 스케줄</div>
        </div>
        <button className="btn primary" onClick={openNewAccount}><Icon name="plus" size={13}/>계정 추가</button>
      </div>

      {open && (
        <div className="card" style={{ marginBottom: 12 }}>
          <form onSubmit={addAccount} style={{ padding: 16, display: 'grid', gap: 10 }}>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 10 }}>
              <div className="field">
                <div className="field-label">preset</div>
                <select className="select" value={preset} onChange={e => applyPreset(e.target.value)}>
                  <option value="korean">Korean · 명운당</option>
                  <option value="spanish">Spanish</option>
                  <option value="china">China</option>
                  <option value="global">Global</option>
                </select>
              </div>
              <div className="field">
                <div className="field-label">platform</div>
                <select className="select" value={form.platform} onChange={e => setForm(f => ({ ...f, platform: e.target.value }))}>
                  <option value="threads">Threads</option>
                  <option value="instagram">Instagram</option>
                  <option value="facebook">Facebook</option>
                  <option value="x">X</option>
                  <option value="linkedin">LinkedIn</option>
                  <option value="telegram">Telegram</option>
                  <option value="other">Other</option>
                </select>
              </div>
              <div className="field">
                <div className="field-label">account_name</div>
                <input className="input" placeholder="Saju Oracle ES" value={form.accountName} onChange={e => setForm(f => ({ ...f, accountName: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">account_handle</div>
                <input className="input" placeholder="@saju.oracle.es" value={form.handle} onChange={e => setForm(f => ({ ...f, handle: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">account_id_external</div>
                <input className="input" placeholder="threads user id" value={form.externalId} onChange={e => setForm(f => ({ ...f, externalId: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">locale</div>
                <input className="input" placeholder="es" value={form.locale} onChange={e => setForm(f => ({ ...f, locale: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">language</div>
                <input className="input" placeholder="Spanish" value={form.language} onChange={e => setForm(f => ({ ...f, language: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">pipeline</div>
                <input className="input" placeholder="global" value={form.pipeline} onChange={e => setForm(f => ({ ...f, pipeline: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">platforms</div>
                <input className="input" placeholder="instagram, tiktok, youtube_shorts, threads" value={form.platforms} onChange={e => setForm(f => ({ ...f, platforms: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">threads_token_env</div>
                <input className="input" placeholder="THREADS_TOKEN_ES_SAJU" value={form.threadsTokenEnv} onChange={e => setForm(f => ({ ...f, threadsTokenEnv: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">youtube_refresh_token_env</div>
                <input className="input" placeholder="YOUTUBE_REFRESH_TOKEN_ES_SAJU" value={form.youtubeRefreshTokenEnv} onChange={e => setForm(f => ({ ...f, youtubeRefreshTokenEnv: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">youtube_login_hint</div>
                <input className="input" placeholder="spanish-account@gmail.com" value={form.youtubeLoginHint} onChange={e => setForm(f => ({ ...f, youtubeLoginHint: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">tiktok_refresh_token_env</div>
                <input className="input" placeholder="TIKTOK_REFRESH_TOKEN_ES_SAJU" value={form.tiktokRefreshTokenEnv} onChange={e => setForm(f => ({ ...f, tiktokRefreshTokenEnv: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">tiktok_open_id</div>
                <input className="input" placeholder="TikTok OAuth open_id" value={form.tiktokOpenId} onChange={e => setForm(f => ({ ...f, tiktokOpenId: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">instagram_access_token_env</div>
                <input className="input" placeholder="INSTAGRAM_ACCESS_TOKEN_ES_SAJU" value={form.instagramAccessTokenEnv} onChange={e => setForm(f => ({ ...f, instagramAccessTokenEnv: e.target.value }))} />
              </div>
              <div className="field">
                <div className="field-label">instagram_business_account_id_env</div>
                <input className="input" placeholder="INSTAGRAM_BUSINESS_ACCOUNT_ID_ES_SAJU" value={form.instagramBusinessAccountIdEnv} onChange={e => setForm(f => ({ ...f, instagramBusinessAccountIdEnv: e.target.value }))} />
              </div>
            </div>
            <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
              <button type="button" className="btn" onClick={() => { setOpen(false); resetForm(); }} disabled={saving}>취소</button>
              <button type="submit" className="btn primary" disabled={saving}>{saving ? '저장 중...' : '저장'}</button>
            </div>
          </form>
        </div>
      )}

      <div style={{display:'grid', gridTemplateColumns:'repeat(auto-fill, minmax(320px, 1fr))', gap:12}}>
        {ACCOUNTS.map(acc => (
          <div key={acc.id} className="card">
            <div style={{padding:16}}>
              <div style={{display:'flex', alignItems:'center', gap:10, marginBottom:14}}>
                <AccountAvatar acc={acc} size={40}/>
                <div style={{flex:1, minWidth:0}}>
                  <div style={{fontSize:13.5, fontWeight:600, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap'}}>{acc.handle}</div>
                  <div style={{fontSize:11, color:'var(--fg-subtle)', fontFamily:'var(--font-mono)'}}>{acc.locale} · {acc.status}</div>
                </div>
                <button type="button" className="btn ghost icon" onClick={() => editAccount(acc)} title="계정 수정"><Icon name="more" size={14}/></button>
              </div>
              <div style={{display:'grid', gridTemplateColumns:'repeat(3,1fr)', gap:8, paddingBottom:12, borderBottom:'1px solid var(--border-subtle)'}}>
                <div><div style={{fontSize:10.5, color:'var(--fg-subtle)'}}>오늘</div><div className="mono" style={{fontSize:17, marginTop:2}}>{acc.today}</div></div>
                <div><div style={{fontSize:10.5, color:'var(--fg-subtle)'}}>예약</div><div className="mono" style={{fontSize:17, marginTop:2}}>{acc.scheduled}</div></div>
                <div><div style={{fontSize:10.5, color:'var(--fg-subtle)'}}>오류</div><div className="mono" style={{fontSize:17, marginTop:2, color:acc.errors>0?'var(--status-failed-fg)':'inherit'}}>{acc.errors}</div></div>
              </div>
              <div style={{paddingTop:12, fontSize:11, color:'var(--fg-subtle)', display:'flex', justifyContent:'space-between', alignItems:'center', gap:8}}>
                <span>토큰 만료 <span className="mono" style={{color:'var(--fg-muted)'}}>D-42</span></span>
                <button type="button" className="btn sm" onClick={() => editAccount(acc)}><Icon name="edit" size={12}/>수정</button>
              </div>
            </div>
          </div>
        ))}

        <div className="card" onClick={openNewAccount} style={{border:'1px dashed var(--border)', display:'flex', alignItems:'center', justifyContent:'center', minHeight:160, cursor:'pointer', color:'var(--fg-subtle)'}}>
          <div style={{textAlign:'center'}}>
            <Icon name="plus" size={18}/>
            <div style={{marginTop:6, fontSize:12}}>Threads 계정 연결</div>
          </div>
        </div>
      </div>
    </>
  );
}

function PostDetailDrawer({ postId, onClose }) {
  const { POSTS, ACCOUNTS, ZODIAC, CATEGORIES } = window.SAJU;
  const p = POSTS.find(x=>x.id===postId);
  const [draftEn, setDraftEn] = React.useState('');
  const [draftKo, setDraftKo] = React.useState('');
  const [saving, setSaving] = React.useState(false);

  React.useEffect(() => {
    if (!p) return;
    setDraftEn(packDraftThreadText(p.en || ''));
    setDraftKo(packDraftThreadText(p.body || ''));
  }, [p?.id, p?.en, p?.body]);

  if (!p) return null;
  const acc = ACCOUNTS.find(a=>a.id===p.account) || { handle: 'Unknown account', locale: 'threads', color: '#84cc16' };
  const z = ZODIAC.find(x=>x.key===p.zodiac) || { emoji:'🐷', ko:'돼지띠' };
  const cat = CATEGORIES.find(c=>c.key===p.category) || { icon:'✨', ko:'전체 흐름' };
  const isEditable = p.status !== 'published';
  const originalEn = packDraftThreadText(p.en || '');
  const originalKo = packDraftThreadText(p.body || '');
  const cleanDraftEn = packDraftThreadText(draftEn);
  const cleanDraftKo = packDraftThreadText(draftKo);
  const replyCount = countDraftReplies(cleanDraftEn);
  const isDirty = cleanDraftEn !== originalEn || cleanDraftKo !== originalKo;

  function formatPromptDate(value) {
    const date = value ? new Date(value) : new Date();
    const yyyy = date.getFullYear();
    const mm = String(date.getMonth() + 1).padStart(2, '0');
    const dd = String(date.getDate()).padStart(2, '0');
    const hh = String(date.getHours()).padStart(2, '0');
    const min = String(date.getMinutes()).padStart(2, '0');
    return `${yyyy}-${mm}-${dd} ${hh}:${min}`;
  }

  async function runAction(action, extra = {}, successMessage) {
    const res = await fetch('/api/admin/social-posts', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ postId: p.id, action, ...extra }),
    });
    const data = await res.json().catch(() => null);
    if (!res.ok || data?.error) throw new Error(data?.error || '작업 처리 실패');
    await window.refreshSajuData?.();
    if (successMessage) alert(successMessage);
    return data;
  }

  async function handleSave() {
    if (!isDirty) return;
    if (!draftEn.trim()) {
      alert('영어 원본 내용을 입력해 주세요.');
      return;
    }
    setSaving(true);
    try {
      await runAction('update', {
        content: cleanDraftEn,
        translation: cleanDraftKo,
      }, '수정이 저장되었습니다.');
    } catch (error) {
      alert(error?.message || '저장 실패');
    } finally {
      setSaving(false);
    }
  }

  async function handleCancelPost() {
    if (!confirm('취소하시겠습니까?')) return;
    setSaving(true);
    try {
      await runAction('cancel', {}, '게시글이 취소되었습니다.');
      onClose?.();
    } catch (error) {
      alert(error?.message || '취소 실패');
    } finally {
      setSaving(false);
    }
  }

  async function handleDeletePost() {
    if (!confirm('삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.')) return;
    setSaving(true);
    try {
      await runAction('delete', {}, '게시글이 삭제되었습니다.');
      onClose?.();
    } catch (error) {
      alert(error?.message || '삭제 실패');
    } finally {
      setSaving(false);
    }
  }

  async function handleReschedule() {
    const input = prompt('재예약 시간을 입력해 주세요. 예: 2026-04-24 20:30', formatPromptDate(p.scheduledAt));
    if (!input) return;
    const parsed = new Date(input.replace(' ', 'T'));
    if (Number.isNaN(parsed.getTime())) {
      alert('시간 형식이 올바르지 않습니다. 예: 2026-04-24 20:30');
      return;
    }

    setSaving(true);
    try {
      if (isDirty) {
        await runAction('update', { content: cleanDraftEn, translation: cleanDraftKo });
      }
      await runAction('schedule', { scheduledFor: parsed.toISOString() }, '재예약이 완료되었습니다.');
      onClose?.();
    } catch (error) {
      alert(error?.message || '재예약 실패');
    } finally {
      setSaving(false);
    }
  }

  async function handlePublishNow() {
    if (!confirm('즉시 발행하시겠습니까?')) return;
    setSaving(true);
    try {
      if (isDirty) {
        await runAction('update', { content: cleanDraftEn, translation: cleanDraftKo });
      }
      await runAction('publish', {}, 'Threads에 즉시 발행되었습니다.');
      onClose?.();
    } catch (error) {
      alert(error?.message || '즉시 발행 실패');
    } finally {
      setSaving(false);
    }
  }

  return (
    <div style={{position:'fixed', inset:0, zIndex:50, background:'rgba(0,0,0,0.5)'}} onClick={onClose}>
      <div style={{position:'absolute', top:0, right:0, bottom:0, width:560, background:'var(--bg-canvas)', borderLeft:'1px solid var(--border)', overflowY:'auto'}} onClick={e=>e.stopPropagation()}>
        <div style={{padding:'14px 20px', borderBottom:'1px solid var(--border-subtle)', display:'flex', alignItems:'center', gap:10}}>
          <span className="mono" style={{color:'var(--fg-subtle)', fontSize:11}}>{p.id}</span>
          <Badge status={p.status}/>
          <button className="btn ghost icon" style={{marginLeft:'auto'}} onClick={onClose}><Icon name="x" size={14}/></button>
        </div>

        <div style={{padding:20}}>
          <div style={{display:'flex', alignItems:'center', gap:10, marginBottom:18}}>
            <AccountAvatar acc={acc} size={36}/>
            <div>
              <div style={{fontSize:13.5, fontWeight:600}}>{acc.handle}</div>
              <div style={{fontSize:11, color:'var(--fg-subtle)'}}>{acc.locale} · 예약 <span className="mono">{fmtTime(p.scheduledAt)}</span> ({fmtRelative(p.scheduledAt)})</div>
            </div>
          </div>

          <div style={{marginBottom:18}}>
            <div style={{fontSize:11.5, color:'var(--fg-subtle)', marginBottom:6}}>상태 플로우</div>
            <StatusFlow current={p.status}/>
          </div>

          <div style={{display:'flex', gap:6, marginBottom:16, flexWrap:'wrap'}}>
            <span className="chip zodiac-chip"><span className="zodiac-ico">{z.emoji}</span><span>{z.ko}</span></span>
            <span className="chip">{cat?.icon} {cat?.ko}</span>
            <span className="chip">{p.type==='day'?'☀︎ 낮 포스팅':'☾ 밤 포스팅'}</span>
            <span className="chip mono">{cleanDraftEn.length} chars · {replyCount || 1} replies</span>
          </div>

          <div className="field" style={{marginBottom:14}}>
            <div className="field-label">영어 원본 <span className="mono" style={{color:'var(--fg-faint)'}}>{cleanDraftEn.length}/500 · {replyCount || 1} replies</span></div>
            <textarea
              className="input"
              value={draftEn}
              onChange={(e)=>setDraftEn(e.target.value)}
              disabled={!isEditable || saving}
              style={{minHeight:84, resize:'vertical', lineHeight:1.55}}
            />
          </div>
          <div className="field" style={{marginBottom:18}}>
            <div className="field-label">한국어 번역 (확인용)</div>
            <textarea
              className="input"
              value={draftKo}
              onChange={(e)=>setDraftKo(e.target.value)}
              disabled={!isEditable || saving}
              style={{minHeight:84, resize:'vertical', lineHeight:1.55}}
            />
          </div>

          {p.error && (
            <div style={{background:'var(--status-failed-bg)', padding:'10px 12px', borderRadius:'var(--r-md)', fontSize:12, color:'var(--status-failed-fg)', marginBottom:14, display:'flex', alignItems:'center', gap:8}}>
              <Icon name="alert" size={14}/>
              <div><strong>게시 실패</strong><div style={{fontFamily:'var(--font-mono)', fontSize:11, marginTop:2, color:'var(--fg-muted)'}}>{p.error}</div></div>
            </div>
          )}
          {p.holdReason && (
            <div style={{background:'var(--status-held-bg)', padding:'10px 12px', borderRadius:'var(--r-md)', fontSize:12, color:'var(--status-held-fg)', marginBottom:14}}>
              <strong>수동 검토 보류</strong><div style={{fontSize:11, marginTop:2, color:'var(--fg-muted)'}}>{p.holdReason}</div>
            </div>
          )}
          {p.metrics && (
            <div style={{display:'grid', gridTemplateColumns:'repeat(3,1fr)', gap:10, marginBottom:14}}>
              <div className="card" style={{padding:12}}><div style={{fontSize:10.5, color:'var(--fg-subtle)'}}>조회</div><div className="mono" style={{fontSize:18, marginTop:2}}>{p.metrics.views.toLocaleString()}</div></div>
              <div className="card" style={{padding:12}}><div style={{fontSize:10.5, color:'var(--fg-subtle)'}}>좋아요</div><div className="mono" style={{fontSize:18, marginTop:2}}>{p.metrics.likes.toLocaleString()}</div></div>
              <div className="card" style={{padding:12}}><div style={{fontSize:10.5, color:'var(--fg-subtle)'}}>답글</div><div className="mono" style={{fontSize:18, marginTop:2}}>{p.metrics.replies}</div></div>
            </div>
          )}

          <div style={{display:'flex', gap:8, paddingTop:8, borderTop:'1px solid var(--border-subtle)', flexWrap:'wrap'}}>
            {isEditable && (
              <button className="btn" onClick={handleSave} disabled={!isDirty || saving}>
                <Icon name="edit" size={13}/>{saving ? '저장 중...' : '수정 저장'}
              </button>
            )}
            {(p.status==='pending' || p.status==='approved') && <>
              <button className="btn" onClick={handleReschedule} disabled={saving}><Icon name="edit" size={13}/>예약</button>
              <button className="btn primary" onClick={handlePublishNow} disabled={saving}><Icon name="send" size={13}/>즉시 발행</button>
            </>}
            {p.status==='scheduled' && <>
              <button className="btn primary" onClick={handlePublishNow} disabled={saving}><Icon name="send" size={13}/>즉시 발행</button>
              <button className="btn" onClick={handleReschedule} disabled={saving}><Icon name="edit" size={13}/>재예약</button>
              <button className="btn danger" onClick={handleCancelPost} disabled={saving}><Icon name="trash" size={13}/>취소</button>
            </>}
            {p.status==='published' && <><button className="btn"><Icon name="eye" size={13}/>Threads에서 보기</button></>}
            {p.status!=='published' && <button className="btn danger" onClick={handleDeletePost} disabled={saving}><Icon name="trash" size={13}/>삭제</button>}
          </div>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { CommentsPage, AccountsPage, PostDetailDrawer });
