// HelperMatch Admin — Phase B3: Videos (PLATFORM + SELF moderation)

const SEGMENT_LABEL = {
  INTRO: '自我介紹', COOKING: '烹飪', CLEANING: '清潔',
  LANGUAGE: '語言', ELDERCARE: '長輩照護', CHILDCARE: '育兒', HOUSEWORK: '家務',
};
const SEGMENT_COLORS = {
  INTRO: '#3B82F6', COOKING: '#F59E0B', CLEANING: '#10B981',
  LANGUAGE: '#8B5CF6', ELDERCARE: '#EF4444', CHILDCARE: '#EC4899', HOUSEWORK: '#14B8A6',
};

// ==== Thumbnail ====
const VideoThumb = ({ v, big }) => {
  const color = SEGMENT_COLORS[v.segment] || '#475569';
  return (
    <div style={{
      aspectRatio:'16/9',
      background: `linear-gradient(135deg, ${color}cc, ${color}66), radial-gradient(circle at 30% 40%, rgba(255,255,255,0.12), transparent 60%)`,
      position:'relative', display:'grid', placeItems:'center', borderRadius: big ? 8 : 4, overflow:'hidden',
    }}>
      {/* Subtle texture */}
      <div style={{position:'absolute',inset:0,backgroundImage:'repeating-linear-gradient(45deg, transparent 0 6px, rgba(255,255,255,0.03) 6px 7px)'}}/>
      {/* Play */}
      <div style={{width: big?64:38, height: big?64:38, borderRadius:'50%', background:'rgba(255,255,255,0.22)', display:'grid', placeItems:'center', color:'#fff', backdropFilter:'blur(4px)'}}>
        <AIcon name="play" size={big?22:14}/>
      </div>
      {/* Duration */}
      <div style={{position:'absolute',bottom:6,right:6,background:'rgba(0,0,0,0.7)',color:'#fff',fontSize:10,fontFamily:'var(--a-mono)',padding:'1px 5px',borderRadius:3}}>{v.duration}</div>
      {/* Source badge */}
      <div style={{position:'absolute',top:6,left:6}}>
        <span className={`a-badge ${v.source==='PLATFORM'?'a-badge-primary':'a-badge-violet'}`} style={{fontSize:9,padding:'1px 5px'}}>{v.source}</span>
      </div>
    </div>
  );
};

