// ============ shared components ============
const { useState, useEffect, useMemo, useRef, Fragment } = React;

// --- Icons (inline SVG, minimal stroke style) ---
// each entry is an array of shapes; each shape is ['tag', attrsObjOrPathString]
const ICON_DATA = {
  home:      [['path', 'M3 11l9-7 9 7v9a1 1 0 01-1 1h-5v-6h-6v6H4a1 1 0 01-1-1z']],
  upload:    [['path', 'M12 16V4'], ['path', 'M7 9l5-5 5 5'], ['path', 'M5 20h14']],
  gallery:   [['rect', {x:3, y:3, width:7, height:7, rx:1.5}], ['rect', {x:14, y:3, width:7, height:7, rx:1.5}], ['rect', {x:3, y:14, width:7, height:7, rx:1.5}], ['rect', {x:14, y:14, width:7, height:7, rx:1.5}]],
  user:      [['circle', {cx:12, cy:8, r:4}], ['path', 'M4 21c1-4 4-6 8-6s7 2 8 6']],
  users:     [['circle', {cx:9, cy:8, r:4}], ['path', 'M2 21c0-4 3-6 7-6s7 2 7 6'], ['circle', {cx:17, cy:6, r:3}], ['path', 'M22 18c0-3-2-5-5-5']],
  grid:      [['rect', {x:3, y:3, width:18, height:18, rx:2}], ['path', 'M3 12h18M12 3v18']],
  comment:   [['path', 'M21 15a2 2 0 01-2 2H8l-5 4V5a2 2 0 012-2h14a2 2 0 012 2z']],
  settings:  [['circle', {cx:12, cy:12, r:3}], ['path', 'M19.4 15a1.7 1.7 0 00.3 1.8l.1.1a2 2 0 11-2.8 2.8l-.1-.1a1.7 1.7 0 00-1.8-.3 1.7 1.7 0 00-1 1.5V21a2 2 0 11-4 0v-.1a1.7 1.7 0 00-1.1-1.5 1.7 1.7 0 00-1.8.3l-.1.1a2 2 0 11-2.8-2.8l.1-.1a1.7 1.7 0 00.3-1.8 1.7 1.7 0 00-1.5-1H3a2 2 0 110-4h.1a1.7 1.7 0 001.5-1.1 1.7 1.7 0 00-.3-1.8l-.1-.1a2 2 0 112.8-2.8l.1.1a1.7 1.7 0 001.8.3H9a1.7 1.7 0 001-1.5V3a2 2 0 114 0v.1a1.7 1.7 0 001 1.5 1.7 1.7 0 001.8-.3l.1-.1a2 2 0 112.8 2.8l-.1.1a1.7 1.7 0 00-.3 1.8V9c.5.2 1 .7 1.5 1H21a2 2 0 110 4h-.1a1.7 1.7 0 00-1.5 1z']],
  plus:      [['path', 'M12 5v14'], ['path', 'M5 12h14']],
  search:    [['circle', {cx:11, cy:11, r:7}], ['path', 'M21 21l-4-4']],
  bell:      [['path', 'M6 8a6 6 0 0112 0c0 7 3 9 3 9H3s3-2 3-9'], ['path', 'M10 21a2 2 0 004 0']],
  heart:     [['path', 'M20.8 8.6a5 5 0 00-8.8-3.2A5 5 0 003.2 8.6c0 3.4 4 6.4 8.8 11.4 4.8-5 8.8-8 8.8-11.4z']],
  chat:      [['path', 'M21 12a8 8 0 11-3.4-6.6L21 4l-1.4 3.4A8 8 0 0121 12z']],
  star:      [['path', 'M12 3l2.6 5.7 6.4.6-4.8 4.3 1.4 6.4L12 17l-5.6 3 1.4-6.4L3 9.3l6.4-.6z']],
  arrow:     [['path', 'M5 12h14'], ['path', 'M13 5l7 7-7 7']],
  arrowLeft: [['path', 'M19 12H5'], ['path', 'M11 19l-7-7 7-7']],
  folder:    [['path', 'M3 6a2 2 0 012-2h4l2 2h8a2 2 0 012 2v9a2 2 0 01-2 2H5a2 2 0 01-2-2z']],
  file:      [['path', 'M14 3H6a2 2 0 00-2 2v14a2 2 0 002 2h12a2 2 0 002-2V9z'], ['path', 'M14 3v6h6']],
  edit:      [['path', 'M11 4H5a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-6'], ['path', 'M18 2l4 4-12 12H6v-4z']],
  trash:     [['path', 'M3 6h18'], ['path', 'M19 6l-1 14a2 2 0 01-2 2H8a2 2 0 01-2-2L5 6'], ['path', 'M10 11v6M14 11v6'], ['path', 'M9 6V4a2 2 0 012-2h2a2 2 0 012 2v2']],
  logout:    [['path', 'M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4'], ['path', 'M16 17l5-5-5-5'], ['path', 'M21 12H9']],
  check:     [['path', 'M20 6L9 17l-5-5']],
  x:         [['path', 'M18 6L6 18'], ['path', 'M6 6l12 12']],
  eye:       [['path', 'M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z'], ['circle', {cx:12, cy:12, r:3}]],
  eyeOff:    [['path', 'M17.94 17.94A10 10 0 0112 20c-7 0-11-8-11-8a18 18 0 014.06-5.06'], ['path', 'M9.9 4.24A10 10 0 0112 4c7 0 11 8 11 8a18 18 0 01-2.16 3.19'], ['path', 'M14.12 14.12a3 3 0 11-4.24-4.24'], ['path', 'M1 1l22 22']],
  download:  [['path', 'M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4'], ['path', 'M7 10l5 5 5-5'], ['path', 'M12 15V3']],
  sparkle:   [['path', 'M12 2l2 7 7 2-7 2-2 7-2-7-7-2 7-2z']],
  play:      [['path', 'M6 4l14 8-14 8z']],
  image:     [['rect', {x:3, y:3, width:18, height:18, rx:2}], ['circle', {cx:9, cy:9, r:2}], ['path', 'M21 15l-5-5L5 21']],
  menu:      [['path', 'M3 12h18'], ['path', 'M3 6h18'], ['path', 'M3 18h18']],
  clock:     [['circle', {cx:12, cy:12, r:9}], ['path', 'M12 7v5l3 2']],
  filter:    [['path', 'M4 4h16l-6 8v6l-4 2v-8z']],
  book:      [['path', 'M4 19.5A2.5 2.5 0 016.5 17H20'], ['path', 'M6.5 2H20v20H6.5A2.5 2.5 0 014 19.5v-15A2.5 2.5 0 016.5 2z']],
  palette:   [['circle', {cx:12, cy:12, r:9}], ['circle', {cx:7, cy:10, r:1}], ['circle', {cx:12, cy:7, r:1}], ['circle', {cx:17, cy:10, r:1}], ['circle', {cx:15, cy:15, r:1}], ['path', 'M12 21a3 3 0 010-6 2 2 0 002-2c0-2 2-2 4-1']],
};

