// Churn Dashboard - Churn prediction scores, alerts, onboarding health
// Follows same patterns as bigdash_main.js

let currentTrendPeriod = 90;
let currentTierFilter = "all";
let currentSort = "score_desc";
let currentPage = 1;
let currentSearch = "";
let searchTimeout = null;

let churnTrendChart = null;
let onboardingChart = null;

// =============================================================================
// Summary Cards
// =============================================================================

async function churn_loadSummaryCards() {
    try {
        const resp = await fetch("/api/churn/summary");
        if (!resp.ok) throw new Error("Failed to load churn summary");
        const data = await resp.json();

        document.getElementById("card-at-risk").textContent = data.at_risk_count;
        document.getElementById("card-at-risk-sub").textContent =
            `of ${data.total_members} total members`;

        document.getElementById("card-critical").textContent = data.critical_count;
        document.getElementById("card-critical-sub").textContent =
            `${data.members_lost_30d} inactive >60d`;

        if (data.monthly_price > 0) {
            document.getElementById("card-revenue").textContent =
                `EUR ${data.estimated_revenue_impact.toFixed(0)}`;
        } else {
            document.getElementById("card-revenue").textContent = "---";
        }

        // Set price input value
        document.getElementById("priceInput").value =
            data.monthly_price > 0 ? data.monthly_price : "";

        const avgScore = data.avg_score;
        document.getElementById("card-avg-score").textContent = avgScore.toFixed(1);

        let tierLabel = "Healthy";
        let tierColor = "#22c55e";
        if (avgScore > 75) { tierLabel = "Critical"; tierColor = "#ef4444"; }
        else if (avgScore > 50) { tierLabel = "At Risk"; tierColor = "#f97316"; }
        else if (avgScore > 25) { tierLabel = "Watch"; tierColor = "#f59e0b"; }

        document.getElementById("card-avg-score").style.color = tierColor;
        document.getElementById("card-avg-score-sub").textContent = tierLabel;
    } catch (e) {
        console.error("Error loading churn summary:", e);
    }
}

// =============================================================================
// Save price
// =============================================================================

async function savePrice() {
    const val = document.getElementById("priceInput").value;
    const price = parseFloat(val) || 0;
    await ConfigEntry.set("churn_monthly_price", price.toString());
    churn_loadSummaryCards();
}

// =============================================================================
// Member Risk Table
// =============================================================================

async function loadMemberTable() {
    try {
        const params = new URLSearchParams({
            page: currentPage,
            pageSize: 50,
            sort: currentSort,
            tier: currentTierFilter,
            search: currentSearch,
        });
        const resp = await fetch(`/api/churn/members?${params}`);
        if (!resp.ok) throw new Error("Failed to load churn members");
        const data = await resp.json();

        const tbody = document.getElementById("churn-table-body");
        if (data.members.length === 0) {
            tbody.innerHTML = '<tr><td colspan="9" style="padding:16px;color:#9ca3af;text-align:center;">No members found</td></tr>';
            document.getElementById("churn-pagination").innerHTML = "";
            return;
        }

        let html = "";
        for (const m of data.members) {
            const riskDot = `<span class="risk-dot ${m.risk_tier}"></span>`;
            const scoreColor = getRiskColor(m.churn_score);

            // Last active
            let lastActiveStr = "Never";
            if (m.last_active > 0) {
                const daysAgo = m.last_active_days_ago;
                if (daysAgo === 0) lastActiveStr = "Today";
                else if (daysAgo === 1) lastActiveStr = "Yesterday";
                else if (daysAgo < 7) lastActiveStr = `${daysAgo}d ago`;
                else if (daysAgo < 30) lastActiveStr = `${Math.floor(daysAgo / 7)}w ago`;
                else lastActiveStr = `${Math.floor(daysAgo / 30)}mo ago`;
            }
            const lastActiveDate = m.last_active > 0
                ? new Date(m.last_active * 1000).toLocaleDateString()
                : "";

            // Trend arrow
            let trendHtml = '<span class="trend-flat">--</span>';
            if (m.trend === "increasing") trendHtml = '<span class="trend-up">&#9650;</span>';
            else if (m.trend === "declining") trendHtml = '<span class="trend-down">&#9660;</span>';

            // Joined date
            let joinedStr = "";
            if (m.member_created_at > 0) {
                joinedStr = new Date(m.member_created_at * 1000).toLocaleDateString();
            }

            // Badges
            let badgesHtml = "";
            for (const b of m.badges) {
                badgesHtml += `<span class="churn-badge ${b}">${formatBadge(b)}</span>`;
            }

            // Profile picture
            const picSrc = m.picture_url
                ? `/api/image/${m.skool_id}`
                : "";
            const picHtml = picSrc
                ? `<img class="member-pic" src="${picSrc}" onerror="this.style.display='none'" loading="lazy">`
                : "";

            html += `<tr>
                <td>${riskDot}</td>
                <td style="color:${scoreColor};font-weight:600;">${m.churn_score}</td>
                <td>${picHtml}${escapeHtml(m.name)}</td>
                <td title="${lastActiveDate}">${lastActiveStr}</td>
                <td>${m.posts_14d}</td>
                <td>${m.comments_14d}</td>
                <td style="text-align:center;">${trendHtml}</td>
                <td>${joinedStr}</td>
                <td>${badgesHtml}</td>
            </tr>`;
        }
        tbody.innerHTML = html;

        // Pagination
        renderPagination(data.page, data.total_pages, data.total);
    } catch (e) {
        console.error("Error loading churn members:", e);
        document.getElementById("churn-table-body").innerHTML =
            '<tr><td colspan="9" style="padding:16px;color:#ef4444;text-align:center;">Failed to load</td></tr>';
    }
}