// ==== Main page ====
const VideosPageReal = () => {
  const { t } = (window.useI18n ? window.useI18n() : { t: (k)=>k });
  const { user } = useAuth();
  const toast = useToast();
  const [tab, setTab] = uS(() => {
    const m = window.location.hash.match(/tab=([A-Z_]+)/);
    return m ? m[1] : 'SELF_PENDING';
  });
  const [q, setQ] = uS('');
  const [segmentFilter, setSegmentFilter] = uS('');
  const [sortBy, setSortBy] = uS('newest');
  const [selected, setSelected] = uS(new Set());
  const [openId, setOpenId] = uS(null);
  const [rejectBulk, setRejectBulk] = uS(false);
  const [showUpload, setShowUpload] = uS(false);
  const [vids, setVids] = uS(() => ADMIN.videos.map(v => ({ ...v })));

  const tabs = [
    { key:'SELF_PENDING',  label:'SELF 待審', n: vids.filter(v => v.source==='SELF' && v.moderationStatus==='PENDING').length },
    { key:'SELF_APPROVED', label:'SELF 已核准', n: vids.filter(v => v.source==='SELF' && v.moderationStatus==='APPROVED').length },
    { key:'SELF_REJECTED', label:'SELF 已駁回', n: vids.filter(v => v.source==='SELF' && v.moderationStatus==='REJECTED').length },
    { key:'PLATFORM',      label:'PLATFORM',   n: vids.filter(v => v.source==='PLATFORM').length },
    { key:'ALL',           label:'全部',        n: vids.length },
  ];

  const filtered = uM(() => {
    let list = vids;
    if (tab === 'SELF_PENDING')       list = list.filter(v => v.source==='SELF' && v.moderationStatus==='PENDING');
    else if (tab === 'SELF_APPROVED') list = list.filter(v => v.source==='SELF' && v.moderationStatus==='APPROVED');
    else if (tab === 'SELF_REJECTED') list = list.filter(v => v.source==='SELF' && v.moderationStatus==='REJECTED');
    else if (tab === 'PLATFORM')      list = list.filter(v => v.source==='PLATFORM');
    if (q) {
      const qL = q.toLowerCase();
      list = list.filter(v => {
        const cand = ADMIN.candidates.find(c => c.id === v.candidateId);
        return v.id.toLowerCase().includes(qL) || (cand && (cand.name.toLowerCase().includes(qL) || cand.id.toLowerCase().includes(qL)));
      });
    }
    if (segmentFilter) list = list.filter(v => v.segment === segmentFilter);
    list = [...list];
    if (sortBy === 'newest') list.sort((a,b) => new Date(b.createdAt) - new Date(a.createdAt));
    if (sortBy === 'oldest') list.sort((a,b) => new Date(a.createdAt) - new Date(b.createdAt));
    if (sortBy === 'duration') list.sort((a,b) => {
      const [am,as] = a.duration.split(':').map(Number);
      const [bm,bs] = b.duration.split(':').map(Number);
      return (bm*60+bs) - (am*60+as);
    });
    return list;
  }, [vids, tab, q, segmentFilter, sortBy]);

  const openVid = vids.find(v => v.id === openId);

  // Actions
  const update = (id, patch, logAction, logDiff) => {
    setVids(xs => xs.map(v => v.id === id ? { ...v, ...patch } : v));
    if (logAction) {
      ADMIN.auditLogs.unshift({
        id:'log_'+Math.random().toString(36).slice(2,8), at:new Date(), actor:'Vincent Chen',
        action: logAction, targetType:'Video', targetId: id, diff: logDiff || {},
      });
    }
  };
  const approve = (id) => { update(id, { moderationStatus:'APPROVED', moderatedBy:'Vincent Chen', moderatedAt: new Date(), moderationNote: null }, 'VIDEO_APPROVE', { moderationStatus:{before:'PENDING',after:'APPROVED'} }); toast('已核准', 'success'); };
  const reject  = (id, reason) => { update(id, { moderationStatus:'REJECTED', moderatedBy:'Vincent Chen', moderatedAt: new Date(), moderationNote: reason }, 'VIDEO_REJECT', { moderationStatus:{before:'PENDING',after:'REJECTED'}, reason }); toast('已駁回', 'warn'); };
  const remove  = (id) => { update(id, {}, null); setVids(xs => xs.filter(v => v.id !== id)); ADMIN.auditLogs.unshift({ id:'log_'+Math.random().toString(36).slice(2,8), at:new Date(), actor:'Vincent Chen', action:'VIDEO_DELETE', targetType:'Video', targetId: id, diff: {} }); toast('已刪除', 'danger'); };
  const restore = (id) => { update(id, { moderationStatus:'PENDING', moderatedBy:null, moderatedAt:null, moderationNote:null }, 'VIDEO_RESTORE', { moderationStatus:{before:'REJECTED',after:'PENDING'} }); toast('已復原為待審', 'info'); };

  const batchApprove = () => { selected.forEach(id => approve(id)); setSelected(new Set()); toast(`已批次核准 ${selected.size} 支`, 'success'); };
  const batchReject  = (reason) => { selected.forEach(id => reject(id, reason)); setSelected(new Set()); setRejectBulk(false); toast(`已批次駁回 ${selected.size} 支`, 'warn'); };

  const toggleSel = (id) => setSelected(s => { const n = new Set(s); n.has(id) ? n.delete(id) : n.add(id); return n; });
  const toggleAll = () => setSelected(s => s.size === filtered.length ? new Set() : new Set(filtered.map(v => v.id)));

  const showBatch = tab === 'SELF_PENDING' && selected.size > 0;

  return (
    <div className="a-page a-page-wide">
      <div className="a-page-header">
        <div>
          <h1 className="a-page-title">{t('admin.videos.title')}</h1>
          <p className="a-page-sub">{t('admin.videos.subtitle')}</p>
        </div>
        <div className="a-page-header-actions">
          {/* CSV export — Super Admin only (data egress / privacy gate). */}
          {isSuperAdmin(user) && <button className="a-btn a-btn-default"><AIcon name="download" size={14}/> 匯出 CSV</button>}
          <button className="a-btn a-btn-primary" onClick={()=>setShowUpload(true)}><AIcon name="upload" size={14}/> 上傳 PLATFORM 影片</button>
        </div>
      </div>

      <div className="a-tabs">
        {tabs.map(t => (
          <button key={t.key} className={`a-tab ${tab===t.key?'active':''}`} onClick={()=>{ setTab(t.key); setSelected(new Set()); }}>
            {t.label} <span className="a-tab-count">{t.n}</span>
          </button>
        ))}
      </div>

      <div className="a-card">
        <div className="a-table-toolbar">
          <div className="a-input-group" style={{width:260}}>
            <span className="a-input-group-prefix"><AIcon name="search" size={14}/></span>
            <input className="a-input" placeholder="搜尋候選人、影片 ID…" value={q} onChange={e=>setQ(e.target.value)}/>
          </div>
          <select className="a-select" style={{width:150}} value={segmentFilter} onChange={e=>setSegmentFilter(e.target.value)}>
            <option value="">所有段落</option>
            {Object.entries(SEGMENT_LABEL).map(([k,v]) => <option key={k} value={k}>{v}</option>)}
          </select>
          <select className="a-select" style={{width:140}} value={sortBy} onChange={e=>setSortBy(e.target.value)}>
            <option value="newest">最新 →</option>
            <option value="oldest">最久 →</option>
            <option value="duration">時長長 →</option>
          </select>
          <span className="ml-auto text-muted fs-13">共 {filtered.length} 支</span>
        </div>

        {/* Batch actions bar (SELF_PENDING only) */}
        {showBatch && (
          <div style={{padding:'10px 16px',background:'var(--a-primary-bg)',borderBottom:'1px solid var(--a-primary-line)',display:'flex',alignItems:'center',gap:12}}>
            <AIcon name="check" size={14} style={{color:'var(--a-primary)'}}/>
            <span className="fs-13 fw-600" style={{color:'var(--a-primary)'}}>已選取 {selected.size} 支影片</span>
            <div className="ml-auto flex gap-6">
              <button className="a-btn a-btn-sm a-btn-default" onClick={()=>setSelected(new Set())}>取消選取</button>
              <button className="a-btn a-btn-sm a-btn-danger" onClick={()=>setRejectBulk(true)}><AIcon name="xCircle" size={12}/> 批次駁回</button>
              <button className="a-btn a-btn-sm a-btn-success-solid" onClick={batchApprove}><AIcon name="check" size={12}/> 批次核准</button>
            </div>
          </div>
        )}

        {/* Grid */}
        <div style={{padding:16}}>
          {filtered.length === 0 ? (
            <AEmpty icon="video" title={tab==='SELF_PENDING'?'🎉 沒有待審影片':'沒有符合條件的影片'} sub={tab==='SELF_PENDING'?'審核佇列已清空。':'調整篩選或切換 tab。'}/>
          ) : (
            <>
              {tab === 'SELF_PENDING' && (
                <div className="flex items-center mb-10">
                  <label className="a-check fs-13"><input type="checkbox" checked={selected.size === filtered.length && filtered.length > 0} onChange={toggleAll}/> 全選本頁</label>
                </div>
              )}
              <div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(260px,1fr))',gap:14}}>
                {filtered.map(v => {
                  const cand = ADMIN.candidates.find(c => c.id === v.candidateId);
                  const isSelected = selected.has(v.id);
                  return (
                    <VideoCard key={v.id} v={v} cand={cand}
                      selectable={tab==='SELF_PENDING'}
                      selected={isSelected}
                      onSelect={()=>toggleSel(v.id)}
                      onClick={()=>setOpenId(v.id)}
                      onApprove={()=>approve(v.id)}
                      onReject={(r)=>reject(v.id, r)}
                      onDelete={()=>remove(v.id)}
                      onRestore={()=>restore(v.id)}
                    />
                  );
                })}
              </div>
            </>
          )}
        </div>
      </div>

      {openVid && <VideoDrawer v={openVid} onClose={()=>setOpenId(null)} onApprove={approve} onReject={reject} onDelete={remove} onRestore={restore}/>}
      {rejectBulk && <BulkRejectModal count={selected.size} onClose={()=>setRejectBulk(false)} onConfirm={batchReject}/>}
      {showUpload && <UploadPlatformModal onClose={()=>setShowUpload(false)} onUpload={(data)=>{
        const newId = 'vid_P' + String(100 + vids.filter(x=>x.source==='PLATFORM').length + 1).padStart(3,'0');
        setVids(xs => [{ id:newId, source:'PLATFORM', status:'PROCESSING', uploadedBy:'Vincent Chen', createdAt:new Date(), moderationStatus:null, ...data }, ...xs]);
        ADMIN.auditLogs.unshift({ id:'log_'+Math.random().toString(36).slice(2,8), at:new Date(), actor:'Vincent Chen', action:'VIDEO_UPLOAD', targetType:'Video', targetId:newId, diff:{ segment:data.segment, candidateId:data.candidateId }});
        toast('PLATFORM 影片已上傳，處理中…', 'success');
        setShowUpload(false);
      }}/>}
    </div>
  );
};