const Icon = ({ name, size = 18, stroke = 1.6, ...rest }) => {
  const shapes = ICON_DATA[name] || [];
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" {...rest}>
      {shapes.map(([tag, attr], i) => {
        if (tag === 'path') return <path key={i} d={attr} />;
        if (tag === 'circle') return <circle key={i} {...attr} />;
        if (tag === 'rect') return <rect key={i} {...attr} />;
        return null;
      })}
    </svg>
  );
};

// --- Avatar ---
const Avatar = ({ person, size = 'md' }) => {
  if (!person) return null;
  const cls = `avatar ${size === 'md' ? '' : size}`;
  if (person.photo) {
    return <img src={person.photo} alt={person.name} className={cls} style={{objectFit:'cover'}} title={person.name} />;
  }
  return (
    <div className={cls} style={{ background: person.color }} title={person.name}>
      {person.initial}
    </div>
  );
};

const AvatarStack = ({ ids, max = 3, size='sm' }) => {
  const visible = ids.slice(0, max);
  const extra = ids.length - max;
  return (
    <div className="avatar-stack">
      {visible.map(id => <Avatar key={id} person={H.person(id)} size={size} />)}
      {extra > 0 && (
        <div className={`avatar ${size}`} style={{ background:'oklch(0.85 0.01 290)', color:'var(--ink)'}}>+{extra}</div>
      )}
    </div>
  );
};