function renderPagination(page, totalPages, total) {
    const container = document.getElementById("churn-pagination");
    if (totalPages <= 1) {
        container.innerHTML = `<small style="color:#9ca3af;">${total} members</small>`;
        return;
    }

    let html = `<small style="color:#9ca3af;">${total} members</small> `;
    html += `<button ${page <= 1 ? 'disabled' : ''} onclick="goToPage(${page - 1})">&lt;</button>`;

    // Show max 7 page buttons
    let startPage = Math.max(1, page - 3);
    let endPage = Math.min(totalPages, startPage + 6);
    startPage = Math.max(1, endPage - 6);

    for (let i = startPage; i <= endPage; i++) {
        html += `<button class="${i === page ? 'active' : ''}" onclick="goToPage(${i})">${i}</button>`;
    }

    html += `<button ${page >= totalPages ? 'disabled' : ''} onclick="goToPage(${page + 1})">&gt;</button>`;
    container.innerHTML = html;
}

function goToPage(page) {
    currentPage = page;
    loadMemberTable();
}

// =============================================================================
// Sorting and Filtering
// =============================================================================

function setSort(column) {
    // Toggle asc/desc
    if (column === "score") {
        currentSort = currentSort === "score_desc" ? "score_asc" : "score_desc";
    } else if (column === "name") {
        currentSort = currentSort === "name_asc" ? "name_desc" : "name_asc";
    } else if (column === "last_active") {
        currentSort = currentSort === "last_active_desc" ? "last_active_asc" : "last_active_desc";
    } else if (column === "joined") {
        currentSort = currentSort === "joined_desc" ? "joined_asc" : "joined_desc";
    }
    currentPage = 1;
    loadMemberTable();
}

function setTierFilter(tier) {
    currentTierFilter = tier;
    currentPage = 1;
    // Update button styles
    document.querySelectorAll(".churn-filter-btn").forEach(btn => {
        btn.classList.toggle("active", btn.dataset.tier === tier);
    });
    loadMemberTable();
}

function debounceSearch() {
    if (searchTimeout) clearTimeout(searchTimeout);
    searchTimeout = setTimeout(() => {
        currentSearch = document.getElementById("churnSearch").value.trim();
        currentPage = 1;
        loadMemberTable();
    }, 300);
}

// =============================================================================
// Churn Trend Chart
// =============================================================================