// ==== Card ====
const VideoCard = ({ v, cand, selectable, selected, onSelect, onClick, onApprove, onReject, onDelete, onRestore }) => {
  const [quickReject, setQuickReject] = uS(false);
  return (
    <div className="a-card" style={{overflow:'hidden',position:'relative',border: selected ? '2px solid var(--a-primary)' : undefined}}>
      {/* Checkbox overlay */}
      {selectable && (
        <label onClick={e=>e.stopPropagation()} style={{position:'absolute',top:8,right:8,zIndex:2,background:'rgba(0,0,0,0.5)',padding:'4px',borderRadius:4,cursor:'pointer',display:'flex'}}>
          <input type="checkbox" checked={selected} onChange={onSelect} style={{width:16,height:16,cursor:'pointer',accentColor:'var(--a-primary)'}}/>
        </label>
      )}
      <div onClick={onClick} style={{cursor:'pointer'}}>
        <VideoThumb v={v}/>
      </div>
      <div style={{padding:'10px 12px'}}>
        {/* Candidate line */}
        <div onClick={onClick} style={{cursor:'pointer'}}>
          {cand ? <CandidateCell c={cand} sub={cand.id}/> : <span className="text-faint fs-13">未知候選人</span>}
        </div>
        {/* Segment + status */}
        <div className="flex items-center gap-6 mt-8">
          <span className="a-badge a-badge-neutral" style={{fontSize:10,padding:'1px 5px'}}>{SEGMENT_LABEL[v.segment] || v.segment}</span>
          {v.status === 'PROCESSING' ? <StatusBadge status="PROCESSING"/>
            : v.moderationStatus ? <StatusBadge status={v.moderationStatus}/>
            : <StatusBadge status="READY"/>}
          <span className="text-muted fs-11 ml-auto">{FMT.rel(v.createdAt)}</span>
        </div>
        {/* Actions */}
        {v.source === 'SELF' && v.moderationStatus === 'PENDING' && (
          <div className="flex gap-6 mt-10">
            <button className="a-btn a-btn-sm a-btn-danger" style={{flex:1}} onClick={()=>setQuickReject(true)}><AIcon name="xCircle" size={12}/> 駁回</button>
            <button className="a-btn a-btn-sm a-btn-success-solid" style={{flex:1}} onClick={onApprove}><AIcon name="check" size={12}/> 核准</button>
          </div>
        )}
        {v.source === 'SELF' && v.moderationStatus === 'REJECTED' && (
          <div className="flex gap-6 mt-10">
            <button className="a-btn a-btn-sm a-btn-default" style={{flex:1}} onClick={onRestore}>復原為待審</button>
            <button className="a-icon-btn" onClick={onDelete} title="刪除"><AIcon name="trash" size={13}/></button>
          </div>
        )}
        {v.source === 'SELF' && v.moderationStatus === 'APPROVED' && v.moderatedBy && (
          <div className="mt-8 fs-11 text-muted">✓ {v.moderatedBy} · {FMT.rel(v.moderatedAt)}</div>
        )}
      </div>

      {quickReject && (
        <QuickRejectModal onClose={()=>setQuickReject(false)} onConfirm={(r)=>{ onReject(r); setQuickReject(false); }}/>
      )}
    </div>
  );
};

