(() => {
  'use strict';
  const STORAGE_KEY = 'apu_sentiscope_records_v37';
  const POSITIVE = ['bagus','baik','hebat','suka','puas','cepat','jelas','membantu','excellent','great','good','love','helpful','easy','amazing','recommended'];
  const NEGATIVE = ['buruk','lambat','sulit','bingung','kecewa','gagal','error','jelek','bad','slow','hard','confusing','disappointed','broken','terrible','poor'];
  const seed = [
    {id:'SEN-1001',text:'Materi sangat jelas dan dosen menjelaskan dengan baik.',source:'Course survey',category:'Teaching',sentiment:'positive',confidence:94,status:'reviewed',createdAt:'2026-06-11T08:30:00.000Z'},
    {id:'SEN-1002',text:'Aplikasi sering lambat ketika mengunggah tugas.',source:'Mobile app',category:'Platform',sentiment:'negative',confidence:91,status:'open',createdAt:'2026-06-12T10:15:00.000Z'},
    {id:'SEN-1003',text:'Jadwal kelas sudah tersedia dan cukup mudah ditemukan.',source:'Helpdesk',category:'Administration',sentiment:'neutral',confidence:78,status:'reviewed',createdAt:'2026-06-12T14:05:00.000Z'},
    {id:'SEN-1004',text:'Support team sangat membantu menyelesaikan masalah login.',source:'Support ticket',category:'Support',sentiment:'positive',confidence:96,status:'reviewed',createdAt:'2026-06-13T09:10:00.000Z'},
    {id:'SEN-1005',text:'Instruksi praktikum membingungkan dan contoh masih kurang.',source:'Lab feedback',category:'Content',sentiment:'negative',confidence:88,status:'open',createdAt:'2026-06-14T05:45:00.000Z'},
    {id:'SEN-1006',text:'Fitur baru bekerja sesuai kebutuhan.',source:'Product review',category:'Platform',sentiment:'positive',confidence:84,status:'reviewed',createdAt:'2026-06-14T11:25:00.000Z'}
  ];

  const $ = (s, root=document) => root.querySelector(s);
  const $$ = (s, root=document) => [...root.querySelectorAll(s)];
  const esc = value => String(value ?? '').replace(/[&<>'"]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;',"'":'&#39;','"':'&quot;'}[c]));
  const uid = () => `SEN-${Date.now().toString(36).toUpperCase()}${Math.random().toString(36).slice(2,5).toUpperCase()}`;
  const validSentiment = v => ['positive','neutral','negative'].includes(v) ? v : 'neutral';
  const validStatus = v => ['open','reviewed','archived'].includes(v) ? v : 'open';
  const normalize = item => ({
    id:String(item?.id || uid()), text:String(item?.text || '').trim(), source:String(item?.source || 'Manual').trim(),
    category:String(item?.category || 'General').trim(), sentiment:validSentiment(String(item?.sentiment || 'neutral')),
    confidence:Math.min(100,Math.max(0,Number(item?.confidence) || 0)), status:validStatus(String(item?.status || 'open')),
    createdAt:item?.createdAt && !Number.isNaN(Date.parse(item.createdAt)) ? item.createdAt : new Date().toISOString()
  });
  const load = () => {
    try { const data = JSON.parse(localStorage.getItem(STORAGE_KEY)); return Array.isArray(data) ? data.map(normalize).filter(x=>x.text) : seed.map(normalize); }
    catch (_) { return seed.map(normalize); }
  };
  let records = load();
  let editingId = '';
  let sortMode = 'newest';

  function save(){ localStorage.setItem(STORAGE_KEY, JSON.stringify(records)); }
  function analyze(text){
    const words = String(text).toLowerCase().match(/[\p{L}\p{N}']+/gu) || [];
    let pos=0, neg=0;
    words.forEach(w => { if(POSITIVE.includes(w)) pos++; if(NEGATIVE.includes(w)) neg++; });
    const score = pos-neg;
    const sentiment = score>0 ? 'positive' : score<0 ? 'negative' : 'neutral';
    const confidence = Math.min(98, Math.max(58, 62 + Math.abs(score)*9 + Math.min(words.length,20)));
    return {sentiment, confidence};
  }
  function download(name, content, type){
    const blob = new Blob([content],{type}); const url=URL.createObjectURL(blob); const a=document.createElement('a');
    a.href=url;a.download=name;document.body.appendChild(a);a.click();a.remove();setTimeout(()=>URL.revokeObjectURL(url),500);
  }
  function csvCell(v){ return `"${String(v??'').replace(/"/g,'""')}"`; }
  function toast(message){ const el=$('#apuSentimentToast'); if(!el)return; el.textContent=message;el.classList.add('is-visible');clearTimeout(el._t);el._t=setTimeout(()=>el.classList.remove('is-visible'),1900); }
  function filtered(){
    const q=($('#sentSearch')?.value||'').trim().toLowerCase(); const f=$('#sentFilter')?.value||'all'; const st=$('#sentStatusFilter')?.value||'all';
    const out=records.filter(r=>(!q || [r.id,r.text,r.source,r.category].join(' ').toLowerCase().includes(q)) && (f==='all'||r.sentiment===f) && (st==='all'||r.status===st));
    return out.sort((a,b)=> sortMode==='oldest' ? Date.parse(a.createdAt)-Date.parse(b.createdAt) : sortMode==='confidence' ? b.confidence-a.confidence : Date.parse(b.createdAt)-Date.parse(a.createdAt));
  }
  function renderStats(){
    const total=records.length, positive=records.filter(x=>x.sentiment==='positive').length, negative=records.filter(x=>x.sentiment==='negative').length;
    const avg=total ? Math.round(records.reduce((s,x)=>s+x.confidence,0)/total) : 0;
    $('#sentTotal').textContent=total;$('#sentPositive').textContent=positive;$('#sentNegative').textContent=negative;$('#sentConfidence').textContent=`${avg}%`;
    const vals={positive,neutral:records.filter(x=>x.sentiment==='neutral').length,negative};
    Object.entries(vals).forEach(([k,v])=>{ const pct=total?Math.round(v/total*100):0; const bar=$(`[data-sent-bar="${k}"]`); const n=$(`[data-sent-value="${k}"]`); if(bar)bar.style.width=`${pct}%`;if(n)n.textContent=`${pct}%`; });
  }
  function render(){
    renderStats(); const body=$('#sentTableBody'); if(!body)return; const rows=filtered();
    body.innerHTML=rows.length ? rows.map(r=>`<tr>
      <td><input type="checkbox" class="sent-row-check" value="${esc(r.id)}" aria-label="Pilih ${esc(r.id)}"></td>
      <td><code>${esc(r.id)}</code><br><small>${new Date(r.createdAt).toLocaleString('id-ID')}</small></td>
      <td><strong>${esc(r.text)}</strong><br><small>${esc(r.source)} · ${esc(r.category)}</small></td>
      <td><span class="apu-badge apu-badge--${esc(r.sentiment)}">${esc(r.sentiment)}</span></td>
      <td>${Math.round(r.confidence)}%</td><td>${esc(r.status)}</td>
      <td class="apu-row-actions"><button class="apu-btn sent-edit" data-id="${esc(r.id)}">Edit</button><button class="apu-btn apu-btn--danger sent-delete" data-id="${esc(r.id)}">Hapus</button></td>
    </tr>`).join('') : '<tr><td colspan="7" class="apu-empty">Tidak ada data yang cocok.</td></tr>';
  }
  function resetForm(){ editingId=''; const f=$('#sentForm'); if(f)f.reset(); $('#sentFormTitle').textContent='Tambah feedback'; $('#sentSubmit').textContent='Simpan data'; $('#sentConfidenceInput').value=''; }
  function edit(id){
    const r=records.find(x=>x.id===id); if(!r)return; editingId=id; $('#sentText').value=r.text;$('#sentSource').value=r.source;$('#sentCategory').value=r.category;$('#sentSentiment').value=r.sentiment;$('#sentConfidenceInput').value=r.confidence;$('#sentStatus').value=r.status;$('#sentFormTitle').textContent=`Edit ${r.id}`;$('#sentSubmit').textContent='Perbarui data';$('#sentText').focus(); document.querySelector('#apuSentimentStudio').scrollIntoView({behavior:'smooth',block:'start'});
  }
  function submit(e){
    e.preventDefault(); const text=$('#sentText').value.trim(); if(!text){toast('Teks feedback wajib diisi.');return;}
    const selected=$('#sentSentiment').value; const result=selected==='auto'?analyze(text):{sentiment:selected,confidence:Number($('#sentConfidenceInput').value)||82};
    const record=normalize({id:editingId||uid(),text,source:$('#sentSource').value,category:$('#sentCategory').value,sentiment:result.sentiment,confidence:Number($('#sentConfidenceInput').value)||result.confidence,status:$('#sentStatus').value,createdAt:editingId?records.find(x=>x.id===editingId)?.createdAt:new Date().toISOString()});
    const wasEditing = Boolean(editingId); if(wasEditing) records=records.map(x=>x.id===editingId?record:x); else records.unshift(record); save();render();resetForm();toast(wasEditing?'Data diperbarui.':'Data ditambahkan.');
  }
  function mount(){
    if($('#apuSentimentStudio'))return;
    const host=document.createElement('section'); host.id='apuSentimentStudio';host.className='apu-data-studio';
    host.innerHTML=`<div class="apu-studio-shell"><div class="apu-studio-hero"><div><span class="apu-studio-kicker">SentiScope · browser-local data</span><h2>SentiScope Data Studio</h2><p>Kelola feedback, jalankan klasifikasi sentimen lokal, cari, filter, edit, hapus, impor, dan ekspor tanpa mengubah data pengunjung lain.</p></div><div class="apu-actions"><button class="apu-btn" id="sentExportJson">Ekspor JSON</button><button class="apu-btn" id="sentExportCsv">Ekspor CSV</button><button class="apu-btn" id="sentImportBtn">Impor JSON</button><input class="apu-file" id="sentImportFile" type="file" accept="application/json"></div></div>
    <div class="apu-studio-grid"><article class="apu-studio-card"><h3 id="sentFormTitle">Tambah feedback</h3><form id="sentForm" class="apu-studio-form"><div class="apu-studio-form-grid">
      <div class="apu-field apu-field--wide"><label for="sentText">Teks feedback</label><textarea id="sentText" required placeholder="Masukkan komentar atau feedback..."></textarea></div>
      <div class="apu-field"><label for="sentSource">Sumber</label><input id="sentSource" value="Manual entry"></div><div class="apu-field"><label for="sentCategory">Kategori</label><input id="sentCategory" value="General"></div>
      <div class="apu-field"><label for="sentSentiment">Sentimen</label><select id="sentSentiment"><option value="auto">Analisis otomatis</option><option value="positive">Positive</option><option value="neutral">Neutral</option><option value="negative">Negative</option></select></div>
      <div class="apu-field"><label for="sentConfidenceInput">Confidence manual (%)</label><input id="sentConfidenceInput" type="number" min="0" max="100" placeholder="Otomatis"></div>
      <div class="apu-field"><label for="sentStatus">Status</label><select id="sentStatus"><option value="open">Open</option><option value="reviewed">Reviewed</option><option value="archived">Archived</option></select></div>
    </div><div class="apu-actions"><button class="apu-btn apu-btn--primary" id="sentSubmit" type="submit">Simpan data</button><button class="apu-btn apu-btn--ghost" id="sentCancel" type="button">Bersihkan</button></div></form>
    <h4>Distribusi sentimen</h4><div class="apu-bars">${['positive','neutral','negative'].map(k=>`<div class="apu-bar"><span>${k}</span><div class="apu-bar-track"><div class="apu-bar-fill" data-sent-bar="${k}"></div></div><b data-sent-value="${k}">0%</b></div>`).join('')}</div><p class="apu-note">Analisis otomatis memakai aturan kata kunci lokal sebagai demonstrasi, bukan keputusan akademik atau psikologis.</p></article>
    <article class="apu-studio-card"><div class="apu-stats"><div class="apu-stat"><strong id="sentTotal">0</strong><span>Total feedback</span></div><div class="apu-stat"><strong id="sentPositive">0</strong><span>Positive</span></div><div class="apu-stat"><strong id="sentNegative">0</strong><span>Negative</span></div><div class="apu-stat"><strong id="sentConfidence">0%</strong><span>Avg. confidence</span></div></div>
    <div class="apu-toolbar"><input id="sentSearch" type="search" placeholder="Cari ID, teks, sumber, kategori..."><select id="sentFilter"><option value="all">Semua sentimen</option><option value="positive">Positive</option><option value="neutral">Neutral</option><option value="negative">Negative</option></select><select id="sentStatusFilter"><option value="all">Semua status</option><option value="open">Open</option><option value="reviewed">Reviewed</option><option value="archived">Archived</option></select></div>
    <div class="apu-actions" style="margin-bottom:12px"><select id="sentSort" class="apu-btn"><option value="newest">Terbaru</option><option value="oldest">Terlama</option><option value="confidence">Confidence tertinggi</option></select><button class="apu-btn apu-btn--danger" id="sentBulkDelete">Hapus terpilih</button><button class="apu-btn" id="sentReset">Pulihkan data demo</button></div>
    <div class="apu-table-wrap"><table class="apu-table"><thead><tr><th>✓</th><th>ID / waktu</th><th>Feedback</th><th>Sentimen</th><th>Confidence</th><th>Status</th><th>Operasi</th></tr></thead><tbody id="sentTableBody"></tbody></table></div></article></div></div><div class="apu-toast" id="apuSentimentToast" role="status"></div>`;
    document.body.appendChild(host);
    const jump=document.createElement('button');jump.className='apu-studio-jump';jump.type='button';jump.textContent='SentiScope Data ↓';jump.addEventListener('click',()=>host.scrollIntoView({behavior:'smooth'}));document.body.appendChild(jump);
    $('#sentForm').addEventListener('submit',submit);$('#sentCancel').addEventListener('click',resetForm);
    ['#sentSearch','#sentFilter','#sentStatusFilter'].forEach(s=>$(s).addEventListener('input',render));$('#sentSort').addEventListener('change',e=>{sortMode=e.target.value;render();});
    $('#sentTableBody').addEventListener('click',async e=>{const editBtn=e.target.closest('.sent-edit');const delBtn=e.target.closest('.sent-delete');if(editBtn)edit(editBtn.dataset.id);if(delBtn&&await APUDialog.confirm('Hapus data ini?',{intent:'danger'})){records=records.filter(x=>x.id!==delBtn.dataset.id);save();render();toast('Data dihapus.');}});
    $('#sentBulkDelete').addEventListener('click',async()=>{const ids=$$('.sent-row-check:checked').map(x=>x.value);if(!ids.length){toast('Pilih data terlebih dahulu.');return;}if(await APUDialog.confirm(`Hapus ${ids.length} data terpilih?`,{intent:'danger'})){records=records.filter(x=>!ids.includes(x.id));save();render();toast('Data terpilih dihapus.');}});
    $('#sentReset').addEventListener('click',async()=>{if(await APUDialog.confirm('Pulihkan data demo dan hapus perubahan lokal?',{intent:'danger'})){records=seed.map(normalize);save();render();resetForm();toast('Data demo dipulihkan.');}});
    $('#sentExportJson').addEventListener('click',()=>download('sentiscope-data.json',JSON.stringify(records,null,2),'application/json'));
    $('#sentExportCsv').addEventListener('click',()=>download('sentiscope-data.csv',[['id','text','source','category','sentiment','confidence','status','createdAt'].join(','),...records.map(r=>[r.id,r.text,r.source,r.category,r.sentiment,r.confidence,r.status,r.createdAt].map(csvCell).join(','))].join('\n'),'text/csv;charset=utf-8'));
    $('#sentImportBtn').addEventListener('click',()=>$('#sentImportFile').click());$('#sentImportFile').addEventListener('change',async e=>{const file=e.target.files?.[0];if(!file)return;try{const data=JSON.parse(await file.text());if(!Array.isArray(data))throw new Error();records=data.map(normalize).filter(x=>x.text);save();render();toast(`${records.length} data diimpor.`);}catch(_){toast('File JSON tidak valid.');}e.target.value='';});
    render();
  }
  if(document.readyState==='loading')document.addEventListener('DOMContentLoaded',()=>setTimeout(mount,450),{once:true});else setTimeout(mount,450);
})();