async function loadChurnTrendChart() {
    try {
        const resp = await fetch(`/api/churn/trend?days=${currentTrendPeriod}`);
        if (!resp.ok) throw new Error("Failed to load churn trend");
        const data = await resp.json();

        const ctx = document.getElementById("churnTrendChart").getContext("2d");
        if (churnTrendChart) churnTrendChart.destroy();

        churnTrendChart = new Chart(ctx, {
            type: "line",
            data: {
                labels: data.days,
                datasets: [
                    {
                        label: "At Risk (51+)",
                        data: data.at_risk,
                        borderColor: "#f97316",
                        backgroundColor: "#f9731622",
                        fill: false,
                        tension: 0.3,
                        pointRadius: 2,
                        borderWidth: 2,
                        spanGaps: true,
                    },
                    {
                        label: "Critical (76+)",
                        data: data.critical,
                        borderColor: "#ef4444",
                        backgroundColor: "#ef444422",
                        fill: false,
                        tension: 0.3,
                        pointRadius: 2,
                        borderWidth: 2,
                        spanGaps: true,
                    },
                ],
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                interaction: { mode: "index", intersect: false },
                plugins: {
                    legend: { position: "top", labels: { usePointStyle: true, boxWidth: 8 } },
                    title: { display: true, text: `Churn Trend (${currentTrendPeriod}d)`, font: { size: 13 } },
                },
                scales: {
                    x: {
                        ticks: {
                            maxTicksLimit: 10,
                            callback: function(val) {
                                const label = this.getLabelForValue(val);
                                return label ? label.substring(5) : "";
                            },
                        },
                        grid: { display: false },
                    },
                    y: {
                        beginAtZero: true,
                        grid: { color: "rgba(128,128,128,0.1)" },
                    },
                },
            },
        });
    } catch (e) {
        console.error("Error loading churn trend:", e);
    }
}

function setTrendPeriod(days) {
    currentTrendPeriod = days;
    ConfigEntry.set("churndash.trend_period", days.toString()).then();
    document.querySelectorAll("#tab-churn .period-btn").forEach(btn => {
        btn.style.fontWeight = parseInt(btn.dataset.days) === days ? "bold" : "normal";
        btn.style.textDecoration = parseInt(btn.dataset.days) === days ? "underline" : "none";
    });
    loadChurnTrendChart();
}

// =============================================================================
// Watchlist Alerts
// =============================================================================

async function loadAlerts() {
    try {
        const resp = await fetch("/api/churn/alerts");
        if (!resp.ok) throw new Error("Failed to load alerts");
        const data = await resp.json();

        const container = document.getElementById("alerts-container");
        if (data.alerts.length === 0) {
            container.innerHTML = '<div style="padding:12px;color:#9ca3af;">No alerts</div>';
            return;
        }

        let html = "";
        for (const alert of data.alerts) {
            if (alert.count === 0) continue;
            const sevClass = alert.severity;
            const sevIcon = alert.severity === "critical" ? "!!" : "!";
            const sevColor = alert.severity === "critical" ? "#ef4444" : "#f59e0b";

            let membersHtml = "";
            for (const m of alert.members) {
                membersHtml += `<div style="padding:2px 0;">${escapeHtml(m.name)} (score: ${m.churn_score}, ${m.last_active_days_ago}d ago)</div>`;
            }
            if (alert.count > alert.members.length) {
                membersHtml += `<div style="padding:2px 0;font-style:italic;">...and ${alert.count - alert.members.length} more</div>`;
            }

            html += `<div class="alert-card ${sevClass}">
                <div class="alert-header" onclick="toggleAlertMembers(this)">
                    <h4><span style="color:${sevColor}">${sevIcon}</span> ${escapeHtml(alert.name)}</h4>
                    <span style="color:#9ca3af;font-size:0.85em;">${alert.count} members</span>
                </div>
                <div class="alert-members">${membersHtml}</div>
            </div>`;
        }
        container.innerHTML = html || '<div style="padding:12px;color:#22c55e;">No active alerts</div>';
    } catch (e) {
        console.error("Error loading alerts:", e);
    }
}

function toggleAlertMembers(header) {
    const members = header.nextElementSibling;
    members.classList.toggle("expanded");
}

// =============================================================================
// Onboarding Health
// =============================================================================