// ==== Drawer — single video detail ====
const VideoDrawer = ({ v, onClose, onApprove, onReject, onDelete, onRestore }) => {
  const cand = ADMIN.candidates.find(c => c.id === v.candidateId);
  const [showReject, setShowReject] = uS(false);
  const [showDelete, setShowDelete] = uS(false);
  const segColor = SEGMENT_COLORS[v.segment] || '#475569';

  return (
    <ADrawer open onClose={onClose} size="lg" title={
      <span style={{display:'flex',alignItems:'center',gap:10}}>
        <AIcon name="video" size={18}/>
        <Mono>{v.id}</Mono>
        <span className={`a-badge ${v.source==='PLATFORM'?'a-badge-primary':'a-badge-violet'}`}>{v.source}</span>
        {v.moderationStatus && <StatusBadge status={v.moderationStatus}/>}
        {!v.moderationStatus && v.status && <StatusBadge status={v.status}/>}
      </span>
    } footer={
      v.source === 'SELF' && v.moderationStatus === 'PENDING' ? (
        <>
          <button className="a-btn a-btn-danger" onClick={()=>setShowReject(true)}><AIcon name="xCircle" size={13}/> 駁回</button>
          <div style={{flex:1}}/>
          <button className="a-btn a-btn-ghost" onClick={onClose}>關閉</button>
          <button className="a-btn a-btn-success-solid" onClick={()=>{ onApprove(v.id); onClose(); }}><AIcon name="check" size={13}/> 核准</button>
        </>
      ) : v.source === 'SELF' && v.moderationStatus === 'REJECTED' ? (
        <>
          <button className="a-btn a-btn-danger" onClick={()=>setShowDelete(true)}><AIcon name="trash" size={13}/> 刪除</button>
          <button className="a-btn a-btn-default" onClick={()=>{ onRestore(v.id); onClose(); }}>復原為待審</button>
          <div style={{flex:1}}/>
          <button className="a-btn a-btn-ghost" onClick={onClose}>關閉</button>
        </>
      ) : (
        <>
          <button className="a-btn a-btn-danger" onClick={()=>setShowDelete(true)}><AIcon name="trash" size={13}/> 刪除</button>
          <div style={{flex:1}}/>
          <button className="a-btn a-btn-ghost" onClick={onClose}>關閉</button>
        </>
      )
    }>
      {/* Big player */}
      <div style={{
        aspectRatio:'16/9',
        background: `linear-gradient(135deg, ${segColor}cc, ${segColor}44), #0F172A`,
        borderRadius:8, display:'grid', placeItems:'center', position:'relative', marginBottom:16, overflow:'hidden',
      }}>
        <div style={{position:'absolute',inset:0,backgroundImage:'repeating-linear-gradient(45deg, transparent 0 8px, rgba(255,255,255,0.04) 8px 9px)'}}/>
        <div style={{width:72,height:72,borderRadius:'50%',background:'rgba(255,255,255,0.25)',display:'grid',placeItems:'center',color:'#fff',cursor:'pointer',backdropFilter:'blur(6px)'}}>
          <AIcon name="play" size={28}/>
        </div>
        <div style={{position:'absolute',bottom:12,left:12,right:12,display:'flex',alignItems:'center',gap:8,color:'#fff',fontSize:11}}>
          <div style={{flex:1,height:3,background:'rgba(255,255,255,0.25)',borderRadius:2,overflow:'hidden'}}>
            <div style={{width:'0%',height:'100%',background:'#fff'}}/>
          </div>
          <span style={{fontFamily:'var(--a-mono)'}}>0:00 / {v.duration}</span>
        </div>
        <div style={{position:'absolute',top:12,right:12}}>
          <span className={`a-badge ${v.source==='PLATFORM'?'a-badge-primary':'a-badge-violet'}`}>{v.source}</span>
        </div>
        <div style={{position:'absolute',top:12,left:12,padding:'3px 9px',background:'rgba(0,0,0,0.55)',color:'#fff',fontSize:11,borderRadius:4,fontWeight:600}}>
          {SEGMENT_LABEL[v.segment] || v.segment}
        </div>
      </div>

      <div className="grid-2" style={{gridTemplateColumns:'1fr 1fr',gap:16}}>
        <div className="a-card">
          <div className="a-card-header"><h3 className="a-card-title">影片資訊</h3></div>
          <div className="a-card-body">
            <dl className="a-dl">
              <dt>ID</dt><dd><Mono>{v.id}</Mono></dd>
              <dt>段落</dt><dd><span className="a-badge a-badge-neutral">{SEGMENT_LABEL[v.segment] || v.segment}</span></dd>
              <dt>時長</dt><dd className="tnum">{v.duration}</dd>
              <dt>狀態</dt><dd><StatusBadge status={v.status}/></dd>
              <dt>來源</dt><dd><span className={`a-badge ${v.source==='PLATFORM'?'a-badge-primary':'a-badge-violet'}`}>{v.source}</span></dd>
              <dt>上傳者</dt><dd>{v.uploadedBy}</dd>
              <dt>上傳時間</dt><dd>{FMT.iso(v.createdAt)}<div className="text-muted fs-11">{FMT.rel(v.createdAt)}</div></dd>
            </dl>
          </div>
        </div>
        <div className="a-card">
          <div className="a-card-header"><h3 className="a-card-title">候選人</h3></div>
          <div className="a-card-body">
            {cand ? (
              <>
                <div className="mb-10"><CandidateCell c={cand} sub={cand.id}/></div>
                <dl className="a-dl">
                  <dt>狀態</dt><dd><StatusBadge status={cand.status}/></dd>
                  <dt>國籍 / 城市</dt><dd className="flex items-center gap-6"><Flag code={cand.nationality} size={12}/> {ADMIN.nat[cand.nationality].name} · {cand.city}</dd>
                  <dt>Tier</dt><dd>{cand.tier ? <Tier t={cand.tier}/> : <span className="text-faint">—</span>}</dd>
                  <dt>目標市場</dt><dd className="flex gap-4">{cand.targetMarkets.map(m => <span key={m} className="a-badge a-badge-neutral" style={{fontSize:10}}>{m}</span>)}</dd>
                </dl>
              </>
            ) : <span className="text-faint">未知候選人</span>}
          </div>
        </div>
      </div>

      {/* Moderation history / info */}
      {v.source === 'SELF' && (
        <div className="a-card mt-16">
          <div className="a-card-header">
            <h3 className="a-card-title">審核資訊</h3>
            {v.moderationStatus && <StatusBadge status={v.moderationStatus} className="ml-auto"/>}
          </div>
          <div className="a-card-body">
            {v.moderationStatus === 'PENDING' ? (
              <div className="fs-13">
                <div className="mb-10 text-muted">此影片等待審核。建議檢查：</div>
                <ul style={{margin:0,paddingLeft:18,lineHeight:1.9,fontSize:13,color:'var(--a-ink-soft)'}}>
                  <li>時長是否 ≥ 30 秒（{v.duration}）</li>
                  <li>內容是否與段落 <b>{SEGMENT_LABEL[v.segment]}</b> 相符</li>
                  <li>聲音/影像是否清晰、無嚴重背景噪音</li>
                  <li>是否包含個資外露（電話、住址、他人肖像）</li>
                  <li>是否疑似 AI 生成或盜用他人影片</li>
                </ul>
              </div>
            ) : (
              <dl className="a-dl">
                <dt>審核者</dt><dd>{v.moderatedBy || '—'}</dd>
                <dt>審核時間</dt><dd>{FMT.iso(v.moderatedAt)}</dd>
                {v.moderationNote && (<><dt style={{color:'var(--a-danger)'}}>駁回原因</dt><dd style={{color:'var(--a-danger)'}}>{v.moderationNote}</dd></>)}
              </dl>
            )}
          </div>
        </div>
      )}

      {v.source === 'PLATFORM' && (
        <div className="a-card mt-16">
          <div className="a-card-header"><h3 className="a-card-title">連結評測</h3></div>
          <div className="a-card-body">
            {(() => {
              const asm = ADMIN.assessments.find(a => a.candidateId === v.candidateId);
              return asm ? (
                <div className="flex items-center gap-12">
                  <div style={{flex:1}}>
                    <div className="fw-600 fs-13">評測 <Mono>{asm.id}</Mono></div>
                    <div className="text-muted fs-12 mt-4">{asm.assessor} · {asm.station} · {FMT.rel(asm.assessedAt)}</div>
                  </div>
                  <StatusBadge status={asm.status}/>
                  {asm.tier && <Tier t={asm.tier}/>}
                </div>
              ) : <AEmpty title="尚未連結評測" sub="上傳後仍可手動指派到某個評測。"/>;
            })()}
          </div>
        </div>
      )}

      {showReject && <QuickRejectModal onClose={()=>setShowReject(false)} onConfirm={(r)=>{ onReject(v.id, r); setShowReject(false); onClose(); }}/>}
      {showDelete && (
        <AModal open onClose={()=>setShowDelete(false)} title="刪除影片" icon={<span style={{color:'var(--a-danger)'}}><AIcon name="trash" size={18}/></span>}
          footer={<>
            <button className="a-btn a-btn-ghost" onClick={()=>setShowDelete(false)}>取消</button>
            <button className="a-btn a-btn-danger-solid" onClick={()=>{ onDelete(v.id); setShowDelete(false); onClose(); }}>確認刪除</button>
          </>}>
          <p className="fs-14">確定要永久刪除 <Mono>{v.id}</Mono>？此操作無法復原。候選人檔案中將不再顯示此影片。</p>
        </AModal>
      )}
    </ADrawer>
  );
};