// --- Work card ---
const WorkCard = ({ work, onClick }) => {
  const owners = work.owners.map(H.person);
  const isGroup = work.owners.length > 1;
  const cls = H.cls(work.classId);
  return (
    <div className="work-card" onClick={() => onClick && onClick(work)}>
      <div className="work-thumb">
        <div className={`thumb-bg ${work.thumb}`}></div>
        <div className="corner">
          <span className="type-badge">
            <span aria-hidden>{H.typeIcon(work.type)}</span>
            {H.typeLabel(work.type)}
          </span>
        </div>
        <div className="corner corner-r">
          {isGroup && <span className="type-badge group-badge">Group · {work.owners.length}</span>}
        </div>
      </div>
      <div className="meta">
        <div className="title">{work.title}</div>
        <div className="by">
          {isGroup ? (
            <>กลุ่ม · {owners.map(o => o.name.split(' ').slice(-1)[0]).join(', ')}</>
          ) : (
            <>{owners[0].name}</>
          )}
          <span className="tag-en"> · {cls.label}</span>
        </div>
        <div className="footer">
          <span className="mono">{H.fmtDate(work.date)}</span>
          <span className="stat"><Icon name="heart" size={11} /> {(work.id.charCodeAt(2)%9)+2}</span>
          <span className="stat"><Icon name="chat" size={11} /> {(work.id.charCodeAt(2)%5)+1}</span>
          {work.status === 'graded' && <span className="stat" style={{color:'var(--green-500)',marginLeft:'auto',fontWeight:600}}>✓ ตรวจแล้ว</span>}
          {work.status === 'pending' && <span className="stat" style={{color:'var(--warm-600)',marginLeft:'auto'}}>รอตรวจ</span>}
        </div>
      </div>
    </div>
  );
};

// --- TopBar ---
const TopBar = ({ titleTh, titleEn, onMenu, right }) => (
  <header className="topbar">
    <button className="menu-btn" onClick={onMenu}><Icon name="menu" size={20} /></button>
    <div>
      <h1>{titleTh}<span className="sub-en">{titleEn}</span></h1>
    </div>
    <div className="spacer"></div>
    {right}
  </header>
);

// --- Sidebar shell ---
const Sidebar = ({ items, current, onSelect, user, role, open, onLogout }) => {
  return (
    <aside className={`sidebar ${open ? 'open' : ''}`}>
      <div className="sidebar-brand">
        <div className="logo"><img src="assets/school-logo.png" alt="CMUDS-ITPC" /></div>
        <div>
          <div className="name">Art & 2D Animation</div>
          <div className="sub">CMUDS-ITPC</div>
        </div>
      </div>
      <nav className="nav-group">
        <div className="lbl">Menu</div>
        {items.map(it => (
          <button key={it.id}
            className={`nav-item ${current === it.id ? 'active' : ''}`}
            onClick={() => onSelect(it.id)}>
            <Icon name={it.icon} size={17} />
            <span>{it.label}</span>
            {it.badge && <span className="badge">{it.badge}</span>}
          </button>
        ))}
      </nav>
      <div className="sidebar-user">
        <Avatar person={user} />
        <div style={{flex:1, minWidth:0}}>
          <div className="who">{user.name}</div>
          <div className="role">{role}</div>
        </div>
        <button className="btn-ghost" style={{padding:6,borderRadius:8,color:'var(--muted)'}} onClick={onLogout} title="Sign out"><Icon name="logout" size={16} /></button>
      </div>
    </aside>
  );
};

// --- Reaction bar ---
const REACTIONS = ['❤️','👏','🎉','🔥','😂','💡'];