async function loadOnboarding() {
    try {
        const resp = await fetch("/api/churn/onboarding");
        if (!resp.ok) throw new Error("Failed to load onboarding");
        const data = await resp.json();

        document.getElementById("onboard-7d").textContent = data.onboarding_rate_7d + "%";
        document.getElementById("onboard-14d").textContent = data.onboarding_rate_14d + "%";
        document.getElementById("onboard-ghost").textContent = data.ghost_rate + "%";
        document.getElementById("onboard-ghost").style.color =
            data.ghost_rate > 50 ? "#ef4444" : data.ghost_rate > 30 ? "#f59e0b" : "#22c55e";
        document.getElementById("onboard-avg-days").textContent =
            data.avg_days_to_first_post > 0 ? data.avg_days_to_first_post.toFixed(1) + "d" : "N/A";

        // Render onboarding chart
        loadOnboardingChart(data);
    } catch (e) {
        console.error("Error loading onboarding:", e);
    }
}

async function loadOnboardingChart(data) {
    if (!data) {
        try {
            const resp = await fetch("/api/churn/onboarding");
            if (!resp.ok) return;
            data = await resp.json();
        } catch (e) { return; }
    }

    const weekly = data.weekly_onboarding || [];
    if (weekly.length === 0) return;

    // Reverse so oldest week is first (left to right)
    const reversed = [...weekly].reverse();

    const ctx = document.getElementById("onboardingChart").getContext("2d");
    if (onboardingChart) onboardingChart.destroy();

    onboardingChart = new Chart(ctx, {
        type: "bar",
        data: {
            labels: reversed.map(w => w.week),
            datasets: [
                {
                    label: "Posted within 7d",
                    data: reversed.map(w => w.posted_7d),
                    backgroundColor: "#22c55e99",
                    borderColor: "#22c55e",
                    borderWidth: 1,
                },
                {
                    label: "No post yet",
                    data: reversed.map(w => w.no_post),
                    backgroundColor: "#ef444466",
                    borderColor: "#ef4444",
                    borderWidth: 1,
                },
            ],
        },
        options: {
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
                legend: { position: "top", labels: { usePointStyle: true, boxWidth: 8 } },
                title: { display: true, text: "Weekly New Member Onboarding", font: { size: 13 } },
            },
            scales: {
                x: {
                    stacked: true,
                    grid: { display: false },
                },
                y: {
                    stacked: true,
                    beginAtZero: true,
                    grid: { color: "rgba(128,128,128,0.1)" },
                },
            },
        },
    });
}

// =============================================================================
// Helpers
// =============================================================================

function getRiskColor(score) {
    if (score <= 25) return "#22c55e";
    if (score <= 50) return "#f59e0b";
    if (score <= 75) return "#f97316";
    return "#ef4444";
}

function formatBadge(badge) {
    const labels = {
        "new": "NEW",
        "silent_churner": "SILENT",
        "hardcore": "HC",
        "crown": "CROWN",
        "liftoff": "LIFTOFF",
        "diamond": "DIAMOND",
        "fire": "FIRE",
        "goat": "GOAT",
        "star": "STAR",
    };
    return labels[badge] || badge.toUpperCase();
}

function escapeHtml(str) {
    if (!str) return "";
    return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;")
              .replace(/"/g, "&quot;").replace(/'/g, "&#039;");
}

// =============================================================================
// Init
// =============================================================================

async function initChurnDash() {
    lib.showLoading("Loading churn dashboard...");

    // Restore saved trend period
    const savedPeriod = await ConfigEntry.get("churndash.trend_period");
    if (savedPeriod && parseInt(savedPeriod) > 0) {
        currentTrendPeriod = parseInt(savedPeriod);
    }

    // Set initial period button state
    document.querySelectorAll("#tab-churn .period-btn").forEach(btn => {
        btn.style.fontWeight = parseInt(btn.dataset.days) === currentTrendPeriod ? "bold" : "normal";
        btn.style.textDecoration = parseInt(btn.dataset.days) === currentTrendPeriod ? "underline" : "none";
    });

    // Load all sections in parallel
    await Promise.all([
        churn_loadSummaryCards(),
        loadMemberTable(),
        loadChurnTrendChart(),
        loadAlerts(),
        loadOnboarding(),
    ]);

    lib.hideLoading();
}
