// This file is part of Moodle - http://moodle.org/
//
// @module     block_mwa_dashboard/engagement
// @copyright  2026 Bruno Porto
// @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later

define([
    'block_mwa_dashboard/dashboardstore',
    'core/log'
], function(Store, Log) {

    'use strict';

    var w = Store.windowFacade();

    (function () {
    'use strict';

    /* ── helpers ── */
    function tr(k, fb) {
        // Store.getStrings() contains translations passed from PHP via export_for_amd()
        var S = Store.getStrings ? Store.getStrings() : {};
        var v = Object.prototype.hasOwnProperty.call(S, k) ? S[k] : '';
        return (v && !/^\[\[/.test(v)) ? v : (fb !== undefined ? fb : k);
    }
    function esc(v) {
        return String(v == null ? '' : v).replace(/[&<>"']/g, function(c) {
            return {'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c];
        });
    }
    function norm(v) { return v == null ? '' : String(v).trim(); }
    function $(id) { return document.getElementById(id); }
    function parseDate(l) {
        if (l._ts) { return new Date(Number(l._ts) * 1000); }
        var s = norm(l.hora);
        var m = s.match(/(\d{2})\/(\d{2})\/(\d{2}),?\s*(\d{2}):(\d{2})/);
        if (m) { return new Date(2000+Number(m[3]), Number(m[2])-1, Number(m[1]), Number(m[4]), Number(m[5])); }
        return null;
    }
    function fmtDate(d) {
        if (!d) { return '—'; }
        return String(d.getDate()).padStart(2,'0')+'/'+String(d.getMonth()+1).padStart(2,'0')+'/'+d.getFullYear();
    }

    /* ── estado ── */
    var EV_DATA = [];
    var EV_FILTER = 'all';

    /* ═══════════════════════════════════════════
       Algoritmo — portado fielmente do dashboard.html
       D5 removido conforme solicitado
    ═══════════════════════════════════════════ */
    function clampScore(v) { return Math.min(98, Math.max(2, Math.round(v))); }

    function calcFull(ago, interactions, avgInter, activeDays, totalDays, w1, w2) {
        // D1: Recency (35%)
        var d1 = ago === 0 ? 100 : ago <= 2 ? 90 : ago <= 5 ? 75 : ago <= 10 ? 55 :
                 ago <= 15 ? 35 : ago <= 21 ? 20 : ago <= 30 ? 10 : 3;

        // D2: Weekly trend (30%) — weight increased after D5 was removed
        var d2 = 50;
        if (w2 > 0) {
            var t = w1 / w2;
            d2 = t >= 1 ? 100 : t >= 0.7 ? 80 : t >= 0.4 ? 55 : t >= 0.2 ? 30 : t > 0 ? 10 : 0;
        } else if (w1 > 0) { d2 = 70; }

        // D3: Historical consistency (20%)
        var cr = totalDays > 0 ? activeDays / totalDays : 0;
        var d3 = cr >= 0.6 ? 100 : cr >= 0.4 ? 80 : cr >= 0.2 ? 55 : cr >= 0.1 ? 35 : cr > 0 ? 15 : 0;

        // D4: Depth — interactions vs average (15%)
        var ir = avgInter > 0 ? Math.min(2, interactions / avgInter) : 0;
        var d4 = ir >= 1.5 ? 100 : ir >= 1 ? 80 : ir >= 0.6 ? 60 : ir >= 0.3 ? 35 : ir > 0 ? 15 : 0;

        // Composite score: D1×35% + D2×30% + D3×20% + D4×15%
        var score = clampScore(d1*0.35 + d2*0.30 + d3*0.20 + d4*0.15);

        return {
            score: score,
            f1Risk: 100-d1,
            f2Risk: 100-d2,
            f3Risk: 100-d3,
            f4Risk: 100-d4,
            trend: w2 > 0 ? Math.round((w1/w2)*100) : null
        };
    }

    function participationScore(n, gradeMap, coverCount, totalActs, delivSet) {
        var nota = (gradeMap[n] !== undefined) ? gradeMap[n] : null;
        var gs   = nota !== null ? Math.min(100, Math.round((nota/100)*100)) : 0;
        var cs   = Math.min(100, Math.round(((coverCount[n]||0)/Math.max(1,totalActs))*100));
        var hd   = delivSet.has(n);
        if (nota !== null) {
            return Math.round(gs*0.50 + cs*0.30 + (hd?100:0)*0.20);
        }
        return Math.min(35, Math.round(cs*0.70 + (hd?100:0)*0.30));
    }

    function riskLabel(score) {
        if (score >= 70) { return {label:tr('ev_high_part','Alta participação'), cls:'badge high',   ring:'#3aab7a', color:'var(--green)'}; }
        if (score >= 40) { return {label:tr('ev_med_part', 'Participação média'), cls:'badge medium', ring:'#5b9bd5', color:'var(--blue)'}; }
        return             {label:tr('ev_low_part','Baixa participação'),          cls:'badge low',    ring:'#d95f5f', color:'var(--red)'};
    }

    /* ═══════════════════════════════════════════
       buildEvData
    ═══════════════════════════════════════════ */
    function buildEvData() {
        var mwa   = w.MWADashboard || {};
        var state = mwa.state || {};
        var logs  = state.logs   || [];
        var grades = state.grades || [];
        if (!logs.length) { return []; }

        var now    = Date.now();
        var last   = {}, inters = {}, days = {}, w1m = {}, w2m = {};
        var covers = {}, actSet = new Set(), delivSet = new Set();
        var gradeMap = {};

        grades.forEach(function(g) {
            var k = norm(g.student_name || g.name || '');
            if (k && g.grade != null) { gradeMap[k] = Number(g.grade); }
        });

        logs.forEach(function(l) {
            var n = norm(l.nomecompleto || l.student_name || '');
            if (!n) { return; }
            var d = parseDate(l);
            if (!d) { return; }
            var t = d.getTime();

            if (!last[n] || d > last[n]) { last[n] = d; }
            inters[n] = (inters[n]||0) + 1;

            var dk = d.getFullYear()+'-'+(d.getMonth()+1)+'-'+d.getDate();
            if (!days[n]) { days[n] = new Set(); }
            days[n].add(dk);

            var ctx = norm(l.contextodoevento);
            if (ctx) {
                actSet.add(ctx);
                if (!covers[n]) { covers[n] = new Set(); }
                covers[n].add(ctx);
            }

            var ev = norm(l.nomedoevento);
            if (ev.indexOf('submetid') >= 0 || ev.indexOf('Submissão') >= 0 || ev === 'Um envio foi submetido.') {
                delivSet.add(n);
            }

            if (t >= now - 7*86400000)        { w1m[n] = (w1m[n]||0)+1; }
            else if (t >= now - 14*86400000)  { w2m[n] = (w2m[n]||0)+1; }
        });

        var totalActs = Math.max(1, actSet.size);
        var coverCount = {};
        Object.keys(covers).forEach(function(n) { coverCount[n] = covers[n].size; });

        var allNames  = Object.keys(last);
        var allDates  = Object.values(last);
        var minDate   = allDates.reduce(function(a,b){return a<b?a:b;}, allDates[0]);
        var maxDate   = allDates.reduce(function(a,b){return a>b?a:b;}, allDates[0]);
        var totalDays = Math.max(1, Math.round((maxDate - minDate) / 86400000));
        var totalI    = Object.values(inters).reduce(function(a,b){return a+b;}, 0);
        var avgInter  = totalI / Math.max(1, allNames.length);

        // aprovados
        var approvedSet = new Set();
        grades.forEach(function(g) {
            if (g.grade != null && Number(g.grade) >= 60) {
                approvedSet.add(norm(g.student_name || g.name || ''));
            }
        });

        return allNames.map(function(n) {
            var lastD  = last[n];
            var ago    = Math.round((now - lastD.getTime()) / 86400000);
            var ni     = inters[n] || 0;
            var actD   = days[n] ? days[n].size : 0;
            var w1     = w1m[n] || 0;
            var w2     = w2m[n] || 0;
            var score  = participationScore(n, gradeMap, coverCount, totalActs, delivSet);
            var full   = calcFull(ago, ni, avgInter, actD, totalDays, w1, w2);
            var risk   = riskLabel(score);
            var reasons = [];
            if (ago > 14) { reasons.push(tr('ev_reason_no_access_ago','Sem acesso há ')+ago+' dias'); }
            else if (ago > 7) { reasons.push(ago+' '+tr('ev_reason_days_no_access','dias sem acesso')); }
            if (full.trend !== null && full.trend < 50) {
                reasons.push(tr('ev_reason_drop','Queda de ')+(100-full.trend)+'% '+tr('ev_reason_drop_this_week','nos acessos esta semana'));
            }
            if (ni < Math.max(1, avgInter*0.3)) { reasons.push(tr('ev_reason_low_inter2','Interações muito abaixo da média')); }
            var stud   = (state.students||[]).find(function(s){ return norm(s.name) === n; });
            return {
                name: n, ago: ago, interactions: ni, activeDays: actD, totalDays: totalDays,
                score: score, risk: risk, full: full,
                lastD: lastD, email: (stud&&stud.email)||'',
                userid: (stud&&stud.userid)||0,
                w1: w1, w2: w2, reasons: reasons,
                approved: approvedSet.has(n)
            };
        }).sort(function(a,b) { return a.score - b.score; });
    }

    /* ═══════════════════════════════════════════
       render
    ═══════════════════════════════════════════ */
    function render() {
        EV_DATA = buildEvData();
        if (!EV_DATA.length) {
            var el = $('evList');
            if (el) { Store.renderHtml(el, '<div class="empty"><p>'+tr('no_data','Sem dados para exibir.')+'</p></div>'); }
            var kpi = $('evKpis'); if (kpi) { Store.clearElement(kpi); }
            return;
        }

        var critico = EV_DATA.filter(function(x){return x.score<40;}).length;
        var medio   = EV_DATA.filter(function(x){return x.score>=40&&x.score<70;}).length;
        var baixo   = EV_DATA.filter(function(x){return x.score>=70;}).length;
        var aprovs  = EV_DATA.filter(function(x){return x.approved;}).length;
        var avg     = Math.round(EV_DATA.reduce(function(s,x){return s+x.score;},0)/Math.max(1,EV_DATA.length));

        // Delta: dividir alunos por last access (metade mais recente vs anterior)
        var dc = window.MWADeltaChip;
        var evSorted = EV_DATA.slice().sort(function(a,b){return (a.lastD?a.lastD.getTime():0)-(b.lastD?b.lastD.getTime():0);});
        var evMid = Math.floor(evSorted.length/2);
        var evPrv = evSorted.slice(0,evMid), evCur = evSorted.slice(evMid);
        function evCount(arr,fn){return arr.filter(fn).length;}
        var dCrit  = dc ? dc(evCount(evCur,function(x){return x.score<40;}),   evCount(evPrv,function(x){return x.score<40;}),   true)  : '';
        var dMed   = dc ? dc(evCount(evCur,function(x){return x.score>=40&&x.score<70;}), evCount(evPrv,function(x){return x.score>=40&&x.score<70;}), false) : '';
        var dBaixo = dc ? dc(evCount(evCur,function(x){return x.score>=70;}),  evCount(evPrv,function(x){return x.score>=70;}),  false) : '';
        var dAprov = dc ? dc(evCount(evCur,function(x){return x.approved;}),   evCount(evPrv,function(x){return x.approved;}),   false) : '';

        /* KPIs */
        var kpiBox = $('evKpis');
        if (kpiBox) {
            Store.renderHtml(kpiBox, mkKpiCard('c-red',   'critico', '🔴 '+tr('ev_low_part','Participação baixa'),   critico, dCrit  || tr('ev_part_low_delta','part. < 40%'))
              + mkKpiCard('c-blue',  'medio',   '🔵 '+tr('ev_med_part','Participação média'),   medio,   dMed   || tr('ev_part_med_delta','part. 40–69%'))
              + mkKpiCard('c-green', 'baixo',   '🟢 '+tr('ev_high_part','Alta participação'),   baixo,   dBaixo || tr('ev_part_high_delta','part. ≥ 70%'))
              + mkKpiCard('c-teal',  'aprovado','✅ '+tr('ev_approved','Approved'),             aprovs,  dAprov || tr('ev_approved_delta','nota ≥ 60 pts')));
        }

        // Event delegation para filtro dos KPIs (substituindo onclick inline)
        var kpiBoxEl = $('evKpis');
        if (kpiBoxEl && !kpiBoxEl._evDelegated) {
            kpiBoxEl._evDelegated = true;
            kpiBoxEl.addEventListener('click', function(e) {
                var kpi = e.target.closest('[data-ev-filter]');
                if (kpi) window.MWAEngagement && window.MWAEngagement.filter(kpi.getAttribute('data-ev-filter'));
            });
        }
        renderCharts(critico, medio, baixo);
        applyFilter(EV_FILTER);
    }

    function mkKpiCard(cls, f, label, val, delta) {
        var chip = (delta && delta.indexOf && delta.indexOf('<span') >= 0) ? delta : '';
        var sub  = chip ? '' : delta;
        return '<div class="kpi ' + cls + '" style="cursor:pointer;" data-ev-filter="' + f + '">'
            + '<div class="kpi-top"><span class="kpi-label">' + label + '</span>' + chip + '</div>'
            + '<div class="kpi-val">' + val + '</div>'
            + '<div class="kpi-delta">' + (sub||'') + '</div>'
            + '</div>';
    }

    function renderCharts(critico, medio, baixo) {
        if (typeof Chart === 'undefined') { return; }

        var c1 = $('cEvDist');
        if (c1) {
            if (c1._evChart) { c1._evChart.destroy(); }
            c1._evChart = new Chart(c1, {
                type: 'doughnut',
                data: {
                    labels: [tr('ev_low_part','Baixa participação'), tr('ev_med_part','Participação média'), tr('ev_high_part','Alta participação')],
                    datasets: [{data: [critico, medio, baixo], backgroundColor: ['#d95f5f','#5b9bd5','#3aab7a'], borderWidth: 0}]
                },
                options: {responsive:true, maintainAspectRatio:false, plugins:{legend:{position:'bottom',labels:{boxWidth:10,font:{size:11}}}}}
            });
        }

        var buckets = [tr('ev_bucket_0_3','0–3 dias'), tr('ev_bucket_4_7','4–7 dias'),
                       tr('ev_bucket_8_14','8–14 dias'), tr('ev_bucket_15_21','15–21 dias'),
                       tr('ev_bucket_21p','>21 dias')];
        var groups = [
            EV_DATA.filter(function(x){return x.ago<=3;}),
            EV_DATA.filter(function(x){return x.ago>=4&&x.ago<=7;}),
            EV_DATA.filter(function(x){return x.ago>=8&&x.ago<=14;}),
            EV_DATA.filter(function(x){return x.ago>=15&&x.ago<=21;}),
            EV_DATA.filter(function(x){return x.ago>21;})
        ];
        var scores = groups.map(function(g){
            return g.length ? Math.round(g.reduce(function(s,x){return s+x.score;},0)/g.length) : 0;
        });

        var c2 = $('cEvScore');
        if (c2) {
            if (c2._evChart) { c2._evChart.destroy(); }
            c2._evChart = new Chart(c2, {
                type: 'bar',
                data: {
                    labels: buckets,
                    datasets: [{
                        data: scores,
                        backgroundColor: scores.map(function(v){return v>=70?'#3aab7a':v>=40?'#5b9bd5':'#d95f5f';}),
                        borderRadius: 6
                    }]
                },
                options: {
                    responsive: true, maintainAspectRatio: false,
                    plugins: {legend:{display:false}},
                    scales: {y:{beginAtZero:true, max:100, ticks:{callback:function(v){return v+'%';}}}}
                }
            });
        }
    }

    /* ═══════════════════════════════════════════
       filter + sort + list render
    ═══════════════════════════════════════════ */
    function applyFilter(f) {
        EV_FILTER = f;

        // buttons
        ['evBtnAll','evBtnCrit','evBtnMedio','evBtnAlta'].forEach(function(id){
            var el = $(id); if (el) { el.className = 'btn-ghost'; }
        });
        var map = {all:'evBtnAll', critico:'evBtnCrit', medio:'evBtnMedio', baixo:'evBtnAlta'};
        var active = $(map[f]); if (active) { active.className = 'btn-accent'; }

        var filtered = f === 'all' ? EV_DATA : EV_DATA.filter(function(x){
            if (f === 'critico')  { return x.score < 40; }
            if (f === 'medio')    { return x.score >= 40 && x.score < 70; }
            if (f === 'baixo')    { return x.score >= 70; }
            if (f === 'aprovado') { return x.approved; }
            return true;
        });

        var labels = {
            all:tr('ev_all','Todos').toLowerCase(), critico:tr('ev_low_part','Participação baixa').toLowerCase(),
            medio:tr('ev_med_part','Participação média').toLowerCase(), baixo:tr('ev_high_part','Alta participação').toLowerCase(), aprovado:tr('ev_approved','Approved').toLowerCase()
        };
        var lbl = $('evFilterLabel');
        if (lbl) { lbl.textContent = filtered.length+' '+(filtered.length!==1?tr('ev_students','alunos'):tr('ev_student','aluno'))+' · '+(labels[f]||f); }

        var sortSel = $('evSort');
        var sm = sortSel ? sortSel.value : 'score';
        filtered = filtered.slice().sort(function(a,b){
            if (sm === 'alpha') { return norm(a.name).localeCompare(norm(b.name)); }
            if (sm === 'ago')   { return b.ago - a.ago; }
            return a.score - b.score;
        });

        renderList(filtered);
    }

    /* ═══════════════════════════════════════════
       renderList — HTML fiel ao dashboard.html
    ═══════════════════════════════════════════ */
    function renderList(data) {
        var box = $('evList');
        if (!box) { return; }
        if (!data.length) {
            Store.renderHtml(box, '<div class="empty"><p>'+tr('ev_empty','Nenhum aluno nesta categoria.')+'</p></div>');
            return;
        }

        Store.renderHtml(box, data.map(function(x, i) {
            var circ = 2 * Math.PI * 26;
            var dash = Math.round((x.score/100) * circ);

            var trendBadge = (x.w2 > 0 && x.w1 < x.w2*0.5)
                ? '<span style="font-size:.7rem;color:var(--red);font-weight:700;" title="'+tr('ev_trend_drop')+'">▼ '+tr('ev_reason_drop')+'</span>'
                : '';

            var reasonsHtml = (x.reasons && x.reasons.length)
                ? '<div style="display:flex;flex-wrap:wrap;gap:.3rem;margin-bottom:.75rem;">'
                  + x.reasons.map(function(r){
                      return '<span style="background:var(--red-dim);color:var(--red);padding:3px 9px;border-radius:99px;font-size:.72rem;font-weight:700;">'+esc(r)+'</span>';
                    }).join('')
                  + '</div>'
                : '';

            var bars = '';
            if (x.full) {
                bars += evBarHtml(tr('ev_factor_recency','Recência / Ausência (35%) — dias sem acessar'), x.full.f1Risk,
                    x.full.f1Risk>60?'#d95f5f':x.full.f1Risk>30?'#c98a2a':'#3aab7a');
                bars += evBarHtml(tr('ev_factor_trend','Tendência semanal (30%)'), x.full.f2Risk,
                    x.full.f2Risk>60?'#d95f5f':x.full.f2Risk>30?'#c98a2a':'#3aab7a');
                bars += evBarHtml(tr('ev_factor_consistency','Consistência histórica (20%)'), x.full.f3Risk,
                    x.full.f3Risk>60?'#d95f5f':x.full.f3Risk>30?'#c98a2a':'#3aab7a');
                bars += evBarHtml(tr('ev_factor_depth','Profundidade / Interações (15%) — volume vs média da turma'), x.full.f4Risk,
                    x.full.f4Risk>60?'#c98a2a':x.full.f4Risk>30?'#5b9bd5':'#3aab7a');
            }

            return '<div class="ev-row" id="evr'+i+'">'

              // ── header ──
              +'<div class="ev-row-header" onclick="window.MWAEngagement&&window.MWAEngagement.toggle('+i+')">'

              // score ring SVG
              +'<div class="ev-score-ring">'
              +'<svg width="64" height="64" viewBox="0 0 64 64">'
              +'<circle cx="32" cy="32" r="26" fill="none" stroke="'+( document.documentElement.getAttribute('data-theme')==='dark'?'#ffffff08':'#e8ecf5')+'" stroke-width="6"/>'
              +'<circle cx="32" cy="32" r="26" fill="none" stroke="'+x.risk.ring+'" stroke-width="6"'
              +' stroke-dasharray="'+dash+' '+(circ-dash)+'" stroke-linecap="round" style="transform:rotate(-90deg);transform-origin:center"/>'
              +'</svg>'
              +'<div class="ev-score-label" style="color:'+x.risk.ring+';">'+x.score+'%</div>'
              +'</div>'

              // info
              +'<div style="flex:1;">'
              +'<div style="font-weight:700;font-size:.9rem;">'+esc(x.name)+'</div>'
              +'<div style="font-size:.73rem;color:var(--muted);margin-top:2px;">'
              +(x.email ? '📧 '+esc(x.email) : tr('ev_no_email','sem email'))
              +' · '+x.interactions+' '+tr('interactions','interações')
              +' · '+tr('ev_active_days','dias ativos')+': '+x.activeDays
              +'</div>'
              +'</div>'

              // badges + quick actions
              +'<div style="display:flex;align-items:center;gap:.6rem;flex-shrink:0;">'
              +'<span class="'+x.risk.cls+'">'+x.risk.label+'</span>'
              +'<span style="font-size:.73rem;color:var(--muted);">⏱ '+x.ago+'d</span>'
              +trendBadge
              +'<div class="ev-quick-actions" onclick="event.stopPropagation()">'
              +'<button class="btn-ghost" style="font-size:.72rem;padding:3px 8px;" title="Enviar mensagem"'
              +' onclick="window.MWAInterventions&&window.MWAInterventions.quickMessage('
              +"'"+esc(x.name)+"','"+esc(x.email)+"',"+x.userid+",'')\">"
              +'✉️</button>'
              +'</div>'
              +'<span style="color:var(--muted);font-size:.85rem;">⌄</span>'
              +'</div>'
              +'</div>'

              // ── expanded detail ──
              +'<div class="ev-detail" id="evd'+i+'">'

              // metrics grid
              +'<div class="ev-factors">'
              +'<div class="ev-factor"><div class="ev-factor-label">⏱ '+tr('ev_days_no_access','Sem acesso')+'</div>'
              +'<div class="ev-factor-val" style="color:'+(x.ago>14?'var(--red)':x.ago>7?'var(--amber)':'var(--green)')+';">'+x.ago+'d</div></div>'

              +'<div class="ev-factor"><div class="ev-factor-label">📅 '+tr('ev_last_access','Last access')+'</div>'
              +'<div class="ev-factor-val" style="font-size:.78rem;">'+fmtDate(x.lastD)+'</div></div>'

              +'<div class="ev-factor"><div class="ev-factor-label">⚡ '+tr('interactions','Interações')+'</div>'
              +'<div class="ev-factor-val">'+x.interactions+'</div></div>'

              +'<div class="ev-factor"><div class="ev-factor-label">📅 '+tr('ev_active_days','Active days')+'</div>'
              +'<div class="ev-factor-val">'+x.activeDays+'</div></div>'

              +(x.w2 > 0
                ? '<div class="ev-factor"><div class="ev-factor-label" title="'+tr('ev_interactions_title')+'">📈 '+tr('ev_trend')+'</div>'
                  +'<div class="ev-factor-val" style="color:'+(x.w1>=x.w2?'var(--green)':'var(--red)')+';">'
                  +(x.w1>=x.w2?'▲':'▼')+' '+Math.round((x.w1/Math.max(1,x.w2))*100)+'%</div></div>'
                : '')

              +'</div>'

              // barras de fatores de risco
              +'<div style="font-size:.65rem;font-weight:700;color:var(--muted);letter-spacing:.06em;text-transform:uppercase;margin-bottom:.4rem;">'+tr('ev_risk_factors','Fatores de risco')+'</div>'
              +'<div style="margin-bottom:.75rem;">'+bars+'</div>'

              // tags de motivo
              +reasonsHtml

              // ai-box
              +'<div class="ai-box" id="aibox'+i+'">'
              +'<div class="ai-box-title">✦ '+tr('ev_ai_title','Análise & Recomendação IA')+'</div>'
              +'<div class="ai-loading"><div class="ai-dot"></div><div class="ai-dot"></div><div class="ai-dot"></div>'
              +'<span style="margin-left:.5rem;font-size:.78rem;color:var(--muted);">'+tr('ev_ai_hint','Clique em "Gerar Recomendação IA" para analisar')+'</span></div>'
              +'</div>'

              // action buttons
              +'<div style="display:flex;gap:.6rem;margin-top:.75rem;">'
              +'<button class="btn-accent" style="font-size:.8rem;" onclick="window.MWAEngagement&&window.MWAEngagement.genAI('+i+');event.stopPropagation()">✦ '+tr('ev_gen_ai','Gerar Recomendação IA')+'</button>'
              +'<button class="btn-ghost" style="font-size:.8rem;" onclick="window.MWAInterventions&&window.MWAInterventions.quickMessage('
              +"'"+esc(x.name)+"','"+esc(x.email)+"',"+x.userid+",'');event.stopPropagation()\">"
              +tr('send_email_ai','✉️ Mensagem')+'</button>'
              +'</div>'

              +'</div></div>';

        }).join('') || '<div class="empty"><p>Nenhum aluno nesta categoria.</p></div>');
    }

    function evBarHtml(label, val, color) {
        return '<div class="ev-bar-wrap">'
            + '<div class="ev-bar-label">'+esc(label)+'</div>'
            + '<div class="ev-bar"><div class="ev-bar-fill" style="width:'+val+'%;background:'+color+';"></div></div>'
            + '<div class="ev-bar-val">'+val+'%</div>'
            + '</div>';
    }

    function toggle(i) {
        var row = $('evr'+i); if (row) { row.classList.toggle('expanded'); }
    }

    /* ── IA individual ── */
    function genAI(i) {
        var x = EV_DATA[i]; if (!x) { return; }
        var box = $('aibox'+i); if (!box) { return; }

        Store.renderHtml(box, '<div class="ai-box-title">✦ '+tr('ev_ai_title','Análise & Recomendação IA')+'</div>'
            + '<div class="ai-loading"><div class="ai-dot"></div><div class="ai-dot"></div><div class="ai-dot"></div>'
            + '<span style="margin-left:.5rem;font-size:.78rem;">'+tr('ev_ai_analyzing','Gerando análise...')+'</span></div>');

        var cfg      = Store.getConfig ? Store.getConfig() : ((w.MWADashboard && w.MWADashboard.config) || {});
        var courseid = parseInt(cfg.courseid||0, 10);
        // Fallback: get courseid from Moodle URL if config not available
        if (!courseid) {
            var urlM = (window.location.search || '').match(/[?&]id=(\d+)/);
            if (urlM) { courseid = parseInt(urlM[1], 10); }
        }
        if (!courseid) {
            Store.renderHtml(box, '<div class="ai-box-title" style="color:var(--red);">✦ '+tr('ev_ai_error','Erro')+'</div>'
                + '<div class="ai-box-text" style="color:var(--red);">'+tr('ev_ai_conn_error','Course ID não disponível. Recarregue a página.')+'</div>');
            return;
        }
        var prompt   = tr('ev_prompt_expert','Você é um especialista em EaD e análise de evasão. Analise este aluno:')+'\n'
            + tr('ev_prompt_name','- Nome: ')+x.name+'\n'
            + tr('ev_prompt_score','- Score de participação: ')+x.score+'% ('+x.risk.label+')\n'
            + tr('ev_prompt_ago','- Dias sem acesso: ')+x.ago+'\n'
            + tr('ev_prompt_last','- Last access: ')+fmtDate(x.lastD)+'\n'
            + tr('ev_prompt_inter','- Interações totais: ')+x.interactions+'\n'
            + tr('ev_prompt_active','- Active days: ')+x.activeDays+' '+tr('ev_prompt_of','de')+' '+x.totalDays+'\n'
            + tr('ev_prompt_reasons','- Motivos de risco: ')+(x.reasons.join('; ')||tr('ev_prompt_none','nenhum identificado'))+'\n\n'
            + tr('ev_prompt_provide','Forneça: 1. Diagnóstico (1-2 frases) 2. Causa provável (1 frase) 3. Ação imediata (1-2 frases) 4. Mensagem sugerida (3-4 frases).')+'\n'
            + tr('ev_prompt_style','Seja direto, empático e prático.')+' '
            +(Store.getConfig&&Store.getConfig().language&&Store.getConfig().language.indexOf('pt')===0
                ?tr('ev_prompt_lang_pt','Responda em português brasileiro.')
                :Store.getConfig().language&&Store.getConfig().language.indexOf('es')===0
                ?tr('ev_prompt_lang_es','Responda en español.'):tr('ev_prompt_lang_en','Respond in English.'));

        var Store2 = Store;
        var safeName = norm(x.name).replace(/<[^>]*>/g,'').substring(0,100);
        Store2.callAction('block_mwa_dashboard_get_ai_recommendation', {
            courseid: courseid, student_name: safeName, prompt: prompt
        }).then(function(res) {
            if (res && res.success === false) {
                throw new Error(res.recommendation || tr('ev_ai_conn_error','Verifique a configuração do módulo IA.'));
            }
            var text = (res && (res.recommendation || res.response || res.content)) || '';
            if (!text) { throw new Error(tr('ev_ai_conn_error','Verifique a configuração do módulo IA.')); }
            // Formatar markdown simples
            text = text
                .replace(/^## (.+)$/gm,'<h3 style="font-size:.9rem;font-weight:700;margin:.9rem 0 .35rem;color:var(--text);">$1</h3>')
                .replace(/\*\*(.+?)\*\*/g,'<strong>$1</strong>')
                .replace(/\n/g,'<br>');
            Store.renderHtml(box, '<div class="ai-box-title">✦ '+tr('ev_ai_title','Análise & Recomendação IA')+'</div>'
                + '<div class="ai-box-text">'+text+'</div>'
                + '<div style="display:flex;gap:.5rem;margin-top:.75rem;">'
                + '<button class="btn-ghost" style="font-size:.75rem;" onclick="window.MWAInterventions&&window.MWAInterventions.quickMessage(\''+esc(x.name)+'\',\''+esc(x.email)+'\','+x.userid+',\'\');event.stopPropagation()">'+tr('send_email_ai','✉️ Mensagem')+'</button>'
                + '</div>');
        }).catch(function(err) {
            Log.error(err);
            var msg = (err && err.message) ? err.message : tr('ev_ai_conn_error','Verifique a configuração do módulo IA.');
            Store.renderHtml(box, '<div class="ai-box-title" style="color:var(--red);">✦ '+tr('ev_ai_error','Erro ao conectar com a IA')+'</div>'
                + '<div class="ai-box-text" style="color:var(--red);">'+esc(msg)+'</div>');
        });
    }

    /* ── IA turma ── */
    function analyzeAll() {
        var modal = $('evModal'); if (!modal) { return; }
        modal.style.display = 'flex';
        var body = $('evModalBody');
        if (body) {
            Store.renderHtml(body, '<div class="ai-loading" style="justify-content:center;margin:20px 0;">'
                + '<div class="ai-dot"></div><div class="ai-dot"></div><div class="ai-dot"></div>'
                + '<span style="margin-left:.5rem;">'+tr('ev_ai_class_analyzing','Gerando análise da turma...')+'</span></div>');
        }

        var cfg      = Store.getConfig ? Store.getConfig() : ((w.MWADashboard && w.MWADashboard.config) || {});
        var courseid = parseInt(cfg.courseid||0, 10);
        var critico  = EV_DATA.filter(function(x){return x.score<40;}).length;
        var medio    = EV_DATA.filter(function(x){return x.score>=40&&x.score<70;}).length;
        var alta     = EV_DATA.filter(function(x){return x.score>=70;}).length;
        var avg      = EV_DATA.length ? Math.round(EV_DATA.reduce(function(s,x){return s+x.score;},0)/EV_DATA.length) : 0;
        var topRisk  = EV_DATA.slice(0,5).map(function(x){
            return x.name+' ('+x.score+'%, '+x.ago+'d sem acesso)';
        }).join('; ');

        var prompt = tr('ev_prompt_class_expert','Você é um especialista em EaD. Analise o engajamento desta turma:')+'\n'
            + tr('ev_prompt_class_total','- Total: ')+EV_DATA.length+' '+tr('ev_students','alunos')+'\n'
            + tr('ev_prompt_class_low','- Participação baixa (<40%): ')+critico+'\n'
            + tr('ev_prompt_class_med','- Participação média (40–70%): ')+medio+'\n'
            + tr('ev_prompt_class_high','- Alta participação (>70%): ')+alta+'\n'
            + tr('ev_prompt_class_avg','- Score médio: ')+avg+'%\n'
            + tr('ev_prompt_class_risk','- Maiores riscos: ')+topRisk+'\n\n'
            + tr('ev_prompt_class_provide','Forneça: 1. Diagnóstico geral (2-3 frases) 2. Padrões preocupantes (2-3 frases) 3. Intervenções imediatas (3-4 ações concretas) 4. Estratégias de médio prazo (2-3 sugestões).')+'\n'
            + tr('ev_prompt_class_style','Seja direto e prático.')+'\n'
            +(Store.getConfig&&Store.getConfig().language&&Store.getConfig().language.indexOf('pt')===0
                ?tr('ev_prompt_lang_pt','Responda em português brasileiro.')
                :Store.getConfig().language&&Store.getConfig().language.indexOf('es')===0
                ?tr('ev_prompt_lang_es','Responda en español.'):tr('ev_prompt_lang_en','Respond in English.'));

        Store.callAction('block_mwa_dashboard_get_ai_recommendation', {
            courseid: courseid, student_name: '', prompt: prompt
        }).then(function(res) {
            var text = (res && (res.recommendation || res.response || res.content)) || '';
            if (body) {
                Store.renderHtml(body, '<div class="ai-box-text">'+esc(text).replace(/\n/g,'<br>')+'</div>');
            }
        }).catch(function(err) {
            Log.error(err);
            if (body) {
                Store.renderHtml(body, '<div style="color:var(--red);">'+tr('ev_ai_conn_error','Erro ao conectar com a IA. Verifique a configuração.')+'</div>');
            }
        });
    }

    w.MWAEngagement = {
        render:     render,
        filter:     applyFilter,
        applySort:  function() { applyFilter(EV_FILTER); },
        toggle:     toggle,
        genAI:      genAI,
        analyzeAll: analyzeAll,
        getData:    function() { return EV_DATA; }
    };

    })();

    return w.MWAEngagement;
});