const ReactionBar = ({ reactions = {}, onToggle, myReactions = new Set() }) => {
  const all = { ...reactions };
  REACTIONS.forEach(r => { if (!(r in all)) all[r] = 0; });
  return (
    <div className="reactions">
      {REACTIONS.map(r => (
        <button key={r} className={`reaction ${myReactions.has(r)?'active':''}`} onClick={()=>onToggle && onToggle(r)}>
          <span>{r}</span>
          {(all[r] > 0) && <span>{all[r]}</span>}
        </button>
      ))}
    </div>
  );
};

// --- Comment ---
const StickerRow = ({ stickers=[] }) => stickers.length ? (
  <div className="sticker-row">
    {stickers.map((s,i)=>(<span key={i} className={`sticker ${i%3===0?'':(i%3===1?'purple':'green')}`}>★ {s}</span>))}
  </div>
) : null;

const CommentItem = ({ comment, depth=0 }) => {
  const person = H.person(comment.authorId);
  const [reactions, setReactions] = useState(comment.reactions || {});
  const [mine, setMine] = useState(new Set());
  const [replying, setReplying] = useState(false);
  const [replyText, setReplyText] = useState('');
  const replies = comment.replies || [];

  const toggle = async (r) => {
    const newMine = new Set(mine);
    const newReactions = { ...reactions };
    if (newMine.has(r)) { newMine.delete(r); newReactions[r] = Math.max(0, (newReactions[r] || 1) - 1); }
    else { newMine.add(r); newReactions[r] = (newReactions[r] || 0) + 1; }
    setReactions(newReactions); setMine(newMine);
    try {
      await window.DB.toggleReaction({ commentId: comment.id, emoji: r });
      if (typeof comment.__onChanged === 'function') await comment.__onChanged();
    } catch (e) { console.error(e); }
  };

  const sendReply = async () => {
    if (!replyText.trim()) return;
    try {
      await window.DB.createComment({
        workId: comment.workId,
        text: replyText,
        parentId: comment.id,
        isTeacher: !!comment.__viewerIsTeacher,
      });
      setReplyText(''); setReplying(false);
      if (typeof comment.__onChanged === 'function') await comment.__onChanged();
    } catch (e) {
      console.error(e);
      alert('ส่งข้อความตอบกลับไม่สำเร็จ: ' + (e.message || e));
    }
  };

  return (
    <div className="comment">
      <Avatar person={person} size="sm" />
      <div style={{flex:1, minWidth:0}}>
        <div className={`comment-body ${comment.isTeacher?'teacher':''}`}>
          <div className="comment-head">
            <span className="name">{person.name}</span>
            {comment.isTeacher && <span className="tag">ครู · Teacher</span>}
            <span className="when">{comment.when}</span>
          </div>
          <div className="comment-text">{comment.text}</div>
          <StickerRow stickers={comment.stickers} />
          <ReactionBar reactions={reactions} onToggle={toggle} myReactions={mine} />
          <div className="comment-actions">
            <button onClick={()=>setReplying(!replying)}><Icon name="chat" size={12} /> ตอบกลับ</button>
          </div>
        </div>
        {replying && (
          <div style={{marginTop:8, display:'flex', gap:8}}>
            <input className="input" placeholder="พิมพ์ข้อความตอบกลับ…" value={replyText} onChange={e=>setReplyText(e.target.value)}
              onKeyDown={e=>e.key==='Enter' && sendReply()} />
            <button className="btn btn-brand" onClick={sendReply}>ส่ง</button>
          </div>
        )}
        {replies.length > 0 && (
          <div className="reply-list">
            {replies.map(r => <CommentItem key={r.id} comment={r} depth={depth+1} />)}
          </div>
        )}
      </div>
    </div>
  );
};

