﻿// Posts page for list / kanban / calendar views with live actions

async function runPostAction(postId, action, event, extra = {}) {
  event?.stopPropagation?.();

  if (action === 'publish' && !confirm('즉시 발행하시겠습니까?')) return;

  if (action === 'schedule' && !extra.scheduledFor) {
    const input = prompt('예약 시간을 입력해 주세요. 예: 2026-04-24 20:30');
    if (!input) return;

    const parsed = new Date(input.replace(' ', 'T'));
    if (Number.isNaN(parsed.getTime())) {
      alert('시간 형식이 올바르지 않습니다. 예: 2026-04-24 20:30');
      return;
    }

    extra = { ...extra, scheduledFor: parsed.toISOString() };
  }

  try {
    const res = await fetch('/api/admin/social-posts', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ postId, action, ...extra }),
    });
    const data = await res.json().catch(() => null);
    if (!res.ok || data?.error) throw new Error(data?.error || '게시글 처리 실패');
    await window.refreshSajuData?.();
  } catch (error) {
    alert(error?.message || '게시글 처리 실패');
  }
}

function PostsPage({ state, setState }) {
  const { ACCOUNTS, POSTS, ZODIAC } = window.SAJU;
  const [view, setView] = React.useState(state.postView || 'list');
  const [filter, setFilter] = React.useState(state.postFilter || 'all');
  const [acctFilter, setAcctFilter] = React.useState(state.selectedAccount || 'all');
  const [search, setSearch] = React.useState('');

  React.useEffect(()=>{ if (state.postView) setView(state.postView); }, [state.postView]);
  React.useEffect(()=>{ if (state.postFilter) setFilter(state.postFilter); }, [state.postFilter]);

  const counts = {
    all: POSTS.length,
    pending: POSTS.filter(p=>p.status==='pending').length,
    approved: POSTS.filter(p=>p.status==='approved').length,
    scheduled: POSTS.filter(p=>p.status==='scheduled').length,
    published: POSTS.filter(p=>p.status==='published').length,
    failed: POSTS.filter(p=>p.status==='failed').length,
    held: POSTS.filter(p=>p.status==='held').length,
  };

  const filtered = POSTS.filter(p => {
    if (filter !== 'all' && p.status !== filter) return false;
    if (acctFilter !== 'all' && p.account !== acctFilter) return false;
    if (search && !`${p.body || ''} ${p.title || ''}`.toLowerCase().includes(search.toLowerCase())) return false;
    return true;
  });

  const filters = [
    { key: 'all', label: '전체' },
    { key: 'pending', label: '대기' },
    { key: 'approved', label: '승인' },
    { key: 'scheduled', label: '예약됨' },
    { key: 'published', label: '게시완료' },
    { key: 'failed', label: '실패' },
    { key: 'held', label: '보류' },
  ];

  return (
    <>
      <div className="page-header">
        <div>
          <h1 className="page-title">예약 게시글</h1>
          <div className="page-subtitle">기본 생성 글은 대기 상태로 두고, 필요할 때 예약 또는 즉시발행합니다.</div>
        </div>
        <div style={{display:'flex',gap:8}}>
          <div className="view-toggle">
            <button className={view==='list'?'active':''} onClick={()=>setView('list')}><Icon name="list" size={12}/>리스트</button>
            <button className={view==='kanban'?'active':''} onClick={()=>setView('kanban')}><Icon name="columns" size={12}/>칸반</button>
            <button className={view==='calendar'?'active':''} onClick={()=>setView('calendar')}><Icon name="calendar" size={12}/>캘린더</button>
          </div>
          <button className="btn primary"><Icon name="plus" size={13}/>새 게시글</button>
        </div>
      </div>

      <div className="filters">
        {filters.map(f => (
          <button key={f.key} className={`filter-tab ${filter===f.key?'active':''}`} onClick={()=>setFilter(f.key)}>
            {f.key !== 'all' && <span className={`badge ${f.key}`} style={{padding:0,background:'transparent'}}><span className="dot"/></span>}
            <span>{f.label}</span>
            <span className="count">{counts[f.key]}</span>
          </button>
        ))}

        <div style={{marginLeft:'auto', display:'flex', gap:8, alignItems:'center'}}>
          <select className="select" style={{width:'auto', padding:'5px 10px'}} 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>
          <div className="search" style={{marginLeft:0, minWidth:200}}>
            <Icon name="search" size={13}/>
            <input placeholder="내용/ID 검색..." value={search} onChange={e=>setSearch(e.target.value)}/>
          </div>
        </div>
      </div>

      {view === 'list' && <PostListView posts={filtered} onSelect={id=>setState(s=>({...s, selectedPost:id}))}/>}
      {view === 'kanban' && <PostKanbanView posts={filtered} onSelect={id=>setState(s=>({...s, selectedPost:id}))}/>}
      {view === 'calendar' && <PostCalendarView posts={filtered} onSelect={id=>setState(s=>({...s, selectedPost:id}))}/>}
    </>
  );
}