// ==== Quick reject modal (single) ====
const REJECT_REASONS = ['時長過短（<30秒）','畫質過低 / 模糊','內容與段落不符','含個資外露','疑似 AI 生成 / 盜用','含有不當內容','其他'];

const QuickRejectModal = ({ onClose, onConfirm }) => {
  const [cat, setCat] = uS('');
  const [detail, setDetail] = uS('');
  const reason = cat && (cat === '其他' ? detail.trim() : (`[${cat}]${detail.trim() ? ' ' + detail.trim() : ''}`));
  return (
    <AModal open onClose={onClose} title="駁回影片" icon={<span style={{color:'var(--a-danger)'}}><AIcon name="xCircle" size={20}/></span>}
      footer={<>
        <button className="a-btn a-btn-ghost" onClick={onClose}>取消</button>
        <button className="a-btn a-btn-danger-solid" disabled={!cat || (cat==='其他' && !detail.trim())} onClick={()=>onConfirm(reason)}>確認駁回</button>
      </>}>
      <p className="fs-14 mb-14">駁回後候選人會收到通知，可重新拍攝上傳。</p>
      <label className="a-label">原因 *</label>
      <div className="flex flex-wrap gap-6 mb-14">
        {REJECT_REASONS.map(r => (
          <button key={r} className={`a-btn a-btn-sm ${cat===r?'a-btn-primary':'a-btn-default'}`} onClick={()=>setCat(r)}>{r}</button>
        ))}
      </div>
      <label className="a-label">補充說明{cat === '其他' && ' *'}</label>
      <textarea className="a-textarea" rows={3} value={detail} onChange={e=>setDetail(e.target.value)} placeholder={cat === '其他' ? '請說明原因' : '（選填）給候選人具體改進建議…'}/>
    </AModal>
  );
};

