let allReviews=[];let dashboardData=null;const C={cyan:'#55e6ff',violet:'#9f7aea',pink:'#ff6bd6',green:'#5ee6a8',amber:'#ffc857',red:'#ff657a'};Chart.defaults.color='#8d95b3';Chart.defaults.borderColor='rgba(255,255,255,.06)';Chart.defaults.font.family='Inter';
const esc=v=>String(v??'').replaceAll('&','&amp;').replaceAll('<','&lt;').replaceAll('>','&gt;').replaceAll('"','&quot;').replaceAll("'",'&#039;');
const pColor=l=>({CRITICAL:C.red,HIGH:'#ff925c',MEDIUM:C.amber,LOW:C.green}[l]||C.cyan);
async function loadDashboard(){const r=await fetch('/api/dashboard');if(!r.ok)throw Error('Could not load dashboard data');dashboardData=await r.json();allReviews=dashboardData.reviews||[];totalReviews.textContent=dashboardData.summary.total_reviews;criticalCount.textContent=dashboardData.summary.critical_count;negativeCount.textContent=dashboardData.summary.negative_count;avgPriority.textContent=dashboardData.summary.avg_priority;renderCharts();renderIssues();setupDepartments();renderReviews(allReviews)}
function renderCharts(){const s=dashboardData.sentiment,p=dashboardData.priority,d=Object.entries(dashboardData.departments).sort((a,b)=>b[1]-a[1]);new Chart(sentimentChart,{type:'doughnut',data:{labels:['Negative','Neutral','Positive'],datasets:[{data:[s.negative||0,s.neutral||0,s.positive||0],backgroundColor:[C.red,C.amber,C.green],borderWidth:0,hoverOffset:5}]},options:{responsive:true,maintainAspectRatio:false,cutout:'72%',plugins:{legend:{position:'bottom',labels:{usePointStyle:true,boxWidth:7,padding:18}}}}});let levels=['CRITICAL','HIGH','MEDIUM','LOW'];new Chart(priorityChart,{type:'bar',data:{labels:levels,datasets:[{data:levels.map(x=>p[x]||0),backgroundColor:levels.map(pColor),borderRadius:8,borderSkipped:false}]},options:{responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false}},scales:{x:{grid:{display:false}},y:{beginAtZero:true,ticks:{precision:0}}}}});new Chart(departmentChart,{type:'bar',data:{labels:d.map(x=>x[0]),datasets:[{data:d.map(x=>x[1]),backgroundColor:[C.cyan,C.violet,C.pink,C.green,C.amber,'#6f82ff'],borderRadius:8,borderSkipped:false}]},options:{indexAxis:'y',responsive:true,maintainAspectRatio:false,plugins:{legend:{display:false}},scales:{y:{grid:{display:false}},x:{beginAtZero:true,ticks:{precision:0}}}}})}
function renderIssues(){let entries=Object.entries(dashboardData.issue_types).sort((a,b)=>b[1]-a[1]),max=Math.max(...entries.map(x=>x[1]),1);issueBars.innerHTML=entries.map(([n,c])=>`<div class="issue-row"><div class="issue-name">${esc(n.replaceAll('_',' '))}</div><div class="issue-track"><div class="issue-fill" style="width:${c/max*100}%"></div></div><div>${c}</div></div>`).join('')}
function setupDepartments(){Object.keys(dashboardData.departments).sort().forEach(d=>{let o=document.createElement('option');o.value=d;o.textContent=d;departmentFilter.appendChild(o)})}
function renderReviews(rows){reviewsTable.innerHTML=rows.map(x=>`<tr title="${esc(x.feedback)}"><td><b>${esc(x.customer_id)}</b></td><td class="issue-cell">${esc(x.issue)}</td><td><span class="badge ${x.sentiment}">${x.sentiment}</span></td><td>${esc(x.department)}</td><td>${x.urgency_score}/10</td><td>${x.churn_risk_score}/10</td><td><span class="score">${x.priority_score}</span> <span class="badge ${x.priority_level}">${x.priority_level}</span></td></tr>`).join('')}
function applyFilters(){let q=searchInput.value.trim().toLowerCase(),p=priorityFilter.value,d=departmentFilter.value;renderReviews(allReviews.filter(x=>(!q||x.customer_id.toLowerCase().includes(q)||x.issue.toLowerCase().includes(q)||x.feedback.toLowerCase().includes(q))&&(!p||x.priority_level===p)&&(!d||x.department===d)))}
[searchInput,priorityFilter,departmentFilter].forEach(el=>{el.addEventListener('input',applyFilters);el.addEventListener('change',applyFilters)});
analyzeBtn.addEventListener('click',async()=>{let text=liveFeedback.value.trim();if(text.length<5){liveStatus.textContent='Please enter a little more customer feedback.';return}analyzeBtn.disabled=true;analyzeBtn.textContent='Agents are analyzing...';liveStatus.textContent='Sentiment + Issue + Risk + Routing agents are running in parallel.';try{let r=await fetch('/api/analyze',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({feedback:text})}),data=await r.json();if(!r.ok)throw Error(data.detail||'Analysis failed');renderLive(data);liveStatus.textContent='Analysis complete.'}catch(e){liveStatus.textContent=e.message}finally{analyzeBtn.disabled=false;analyzeBtn.textContent='Run 4-Agent Analysis →'}});
function renderLive(x){liveResult.innerHTML=`<div><div class="live-top"><div><p class="kicker">FINAL FAN-IN RESULT</p><h2>${esc(x.customer_id)}</h2></div><div class="priority-big" style="color:${pColor(x.priority_level)}">${x.priority_score}<small>${x.priority_level} PRIORITY</small></div></div><div class="quote">“${esc(x.feedback)}”</div><div class="analysis-grid" style="margin-top:10px"><div class="analysis-box"><span>Sentiment Agent</span><strong>${esc(x.sentiment.sentiment)} · frustration ${x.sentiment.frustration_score}/10</strong></div><div class="analysis-box"><span>Issue Agent</span><strong>${esc(x.issue.issue_type.replaceAll('_',' '))}: ${esc(x.issue.issue)}</strong></div><div class="analysis-box"><span>Risk Agent</span><strong>Urgency ${x.risk.urgency_score}/10 · Churn ${x.risk.churn_risk_score}/10</strong></div><div class="analysis-box"><span>Routing Agent</span><strong>${esc(x.routing.department)}</strong></div></div><div class="analysis-box" style="margin-top:8px"><span>Churn Signal</span><strong>${esc(x.risk.churn_signal)}</strong></div></div>`}
loadDashboard().catch(e=>console.error(e));