// --- New comment composer ---
const CommentComposer = ({ asPerson, isTeacher=false, onPost }) => {
  const [text, setText] = useState('');
  const [sticker, setSticker] = useState(null);
  const stickers = ['ดีมาก','ยอดเยี่ยม','สุดยอด','พัฒนาขึ้น','สร้างสรรค์'];
  const post = () => {
    if (!text.trim() && !sticker) return;
    onPost && onPost({
      id:`c${Date.now()}`, authorId: asPerson.id, text, when:'เมื่อกี้นี้',
      isTeacher, stickers: sticker ? [sticker] : [], reactions:{},
    });
    setText(''); setSticker(null);
  };
  return (
    <div className="surface" style={{padding:14}}>
      <div className="row" style={{alignItems:'flex-start'}}>
        <Avatar person={asPerson} size="sm" />
        <div style={{flex:1, display:'flex', flexDirection:'column', gap:8}}>
          <textarea className="textarea" placeholder={isTeacher ? "เขียนคอมเมนต์ให้นักเรียน… (ภาษาไทย/English)" : "ชื่นชมหรือให้กำลังใจเพื่อน…"} value={text} onChange={e=>setText(e.target.value)} />
          <div className="row wrap" style={{gap:6}}>
            <span className="muted" style={{fontSize:11.5, marginRight:4}}>Sticker:</span>
            {stickers.map(s => (
              <button key={s} className={`sticker ${sticker===s?'':'neutral'}`}
                style={{cursor:'pointer', opacity:sticker===s?1:.7, background: sticker===s ? '' : 'oklch(0.94 0.005 290)', color: sticker===s ? '' : 'var(--ink-2)'}}
                onClick={()=>setSticker(sticker===s?null:s)}>★ {s}</button>
            ))}
          </div>
          <div className="row between">
            <span className="muted" style={{fontSize:11}}>Enter to send · Shift+Enter for newline</span>
            <button className="btn btn-brand sm" onClick={post}><Icon name="arrow" size={12} /> ส่งคอมเมนต์</button>
          </div>
        </div>
      </div>
    </div>
  );
};

// --- Modal shell ---
const Modal = ({ onClose, children, wide }) => {
  useEffect(() => {
    const h = (e) => e.key === 'Escape' && onClose && onClose();
    window.addEventListener('keydown', h); return () => window.removeEventListener('keydown', h);
  }, [onClose]);
  return (
    <div className="modal-veil" onClick={onClose}>
      <div className="modal" style={wide?{maxWidth:1100}:{}} onClick={e=>e.stopPropagation()}>{children}</div>
    </div>
  );
};