const BulkRejectModal = ({ count, onClose, onConfirm }) => {
  const [cat, setCat] = uS('');
  const [detail, setDetail] = uS('');
  const reason = cat && (cat === '其他' ? detail.trim() : (`[${cat}]${detail.trim() ? ' ' + detail.trim() : ''}`));
  return (
    <AModal open onClose={onClose} title={`批次駁回 ${count} 支影片`} icon={<span style={{color:'var(--a-danger)'}}><AIcon name="xCircle" size={20}/></span>}
      footer={<>
        <button className="a-btn a-btn-ghost" onClick={onClose}>取消</button>
        <button className="a-btn a-btn-danger-solid" disabled={!cat || (cat==='其他' && !detail.trim())} onClick={()=>onConfirm(reason)}>批次駁回</button>
      </>}>
      <p className="fs-14 mb-14">所有選取的影片將套用相同的駁回原因。</p>
      <label className="a-label">原因 *</label>
      <div className="flex flex-wrap gap-6 mb-14">
        {REJECT_REASONS.map(r => (
          <button key={r} className={`a-btn a-btn-sm ${cat===r?'a-btn-primary':'a-btn-default'}`} onClick={()=>setCat(r)}>{r}</button>
        ))}
      </div>
      <label className="a-label">補充說明{cat === '其他' && ' *'}</label>
      <textarea className="a-textarea" rows={3} value={detail} onChange={e=>setDetail(e.target.value)}/>
    </AModal>
  );
};