function PostListView({ posts, onSelect }) {
  const { ACCOUNTS, ZODIAC, CATEGORIES } = window.SAJU;
  const [checked, setChecked] = React.useState({});
  const allChecked = posts.length > 0 && posts.every(p => checked[p.id]);
  const checkedIds = posts.filter(p => checked[p.id]).map(p => p.id);

  const toggleAll = () => {
    if (allChecked) setChecked({});
    else setChecked(Object.fromEntries(posts.map(p => [p.id, true])));
  };

  const deleteSelected = async () => {
    if (checkedIds.length === 0) return;
    if (!confirm(`선택한 ${checkedIds.length}개 게시글을 삭제하시겠습니까?`)) return;
    try {
      await Promise.all(checkedIds.map(id =>
        fetch('/api/admin/social-posts', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ postId: id, action: 'delete' }),
        })
      ));
      setChecked({});
      await window.refreshSajuData?.();
    } catch (e) {
      alert('삭제 중 오류가 발생했습니다: ' + e.message);
    }
  };

  return (
    <div className="card" style={{overflow:'hidden'}}>
      {checkedIds.length > 0 && (
        <div style={{display:'flex', alignItems:'center', gap:12, padding:'8px 16px', background:'var(--bg-2)', borderBottom:'1px solid var(--border)'}}>
          <span style={{fontSize:13, color:'var(--fg-muted)'}}>{checkedIds.length}개 선택됨</span>
          <button className="btn sm" style={{color:'var(--red,#e05)',borderColor:'var(--red,#e05)'}} onClick={deleteSelected}>
            <Icon name="trash" size={12}/>선택 삭제
          </button>
        </div>
      )}
      <table className="table">
        <thead>
          <tr>
            <th style={{width:36}}><input type="checkbox" checked={allChecked} onChange={toggleAll}/></th>
            <th style={{width:80}}>ID</th>
            <th>내용</th>
            <th style={{width:160}}>계정</th>
            <th style={{width:130}}>예약 시간</th>
            <th style={{width:110}}>상태</th>
            <th style={{width:180}}></th>
          </tr>
        </thead>
        <tbody>
          {posts.map(p => {
            const acc = ACCOUNTS.find(a=>a.id===p.account) || { handle: 'unknown' };
            const z = ZODIAC.find(x=>x.key===p.zodiac);
            const cat = CATEGORIES.find(c=>c.key===p.category);
            return (
              <tr key={p.id} onClick={()=>onSelect(p.id)} style={{cursor:'pointer', background: checked[p.id] ? 'var(--bg-2)' : ''}}>
                <td><input type="checkbox" checked={!!checked[p.id]} onChange={e=>{e.stopPropagation(); setChecked(s=>({...s, [p.id]: e.target.checked}))}} onClick={e=>e.stopPropagation()}/></td>
                <td className="mono" style={{color:'var(--fg-subtle)', fontSize:11}}>{p.id}</td>
                <td>
                  <div style={{display:'flex',alignItems:'center',gap:8, marginBottom:3}}>
                    <span style={{fontSize:14}}>{z?.emoji}</span>
                    <span style={{color:'var(--fg-muted)', fontSize:11}}>
                      {p.type==='day' ? '낮' : '밤'} · {cat?.ko}
                    </span>
                  </div>
                  <div style={{fontSize:12.5, color:'var(--fg)', overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap', maxWidth:520}}>{p.body}</div>
                </td>
                <td>
                  <div style={{display:'flex',alignItems:'center',gap:6}}>
                    <AccountAvatar acc={acc} size={18}/>
                    <span style={{fontSize:11.5, color:'var(--fg-muted)'}}>{acc.handle}</span>
                  </div>
                </td>
                <td className="mono" style={{fontSize:11.5, color:'var(--fg-muted)'}}>
                  {fmtTime(p.scheduledAt)}
                  <div style={{color:'var(--fg-faint)', fontSize:10.5, marginTop:2}}>{fmtRelative(p.scheduledAt)}</div>
                </td>
                <td><Badge status={p.status}/></td>
                <td>
                  <div style={{display:'flex',gap:4,justifyContent:'flex-end', flexWrap:'wrap'}}>
                    {p.status==='pending' && <>
                      <button className="btn sm" onClick={e=>runPostAction(p.id,'schedule',e)}>예약</button>
                      <button className="btn sm primary" onClick={e=>runPostAction(p.id,'publish',e)}>즉시발행</button>
                    </>}
                    {p.status==='approved' && <>
                      <button className="btn sm" onClick={e=>runPostAction(p.id,'schedule',e)}>예약</button>
                      <button className="btn sm primary" onClick={e=>runPostAction(p.id,'publish',e)}>즉시발행</button>
                    </>}
                    {p.status==='scheduled' && <button className="btn sm primary" onClick={e=>runPostAction(p.id,'publish',e)}>즉시발행</button>}
                    {p.status==='published' && <button className="btn ghost sm" onClick={e=>e.stopPropagation()}><Icon name="eye" size={11}/>보기</button>}
                    {p.status==='failed' && <button className="btn sm" onClick={e=>runPostAction(p.id,'publish',e)}><Icon name="refresh" size={11}/>재시도</button>}
                    {p.status==='held' && <button className="btn sm" onClick={e=>e.stopPropagation()}>검토</button>}
                    <button className="btn ghost icon sm" onClick={e=>e.stopPropagation()}><Icon name="more" size={13}/></button>
                  </div>
                </td>
              </tr>
            );
          })}
          {posts.length === 0 && (
            <tr><td colSpan="7"><div className="empty">조건에 해당하는 게시글이 없습니다</div></td></tr>
          )}
        </tbody>
      </table>
    </div>
  );
}

function PostKanbanView({ posts, onSelect }) {
  const { ACCOUNTS, ZODIAC } = window.SAJU;
  const cols = [
    { key:'pending', label:'대기', hint:'생성 직후 상태' },
    { key:'approved', label:'승인', hint:'즉시발행 또는 예약 가능' },
    { key:'scheduled', label:'예약됨', hint:'예약 시간이 저장된 상태' },
    { key:'published', label:'게시완료', hint:'Threads 게시 완료' },
  ];
  return (
    <div className="kanban">
      {cols.map(col => {
        const items = posts.filter(p => p.status === col.key);
        return (
          <div key={col.key} className="kanban-col">
            <div className="kanban-head">
              <Badge status={col.key}/>
              <span style={{color:'var(--fg-subtle)', fontSize:11}}>{col.hint}</span>
              <span className="count">{items.length}</span>
            </div>
            <div className="kanban-body">
              {items.map(p => {
                const acc = ACCOUNTS.find(a=>a.id===p.account) || { handle: 'unknown' };
                const z = ZODIAC.find(x=>x.key===p.zodiac);
                return (
                  <div key={p.id} className="kanban-card" onClick={()=>onSelect(p.id)}>
                    <div className="kanban-card-head">
                      <span style={{fontSize:14}}>{z?.emoji}</span>
                      <span style={{color:'var(--fg-muted)'}}>{p.type==='day'?'낮':'밤'}</span>
                      <AccountAvatar acc={acc} size={14}/>
                      <span className="mono" style={{marginLeft:'auto', fontSize:10}}>{p.id}</span>
                    </div>
                    <div className="kanban-card-text">{p.body}</div>
                    <div className="kanban-card-foot">
                      <span>{fmtTime(p.scheduledAt)}</span>
                      <span>{fmtRelative(p.scheduledAt)}</span>
                    </div>
                  </div>
                );
              })}
              {items.length === 0 && <div style={{color:'var(--fg-faint)', fontSize:11, textAlign:'center', padding:'24px 0'}}>없음</div>}
            </div>
          </div>
        );
      })}
    </div>
  );
}

function PostCalendarView({ posts, onSelect }) {
  const { ACCOUNTS, ZODIAC } = window.SAJU;
  const days = [];
  for (let i = 0; i < 3; i++) days.push({ dim: true, day: 28 + i });
  for (let i = 1; i <= 30; i++) days.push({ dim: false, day: i });
  while (days.length % 7 !== 0) days.push({ dim: true, day: days.length - 30 });

  const byDay = {};
  posts.forEach(p => {
    const d = new Date(p.scheduledAt);
    if (d.getMonth() !== 3) return;
    const k = d.getDate();
    (byDay[k] = byDay[k] || []).push(p);
  });

  const today = 20;

  return (
    <div className="card">
      <div className="card-header">
        <div>
          <div className="card-title">2026년 4월</div>
          <div className="card-sub">예약 게시 시간 분포</div>
        </div>
      </div>
      <div style={{padding:14}}>
        <div className="calendar">
          {['일','월','화','수','목','금','토'].map(d => <div key={d} className="cal-head">{d}</div>)}
          {days.map((c, i) => {
            const items = !c.dim ? (byDay[c.day] || []) : [];
            return (
              <div key={i} className={`cal-cell ${c.dim?'dim':''} ${c.day===today && !c.dim?'today':''}`}>
                <div className="cal-num">{c.day}</div>
                {items.slice(0,3).map(p => {
                  const acc = ACCOUNTS.find(a=>a.id===p.account) || { handle: 'acct' };
                  const z = ZODIAC.find(x=>x.key===p.zodiac);
                  const hh = String(new Date(p.scheduledAt).getHours()).padStart(2,'0');
                  const mm = String(new Date(p.scheduledAt).getMinutes()).padStart(2,'0');
                  return (
                    <span key={p.id} className={`cal-chip ${p.status}`} onClick={()=>onSelect(p.id)}>
                      <span className="mono">{hh}:{mm}</span> {z?.emoji} {acc.handle.replace('@saju.oracle.','').replace('@korea.saju.oracle','kr').slice(0,4)}
                    </span>
                  );
                })}
                {items.length > 3 && <div style={{fontSize:10, color:'var(--fg-subtle)', marginTop:2}}>+{items.length-3}개</div>}
              </div>
            );
          })}
        </div>
      </div>
    </div>
  );
}

window.PostsPage = PostsPage;