// --- Work detail (used by all roles) ---
const WorkDetail = ({ work, asPerson, role, onClose, onChanged }) => {
  const owners = work.owners.map(H.person);
  const cls = H.cls(work.classId);
  const isGroup = work.owners.length > 1;
  const [, setTick] = useState(0);
  const localComments = window.DATA.commentsByWork[work.id] || [];
  const [posting, setPosting] = useState(false);

  const refresh = async () => {
    if (onChanged) await onChanged();
    setTick(t => t + 1);
  };

  const post = async (c) => {
    if (posting) return;
    setPosting(true);
    try {
      await window.DB.createComment({
        workId: work.id,
        text: c.text,
        isTeacher: role === 'teacher',
        sticker: (c.stickers && c.stickers[0]) || null,
      });
      await refresh();
    } catch (e) {
      console.error(e);
      alert('ส่งคอมเมนต์ไม่สำเร็จ: ' + (e.message || e));
    } finally {
      setPosting(false);
    }
  };

  return (
    <Modal onClose={onClose} wide>
      <div className="modal-head">
        <span className="chip"><span aria-hidden>{H.typeIcon(work.type)}</span> {H.typeLabel(work.type)}</span>
        {isGroup && <span className="chip warm">Group · {work.owners.length} คน</span>}
        <span className="muted mono" style={{fontSize:11.5}}>{cls.label} · {H.fmtDate(work.date)}</span>
        {work.status === 'graded' && <span className="chip" style={{background:'oklch(0.95 0.05 150)', color:'oklch(0.4 0.13 150)'}}><Icon name="check" size={12} /> ครูตรวจแล้ว</span>}
        <div className="spacer" style={{flex:1}}></div>
        {role === 'teacher' && (
          <>
            <button className="btn btn-outline sm"><Icon name="edit" size={12} /> แก้ไขการส่ง</button>
          </>
        )}
        <button className="btn-ghost" style={{padding:6}} onClick={onClose}><Icon name="x" size={16} /></button>
      </div>
      <div className="modal-body" style={{gridTemplateColumns:'1.4fr 1fr'}}>
        {/* left: artwork */}
        <div style={{padding:20, background:'oklch(0.97 0.01 290)', display:'flex', flexDirection:'column', gap:14, maxHeight:'calc(90vh - 70px)', overflow:'auto'}}>
          <div style={{position:'relative', aspectRatio:'4/3', borderRadius:'var(--radius-lg)', overflow:'hidden', border:'1px solid var(--line)'}}>
            <div className={`thumb-bg ${work.thumb}`}></div>
            {work.type === 'animation' && (
              <div style={{position:'absolute', inset:0, display:'grid', placeItems:'center'}}>
                <button className="btn btn-primary lg" style={{borderRadius:99}}><Icon name="play" size={16} /> เล่นแอนิเมชัน</button>
              </div>
            )}
          </div>
          <div>
            <div style={{fontFamily:'var(--font-serif)', fontSize:32, lineHeight:1.1, letterSpacing:'-.01em'}}>{work.title}</div>
            <div className="tag-en" style={{fontSize:16, marginTop:2}}>{work.titleEn}</div>
          </div>
          <div className="row wrap" style={{gap:6}}>
            <span className="muted" style={{fontSize:12}}>เจ้าของผลงาน:</span>
            {owners.map(o => <span key={o.id} className="chip"><Avatar person={o} size="sm" style={{width:18,height:18,fontSize:9}} /> {o.name}</span>)}
          </div>
          {work.descriptionTh && (
            <p style={{margin:0, fontSize:13.5, lineHeight:1.6, color:'var(--ink-2)'}}>{work.descriptionTh}</p>
          )}
          <div className="row" style={{gap:8, marginTop:4}}>
            <button className="btn btn-outline sm"><Icon name="download" size={12} /> ดาวน์โหลด</button>
            <button className="btn btn-outline sm"><Icon name="heart" size={12} /> ถูกใจ</button>
          </div>
        </div>
        {/* right: comments */}
        <div style={{padding:20, display:'flex', flexDirection:'column', gap:14, borderLeft:'1px solid var(--line)', maxHeight:'calc(90vh - 70px)', overflow:'auto'}}>
          <div className="row between">
            <strong style={{fontSize:14}}>คอมเมนต์ <span className="muted">· Comments ({localComments.length})</span></strong>
          </div>
          <CommentComposer asPerson={asPerson} isTeacher={role==='teacher'} onPost={post} />
          <div className="comment-list">
            {localComments.length === 0 && (
              <div className="muted" style={{fontSize:13, padding:'20px 0', textAlign:'center'}}>ยังไม่มีคอมเมนต์ — เป็นคนแรกที่ให้กำลังใจ</div>
            )}
            {localComments.map(c => {
              const decorated = { ...c, __onChanged: refresh, __viewerIsTeacher: role === 'teacher' };
              decorated.replies = (c.replies || []).map(r => ({ ...r, __onChanged: refresh, __viewerIsTeacher: role === 'teacher' }));
              return <CommentItem key={c.id} comment={decorated} />;
            })}
          </div>
        </div>
      </div>
    </Modal>
  );
};

// --- Filters bar (segmented) ---
const Seg = ({ value, onChange, options }) => (
  <div className="seg">
    {options.map(o => (
      <button key={o.value} className={value===o.value?'on':''} onClick={()=>onChange(o.value)}>{o.label}</button>
    ))}
  </div>
);

// --- Empty state ---
const Empty = ({ icon='image', title='ยังไม่มีข้อมูล', sub='Empty' }) => (
  <div style={{padding:48, textAlign:'center', color:'var(--muted)'}}>
    <Icon name={icon} size={32} stroke={1.4} />
    <div style={{marginTop:10, fontWeight:600, color:'var(--ink-2)'}}>{title}</div>
    <div className="tag-en" style={{fontSize:13}}>{sub}</div>
  </div>
);

Object.assign(window, {
  Icon, Avatar, AvatarStack, WorkCard, TopBar, Sidebar,
  ReactionBar, CommentItem, CommentComposer, Modal, WorkDetail,
  Seg, Empty, REACTIONS
});