// ==== Upload PLATFORM video modal ====
// PLATFORM videos are recorded at Surabaya for officially-assessed candidates.
// They cover the 4 public skill categories — INTRO is a SELF-only segment,
// so it's hidden from this picker.
// Format seconds → "m:ss" (admin convention)
const formatDuration = (totalSeconds) => {
  const s = Math.max(0, Math.round(totalSeconds));
  return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, '0')}`;
};

const UploadPlatformModal = ({ onClose, onUpload }) => {
  const [candidateId, setCandidateId] = uS('');
  const [candQ, setCandQ] = uS('');
  const [segment, setSegment] = uS('COOKING');
  const [file, setFile] = uS(null);
  const [duration, setDuration] = uS('');
  const [reading, setReading] = uS(false);
  const [readError, setReadError] = uS('');
  const fileInputRef = window.React.useRef(null);
  const platformSegments = Object.entries(SEGMENT_LABEL).filter(([k]) => k !== 'INTRO');

  const cands = ADMIN.candidates.filter(c => c.status === 'ACTIVE' || c.status === 'PENDING_REVIEW')
    .filter(c => !candQ || c.name.toLowerCase().includes(candQ.toLowerCase()) || c.id.includes(candQ));
  const selected = ADMIN.candidates.find(c => c.id === candidateId);

  // Pull duration out of the selected file via a hidden HTMLVideoElement.
  // Falls back to a clear error if the browser can't decode the file.
  const handleFile = (f) => {
    if (!f) return;
    setFile(f); setDuration(''); setReadError(''); setReading(true);
    const url = URL.createObjectURL(f);
    const video = document.createElement('video');
    video.preload = 'metadata';
    video.onloadedmetadata = () => {
      setDuration(formatDuration(video.duration));
      setReading(false);
      URL.revokeObjectURL(url);
    };
    video.onerror = () => {
      setReadError('無法讀取影片時長，請改用 MP4 / MOV。');
      setReading(false);
      URL.revokeObjectURL(url);
    };
    video.src = url;
  };

  const onPickClick = () => fileInputRef.current && fileInputRef.current.click();
  const onDrop = (e) => { e.preventDefault(); const f = e.dataTransfer?.files?.[0]; if (f) handleFile(f); };
  const onDragOver = (e) => e.preventDefault();
  const clearFile = () => { setFile(null); setDuration(''); setReadError(''); if (fileInputRef.current) fileInputRef.current.value = ''; };

  const canSubmit = candidateId && segment && duration && !reading;

  return (
    <AModal open onClose={onClose} size="lg" title="上傳 PLATFORM 影片" icon={<AIcon name="upload" size={18}/>}
      footer={<>
        <button className="a-btn a-btn-ghost" onClick={onClose}>取消</button>
        <button className="a-btn a-btn-primary" disabled={!canSubmit} onClick={()=>onUpload({ candidateId, segment, duration })}>上傳</button>
      </>}>
      <div className="fcol gap-14">
        <div>
          <label className="a-label">候選人 *</label>
          {selected ? (
            <div className="flex items-center gap-10 p-10" style={{background:'var(--a-paper-2)',borderRadius:6,border:'1px solid var(--a-line)'}}>
              <CandidateCell c={selected}/>
              <button className="a-btn a-btn-sm a-btn-ghost ml-auto" onClick={()=>setCandidateId('')}>更換</button>
            </div>
          ) : (
            <>
              <input className="a-input" placeholder="搜尋候選人…" value={candQ} onChange={e=>setCandQ(e.target.value)}/>
              <div style={{maxHeight:200,overflow:'auto',marginTop:8,border:'1px solid var(--a-line)',borderRadius:6}}>
                {cands.slice(0,20).map(c => (
                  <div key={c.id} onClick={()=>{ setCandidateId(c.id); setCandQ(''); }} style={{padding:'8px 12px',borderBottom:'1px solid var(--a-line-soft)',cursor:'pointer'}}>
                    <CandidateCell c={c}/>
                  </div>
                ))}
              </div>
            </>
          )}
        </div>
        <div>
          <label className="a-label">段落 * <span className="a-label-hint">PLATFORM 影片用於 4 個技能類別，自我介紹（INTRO）由候選人自行錄製</span></label>
          <div className="flex flex-wrap gap-6">
            {platformSegments.map(([k,v]) => (
              <button key={k} className={`a-btn a-btn-sm ${segment===k?'a-btn-primary':'a-btn-default'}`} onClick={()=>setSegment(k)}>{v}</button>
            ))}
          </div>
        </div>
        <div>
          <label className="a-label">影片檔 *</label>
          <input ref={fileInputRef} type="file" accept="video/mp4,video/quicktime,video/*" style={{display:'none'}}
            onChange={e => handleFile(e.target.files?.[0])}/>
          {!file ? (
            <div onClick={onPickClick} onDrop={onDrop} onDragOver={onDragOver}
              style={{padding:14,border:'2px dashed var(--a-line-strong)',borderRadius:8,textAlign:'center',background:'var(--a-paper-2)',cursor:'pointer'}}>
              <AIcon name="upload" size={24} className="text-muted"/>
              <div className="fs-13 fw-600 mt-8">拖放影片檔至此，或點擊上傳</div>
              <div className="text-muted fs-11 mt-4">MP4 / MOV · 最大 500MB · 建議 1080p · 時長將自動讀取</div>
              <button type="button" className="a-btn a-btn-sm a-btn-default mt-10" onClick={(e)=>{ e.stopPropagation(); onPickClick(); }}>選擇檔案</button>
            </div>
          ) : (
            <div style={{padding:14,border:'1px solid var(--a-line)',borderRadius:8,background:'var(--a-paper-2)'}}>
              <div className="flex items-center gap-10">
                <div style={{width:36,height:36,borderRadius:8,background:'var(--a-primary-50)',color:'var(--a-primary)',display:'grid',placeItems:'center'}}>
                  <AIcon name="video" size={18}/>
                </div>
                <div style={{flex:1,minWidth:0}}>
                  <div className="fs-13 fw-600" style={{overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{file.name}</div>
                  <div className="text-muted fs-11 mt-2">
                    {(file.size / (1024*1024)).toFixed(1)} MB
                    {' · '}
                    {reading
                      ? <span>讀取時長中…</span>
                      : duration
                        ? <span>時長 <Mono>{duration}</Mono>（自動讀取）</span>
                        : <span style={{color:'var(--a-danger)'}}>{readError || '時長未知'}</span>}
                  </div>
                </div>
                <button className="a-btn a-btn-sm a-btn-ghost" onClick={clearFile}><AIcon name="x" size={13}/> 移除</button>
              </div>
            </div>
          )}
        </div>
      </div>
    </AModal>
  );
};

Object.assign(window, { VideosPageReal, VideoCard, VideoDrawer, QuickRejectModal });
